Hi all,
I’m trying to load a GLTF model of a car and sync it with a rigid vehicle from Cannon-es in order to create a drivable car. I started by setting up the physics world and that went extremely smoothly:
/**
* Physics
*/
// World
const world = new CANNON.World()
world.broadphase = new CANNON.SAPBroadphase(world)
//world.allowSleep = true
world.gravity.set(0, -29.81, 0)
// Ground
const groundBody = new CANNON.Body({
type: CANNON.Body.STATIC,
shape: new CANNON.Plane(),
})
groundBody.quaternion.setFromEuler(-Math.PI * 0.5, -Math.PI * 0.00, 0)
world.addBody(groundBody)
// Default material
const defaultMaterial = new CANNON.Material('ground')
const defaultContactMaterial = new CANNON.ContactMaterial(
defaultMaterial,
defaultMaterial,
{
friction: 0.2,
restitution: 0.0
}
)
world.defaultContactMaterial = defaultContactMaterial
// Debugger
const cannonDebugger = new CannonDebugger(scene, world)
// Build the car chassis
const chassisShape = new CANNON.Box(new CANNON.Vec3(5, 0.5, 2))
const chassisBody = new CANNON.Body({ mass: 1 })
const centerOfMassAdjust = new CANNON.Vec3(0, -1, 0)
chassisBody.addShape(chassisShape, centerOfMassAdjust)
// Create the vehicle
const vehicle = new CANNON.RigidVehicle({
chassisBody,
})
const mass = 1
const axisWidth = 3
const wheelShape = new CANNON.Sphere(1.5)
const wheelMaterial = new CANNON.Material('wheel')
const down = new CANNON.Vec3(0, -1, 0)
const wheelBody1 = new CANNON.Body({ mass, material: wheelMaterial })
wheelBody1.addShape(wheelShape)
vehicle.addWheel({
body: wheelBody1,
position: new CANNON.Vec3(-5, 0, axisWidth / 2).vadd(centerOfMassAdjust),
axis: new CANNON.Vec3(0, 0, 1),
direction: down,
})
const wheelBody2 = new CANNON.Body({ mass, material: wheelMaterial })
wheelBody2.addShape(wheelShape)
vehicle.addWheel({
body: wheelBody2,
position: new CANNON.Vec3(-5, 0, -axisWidth / 2).vadd(centerOfMassAdjust),
axis: new CANNON.Vec3(0, 0, -1),
direction: down,
})
const wheelBody3 = new CANNON.Body({ mass, material: wheelMaterial })
wheelBody3.addShape(wheelShape)
vehicle.addWheel({
body: wheelBody3,
position: new CANNON.Vec3(5, 0, axisWidth / 2).vadd(centerOfMassAdjust),
axis: new CANNON.Vec3(0, 0, 1),
direction: down,
})
const wheelBody4 = new CANNON.Body({ mass, material: wheelMaterial })
wheelBody4.addShape(wheelShape)
vehicle.addWheel({
body: wheelBody4,
position: new CANNON.Vec3(5, 0, -axisWidth / 2).vadd(centerOfMassAdjust),
axis: new CANNON.Vec3(0, 0, -1),
direction: down,
})
vehicle.wheelBodies.forEach((wheelBody) => {
// Some damping to not spin wheels too fast
wheelBody.angularDamping = 0.4
})
vehicle.addToWorld(world)
I then loaded the GLTF model and defined independent variables for the wheels I selected by traversing the model. I also selected the body:
/**
* GLTF Model
*/
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('/draco/')
const gltfLoader = new GLTFLoader()
gltfLoader.setDRACOLoader(dracoLoader)
let model;
let wheel1;
let wheel2;
let wheel3;
let wheel4;
let whell5; // Spare wheel
let test_body;
gltfLoader.load(
'/models/fw190_airplanecar/scene.gltf',
(gltf) => {
model = gltf.scene
model.scale.set(0.025, 0.025, 0.025)
model.traverse(function (node) {
if (node.isMesh) {
node.castShadow = true;
node.receiveShadow = true;
node.material.wireframe = true;
}
if (node.isMesh && node.name === "Circle043_rear_wheel_0") {
wheel1 = node;
}
if (node.isMesh && node.name === "Circle001_front_wheel_0") {
wheel2 = node;
}
if (node.isMesh && node.name === "Tyre-Left-Front_spare_wheel_0") {
wheel3 = node;
}
if (node.isMesh && node.name === "Circle015_rear_wheel_0") {
wheel4 = node;
}
if (node.isMesh && node.name === "Circle023_front_wheel_0") {
//console.log("Nai re file")
wheel5 = node;
}
if (node.isMesh && node.name === "Body_body_0") {
test_body = node;
}
});
scene.add(model)
tick()
}
)
I then tried to sync the rigid vehicle with the three.js GLTF model and strange things started happening. Here is the code:
const tick = () => {
// Update controls
controls.update()
// Render
renderer.render(scene, camera)
// Physics
world.fixedStep()
cannonDebugger.update()
model.position.copy(chassisBody.position)
model.quaternion.copy(chassisBody.quaternion)
wheel1.position.copy(wheelBody1.position)
wheel1.quaternion.copy(wheelBody1.quaternion)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
Specifically, the rigid vehicle and the GLTF model form a 90 degrees angle, the wheel appears in a different location than the GLTF, and when I use the keys I can see the wheels of the rigid vehicle (CANNON) working just fine, the GLTF model is kind of following the motion in a strange 90-degree angle, and the one wheel I show in the code wanders off the screen (it does spin though). So what is going on? Why is the wheel, selected from the tree nodes at a different location? And why is the model at a 90-degree angle, and a few meters up in the y-direction?
Relevant pics attached