Closed JackBiofryd closed 2 years ago
After trying things for so long, the bug was the rotation of the plane. My mistake. I replaced the planes with: ` const plane = new THREE.Mesh( new THREE.PlaneBufferGeometry(100, 100), new THREE.MeshStandardMaterial({ metalness: 0.3, roughness: 0.4, color: '#777777' }) ); plane.rotation.x = Math.PI * -0.5;
const q = plane.quaternion; const planeBody = new CANNON.Body({ shape: new CANNON.Plane(), mass: 0, material: groundMaterial, position: new CANNON.Vec3(0, 0, 0), quaternion: new CANNON.Quaternion(q.x, q.y, q.z, q.w) }); planeBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), Math.PI * -0.5);
world.addBody(planeBody); scene.add(plane);
`
Hey! So, I managed to make the Raycaster vehicle work properly, except for one huge bug. Whenever I try to drive with the vehicle in the positive z axis it glitches through the floor a bit down (about half of the wheels are below the plane) and slides to infinity. I have had this bug for a very very long time and I have no idea how to fix it. I don't think my code is the problem because I followed the examples completely. Any ideas? It might be because of the materials. Changing the default contact material changes how much the car slides (how fast), but no value fixes the bug.
Here is what the glitch looks like before it starts sliding:![123](https://user-images.githubusercontent.com/69092105/126150536-af28c367-7056-4513-a035-d36d33905de5.PNG)
Here's my code: ` const canvas = document.querySelector('canvas.webgl'); // Scene const scene = new THREE.Scene();
// Physics world const world = new CANNON.World(); world.gravity.set(0, -9.81, 0); world.defaultContactMaterial.friction = 0; const groundMaterial = new CANNON.Material('groundMaterial'); const wheelMaterial = new CANNON.Material('wheelMaterial'); const wheelGroundContactMaterial = new CANNON.ContactMaterial( wheelMaterial, groundMaterial, { friction: 0.3, restitution: 0, contactEquationStiffness: 1000 } ); world.addContactMaterial(wheelGroundContactMaterial); // Performance world.broadphase = new CANNON.SAPBroadphase(world); world.allowSleep = true;
// Cameras const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.set(10, 10, 10);
// Lights const ambientLight = new THREE.AmbientLight(0xffffff, 0.7); const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); directionalLight.position.set(10, 12, 0);
scene.add(ambientLight, directionalLight);
// Planes const plane = new THREE.Mesh( new THREE.PlaneBufferGeometry(100, 100), new THREE.MeshStandardMaterial({ metalness: 0.3, roughness: 0.4, color: '#777777' }) ); plane.rotation.x = Math.PI * -0.5;
const planeBody = new CANNON.Body({ shape: new CANNON.Plane(), mass: 0, material: groundMaterial, position: new CANNON.Vec3(0, 0, 0) }); planeBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), Math.PI * -0.5);
world.addBody(planeBody); scene.add(plane);
/**
// Vehicle physics body const chassisShape = new CANNON.Box(new CANNON.Vec3(0.4, 0.25, 0.75)); const chassisBody = new CANNON.Body({ mass: 1500 }); chassisBody.addShape(chassisShape); chassisBody.position.set(1, 2, -3); chassisBody.angularVelocity.set(0, 0, 0); // Initial velocity
// Vehicle Three.js mesh const chassisGeometry = new THREE.BoxBufferGeometry(0.8, 0.5, 1.5); const chassisMaterial = new THREE.MeshStandardMaterial({ metalness: 0.8, roughness: 0.4, color: '#DF2800' }); const chassisMesh = new THREE.Mesh(chassisGeometry, chassisMaterial); scene.add(chassisMesh); chassisMesh.castShadow = true;
// Parent vehicle object const vehicle = new CANNON.RaycastVehicle({ chassisBody: chassisBody, indexRightAxis: 0, // x indexUpAxis: 1, // y indexForwardAxis: 2 // z });
// Wheels const wheelOptions = { radius: 0.2, directionLocal: new CANNON.Vec3(0, -1, 0), suspensionStiffness: 45, suspensionRestLength: 0.4, frictionSlip: 5, dampingRelaxation: 2.3, dampingCompression: 4.5, maxSuspensionForce: 200000, rollInfluence: 0.01, axleLocal: new CANNON.Vec3(-1, 0, 0), chassisConnectionPointLocal: new CANNON.Vec3(1, 1, 0), maxSuspensionTravel: 0.25, customSlidingRotationalSpeed: -30, useCustomSlidingRotationalSpeed: true };
const axlewidth = 0.4; wheelOptions.chassisConnectionPointLocal.set(axlewidth, 0.1, -0.7); vehicle.addWheel(wheelOptions); wheelOptions.chassisConnectionPointLocal.set(-axlewidth, 0.1, -0.7); vehicle.addWheel(wheelOptions); wheelOptions.chassisConnectionPointLocal.set(axlewidth, 0.1, 0.7); vehicle.addWheel(wheelOptions); wheelOptions.chassisConnectionPointLocal.set(-axlewidth, 0.1, 0.7); vehicle.addWheel(wheelOptions);
vehicle.addToWorld(world);
const wheelBodies = [], wheelMeshes = [];
vehicle.wheelInfos.forEach(wheel => { // Wheel physics body const shape = new CANNON.Cylinder( wheel.radius, wheel.radius, wheel.radius / 2, 20 ); const body = new CANNON.Body({ mass: 1, material: wheelMaterial }); var q = new CANNON.Quaternion(); q.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), Math.PI / 2); body.addShape(shape, new CANNON.Vec3(), q); wheelBodies.push(body);
});
// Update the wheels to match the physics world.addEventListener('postStep', function () { chassisBody.wakeUp();
});
const moveCar = e => { if (e.type !== 'keydown' && e.type !== 'keyup') return;
}; window.onkeydown = moveCar; window.onkeyup = moveCar;
// Controls const controls = new OrbitControls(camera, canvas); controls.enableDamping = true;
const h = new THREE.AxesHelper(10); scene.add(h);
// Renderer const renderer = new THREE.WebGLRenderer({ canvas, antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); renderer.render(scene, camera);
renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap;
directionalLight.castShadow = true; directionalLight.shadow.mapSize.width = 1024; directionalLight.shadow.mapSize.height = 1024; directionalLight.shadow.camera.far = 20;
plane.receiveShadow = true;
// Animation const clock = new THREE.Clock(); let oldTime = 0;
const tick = () => { const elapsedTime = clock.getElapsedTime(); const frameTime = elapsedTime - oldTime; oldTime = elapsedTime;
};
tick();
// Resize scene on window resize window.onresize = () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix();
};
`