This commit is contained in:
Evert Prants 2022-04-14 18:59:00 +03:00
parent d7937fc7e5
commit 4aa2dd0237
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
2 changed files with 77 additions and 35 deletions

View File

@ -62,7 +62,7 @@ export class ThirdPersonCamera {
mousemove: (e: MouseEvent) => this.dragEvent(e.clientX, e.clientY), mousemove: (e: MouseEvent) => this.dragEvent(e.clientX, e.clientY),
wheel: (e: WheelEvent) => { wheel: (e: WheelEvent) => {
e.deltaY < 0 ? (this.distance /= 1.2) : (this.distance *= 1.2); e.deltaY < 0 ? (this.distance /= 1.2) : (this.distance *= 1.2);
this.distance = clamp(this.distance, 4, 20); this.distance = clamp(this.distance, 3, 20);
this.calculateCameraOffset(); this.calculateCameraOffset();
}, },
// mobile // mobile
@ -88,22 +88,19 @@ export class ThirdPersonCamera {
if (this.previousPinchLength) { if (this.previousPinchLength) {
const delta = pinchLength / this.previousPinchLength; const delta = pinchLength / this.previousPinchLength;
delta > 0 ? (this.distance *= delta) : (this.distance /= delta); delta > 0 ? (this.distance *= delta) : (this.distance /= delta);
this.distance = clamp(this.distance, 4, 20); this.distance = clamp(this.distance, 3, 20);
this.calculateCameraOffset(); this.calculateCameraOffset();
} }
this.previousPinchLength = pinchLength; this.previousPinchLength = pinchLength;
} else { } else if (this.panning) {
this.dragEvent(ev.touches[0].clientX, ev.touches[0].clientY); this.dragEvent(ev.touches[0].clientX, ev.touches[0].clientY);
} }
}, },
touchend: (ev: TouchEvent) => { touchend: (ev: TouchEvent) => {
this.pinching = false; this.pinching = false;
this.panning = false;
this.previousPinchLength = 0; this.previousPinchLength = 0;
if (!ev.touches?.length) {
this.panning = false;
}
}, },
}; };

View File

