auto-git:
[add] src/rendering/terrain-layer-material.ts [add] tests/domain/terrains.test.ts [change] src/app/App.tsx [change] src/core/terrain-brush.ts [change] src/document/migrate-scene-document.ts [change] src/document/scene-document-validation.ts [change] src/document/scene-document.ts [change] src/document/terrains.ts [change] src/geometry/terrain-brush.ts [change] src/geometry/terrain-mesh.ts [change] src/runtime-three/rapier-collision-world.ts [change] src/runtime-three/runtime-host.ts [change] src/runtime-three/runtime-scene-build.ts [change] src/viewport-three/ViewportCanvas.tsx [change] src/viewport-three/ViewportPanel.tsx [change] src/viewport-three/viewport-host.ts [change] tests/domain/build-runtime-scene.test.ts [change] tests/domain/rapier-collision-world.test.ts [change] tests/domain/terrain.command.test.ts [change] tests/domain/water-material.test.ts [change] tests/geometry/terrain-brush.test.ts [change] tests/geometry/terrain-mesh.test.ts [change] tests/serialization/scene-document-json.test.ts [change] tests/unit/terrain-foundation.integration.test.tsx [change] tests/unit/viewport-canvas.test.tsx
This commit is contained in:
@@ -19,6 +19,7 @@ import { getFirstPersonPlayerShapeSignature } from "./player-collision";
|
||||
import type {
|
||||
RuntimeBrushTriMeshCollider,
|
||||
RuntimeNpcCollider,
|
||||
RuntimeTerrainHeightfieldCollider,
|
||||
RuntimeSceneCollider
|
||||
} from "./runtime-scene-build";
|
||||
|
||||
@@ -86,7 +87,11 @@ function scaleBoundsCenter(bounds: { min: Vec3; max: Vec3 }, scale: Vec3): Vec3
|
||||
};
|
||||
}
|
||||
|
||||
function createRapierHeightfieldHeights(collider: GeneratedModelHeightfieldCollider): Float32Array {
|
||||
function createRapierHeightfieldHeights(collider: {
|
||||
rows: number;
|
||||
cols: number;
|
||||
heights: ArrayLike<number>;
|
||||
}): Float32Array {
|
||||
const heights = new Float32Array(collider.heights.length);
|
||||
|
||||
// Rapier's heightfield samples are column-major, with the Z axis varying
|
||||
@@ -182,6 +187,45 @@ function attachTerrainModelCollider(world: RAPIER.World, collider: GeneratedMode
|
||||
);
|
||||
}
|
||||
|
||||
function attachTerrainCollider(
|
||||
world: RAPIER.World,
|
||||
collider: RuntimeTerrainHeightfieldCollider
|
||||
) {
|
||||
if (collider.rows < 2 || collider.cols < 2) {
|
||||
throw new Error(
|
||||
`Terrain collider ${collider.terrainId} must have at least a 2x2 height sample grid.`
|
||||
);
|
||||
}
|
||||
|
||||
const body = world.createRigidBody(
|
||||
RAPIER.RigidBodyDesc.fixed().setTranslation(
|
||||
collider.position.x,
|
||||
collider.position.y,
|
||||
collider.position.z
|
||||
)
|
||||
);
|
||||
const rowSubdivisions = collider.rows - 1;
|
||||
const colSubdivisions = collider.cols - 1;
|
||||
|
||||
world.createCollider(
|
||||
RAPIER.ColliderDesc.heightfield(
|
||||
rowSubdivisions,
|
||||
colSubdivisions,
|
||||
createRapierHeightfieldHeights(collider),
|
||||
{
|
||||
x: collider.maxX - collider.minX,
|
||||
y: 1,
|
||||
z: collider.maxZ - collider.minZ
|
||||
}
|
||||
).setTranslation(
|
||||
(collider.minX + collider.maxX) * 0.5,
|
||||
0,
|
||||
(collider.minZ + collider.maxZ) * 0.5
|
||||
),
|
||||
body
|
||||
);
|
||||
}
|
||||
|
||||
function attachDynamicModelCollider(world: RAPIER.World, collider: GeneratedModelCompoundCollider) {
|
||||
const body = createFixedBodyForModelCollider(world, collider);
|
||||
|
||||
@@ -385,6 +429,11 @@ export class RapierCollisionWorld {
|
||||
});
|
||||
|
||||
for (const collider of colliders) {
|
||||
if (collider.source === "terrain") {
|
||||
attachTerrainCollider(world, collider);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (collider.source === "brush") {
|
||||
attachBrushCollider(world, collider);
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user