add client side terrain without collision

This commit is contained in:
2024-12-23 11:57:36 +09:00
parent 604368b52c
commit ba0d8f606a
6 changed files with 107 additions and 9 deletions
+61
View File
@@ -0,0 +1,61 @@
import SAT from 'sat'
import { Shape, ShapeUtils, Vector2 } from 'three'
export default class Terrain {
id = crypto.randomUUID()
position = new Vector2()
relativeVertices = []
#colliders = []
#vertices = []
constructor(vertices) {
this.#vertices = vertices.map((v) => new Vector2(v.x, v.y))
this.#calculateColliders()
this.#calculatePosition()
this.#calculateRelativeVertices()
}
get colliders() { return this.#colliders }
get vertices() { return this.#vertices }
state() {
return {
...this,
position: {
x: this.x,
y: this.y,
},
}
}
#calculateColliders() {
const complexShape = new Shape()
complexShape.moveTo(this.#vertices.at(0).x, this.#vertices.at(0).y)
this.#vertices.slice(1).forEach((v) => complexShape.lineTo(v.x, v.y))
const points = complexShape.extractPoints(16)
const indicesToPolygon = (indices) => {
const satPoints = [
new SAT.Vector(...points.shape[indices[0]].toArray()),
new SAT.Vector(...points.shape[indices[1]].toArray()),
new SAT.Vector(...points.shape[indices[2]].toArray()),
]
return new SAT.Polygon(satPoints[0], [new SAT.Vector(), satPoints[1], satPoints[2]])
}
this.#colliders = ShapeUtils.triangulateShape(points.shape, points.holes).map(indicesToPolygon)
}
#calculatePosition() {
this.position = this.#vertices.reduce(((sum, v) => sum.add(v)), new Vector2()).divideScalar(this.#vertices.length)
}
#calculateRelativeVertices() {
this.relativeVertices = this.#vertices.map((v) => v.clone().sub(this.position))
}
}