@ -21,21 +21,22 @@ export enum LODSide {
LEFT, LEFT,
} }
export function mirrorSide(x: number): number { export function mirrorSide(side: number): number {
return (x + 2) % 4; return (side + 2) % 4;
} }
export function isAdjacent(s: number, q: number): boolean { export function isAdjacent(side: number, quadrant: number): boolean {
return (4 + q - s) % 4 <= 1; return (4 + quadrant - side) % 4 <= 1;
} }
export function reflectSide(s: number, q: number): number { export function reflectSide(side: number, quadrant: number): number {
return s % 2 ? (q % 2 ? q - 1 : q + 1) : 3 - q; return side % 2 ? (quadrant % 2 ? quadrant - 1 : quadrant + 1) : 3 - quadrant;
} }
export class QuadtreeNode { export class QuadtreeNode {
public _children: QuadtreeNode[] = []; private _children: QuadtreeNode[] = [];
public _neighbors: QuadtreeNode[] = []; private _neighbors: QuadtreeNode[] = [];
private _detailDifferences: number[] = [];
private _leaf = true; private _leaf = true;
private _mesh?: Mesh; private _mesh?: Mesh;
@ -103,7 +104,12 @@ export class QuadtreeNode {
public setNeighbor(side: LODSide, neighbor: QuadtreeNode) { public setNeighbor(side: LODSide, neighbor: QuadtreeNode) {
this._neighbors[side] = neighbor; this._neighbors[side] = neighbor;
neighbor._neighbors[mirrorSide(side)] = this; if (neighbor) {
const mirrored = mirrorSide(side);
neighbor._neighbors[mirrored] = this;
neighbor._updateNeighborDetailDifferences(mirrored);
}
this._updateNeighborDetailDifferences(side);
} }
public findNeighbor(side: LODSide) { public findNeighbor(side: LODSide) {
@ -128,6 +134,31 @@ export class QuadtreeNode {
} }
} }
private _equalOrHigherNeighbor(side: LODSide): QuadtreeNode {
for (let node: QuadtreeNode = this; !!node; node = node.parent) {
if (node?._neighbors[side]) {
return node._neighbors[side];
}
}
return null;
}
private _updateNeighborDetailDifferences(side: LODSide) {
for (let i = 0; i < 4; i++) {
const neighbor = this._equalOrHigherNeighbor(i);
if (neighbor) {
this._detailDifferences[i] = Math.min(this.level - neighbor.level, 4);
}
}
if (!this._leaf) {
for (let i = 0; i < 4; i++) {
if (isAdjacent(side, i))
this._children[i]._updateNeighborDetailDifferences(side);
}
}
}
private _createGeometry(): BufferGeometry { private _createGeometry(): BufferGeometry {
const apparentSize = this.root.size / Math.pow(2, this.level); const apparentSize = this.root.size / Math.pow(2, this.level);
const vertCount = const vertCount =
@ -144,36 +175,50 @@ export class QuadtreeNode {
const vertDivj = y / (vertCount - 1); const vertDivj = y / (vertCount - 1);
const vertDivi = x / (vertCount - 1); const vertDivi = x / (vertCount - 1);
const absX = this.position.x + (y / (vertCount - 1)) * apparentSize; const absX = this.position.x + vertDivj * apparentSize;
const absY = this.position.y + (x / (vertCount - 1)) * apparentSize; const absY = this.position.y + vertDivi * apparentSize;
const normal = this.root.getNormal(absX, absY); const normal = this.root.getNormal(absX, absY);
const height = this.root.getHeight(absX, absY);
// Calculate relative resolution // Calculate relative resolution
const pj = vertDivj * (this.root.size / divisionLevel); const pj = vertDivj * (this.root.size / divisionLevel);
const pi = vertDivi * (this.root.size / divisionLevel); const pi = vertDivi * (this.root.size / divisionLevel);
vertices.push(pj, this.root.getHeight(absX, absY), pi); vertices.push(pj, height, pi);
normals.push(normal.x, normal.y, normal.z); normals.push(normal.x, normal.y, normal.z);
uvs.push(absX / (this.root.size - 1), absY / (this.root.size - 1)); uvs.push(absX / (this.root.size - 1), absY / (this.root.size - 1));
// Create quad
if (x !== vertCount - 1 && y !== vertCount - 1) {
const topLeft = x * vertCount + y;
const topRight = topLeft + 1;
const bottomLeft = (x + 1) * vertCount + y;
const bottomRight = bottomLeft + 1;
indices.push(
topLeft,
bottomLeft,
topRight,
topRight,
bottomLeft,
bottomRight,
);
}
} }
} }
for (let x = 0; x < vertCount - 1; x++) { // for (let test = 1; test < vertCount; test += 2) {
for (let y = 0; y < vertCount - 1; y++) { // // bottom
const topLeft = x * vertCount + y; // vertices[test * 3 + 1] = vertices[test * 3 + 1] + 2;
const topRight = topLeft + 1; // // top
const bottomLeft = (x + 1) * vertCount + y; // const testi = vertCount * vertCount * 3 - vertCount * 3 + test * 3;
const bottomRight = bottomLeft + 1; // vertices[testi + 1] = vertices[testi + 1] + 2;
indices.push( // // right
topLeft, // const testi2 = vertCount * 3 * test;
bottomLeft, // vertices[testi2 + 1] = vertices[testi2 + 1] + 2;
topRight, // // left
topRight, // const testi3 = vertCount * 3 * test + (vertCount - 1) * 3;
bottomLeft, // vertices[testi3 + 1] = vertices[testi3 + 1] + 2;
bottomRight, // }
);
}
}
geometry.setIndex(indices); geometry.setIndex(indices);
geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3)); geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));