我最近开始使用物理引擎。我正在使用 cannon.es/js 和 three.js 盒子和加载的模型刚好穿过平面并从视野中掉落。我尝试使用
groundBody.quaternion.setFromEuler(-Math.PI/2,0,0)
但对象在屏幕上移动而不是向下移动。我认为我的定位和尺寸是这里的问题。你能帮帮我吗?非常感谢
这是我正在处理的代码
<html>
<head>
<title>My 3D Model</title>
<script type="module">
import * as THREE from "https://cdn.skypack.dev/[email protected]/build/three.module.js";
import { GUI } from "https://cdn.skypack.dev/[email protected]/build/dat.gui.module.js";
import { TrackballControls } from "https://cdn.skypack.dev/[email protected]/examples/jsm/controls/TrackballControls.js";
import {OrbitControls} from "https://cdn.skypack.dev/[email protected]/examples/jsm/controls/OrbitControls.js";
import { STLLoader } from "https://cdn.skypack.dev/[email protected]/examples/jsm/loaders/STLLoader.js";
import { OBJLoader } from "https://cdn.skypack.dev/[email protected]/examples/jsm/loaders/OBJLoader.js";
import * as CANNON from 'https://unpkg.com/[email protected]/dist/cannon-es.js'
// webgl
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
// scene
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth/window.innerHeight,
0.1,
1000
);
const orbit = new OrbitControls(camera,renderer.domElement);
camera.position.set(0,200,-100);
orbit.update();
const ambientLight = new THREE.AmbientLight();
scene.add( ambientLight );
const directionalLight = new THREE.DirectionalLight( 0xffffff, 5.0 );
directionalLight.position.set( 10, 100, -100 );
scene.add( directionalLight );
const world = new CANNON.World({
gravity : new CANNON.Vec3(0,-9.81,0)
});
const groundBody = new CANNON.Body({
shape : new CANNON.Plane(),
type : CANNON.Body.STATIC,
})
world.addBody(groundBody);
groundBody.quaternion.setFromEuler(Math.PI/2,0,0);
let mesh,body;
const material = new THREE.MeshPhysicalMaterial({ color: 0xaaaaaa })
const loader = new OBJLoader()
loader.load('resources/Model_8_8.obj', (object) => {
const geometry = object.children[0].geometry;
mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
//mesh.rotateZ(Math.PI);
const boundingBox = new THREE.Box3().setFromObject(object);
const width = boundingBox.max.x - boundingBox.min.x;
const height = boundingBox.max.y - boundingBox.min.y;
const depth = boundingBox.max.z - boundingBox.min.z;
const shape = new CANNON.Box(new CANNON.Vec3(width / 2, height / 2, depth / 2))
body= new CANNON.Body({
mass :10,
shape :shape
})
//body3.position.set(0, 1800, -100);
world.addBody(body);
const boxGeometry = new THREE.BoxGeometry(30,30,30);
const boxMat = new THREE.MeshBasicMaterial({
color: 0x00ff00,
wireframe : true
});
const boxMesh = new THREE.Mesh(boxGeometry,boxMat);
scene.add(boxMesh);
const groundGeo = new THREE.PlaneGeometry(300,300);
const groundMat = new THREE.MeshBasicMaterial({
color:0xffffff,
side : THREE.DoubleSide,
wireframe: true
});
const groundMesh = new THREE.Mesh(groundGeo,groundMat);
scene.add(groundMesh);
const boxBody = new CANNON.Body({
mass : 10,
shape : new CANNON.Box(new CANNON.Vec3(15,15,15))
});
world.addBody(boxBody);
const timeStep = 1 / 60 ;
function animate(){
world.step(timeStep);
groundMesh.position.copy(groundBody.position);
groundMesh.quaternion.copy(groundBody.quaternion);
boxMesh.position.copy(boxBody.position);
boxMesh.quaternion.copy(boxBody.quaternion);
mesh.position.copy(body.position);
mesh.quaternion.copy(body.quaternion);
renderer.render(scene,camera);
}
renderer.setAnimationLoop(animate);
window.addEventListener('resize',function(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth,window.innerHeight);
});
})
</script>
</head>
<body>
</body>
</html>
我不熟悉 cannonJS,但似乎有 2 个选项可以使用。 就像在 https://github.com/schteppe/cannon.js?files=1 中,重力设置为 Z 坐标,将重力更改为 Z 坐标,不要随平面旋转。然后给 boxBody.position.z = 100 一个位置,它起作用了。
否则你必须改变你的平面几何尺寸,而不是新的 CANNON.Plane() 形状,一个新的 CANNON.Box(new CANNON.Vec3(15, 15, 1)) 形状,而 Z 坐标只是1,旋转后这是你的 Y 尺寸。在这种情况下,不在 z 中而是在 y 中设置位置 (boxBody.position.y = 100)。我认为,你的例子中的错误是两种物理学在它们中的每一个中都在一起,这是造成失败的原因。 (我真的不知道 new Cannon.Plane() 在做什么。)干杯
一些应该有效的代码片段:
const groundBody = new CANNON.Body({
shape: new CANNON.Box(new CANNON.Vec3(15, 15, 1)),
type: CANNON.Body.STATIC,
});
world.addBody(boxBody);
boxBody.position.y = 100;