Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GLTF to Convex Hull Collision and Trimesh Examples #285

Merged
merged 8 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions testbed3d/src/demos/glbToTrimesh.ts
Original file line number Diff line number Diff line change
@@ -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("./sword.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 changes: 68 additions & 0 deletions testbed3d/src/demos/glbtoConvexHull.ts
Original file line number Diff line number Diff line change
@@ -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("./sword.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);
}
6 changes: 5 additions & 1 deletion testbed3d/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import * as ConvexPolyhedron from "./demos/convexPolyhedron";
import * as CCD from "./demos/ccd";
import * as Platform from "./demos/platform";
import * as CharacterController from "./demos/characterController";
import * as glbToTrimesh from './demos/glbToTrimesh'
import * as glbToConvexHull from './demos/glbtoConvexHull'

import("@dimforge/rapier3d").then((RAPIER) => {
let builders = new Map([
Expand All @@ -28,7 +30,9 @@ import("@dimforge/rapier3d").then((RAPIER) => {
["platform", Platform.initWorld],
["pyramid", Pyramid.initWorld],
["triangle mesh", Trimesh.initWorld],
["GLTF to convexHull", glbToConvexHull.initWorld],
["GLTF to trimesh", glbToTrimesh.initWorld],
]);
let testbed = new Testbed(RAPIER, builders);
testbed.run();
});
});
Binary file added testbed3d/static/sword.glb
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a license accompanying this file ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, A friend of mine made it so we don't need a license. Basically CC0 license especially for me :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the precision!

Unfortunately licensing is quite complex and not risk free, so I'd like to move from this model to either stanford bunny or blender suzanne ; let me know if you're up to make the modification, otherwise I can take it from there.

Binary file not shown.
Loading