'Adding Cannon.js Body to Three.js Mesh causing Vec3 error with groups and multiple shapes
Basically I've created a group of 2 meshes in Three.js and a Body containing 2 Shapes in Cannon.
Separately they appear fine but when I copy the Body position to the meshes to add physics the code breaks, nothing appears on screen and when logging the positions, for the Body everythings ok but the mesh its showing as undefined.
(The end goal is to replace the mesh with the model)
Any help would be great, heres the code in question:
import './style.css'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import * as dat from 'lil-gui'
import * as CANNON from 'cannon-es'
/**
* Base
*/
// Debug
const gui = new dat.GUI()
// Canvas
const canvas = document.querySelector('canvas.webgl')
// Scene
const scene = new THREE.Scene()
/**
* Models
*/
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('/draco/')
const gltfLoader = new GLTFLoader()
gltfLoader.setDRACOLoader(dracoLoader)
let mixer = null
let gunModel = null
gltfLoader.load(
'/models/hamburger.glb',
(gltf) =>
{
gltf.scene.position.set(0, 4, 0)
gunModel = gltf.scene
scene.add(gunModel)
console.log(gunModel.position)
}
)
/**
* test wireframe cubes
*/
const YGeo = new THREE.BoxBufferGeometry(2, 6, 2);
const YMat = new THREE.MeshBasicMaterial({
color: 'green',
wireframe: true
})
const gun = new THREE.Group();
const blockY = new THREE.Mesh(YGeo, YMat);
blockY.position.x = 4;
const XGeo = new THREE.BoxBufferGeometry(6,2,2);
const XMat = new THREE.MeshBasicMaterial({
color: 'green',
wireframe: true
})
const blockX = new THREE.Mesh(XGeo, XMat);
blockX.position.y = 2
gun.add(blockY)
gun.add(blockX)
gui.add(gun.position, 'y', 0, 5, 0.01);
gui.add(gun.position, 'x', -3, 4, 0.01)
gui.add(gun.position, 'z', -3, 3, 0.01)
scene.add(gun)
/**
* Floor
*/
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(50, 50),
new THREE.MeshStandardMaterial({
color: '#444444',
metalness: 0,
roughness: 0.5
})
)
floor.receiveShadow = true
floor.rotation.x = - Math.PI * 0.5
scene.add(floor)
/**
* Lights
*/
const ambientLight = new THREE.AmbientLight(0xffffff, 0.8)
scene.add(ambientLight)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.6)
directionalLight.castShadow = true
directionalLight.shadow.mapSize.set(1024, 1024)
directionalLight.shadow.camera.far = 15
directionalLight.shadow.camera.left = - 7
directionalLight.shadow.camera.top = 7
directionalLight.shadow.camera.right = 7
directionalLight.shadow.camera.bottom = - 7
directionalLight.position.set(5, 5, 5)
scene.add(directionalLight)
/**
* Sizes
*/
const sizes = {
width: window.innerWidth,
height: window.innerHeight
}
window.addEventListener('resize', () =>
{
// Update sizes
sizes.width = window.innerWidth
sizes.height = window.innerHeight
// Update camera
camera.aspect = sizes.width / sizes.height
camera.updateProjectionMatrix()
// Update renderer
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})
/**
* Camera
*/
// Base camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
camera.position.set(- 8, 4, 8)
scene.add(camera)
// Controls
const controls = new OrbitControls(camera, canvas)
controls.target.set(0, 1, 0)
controls.enableDamping = true
/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.shadowMap.enabled = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
/**
* Physics
*/
const world = new CANNON.World({
gravity: new CANNON.Vec3(0, -9.81, 0)
});
const floorBody = new CANNON.Body({
shape: new CANNON.Plane(),
mass: 0
})
world.addBody(floorBody)
const shapeY = new CANNON.Box(new CANNON.Vec3(1,3,1))
const shapeX = new CANNON.Box(new CANNON.Vec3(3,1,1))
const boxBody = new CANNON.Body({
mass: 1
})
boxBody.addShape(shapeY, new CANNON.Vec3(3, 0, 0), new CANNON.Quaternion())
boxBody.addShape(shapeX, new CANNON.Vec3(0,2,0), new CANNON.Quaternion())
world.addBody(boxBody)
boxBody.position.set(-0.56, 4.13, -0.02)
console.log(boxBody.position)
gui.add(boxBody.position, 'y', 0, 10, 0.01);
/**
* Animate
*/
const clock = new THREE.Clock()
let previousTime = 0
const tick = () =>
{
const elapsedTime = clock.getElapsedTime()
const deltaTime = elapsedTime - previousTime
previousTime = elapsedTime
world.step(1/60, deltaTime, 3)
floor.position.copy(floorBody.position);
floorBody.quaternion.copy(floor.quaternion);
// if(gunModel) {
// gunModel.position.copy(boxBody);
// gunModel.quaternion.copy(boxBody)
// console.log(gunModel.position)
// }
gun.position.copy(boxBody);
gun.quaternion.copy(boxBody)
console.log(gun.position.x)
if(mixer)
{
mixer.update(deltaTime)
}
// Update controls
controls.update()
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()
Solution 1:[1]
// access boxBody attributes?
gun.position.copy(boxBody.position);
gun.quaternion.copy(boxBody.quaternion);
console.log(gun.position.x)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | PartialFlavor_55KP |
