feat: 添加跨平台运行时、资产系统和UI适配功能 (#256)
* feat(platform-common): 添加WASM加载器和环境检测API * feat(rapier2d): 新增Rapier2D WASM绑定包 * feat(physics-rapier2d): 添加跨平台WASM加载器 * feat(asset-system): 添加运行时资产目录和bundle格式 * feat(asset-system-editor): 新增编辑器资产管理包 * feat(editor-core): 添加构建系统和模块管理 * feat(editor-app): 重构浏览器预览使用import maps * feat(platform-web): 添加BrowserRuntime和资产读取 * feat(engine): 添加材质系统和着色器管理 * feat(material): 新增材质系统和着色器编辑器 * feat(tilemap): 增强tilemap编辑器和动画系统 * feat(modules): 添加module.json配置 * feat(core): 添加module.json和类型定义更新 * chore: 更新依赖和构建配置 * refactor(plugins): 更新插件模板使用ModuleManifest * chore: 添加第三方依赖库 * chore: 移除BehaviourTree-ai和ecs-astar子模块 * docs: 更新README和文档主题样式 * fix: 修复Rust文档测试和添加rapier2d WASM绑定 * fix(tilemap-editor): 修复画布高DPI屏幕分辨率适配问题 * feat(ui): 添加UI屏幕适配系统(CanvasScaler/SafeArea) * fix(ecs-engine-bindgen): 添加缺失的ecs-framework-math依赖 * fix: 添加缺失的包依赖修复CI构建 * fix: 修复CodeQL检测到的代码问题 * fix: 修复构建错误和缺失依赖 * fix: 修复类型检查错误 * fix(material-system): 修复tsconfig配置支持TypeScript项目引用 * fix(editor-core): 修复Rollup构建配置添加tauri external * fix: 修复CodeQL检测到的代码问题 * fix: 修复CodeQL检测到的代码问题
This commit is contained in:
75
thirdparty/rapier.js/testbed3d/src/demos/ccd.ts
vendored
Normal file
75
thirdparty/rapier.js/testbed3d/src/demos/ccd.ts
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
import type RAPIER from "@dimforge/rapier3d";
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
function createWall(
|
||||
RAPIER: RAPIER_API,
|
||||
testbed: Testbed,
|
||||
world: RAPIER.World,
|
||||
offset: {x: number; y: number; z: number},
|
||||
stackHeight: number,
|
||||
) {
|
||||
let i, j;
|
||||
|
||||
let shiftY = 1.0;
|
||||
let shiftZ = 2.0;
|
||||
|
||||
for (i = 0; i < stackHeight; ++i) {
|
||||
for (j = i; j < stackHeight; ++j) {
|
||||
let x = offset.x;
|
||||
let y = i * shiftY + offset.y;
|
||||
let z =
|
||||
(i * shiftZ) / 2.0 + (j - i) * shiftZ + offset.z - stackHeight;
|
||||
|
||||
// Create dynamic cube.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(0.5, 0.5, 1.0);
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let groundHeight = 0.1;
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(30.0, 0.1, 30.0);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
let numX = 5;
|
||||
let numZ = 8;
|
||||
let shiftY = groundHeight + 0.5;
|
||||
|
||||
let i;
|
||||
for (i = 0; i < numX; ++i) {
|
||||
let x = i * 6.0;
|
||||
createWall(RAPIER, testbed, world, {x: x, y: shiftY, z: 0.0}, numZ);
|
||||
}
|
||||
|
||||
// A very fast rigid-body with CCD enabled.
|
||||
// Create dynamic cube.
|
||||
bodyDesc = RAPIER.RigidBodyDesc.dynamic()
|
||||
.setTranslation(-20.0, shiftY + 2.0, 0.0)
|
||||
.setLinvel(1000.0, 0.0, 0.0)
|
||||
.setCcdEnabled(true);
|
||||
body = world.createRigidBody(bodyDesc);
|
||||
colliderDesc = RAPIER.ColliderDesc.ball(1.0).setDensity(10.0);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
testbed.setWorld(world);
|
||||
let cameraPosition = {
|
||||
eye: {x: -31.96000000000001, y: 19.730000000000008, z: -27.86},
|
||||
target: {x: -0.0505, y: -0.4126, z: -0.0229},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
106
thirdparty/rapier.js/testbed3d/src/demos/characterController.ts
vendored
Normal file
106
thirdparty/rapier.js/testbed3d/src/demos/characterController.ts
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(15.0, 0.1, 15.0);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
// Dynamic cubes.
|
||||
let rad = 0.5;
|
||||
let num = 5;
|
||||
let i, j, k;
|
||||
let shift = rad * 2.5;
|
||||
let center = num * rad;
|
||||
let height = 5.0;
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
for (j = i; j < num; ++j) {
|
||||
for (k = i; k < num; ++k) {
|
||||
let x = (i * shift) / 2.0 + (k - i) * shift - center;
|
||||
let y = (i * shift) / 2.0 + height;
|
||||
let z = (i * shift) / 2.0 + (j - i) * shift - center;
|
||||
|
||||
// Create dynamic cube.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad,
|
||||
rad / 2.0,
|
||||
rad,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Character.
|
||||
let characterDesc =
|
||||
RAPIER.RigidBodyDesc.kinematicPositionBased().setTranslation(
|
||||
-10.0,
|
||||
4.0,
|
||||
-10.0,
|
||||
);
|
||||
let character = world.createRigidBody(characterDesc);
|
||||
let characterColliderDesc = RAPIER.ColliderDesc.cylinder(1.2, 0.6);
|
||||
let characterCollider = world.createCollider(
|
||||
characterColliderDesc,
|
||||
character,
|
||||
);
|
||||
|
||||
let characterController = world.createCharacterController(0.1);
|
||||
characterController.enableAutostep(0.7, 0.3, true);
|
||||
characterController.enableSnapToGround(0.7);
|
||||
|
||||
let speed = 0.2;
|
||||
let movementDirection = {x: 0.0, y: -speed, z: 0.0};
|
||||
|
||||
let updateCharacter = () => {
|
||||
characterController.computeColliderMovement(
|
||||
characterCollider,
|
||||
movementDirection,
|
||||
);
|
||||
|
||||
let movement = characterController.computedMovement();
|
||||
let newPos = character.translation();
|
||||
newPos.x += movement.x;
|
||||
newPos.y += movement.y;
|
||||
newPos.z += movement.z;
|
||||
character.setNextKinematicTranslation(newPos);
|
||||
};
|
||||
|
||||
testbed.setWorld(world);
|
||||
testbed.setpreTimestepAction(updateCharacter);
|
||||
|
||||
document.onkeydown = function (event: KeyboardEvent) {
|
||||
if (event.key == "ArrowUp") movementDirection.x = speed;
|
||||
if (event.key == "ArrowDown") movementDirection.x = -speed;
|
||||
if (event.key == "ArrowLeft") movementDirection.z = -speed;
|
||||
if (event.key == "ArrowRight") movementDirection.z = speed;
|
||||
if (event.key == " ") movementDirection.y = speed;
|
||||
};
|
||||
|
||||
document.onkeyup = function (event: KeyboardEvent) {
|
||||
if (event.key == "ArrowUp") movementDirection.x = 0.0;
|
||||
if (event.key == "ArrowDown") movementDirection.x = 0.0;
|
||||
if (event.key == "ArrowLeft") movementDirection.z = 0.0;
|
||||
if (event.key == "ArrowRight") movementDirection.z = 0.0;
|
||||
if (event.key == " ") movementDirection.y = -speed; // Gravity
|
||||
};
|
||||
|
||||
let cameraPosition = {
|
||||
eye: {x: -40.0, y: 19.730000000000008, z: 0.0},
|
||||
target: {x: 0.0, y: -0.4126, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
73
thirdparty/rapier.js/testbed3d/src/demos/collisionGroups.ts
vendored
Normal file
73
thirdparty/rapier.js/testbed3d/src/demos/collisionGroups.ts
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let groundBody = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(5.0, 0.1, 5.0);
|
||||
world.createCollider(colliderDesc, groundBody);
|
||||
|
||||
// Setup groups.
|
||||
let group1 = 0x00010001;
|
||||
let group2 = 0x00020002;
|
||||
|
||||
// Add one floor that collides with the first group only.
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(1.0, 0.1, 1.0)
|
||||
.setTranslation(0.0, 1.0, 0.0)
|
||||
.setCollisionGroups(group1);
|
||||
world.createCollider(colliderDesc, groundBody);
|
||||
|
||||
// Add one floor that collides with the second group only.
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(1.0, 0.1, 1.0)
|
||||
.setTranslation(0.0, 2.0, 0.0)
|
||||
.setCollisionGroups(group2);
|
||||
world.createCollider(colliderDesc, groundBody);
|
||||
|
||||
// Dynamic cubes.
|
||||
let num = 8;
|
||||
let rad = 0.1;
|
||||
|
||||
let shift = rad * 2.0;
|
||||
let centerx = shift * (num / 2);
|
||||
let centery = 2.5;
|
||||
let centerz = shift * (num / 2);
|
||||
let i, j, k;
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
for (i = 0; i < num; i++) {
|
||||
for (k = 0; k < num; k++) {
|
||||
let x = i * shift - centerx;
|
||||
let y = j * shift + centery;
|
||||
let z = k * shift - centerz;
|
||||
|
||||
// Alternate between the green and blue groups.
|
||||
let group = k % 2 == 0 ? group1 : group2;
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad,
|
||||
rad,
|
||||
rad,
|
||||
).setCollisionGroups(group);
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testbed.setWorld(world);
|
||||
let cameraPosition = {
|
||||
eye: {x: 10.0, y: 5.0, z: 10.0},
|
||||
target: {x: 0.0, y: 0.0, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
111
thirdparty/rapier.js/testbed3d/src/demos/convexPolyhedron.ts
vendored
Normal file
111
thirdparty/rapier.js/testbed3d/src/demos/convexPolyhedron.ts
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
import type {Testbed} from "../Testbed";
|
||||
import seedrandom from "seedrandom";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
function generateTriMesh(nsubdivs: number, wx: number, wy: number, wz: number) {
|
||||
let vertices = [];
|
||||
let indices = [];
|
||||
|
||||
let elementWidth = 1.0 / nsubdivs;
|
||||
let rng = seedrandom("trimesh");
|
||||
|
||||
let i, j;
|
||||
for (i = 0; i <= nsubdivs; ++i) {
|
||||
for (j = 0; j <= nsubdivs; ++j) {
|
||||
let x = (j * elementWidth - 0.5) * wx;
|
||||
let y = rng() * wy;
|
||||
let z = (i * elementWidth - 0.5) * wz;
|
||||
|
||||
vertices.push(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nsubdivs; ++i) {
|
||||
for (j = 0; j < nsubdivs; ++j) {
|
||||
let i1 = (i + 0) * (nsubdivs + 1) + (j + 0);
|
||||
let i2 = (i + 0) * (nsubdivs + 1) + (j + 1);
|
||||
let i3 = (i + 1) * (nsubdivs + 1) + (j + 0);
|
||||
let i4 = (i + 1) * (nsubdivs + 1) + (j + 1);
|
||||
|
||||
indices.push(i1, i3, i2);
|
||||
indices.push(i3, i4, i2);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
vertices: new Float32Array(vertices),
|
||||
indices: new Uint32Array(indices),
|
||||
};
|
||||
}
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let trimesh = generateTriMesh(20, 40.0, 4.0, 40.0);
|
||||
let colliderDesc = RAPIER.ColliderDesc.trimesh(
|
||||
trimesh.vertices,
|
||||
trimesh.indices,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
/*
|
||||
* Create the polyhedra
|
||||
*/
|
||||
let num = 5;
|
||||
let scale = 2.0;
|
||||
let border_rad = 0.1;
|
||||
|
||||
let shift = border_rad * 2.0 + scale;
|
||||
let centerx = shift * (num / 2);
|
||||
let centery = shift / 2.0;
|
||||
let centerz = shift * (num / 2);
|
||||
|
||||
let rng = seedrandom("convexPolyhedron");
|
||||
let i, j, k, l;
|
||||
|
||||
for (j = 0; j < 15; ++j) {
|
||||
for (i = 0; i < num; ++i) {
|
||||
for (k = 0; k < num; ++k) {
|
||||
let x = i * shift - centerx;
|
||||
let y = j * shift + centery + 3.0;
|
||||
let z = k * shift - centerz;
|
||||
|
||||
let vertices = [];
|
||||
for (l = 0; l < 10; ++l) {
|
||||
vertices.push(rng() * scale, rng() * scale, rng() * scale);
|
||||
}
|
||||
let v = new Float32Array(vertices);
|
||||
|
||||
// Build the rigid body.
|
||||
bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
);
|
||||
body = world.createRigidBody(bodyDesc);
|
||||
colliderDesc = RAPIER.ColliderDesc.roundConvexHull(
|
||||
v,
|
||||
border_rad,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testbed.setWorld(world);
|
||||
|
||||
let cameraPosition = {
|
||||
eye: {
|
||||
x: -88.48024008669711,
|
||||
y: 46.911325612198354,
|
||||
z: 83.56055570254844,
|
||||
},
|
||||
target: {x: 0.0, y: 0.0, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
42
thirdparty/rapier.js/testbed3d/src/demos/damping.ts
vendored
Normal file
42
thirdparty/rapier.js/testbed3d/src/demos/damping.ts
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, 0.0, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
/*
|
||||
* Create the cubes
|
||||
*/
|
||||
let num = 10;
|
||||
let rad = 0.2;
|
||||
|
||||
let subdiv = 1.0 / num;
|
||||
|
||||
let i;
|
||||
for (i = 0; i < num; ++i) {
|
||||
let x = Math.sin(i * subdiv * Math.PI * 2.0);
|
||||
let y = Math.cos(i * subdiv * Math.PI * 2.0);
|
||||
|
||||
// Build the rigid body.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic()
|
||||
.setTranslation(x, y, 0.0)
|
||||
.setLinvel(x * 10.0, y * 10.0, 0.0)
|
||||
.setAngvel(new RAPIER.Vector3(0.0, 0.0, 100.0))
|
||||
.setLinearDamping((i + 1) * subdiv * 10.0)
|
||||
.setAngularDamping((num - i) * subdiv * 10.0);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
|
||||
// Build the collider.
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad, rad);
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
|
||||
testbed.setWorld(world);
|
||||
let cameraPosition = {
|
||||
eye: {x: 0, y: 2.0, z: 20},
|
||||
target: {x: 0, y: 2.0, z: 0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
78
thirdparty/rapier.js/testbed3d/src/demos/fountain.ts
vendored
Normal file
78
thirdparty/rapier.js/testbed3d/src/demos/fountain.ts
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
let removableBodies = new Array();
|
||||
|
||||
// Create Ground.
|
||||
let groundBodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let groundBody = world.createRigidBody(groundBodyDesc);
|
||||
let groundColliderDesc = RAPIER.ColliderDesc.cuboid(40.0, 0.1, 40.0);
|
||||
world.createCollider(groundColliderDesc, groundBody);
|
||||
|
||||
// Dynamic cubes.
|
||||
let rad = 1.0;
|
||||
let j = 0;
|
||||
let spawn_interval = 5;
|
||||
|
||||
let spawnBodies = (graphics: Testbed["graphics"]) => {
|
||||
j += 1;
|
||||
if (j % spawn_interval != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic()
|
||||
.setLinvel(0.0, 15.0, 0.0)
|
||||
.setTranslation(0.0, 10.0, 0.0);
|
||||
let colliderDesc;
|
||||
|
||||
switch ((j / spawn_interval) % 4) {
|
||||
case 0:
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad, rad);
|
||||
break;
|
||||
case 1:
|
||||
colliderDesc = RAPIER.ColliderDesc.ball(rad);
|
||||
break;
|
||||
case 2:
|
||||
colliderDesc = RAPIER.ColliderDesc.roundCylinder(
|
||||
rad,
|
||||
rad,
|
||||
rad / 10.0,
|
||||
);
|
||||
break;
|
||||
case 3:
|
||||
colliderDesc = RAPIER.ColliderDesc.cone(rad, rad);
|
||||
break;
|
||||
}
|
||||
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let collider = world.createCollider(colliderDesc, body);
|
||||
graphics.addCollider(RAPIER, world, collider);
|
||||
|
||||
removableBodies.push(body);
|
||||
|
||||
// We reached the max number, delete the oldest rigid-body.
|
||||
if (removableBodies.length > 400) {
|
||||
let rb = removableBodies[0];
|
||||
world.removeRigidBody(rb);
|
||||
graphics.removeRigidBody(rb);
|
||||
removableBodies.shift();
|
||||
}
|
||||
};
|
||||
|
||||
testbed.setWorld(world);
|
||||
testbed.setpreTimestepAction(spawnBodies);
|
||||
|
||||
let cameraPosition = {
|
||||
eye: {
|
||||
x: -88.48024008669711,
|
||||
y: 46.911325612198354,
|
||||
z: 83.56055570254844,
|
||||
},
|
||||
target: {x: 0.0, y: 10.0, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
68
thirdparty/rapier.js/testbed3d/src/demos/glbToTrimesh.ts
vendored
Normal file
68
thirdparty/rapier.js/testbed3d/src/demos/glbToTrimesh.ts
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import type {Testbed} from "../Testbed";
|
||||
import {Vector3, Object3D, Mesh, BufferGeometry, BufferAttribute} from "three";
|
||||
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader";
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
testbed.parameters.debugRender = true;
|
||||
|
||||
// Create Ground.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let groundBody = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(5.0, 0.1, 5.0);
|
||||
world.createCollider(colliderDesc, groundBody);
|
||||
|
||||
// Adding the 3d model
|
||||
|
||||
let loader = new GLTFLoader();
|
||||
|
||||
loader.load("./suzanne_blender_monkey.glb", (gltf) => {
|
||||
gltf.scene.position.set(0, 1.2, 0);
|
||||
gltf.scene.scale.set(3, 3, 3);
|
||||
testbed.graphics.scene.add(gltf.scene);
|
||||
gltf.scene.updateMatrixWorld(true); // ensure world matrix is up to date
|
||||
gltf.scene.traverse((child: Object3D) => {
|
||||
if ((child as Mesh).isMesh && (child as Mesh).geometry) {
|
||||
const mesh = child as Mesh;
|
||||
const geometry = mesh.geometry as BufferGeometry;
|
||||
|
||||
const vertices: number[] = [];
|
||||
const indices = new Uint32Array(geometry.index!.array); // assume index is non-null
|
||||
const positionAttribute = geometry.getAttribute(
|
||||
"position",
|
||||
) as BufferAttribute;
|
||||
|
||||
mesh.updateWorldMatrix(true, true);
|
||||
|
||||
const v = new Vector3();
|
||||
|
||||
for (let i = 0, l = positionAttribute.count; i < l; i++) {
|
||||
v.fromBufferAttribute(positionAttribute, i);
|
||||
v.applyMatrix4(mesh.matrixWorld);
|
||||
vertices.push(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
const verticesArray = new Float32Array(vertices);
|
||||
|
||||
const rigidBodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
const rigidBody = world.createRigidBody(rigidBodyDesc);
|
||||
|
||||
const colliderDesc = RAPIER.ColliderDesc.trimesh(
|
||||
verticesArray,
|
||||
indices,
|
||||
);
|
||||
world.createCollider(colliderDesc, rigidBody);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
testbed.setWorld(world);
|
||||
let cameraPosition = {
|
||||
eye: {x: 10.0, y: 5.0, z: 10.0},
|
||||
target: {x: 0.0, y: 0.0, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
68
thirdparty/rapier.js/testbed3d/src/demos/glbtoConvexHull.ts
vendored
Normal file
68
thirdparty/rapier.js/testbed3d/src/demos/glbtoConvexHull.ts
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import type {Testbed} from "../Testbed";
|
||||
import {
|
||||
Vector3,
|
||||
Object3D,
|
||||
Mesh,
|
||||
BufferGeometry,
|
||||
BufferAttribute,
|
||||
TriangleStripDrawMode,
|
||||
} from "three";
|
||||
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader";
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let groundBody = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(5.0, 0.1, 5.0);
|
||||
world.createCollider(colliderDesc, groundBody);
|
||||
|
||||
// Adding the 3d model
|
||||
|
||||
let loader = new GLTFLoader();
|
||||
|
||||
loader.load("./suzanne_blender_monkey.glb", (gltf) => {
|
||||
gltf.scene.position.set(0, 1.2, 0);
|
||||
gltf.scene.scale.set(3, 3, 3);
|
||||
testbed.graphics.scene.add(gltf.scene);
|
||||
testbed.parameters.debugRender = true;
|
||||
gltf.scene.updateMatrixWorld(true); // ensure world matrix is up to date
|
||||
|
||||
const v = new Vector3();
|
||||
const positions: number[] = [];
|
||||
|
||||
gltf.scene.traverse((child: Object3D) => {
|
||||
if ((child as Mesh).isMesh && (child as Mesh).geometry) {
|
||||
const mesh = child as Mesh;
|
||||
const geometry = mesh.geometry as BufferGeometry;
|
||||
const positionAttribute = geometry.getAttribute(
|
||||
"position",
|
||||
) as BufferAttribute;
|
||||
|
||||
for (let i = 0, l = positionAttribute.count; i < l; i++) {
|
||||
v.fromBufferAttribute(positionAttribute, i);
|
||||
v.applyMatrix4(mesh.matrixWorld);
|
||||
positions.push(v.x, v.y, v.z);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const rigidBodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
const rigidBody = world.createRigidBody(rigidBodyDesc);
|
||||
|
||||
const colliderDesc = RAPIER.ColliderDesc.convexHull(
|
||||
new Float32Array(positions),
|
||||
);
|
||||
world.createCollider(colliderDesc, rigidBody);
|
||||
});
|
||||
|
||||
testbed.setWorld(world);
|
||||
let cameraPosition = {
|
||||
eye: {x: 10.0, y: 5.0, z: 10.0},
|
||||
target: {x: 0.0, y: 0.0, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
126
thirdparty/rapier.js/testbed3d/src/demos/heightfield.ts
vendored
Normal file
126
thirdparty/rapier.js/testbed3d/src/demos/heightfield.ts
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
import seedrandom from "seedrandom";
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
function generateHeightfield(nsubdivs: number) {
|
||||
let heights = [];
|
||||
|
||||
let rng = seedrandom("heightfield");
|
||||
|
||||
let i, j;
|
||||
for (i = 0; i <= nsubdivs; ++i) {
|
||||
for (j = 0; j <= nsubdivs; ++j) {
|
||||
heights.push(rng());
|
||||
}
|
||||
}
|
||||
|
||||
return new Float32Array(heights);
|
||||
}
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let nsubdivs = 20;
|
||||
let scale = new RAPIER.Vector3(70.0, 4.0, 70.0);
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let heights = generateHeightfield(nsubdivs);
|
||||
let colliderDesc = RAPIER.ColliderDesc.heightfield(
|
||||
nsubdivs,
|
||||
nsubdivs,
|
||||
heights,
|
||||
scale,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
// Dynamic cubes.
|
||||
let num = 4;
|
||||
let numy = 10;
|
||||
let rad = 1.0;
|
||||
|
||||
let shift = rad * 2.0 + rad;
|
||||
let centery = shift / 2.0;
|
||||
|
||||
let offset = -num * (rad * 2.0 + rad) * 0.5;
|
||||
let i, j, k;
|
||||
|
||||
for (j = 0; j < numy; ++j) {
|
||||
for (i = 0; i < num; ++i) {
|
||||
for (k = 0; k < num; ++k) {
|
||||
let x = i * shift + offset;
|
||||
let y = j * shift + centery + 3.0;
|
||||
let z = k * shift + offset;
|
||||
|
||||
// Create dynamic cube.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc;
|
||||
|
||||
switch (j % 5) {
|
||||
case 0:
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad,
|
||||
rad,
|
||||
rad,
|
||||
);
|
||||
break;
|
||||
case 1:
|
||||
colliderDesc = RAPIER.ColliderDesc.ball(rad);
|
||||
break;
|
||||
case 2:
|
||||
colliderDesc = RAPIER.ColliderDesc.roundCylinder(
|
||||
rad,
|
||||
rad,
|
||||
rad / 10.0,
|
||||
);
|
||||
break;
|
||||
case 3:
|
||||
colliderDesc = RAPIER.ColliderDesc.cone(rad, rad);
|
||||
break;
|
||||
case 4:
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad / 2.0,
|
||||
rad / 2.0,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad,
|
||||
rad / 2.0,
|
||||
).setTranslation(rad, 0.0, 0.0);
|
||||
world.createCollider(colliderDesc, body);
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad,
|
||||
rad / 2.0,
|
||||
).setTranslation(-rad, 0.0, 0.0);
|
||||
break;
|
||||
}
|
||||
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
|
||||
offset -= 0.05 * rad * (num - 1.0);
|
||||
}
|
||||
|
||||
testbed.setWorld(world);
|
||||
|
||||
let cameraPosition = {
|
||||
eye: {
|
||||
x: -88.48024008669711,
|
||||
y: 46.911325612198354,
|
||||
z: 83.56055570254844,
|
||||
},
|
||||
target: {x: 0.0, y: 0.0, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
292
thirdparty/rapier.js/testbed3d/src/demos/joints.ts
vendored
Normal file
292
thirdparty/rapier.js/testbed3d/src/demos/joints.ts
vendored
Normal file
@@ -0,0 +1,292 @@
|
||||
import type RAPIER from "@dimforge/rapier3d";
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
function createPrismaticJoints(
|
||||
RAPIER: RAPIER_API,
|
||||
world: RAPIER.World,
|
||||
origin: RAPIER.Vector,
|
||||
num: number,
|
||||
) {
|
||||
let rad = 0.4;
|
||||
let shift = 1.0;
|
||||
|
||||
let groundDesc = RAPIER.RigidBodyDesc.fixed().setTranslation(
|
||||
origin.x,
|
||||
origin.y,
|
||||
origin.z,
|
||||
);
|
||||
let currParent = world.createRigidBody(groundDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad, rad);
|
||||
world.createCollider(colliderDesc, currParent);
|
||||
|
||||
let i;
|
||||
let z;
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
z = origin.z + (i + 1) * shift;
|
||||
let rigidBodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
origin.x,
|
||||
origin.y,
|
||||
z,
|
||||
);
|
||||
let currChild = world.createRigidBody(rigidBodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad, rad);
|
||||
world.createCollider(colliderDesc, currChild);
|
||||
|
||||
let axis;
|
||||
|
||||
if (i % 2 == 0) {
|
||||
axis = new RAPIER.Vector3(1.0, 1.0, 0.0);
|
||||
} else {
|
||||
axis = new RAPIER.Vector3(-1.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
z = new RAPIER.Vector3(0.0, 0.0, 1.0);
|
||||
let prism = RAPIER.JointData.prismatic(
|
||||
new RAPIER.Vector3(0.0, 0.0, 0.0),
|
||||
new RAPIER.Vector3(0.0, 0.0, -shift),
|
||||
axis,
|
||||
);
|
||||
prism.limitsEnabled = true;
|
||||
prism.limits = [-2.0, 2.0];
|
||||
world.createImpulseJoint(prism, currParent, currChild, true);
|
||||
|
||||
currParent = currChild;
|
||||
}
|
||||
}
|
||||
|
||||
function createRevoluteJoints(
|
||||
RAPIER: RAPIER_API,
|
||||
world: RAPIER.World,
|
||||
origin: RAPIER.Vector3,
|
||||
num: number,
|
||||
) {
|
||||
let rad = 0.4;
|
||||
let shift = 2.0;
|
||||
|
||||
let groundDesc = RAPIER.RigidBodyDesc.fixed().setTranslation(
|
||||
origin.x,
|
||||
origin.y,
|
||||
0.0,
|
||||
);
|
||||
let currParent = world.createRigidBody(groundDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad, rad);
|
||||
world.createCollider(colliderDesc, currParent);
|
||||
|
||||
let i, k;
|
||||
let z;
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
// Create four bodies.
|
||||
z = origin.z + i * shift * 2.0 + shift;
|
||||
|
||||
let positions = [
|
||||
new RAPIER.Vector3(origin.x, origin.y, z),
|
||||
new RAPIER.Vector3(origin.x + shift, origin.y, z),
|
||||
new RAPIER.Vector3(origin.x + shift, origin.y, z + shift),
|
||||
new RAPIER.Vector3(origin.x, origin.y, z + shift),
|
||||
];
|
||||
|
||||
let parents = [currParent, currParent, currParent, currParent];
|
||||
|
||||
for (k = 0; k < 4; ++k) {
|
||||
let rigidBodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
positions[k].x,
|
||||
positions[k].y,
|
||||
positions[k].z,
|
||||
);
|
||||
let rigidBody = world.createRigidBody(rigidBodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad, rad);
|
||||
world.createCollider(colliderDesc, rigidBody);
|
||||
|
||||
parents[k] = rigidBody;
|
||||
}
|
||||
|
||||
// Setup four joints.
|
||||
let o = new RAPIER.Vector3(0.0, 0.0, 0.0);
|
||||
let x = new RAPIER.Vector3(1.0, 0.0, 0.0);
|
||||
z = new RAPIER.Vector3(0.0, 0.0, 1.0);
|
||||
|
||||
let revs = [
|
||||
RAPIER.JointData.revolute(
|
||||
o,
|
||||
new RAPIER.Vector3(0.0, 0.0, -shift),
|
||||
z,
|
||||
),
|
||||
RAPIER.JointData.revolute(
|
||||
o,
|
||||
new RAPIER.Vector3(-shift, 0.0, 0.0),
|
||||
x,
|
||||
),
|
||||
RAPIER.JointData.revolute(
|
||||
o,
|
||||
new RAPIER.Vector3(0.0, 0.0, -shift),
|
||||
z,
|
||||
),
|
||||
RAPIER.JointData.revolute(
|
||||
o,
|
||||
new RAPIER.Vector3(shift, 0.0, 0.0),
|
||||
x,
|
||||
),
|
||||
];
|
||||
|
||||
world.createImpulseJoint(revs[0], currParent, parents[0], true);
|
||||
world.createImpulseJoint(revs[1], parents[0], parents[1], true);
|
||||
world.createImpulseJoint(revs[2], parents[1], parents[2], true);
|
||||
world.createImpulseJoint(revs[3], parents[2], parents[3], true);
|
||||
|
||||
currParent = parents[3];
|
||||
}
|
||||
}
|
||||
|
||||
function createFixedJoints(
|
||||
RAPIER: RAPIER_API,
|
||||
world: RAPIER.World,
|
||||
origin: RAPIER.Vector3,
|
||||
num: number,
|
||||
) {
|
||||
let rad = 0.4;
|
||||
let shift = 1.0;
|
||||
let i, k;
|
||||
let parents = [];
|
||||
|
||||
for (k = 0; k < num; ++k) {
|
||||
for (i = 0; i < num; ++i) {
|
||||
let fk = k;
|
||||
let fi = i;
|
||||
|
||||
// NOTE: the num - 2 test is to avoid two consecutive
|
||||
// fixed bodies. Because physx will crash if we add
|
||||
// a joint between these.
|
||||
let bodyType;
|
||||
|
||||
if (i == 0 && ((k % 4 == 0 && k != num - 2) || k == num - 1)) {
|
||||
bodyType = RAPIER.RigidBodyType.Fixed;
|
||||
} else {
|
||||
bodyType = RAPIER.RigidBodyType.Dynamic;
|
||||
}
|
||||
|
||||
let rigidBody = new RAPIER.RigidBodyDesc(bodyType).setTranslation(
|
||||
origin.x + fk * shift,
|
||||
origin.y,
|
||||
origin.z + fi * shift,
|
||||
);
|
||||
let child = world.createRigidBody(rigidBody);
|
||||
let colliderDesc = RAPIER.ColliderDesc.ball(rad);
|
||||
world.createCollider(colliderDesc, child);
|
||||
|
||||
// Vertical joint.
|
||||
if (i > 0) {
|
||||
let parent = parents[parents.length - 1];
|
||||
let params = RAPIER.JointData.fixed(
|
||||
new RAPIER.Vector3(0.0, 0.0, 0.0),
|
||||
new RAPIER.Quaternion(0.0, 0.0, 0.0, 1.0),
|
||||
new RAPIER.Vector3(0.0, 0.0, -shift),
|
||||
new RAPIER.Quaternion(0.0, 0.0, 0.0, 1.0),
|
||||
);
|
||||
|
||||
world.createImpulseJoint(params, parent, child, true);
|
||||
}
|
||||
|
||||
// Horizontal joint.
|
||||
if (k > 0) {
|
||||
let parent_index = parents.length - num;
|
||||
let parent = parents[parent_index];
|
||||
let params = RAPIER.JointData.fixed(
|
||||
new RAPIER.Vector3(0.0, 0.0, 0.0),
|
||||
new RAPIER.Quaternion(0.0, 0.0, 0.0, 1.0),
|
||||
new RAPIER.Vector3(-shift, 0.0, 0.0),
|
||||
new RAPIER.Quaternion(0.0, 0.0, 0.0, 1.0),
|
||||
);
|
||||
|
||||
world.createImpulseJoint(params, parent, child, true);
|
||||
}
|
||||
|
||||
parents.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createBallJoints(
|
||||
RAPIER: RAPIER_API,
|
||||
world: RAPIER.World,
|
||||
num: number,
|
||||
) {
|
||||
let rad = 0.4;
|
||||
let shift = 1.0;
|
||||
let i, k;
|
||||
let parents = [];
|
||||
|
||||
for (k = 0; k < num; ++k) {
|
||||
for (i = 0; i < num; ++i) {
|
||||
let fk = k;
|
||||
let fi = i;
|
||||
|
||||
let bodyType;
|
||||
|
||||
if (i == 0 && (k % 4 == 0 || k == num - 1)) {
|
||||
bodyType = RAPIER.RigidBodyType.Fixed;
|
||||
} else {
|
||||
bodyType = RAPIER.RigidBodyType.Dynamic;
|
||||
}
|
||||
|
||||
let bodyDesc = new RAPIER.RigidBodyDesc(bodyType).setTranslation(
|
||||
fk * shift,
|
||||
0.0,
|
||||
fi * shift,
|
||||
);
|
||||
let child = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.ball(rad);
|
||||
world.createCollider(colliderDesc, child);
|
||||
|
||||
// Vertical joint.
|
||||
let o = new RAPIER.Vector3(0.0, 0.0, 0.0);
|
||||
|
||||
if (i > 0) {
|
||||
let parent = parents[parents.length - 1];
|
||||
let params = RAPIER.JointData.spherical(
|
||||
o,
|
||||
new RAPIER.Vector3(0.0, 0.0, -shift),
|
||||
);
|
||||
world.createImpulseJoint(params, parent, child, true);
|
||||
}
|
||||
|
||||
// Horizontal joint.
|
||||
if (k > 0) {
|
||||
let parent_index = parents.length - num;
|
||||
let parent = parents[parent_index];
|
||||
let params = RAPIER.JointData.spherical(
|
||||
o,
|
||||
new RAPIER.Vector3(-shift, 0.0, 0.0),
|
||||
);
|
||||
world.createImpulseJoint(params, parent, child, true);
|
||||
}
|
||||
|
||||
parents.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
createPrismaticJoints(
|
||||
RAPIER,
|
||||
world,
|
||||
new RAPIER.Vector3(20.0, 10.0, 0.0),
|
||||
5,
|
||||
);
|
||||
createFixedJoints(RAPIER, world, new RAPIER.Vector3(0.0, 10.0, 0.0), 5);
|
||||
createRevoluteJoints(RAPIER, world, new RAPIER.Vector3(20.0, 0.0, 0.0), 3);
|
||||
createBallJoints(RAPIER, world, 15);
|
||||
|
||||
testbed.setWorld(world);
|
||||
let cameraPosition = {
|
||||
eye: {x: 15.0, y: 5.0, z: 42.0},
|
||||
target: {x: 13.0, y: 1.0, z: 1.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
139
thirdparty/rapier.js/testbed3d/src/demos/keva.ts
vendored
Normal file
139
thirdparty/rapier.js/testbed3d/src/demos/keva.ts
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
import type RAPIER from "@dimforge/rapier3d";
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
function buildBlock(
|
||||
RAPIER: RAPIER_API,
|
||||
world: RAPIER.World,
|
||||
halfExtents: RAPIER.Vector,
|
||||
shift: RAPIER.Vector,
|
||||
numx: number,
|
||||
numy: number,
|
||||
numz: number,
|
||||
) {
|
||||
let half_extents_zyx = {
|
||||
x: halfExtents.z,
|
||||
y: halfExtents.y,
|
||||
z: halfExtents.x,
|
||||
};
|
||||
let dimensions = [halfExtents, half_extents_zyx];
|
||||
let blockWidth = 2.0 * halfExtents.z * numx;
|
||||
let blockHeight = 2.0 * halfExtents.y * numy;
|
||||
let spacing = (halfExtents.z * numx - halfExtents.x) / (numz - 1.0);
|
||||
|
||||
let i;
|
||||
let j;
|
||||
let k;
|
||||
|
||||
for (i = 0; i < numy; ++i) {
|
||||
[numx, numz] = [numz, numx];
|
||||
let dim = dimensions[i % 2];
|
||||
let y = dim.y * i * 2.0;
|
||||
|
||||
for (j = 0; j < numx; ++j) {
|
||||
let x = i % 2 == 0 ? spacing * j * 2.0 : dim.x * j * 2.0;
|
||||
|
||||
for (k = 0; k < numz; ++k) {
|
||||
let z = i % 2 == 0 ? dim.z * k * 2.0 : spacing * k * 2.0;
|
||||
// Build the rigid body.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
x + dim.x + shift.x,
|
||||
y + dim.y + shift.y,
|
||||
z + dim.z + shift.z,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
dim.x,
|
||||
dim.y,
|
||||
dim.z,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the top.
|
||||
let dim = {x: halfExtents.z, y: halfExtents.x, z: halfExtents.y};
|
||||
|
||||
for (i = 0; i < blockWidth / (dim.x * 2.0); ++i) {
|
||||
for (j = 0; j < blockWidth / (dim.z * 2.0); ++j) {
|
||||
// Build the rigid body.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
i * dim.x * 2.0 + dim.x + shift.x,
|
||||
dim.y + shift.y + blockHeight,
|
||||
j * dim.z * 2.0 + dim.z + shift.z,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(dim.x, dim.y, dim.z);
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let groundSize = 50.0;
|
||||
let groundHeight = 0.1;
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed().setTranslation(
|
||||
0.0,
|
||||
-groundHeight,
|
||||
0.0,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
groundSize,
|
||||
groundHeight,
|
||||
groundSize,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
// Keva tower.
|
||||
let halfExtents = new RAPIER.Vector3(0.1, 0.5, 2.0);
|
||||
let blockHeight = 0.0;
|
||||
// These should only be set to odd values otherwise
|
||||
// the blocks won't align in the nicest way.
|
||||
let numyArr = [0, 3, 5, 5, 7, 9];
|
||||
let numBlocksBuilt = 0;
|
||||
let i;
|
||||
|
||||
for (i = 5; i >= 1; --i) {
|
||||
let numx = i;
|
||||
let numy = numyArr[i];
|
||||
let numz = numx * 3 + 1;
|
||||
let blockWidth = numx * halfExtents.z * 2.0;
|
||||
buildBlock(
|
||||
RAPIER,
|
||||
world,
|
||||
halfExtents,
|
||||
new RAPIER.Vector3(
|
||||
-blockWidth / 2.0,
|
||||
blockHeight,
|
||||
-blockWidth / 2.0,
|
||||
),
|
||||
numx,
|
||||
numy,
|
||||
numz,
|
||||
);
|
||||
blockHeight += numy * halfExtents.y * 2.0 + halfExtents.x * 2.0;
|
||||
numBlocksBuilt += numx * numy * numz;
|
||||
}
|
||||
|
||||
testbed.setWorld(world);
|
||||
let cameraPosition = {
|
||||
eye: {
|
||||
x: -70.38553832116718,
|
||||
y: 17.893810295517365,
|
||||
z: 29.34767842147597,
|
||||
},
|
||||
target: {
|
||||
x: 0.5890869353464383,
|
||||
y: 3.132044603021203,
|
||||
z: -0.2899937806661885,
|
||||
},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
58
thirdparty/rapier.js/testbed3d/src/demos/lockedRotations.ts
vendored
Normal file
58
thirdparty/rapier.js/testbed3d/src/demos/lockedRotations.ts
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
/*
|
||||
* The ground
|
||||
*/
|
||||
let ground_size = 1.7;
|
||||
let ground_height = 0.1;
|
||||
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed().setTranslation(
|
||||
0.0,
|
||||
-ground_height,
|
||||
0.0,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
ground_size,
|
||||
ground_height,
|
||||
ground_size,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
/*
|
||||
* A rectangle that only rotates along the `x` axis.
|
||||
*/
|
||||
bodyDesc = RAPIER.RigidBodyDesc.dynamic()
|
||||
.setTranslation(0.0, 3.0, 0.0)
|
||||
.lockTranslations()
|
||||
.enabledRotations(true, false, false);
|
||||
body = world.createRigidBody(bodyDesc);
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(0.2, 0.6, 2.0);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
/*
|
||||
* A cylinder that cannot rotate.
|
||||
*/
|
||||
bodyDesc = RAPIER.RigidBodyDesc.dynamic()
|
||||
.setTranslation(0.2, 5.0, 0.4)
|
||||
.lockRotations();
|
||||
body = world.createRigidBody(bodyDesc);
|
||||
colliderDesc = RAPIER.ColliderDesc.cylinder(0.6, 0.4);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
/*
|
||||
* Setup the testbed.
|
||||
*/
|
||||
testbed.setWorld(world);
|
||||
let cameraPosition = {
|
||||
eye: {x: -10.0, y: 3.0, z: 0.0},
|
||||
target: {x: 0.0, y: 3.0, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
127
thirdparty/rapier.js/testbed3d/src/demos/pidController.ts
vendored
Normal file
127
thirdparty/rapier.js/testbed3d/src/demos/pidController.ts
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(15.0, 0.1, 15.0);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
// Dynamic cubes.
|
||||
let rad = 0.5;
|
||||
let num = 5;
|
||||
let i, j, k;
|
||||
let shift = rad * 2.5;
|
||||
let center = num * rad;
|
||||
let height = 5.0;
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
for (j = i; j < num; ++j) {
|
||||
for (k = i; k < num; ++k) {
|
||||
let x = (i * shift) / 2.0 + (k - i) * shift - center;
|
||||
let y = (i * shift) / 2.0 + height;
|
||||
let z = (i * shift) / 2.0 + (j - i) * shift - center;
|
||||
|
||||
// Create dynamic cube.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad,
|
||||
rad / 2.0,
|
||||
rad,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Character.
|
||||
let characterDesc = RAPIER.RigidBodyDesc.dynamic()
|
||||
.setTranslation(-10.0, 4.0, -10.0)
|
||||
.setGravityScale(10.0)
|
||||
.setSoftCcdPrediction(10.0);
|
||||
let character = world.createRigidBody(characterDesc);
|
||||
let characterColliderDesc = RAPIER.ColliderDesc.cylinder(1.2, 0.6);
|
||||
world.createCollider(characterColliderDesc, character);
|
||||
|
||||
let pidController = world.createPidController(
|
||||
60.0,
|
||||
0.0,
|
||||
1.0,
|
||||
RAPIER.PidAxesMask.AllAng,
|
||||
);
|
||||
let speed = 0.2;
|
||||
let movementDirection = {x: 0.0, y: 0.0, z: 0.0};
|
||||
let targetVelocity = {x: 0.0, y: 0.0, z: 0.0};
|
||||
let targetRotation = new RAPIER.Quaternion(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
let updateCharacter = () => {
|
||||
if (
|
||||
movementDirection.x == 0.0 &&
|
||||
movementDirection.y == 0.0 &&
|
||||
movementDirection.z == 0.0
|
||||
) {
|
||||
// Only adjust the rotation, but let translation.
|
||||
pidController.setAxes(RAPIER.PidAxesMask.AllAng);
|
||||
} else if (movementDirection.y == 0.0) {
|
||||
// Don’t control the linear Y axis so the player can fall down due to gravity.
|
||||
pidController.setAxes(
|
||||
RAPIER.PidAxesMask.AllAng |
|
||||
RAPIER.PidAxesMask.LinX |
|
||||
RAPIER.PidAxesMask.LinZ,
|
||||
);
|
||||
} else {
|
||||
pidController.setAxes(RAPIER.PidAxesMask.All);
|
||||
}
|
||||
|
||||
let targetPoint = character.translation();
|
||||
targetPoint.x += movementDirection.x;
|
||||
targetPoint.y += movementDirection.y;
|
||||
targetPoint.z += movementDirection.z;
|
||||
|
||||
pidController.applyLinearCorrection(
|
||||
character,
|
||||
targetPoint,
|
||||
targetVelocity,
|
||||
);
|
||||
pidController.applyAngularCorrection(
|
||||
character,
|
||||
targetRotation,
|
||||
targetVelocity,
|
||||
);
|
||||
};
|
||||
|
||||
testbed.setWorld(world);
|
||||
testbed.setpreTimestepAction(updateCharacter);
|
||||
|
||||
document.onkeydown = function (event: KeyboardEvent) {
|
||||
if (event.key == "ArrowUp") movementDirection.x = speed;
|
||||
if (event.key == "ArrowDown") movementDirection.x = -speed;
|
||||
if (event.key == "ArrowLeft") movementDirection.z = -speed;
|
||||
if (event.key == "ArrowRight") movementDirection.z = speed;
|
||||
if (event.key == " ") movementDirection.y = speed;
|
||||
};
|
||||
|
||||
document.onkeyup = function (event: KeyboardEvent) {
|
||||
if (event.key == "ArrowUp") movementDirection.x = 0.0;
|
||||
if (event.key == "ArrowDown") movementDirection.x = 0.0;
|
||||
if (event.key == "ArrowLeft") movementDirection.z = 0.0;
|
||||
if (event.key == "ArrowRight") movementDirection.z = 0.0;
|
||||
if (event.key == " ") movementDirection.y = 0.0;
|
||||
};
|
||||
|
||||
let cameraPosition = {
|
||||
eye: {x: -40.0, y: 19.730000000000008, z: 0.0},
|
||||
target: {x: 0.0, y: -0.4126, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
153
thirdparty/rapier.js/testbed3d/src/demos/platform.ts
vendored
Normal file
153
thirdparty/rapier.js/testbed3d/src/demos/platform.ts
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
import seedrandom from "seedrandom";
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
function generateTriMesh(nsubdivs: number, wx: number, wy: number, wz: number) {
|
||||
let vertices = [];
|
||||
let indices = [];
|
||||
|
||||
let elementWidth = 1.0 / nsubdivs;
|
||||
let rng = seedrandom("trimesh");
|
||||
|
||||
let i, j;
|
||||
for (i = 0; i <= nsubdivs; ++i) {
|
||||
for (j = 0; j <= nsubdivs; ++j) {
|
||||
let x = (j * elementWidth - 0.5) * wx;
|
||||
let y = rng() * wy;
|
||||
let z = (i * elementWidth - 0.5) * wz;
|
||||
|
||||
vertices.push(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nsubdivs; ++i) {
|
||||
for (j = 0; j < nsubdivs; ++j) {
|
||||
let i1 = (i + 0) * (nsubdivs + 1) + (j + 0);
|
||||
let i2 = (i + 0) * (nsubdivs + 1) + (j + 1);
|
||||
let i3 = (i + 1) * (nsubdivs + 1) + (j + 0);
|
||||
let i4 = (i + 1) * (nsubdivs + 1) + (j + 1);
|
||||
|
||||
indices.push(i1, i3, i2);
|
||||
indices.push(i3, i4, i2);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
vertices: new Float32Array(vertices),
|
||||
indices: new Uint32Array(indices),
|
||||
};
|
||||
}
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.kinematicVelocityBased();
|
||||
let platformBody = world.createRigidBody(bodyDesc);
|
||||
let trimesh = generateTriMesh(20, 70.0, 4.0, 70.0);
|
||||
let colliderDesc = RAPIER.ColliderDesc.trimesh(
|
||||
trimesh.vertices,
|
||||
trimesh.indices,
|
||||
);
|
||||
world.createCollider(colliderDesc, platformBody);
|
||||
let t = 0.0;
|
||||
|
||||
let movePlatform = () => {
|
||||
t += 0.016;
|
||||
let dy = Math.sin(t) * 10.0;
|
||||
let dang = Math.sin(t) * 0.2;
|
||||
platformBody.setLinvel({x: 0.0, y: dy, z: 0.0}, true);
|
||||
platformBody.setAngvel({x: 0.0, y: dang, z: 0.0}, true);
|
||||
};
|
||||
|
||||
// Dynamic cubes.
|
||||
let num = 4;
|
||||
let numy = 10;
|
||||
let rad = 1.0;
|
||||
|
||||
let shift = rad * 2.0 + rad;
|
||||
let centery = shift / 2.0;
|
||||
|
||||
let offset = -num * (rad * 2.0 + rad) * 0.5;
|
||||
let i, j, k;
|
||||
|
||||
for (j = 0; j < numy; ++j) {
|
||||
for (i = 0; i < num; ++i) {
|
||||
for (k = 0; k < num; ++k) {
|
||||
let x = i * shift + offset;
|
||||
let y = j * shift + centery + 3.0;
|
||||
let z = k * shift + offset;
|
||||
|
||||
// Create dynamic cube.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc;
|
||||
|
||||
switch (j % 5) {
|
||||
case 0:
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad,
|
||||
rad,
|
||||
rad,
|
||||
);
|
||||
break;
|
||||
case 1:
|
||||
colliderDesc = RAPIER.ColliderDesc.ball(rad);
|
||||
break;
|
||||
case 2:
|
||||
colliderDesc = RAPIER.ColliderDesc.roundCylinder(
|
||||
rad,
|
||||
rad,
|
||||
rad / 10.0,
|
||||
);
|
||||
break;
|
||||
case 3:
|
||||
colliderDesc = RAPIER.ColliderDesc.cone(rad, rad);
|
||||
break;
|
||||
case 4:
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad / 2.0,
|
||||
rad / 2.0,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad,
|
||||
rad / 2.0,
|
||||
).setTranslation(rad, 0.0, 0.0);
|
||||
world.createCollider(colliderDesc, body);
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad,
|
||||
rad / 2.0,
|
||||
).setTranslation(-rad, 0.0, 0.0);
|
||||
break;
|
||||
}
|
||||
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
|
||||
offset -= 0.05 * rad * (num - 1.0);
|
||||
}
|
||||
|
||||
testbed.setWorld(world);
|
||||
testbed.setpreTimestepAction(movePlatform);
|
||||
|
||||
let cameraPosition = {
|
||||
eye: {
|
||||
x: -88.48024008669711,
|
||||
y: 46.911325612198354,
|
||||
z: 83.56055570254844,
|
||||
},
|
||||
target: {x: 0.0, y: 0.0, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
51
thirdparty/rapier.js/testbed3d/src/demos/pyramid.ts
vendored
Normal file
51
thirdparty/rapier.js/testbed3d/src/demos/pyramid.ts
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(30.0, 0.1, 30.0);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
// Dynamic cubes.
|
||||
let rad = 0.5;
|
||||
let num = 10;
|
||||
let i, j, k;
|
||||
let shift = rad * 2.5;
|
||||
let center = num * rad;
|
||||
let height = 10.0;
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
for (j = i; j < num; ++j) {
|
||||
for (k = i; k < num; ++k) {
|
||||
let x =
|
||||
(i * shift) / 2.0 + (k - i) * shift - height * rad - center;
|
||||
let y = i * shift + height;
|
||||
let z =
|
||||
(i * shift) / 2.0 + (j - i) * shift - height * rad - center;
|
||||
|
||||
// Create dynamic cube.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad, rad);
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testbed.setWorld(world);
|
||||
let cameraPosition = {
|
||||
eye: {x: -31.96000000000001, y: 19.730000000000008, z: -27.86},
|
||||
target: {x: -0.0505, y: -0.4126, z: -0.0229},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
143
thirdparty/rapier.js/testbed3d/src/demos/trimesh.ts
vendored
Normal file
143
thirdparty/rapier.js/testbed3d/src/demos/trimesh.ts
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
import seedrandom from "seedrandom";
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
function generateTriMesh(nsubdivs: number, wx: number, wy: number, wz: number) {
|
||||
let vertices = [];
|
||||
let indices = [];
|
||||
|
||||
let elementWidth = 1.0 / nsubdivs;
|
||||
let rng = seedrandom("trimesh");
|
||||
|
||||
let i, j;
|
||||
for (i = 0; i <= nsubdivs; ++i) {
|
||||
for (j = 0; j <= nsubdivs; ++j) {
|
||||
let x = (j * elementWidth - 0.5) * wx;
|
||||
let y = rng() * wy;
|
||||
let z = (i * elementWidth - 0.5) * wz;
|
||||
|
||||
vertices.push(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nsubdivs; ++i) {
|
||||
for (j = 0; j < nsubdivs; ++j) {
|
||||
let i1 = (i + 0) * (nsubdivs + 1) + (j + 0);
|
||||
let i2 = (i + 0) * (nsubdivs + 1) + (j + 1);
|
||||
let i3 = (i + 1) * (nsubdivs + 1) + (j + 0);
|
||||
let i4 = (i + 1) * (nsubdivs + 1) + (j + 1);
|
||||
|
||||
indices.push(i1, i3, i2);
|
||||
indices.push(i3, i4, i2);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
vertices: new Float32Array(vertices),
|
||||
indices: new Uint32Array(indices),
|
||||
};
|
||||
}
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let trimesh = generateTriMesh(20, 70.0, 4.0, 70.0);
|
||||
let colliderDesc = RAPIER.ColliderDesc.trimesh(
|
||||
trimesh.vertices,
|
||||
trimesh.indices,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
// Dynamic cubes.
|
||||
let num = 4;
|
||||
let numy = 10;
|
||||
let rad = 1.0;
|
||||
|
||||
let shift = rad * 2.0 + rad;
|
||||
let centery = shift / 2.0;
|
||||
|
||||
let offset = -num * (rad * 2.0 + rad) * 0.5;
|
||||
let i, j, k;
|
||||
|
||||
for (j = 0; j < numy; ++j) {
|
||||
for (i = 0; i < num; ++i) {
|
||||
for (k = 0; k < num; ++k) {
|
||||
let x = i * shift + offset;
|
||||
let y = j * shift + centery + 3.0;
|
||||
let z = k * shift + offset;
|
||||
|
||||
// Create dynamic cube.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc;
|
||||
|
||||
switch (j % 5) {
|
||||
case 0:
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad,
|
||||
rad,
|
||||
rad,
|
||||
);
|
||||
break;
|
||||
case 1:
|
||||
colliderDesc = RAPIER.ColliderDesc.ball(rad);
|
||||
break;
|
||||
case 2:
|
||||
colliderDesc = RAPIER.ColliderDesc.roundCylinder(
|
||||
rad,
|
||||
rad,
|
||||
rad / 10.0,
|
||||
);
|
||||
break;
|
||||
case 3:
|
||||
colliderDesc = RAPIER.ColliderDesc.cone(rad, rad);
|
||||
break;
|
||||
case 4:
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad / 2.0,
|
||||
rad / 2.0,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad,
|
||||
rad / 2.0,
|
||||
).setTranslation(rad, 0.0, 0.0);
|
||||
world.createCollider(colliderDesc, body);
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad,
|
||||
rad / 2.0,
|
||||
).setTranslation(-rad, 0.0, 0.0);
|
||||
break;
|
||||
}
|
||||
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
|
||||
offset -= 0.05 * rad * (num - 1.0);
|
||||
}
|
||||
|
||||
testbed.setWorld(world);
|
||||
|
||||
let cameraPosition = {
|
||||
eye: {
|
||||
x: -88.48024008669711,
|
||||
y: 46.911325612198354,
|
||||
z: 83.56055570254844,
|
||||
},
|
||||
target: {x: 0.0, y: 0.0, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
130
thirdparty/rapier.js/testbed3d/src/demos/voxels.ts
vendored
Normal file
130
thirdparty/rapier.js/testbed3d/src/demos/voxels.ts
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
import seedrandom from "seedrandom";
|
||||
import type {Testbed} from "../Testbed";
|
||||
|
||||
type RAPIER_API = typeof import("@dimforge/rapier3d");
|
||||
|
||||
function generateVoxels(n: number) {
|
||||
let points = [];
|
||||
|
||||
let i, j;
|
||||
for (i = 0; i <= n; ++i) {
|
||||
for (j = 0; j <= n; ++j) {
|
||||
let y =
|
||||
Math.max(
|
||||
-0.8,
|
||||
Math.min(
|
||||
Math.sin((i / n) * 10.0) * Math.cos((j / n) * 10.0),
|
||||
0.8,
|
||||
),
|
||||
) * 8.0;
|
||||
points.push(i - n / 2.0, y, j - n / 2.0);
|
||||
}
|
||||
}
|
||||
return {
|
||||
points: new Float32Array(points),
|
||||
voxelSize: {x: 1.0, y: 1.2, z: 1.5},
|
||||
};
|
||||
}
|
||||
|
||||
export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
|
||||
let gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
|
||||
let world = new RAPIER.World(gravity);
|
||||
|
||||
// Create Ground.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let voxels = generateVoxels(100);
|
||||
let colliderDesc = RAPIER.ColliderDesc.voxels(
|
||||
voxels.points,
|
||||
voxels.voxelSize,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
|
||||
// Dynamic cubes.
|
||||
let num = 10;
|
||||
let numy = 4;
|
||||
let rad = 1.0;
|
||||
|
||||
let shift = rad * 2.0 + rad;
|
||||
let centery = shift / 2.0;
|
||||
|
||||
let offset = -num * (rad * 2.0 + rad) * 0.5;
|
||||
let i, j, k;
|
||||
|
||||
for (j = 0; j < numy; ++j) {
|
||||
for (i = 0; i < num; ++i) {
|
||||
for (k = 0; k < num; ++k) {
|
||||
let x = i * shift + offset;
|
||||
let y = j * shift + centery + 10.0;
|
||||
let z = k * shift + offset;
|
||||
|
||||
// Create dynamic cube.
|
||||
let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
);
|
||||
let body = world.createRigidBody(bodyDesc);
|
||||
let colliderDesc;
|
||||
|
||||
switch (j % 5) {
|
||||
case 0:
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad,
|
||||
rad,
|
||||
rad,
|
||||
);
|
||||
break;
|
||||
case 1:
|
||||
colliderDesc = RAPIER.ColliderDesc.ball(rad);
|
||||
break;
|
||||
case 2:
|
||||
colliderDesc = RAPIER.ColliderDesc.roundCylinder(
|
||||
rad,
|
||||
rad,
|
||||
rad / 10.0,
|
||||
);
|
||||
break;
|
||||
case 3:
|
||||
colliderDesc = RAPIER.ColliderDesc.cone(rad, rad);
|
||||
break;
|
||||
case 4:
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad / 2.0,
|
||||
rad / 2.0,
|
||||
);
|
||||
world.createCollider(colliderDesc, body);
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad,
|
||||
rad / 2.0,
|
||||
).setTranslation(rad, 0.0, 0.0);
|
||||
world.createCollider(colliderDesc, body);
|
||||
colliderDesc = RAPIER.ColliderDesc.cuboid(
|
||||
rad / 2.0,
|
||||
rad,
|
||||
rad / 2.0,
|
||||
).setTranslation(-rad, 0.0, 0.0);
|
||||
break;
|
||||
}
|
||||
|
||||
world.createCollider(colliderDesc, body);
|
||||
}
|
||||
}
|
||||
|
||||
offset -= 0.05 * rad * (num - 1.0);
|
||||
}
|
||||
|
||||
testbed.setWorld(world);
|
||||
|
||||
let cameraPosition = {
|
||||
eye: {
|
||||
x: -88.48024008669711,
|
||||
y: 46.911325612198354,
|
||||
z: 83.56055570254844,
|
||||
},
|
||||
target: {x: 0.0, y: 0.0, z: 0.0},
|
||||
};
|
||||
testbed.lookAt(cameraPosition);
|
||||
}
|
||||
Reference in New Issue
Block a user