我在三个js中创建了一个房间,并在其中添加了各种物体。但是, 物体正在移出房间。这里是其中我的代码正在运行的网址:防止物体在三个js室外移动
http://istation-demo.cladev.com/room.html
我在三个js中创建了一个房间,并在其中添加了各种物体。但是, 物体正在移出房间。这里是其中我的代码正在运行的网址:防止物体在三个js室外移动
http://istation-demo.cladev.com/room.html
为了防止物体离开房间或相互碰撞,你必须至少有碰撞检测的简单形式。大多数3D引擎,包括three.js,都有Axis-Aligned Bounding Boxes(或AABB)用于创建的所有3D对象。在three.js中可以访问边界框,最简单的方法是调用 var boundingBoxHelperObject = new THREE.BoundingBoxHelper(object)
如果将它添加到场景中,它将显示为线框灰色框,可以紧密贴合对象。如果您在帮助器上调用更新(就像您很快会看到的那样),它会实时更新到3d对象的尺寸和移动 - 非常酷!
然后,在所有这些盒子进行碰撞检测,你叫 boundingBoxHelperObject.box.intersectsBox(anotherBoxHelperObject.box)
如果发生碰撞或如果不发生碰撞假,输出正确的。然后执行相应的操作,例如将框移回框架以防止其逃离房间或穿透另一个实体对象,或者更改碰撞对象的颜色或任何您想要的。
下面是最终的代码示例与我纠正采摘/从去年你几个月前发的帖子拖码,再加上新的边框和碰撞测试代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/html">
<head lang="en">
<meta charset="UTF-8">
<title>Room</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r75/three.js"></script>
<script src="http://alexan0308.github.io/threejs/examples/js/loaders/OBJLoader.js"></script>
<script src="http://alexan0308.github.io/threejs/examples/js/loaders/MTLLoader.js"></script>
<script src="http://alexan0308.github.io/threejs/examples/js/loaders/OBJMTLLoader.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="workspace"></div>
<script>
//define global variables here
var container, renderer;
var camera, scene, projector, mouseVector, controls;
var mouseX, mouseY, draggable;
var pen, c_mesh, interactiveObj = [], rotateObj = [], groundRaycastObj = [];
var wallWidth = 1200;
var wallHeight = 400;
var chair_model, sofa_model;
var chair_selected = false;
var sofa_selected = false;
var raycaster;
var mouse = new THREE.Vector2(), INTERSECTED;
var radius = 100, theta = 0;
var oldIntersectPoint = new THREE.Vector3();
var newIntersectPoint = new THREE.Vector3();
var intersectOffset = new THREE.Vector3();
var chairOldPosition = new THREE.Vector3();
var sofaOldPosition = new THREE.Vector3();
var chair_rotate = false;
var walls;
var mesh_box;
var wallright, wallleft, wallback, wallfront, ceiling, ground;
var strDownloadMime = "image/octet-stream";
var chairBox, sofaBox;
var wallrightBox, wallleftBox, wallbackBox, wallfrontBox;
init();
animate();
function init() {
container = document.getElementById('workspace'); //document.createElement('div');
document.body.appendChild(container);
//camera
//camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 10, 10000);
// camera.position.set(0, -wallHeight/2 + 10, wallWidth);
// camera.lookAt(new THREE.Vector3(10, 10, 10));
//renderer
renderer = new THREE.WebGLRenderer({preserveDrawingBuffer: true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x889988);
renderer.shadowMapEnabled = true;
container.appendChild(renderer.domElement);
scene = new THREE.Scene();
raycaster = new THREE.Raycaster();
var ambient = new THREE.AmbientLight(0xffffff);
scene.add(ambient);
camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 1, 10000);
camera.position.z= wallWidth;
camera.position.y= wallWidth/2;
controls = new THREE.OrbitControls(camera, renderer.domElement);
//controls.addEventListener('change', render); // add this only if there is no animation loop (requestAnimationFrame)
controls.enableDamping = true;
controls.dampingFactor = 0.25;
//controls.enableZoom = false;
//walls
walls = new THREE.Object3D();
var groundGeo_2 = new THREE.PlaneGeometry(wallWidth, wallWidth); //for roof and floor
var groundGeo = new THREE.PlaneGeometry(wallWidth, wallHeight);
var wallTextureRight = new THREE.MeshBasicMaterial({
map: THREE.ImageUtils.loadTexture('textures/walls/rainbow.jpg')
});
wallTextureRight.map.needsUpdate = true;
var wallTextureLeft = new THREE.MeshBasicMaterial({
map: THREE.ImageUtils.loadTexture('textures/walls/rainbow.jpg')
});
var wallTextureFront = new THREE.MeshBasicMaterial({
map: THREE.ImageUtils.loadTexture('textures/walls/wall4.jpg')
});
var wallTextureBack = new THREE.MeshBasicMaterial({
map: THREE.ImageUtils.loadTexture('textures/walls/wall3.png')
});
var floorTexture = new THREE.MeshBasicMaterial({
map: THREE.ImageUtils.loadTexture('textures/walls/floor.jpg')
});
floorTexture.map.needsUpdate = true;
var ceilTexture = new THREE.MeshBasicMaterial({
map: THREE.ImageUtils.loadTexture('textures/walls/wall4.jpg')
});
ground = new THREE.Mesh(groundGeo_2, floorTexture);
ground.overdraw = true;
ground.position.set(0, 0, 0);
ground.rotation.x = -Math.PI/2;
walls.add(ground);
console.log(ground);
wallleft = new THREE.Mesh(groundGeo, wallTextureLeft);
wallleft.overdraw = true;
wallleft.position.set(-wallWidth/2, wallHeight/2, 0);
wallleft.rotation.y = Math.PI/2;
walls.add(wallleft);
wallleftBox = new THREE.BoundingBoxHelper(wallleft);
wallleftBox.update(wallleft);
//wallleftBox.box.min.x -= 0.1;
//wallleftBox.box.max.x += 0.1;
//scene.add(wallleftBox);
wallright = new THREE.Mesh(groundGeo, wallTextureRight);
wallright.overdraw = true;
wallright.position.set(wallWidth/2, wallHeight/2, 0);
wallright.rotation.y = -Math.PI/2;
walls.add(wallright);
wallrightBox = new THREE.BoundingBoxHelper(wallright);
wallrightBox.update(wallright);
//wallrightBox.box.min.x -= 0.1;
//wallrightBox.box.max.x += 0.1;
//scene.add(wallrightBox);
wallback = new THREE.Mesh(groundGeo, wallTextureBack);
wallback.overdraw = true;
wallback.position.set(0, wallHeight/2, -wallWidth/2);
walls.add(wallback);
wallbackBox = new THREE.BoundingBoxHelper(wallback);
wallbackBox.update(wallback);
//scene.add(wallbackBox);
wallfront = new THREE.Mesh(groundGeo, wallTextureFront);
wallfront.overdraw = true;
wallfront.position.set(0, wallHeight/2, wallWidth/2);
wallfront.rotation.y = -Math.PI;
walls.add(wallfront);
wallfrontBox = new THREE.BoundingBoxHelper(wallfront);
wallfrontBox.update(wallfront);
//scene.add(wallfrontBox);
ceiling = new THREE.Mesh(groundGeo_2, ceilTexture);
ceiling.position.set(0, wallHeight, 0);
ceiling.rotation.x = Math.PI/2;
walls.add(ceiling);
scene.add(walls);
groundRaycastObj.push(walls);
//load bed texture
var bed_texture = new THREE.ImageUtils.loadTexture("textures/cb-rochelle-gray_baked.png");
var bedMaterial = new THREE.MeshBasicMaterial({
map: bed_texture,
side: THREE.DoubleSide
});
//load bed
var loader = new THREE.JSONLoader();
loader.load('js/sofa.js', function (geometry) {
sofa_model = new THREE.Mesh(geometry, bedMaterial);
for (var i = 0; i < sofa_model.children.length; i++) {
sofa_model.children[i].material = material;
sofa_model.children[i].userDataParent = sofa_model;
sofa_model.children[i].name = 'sofa_model';
}
sofa_model.position.set(200,0, -200);
sofa_model.rotation.set(0, 0, 0);
sofa_model.scale.set(3, 3, 3);
sofa_model.name = 'sofa_model';
interactiveObj.push(sofa_model);
scene.add(sofa_model);
sofaBox = new THREE.BoundingBoxHelper(sofa_model);
// comment next line out if you don't want to see the wireframe sofa boxHelper
scene.add(sofaBox);
});
//load chair texture
var chair_texture = new THREE.ImageUtils.loadTexture("textures/chair.png");
var chairMaterial = new THREE.MeshBasicMaterial({
map: chair_texture,
side: THREE.DoubleSide
});
//load chair
var loader = new THREE.JSONLoader();
loader.load('js/chair_model.js', function (geometry) {
chair_model = new THREE.Mesh(geometry, chairMaterial);
for (var i = 0; i < chair_model.children.length; i++) {
chair_model.children[i].material = material;
chair_model.children[i].userDataParent = sofa_model;
chair_model.children[i].name = 'chair_model';
}
chair_model.position.set(-300,0, -200);
chair_model.rotation.set(0, 0, 0);
chair_model.scale.set(3, 3, 3);
chair_model.name = 'chair_model';
interactiveObj.push(chair_model);
scene.add(chair_model);
chairBox = new THREE.BoundingBoxHelper(chair_model);
// comment next line out if you don't want to see the wireframe chair boxHelper
scene.add(chairBox);
});
//IE, Chrome, Safari, Opera
document.addEventListener('mousewheel', onDocumentMouseWheel, false);
//Firefox
document.addEventListener('DOMMouseScroll', onDocumentMouseWheel, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
document.addEventListener('mousedown', onDocumentMouseDown, false);
document.addEventListener('mouseup', onDocumentMouseUp, false);
window.addEventListener('resize', onWindowResize, false);
}
function animate() {
requestAnimationFrame(animate);
chair_model.rotation.y += 0.02;
chairBox.update(chair_model);
sofaBox.update(sofa_model);
//wallrightBox.update(wallright);
//wallleftBox.update(wallleft);
//wallfrontBox.update(wallfront);
//wallbackBox.update(wallback);
controls.update();
// Render the frame
//Don't render twice, it will slow down your animation!
//render();
renderer.render(scene, camera);
}
function render() {
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth/window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
//controls.handleResize();
}
function onDocumentMouseDown(event) {
draggable = true;
event.preventDefault();
var testIntersects;
testIntersects = raycaster.intersectObjects(groundRaycastObj, true);
if (testIntersects.length > 0)
oldIntersectPoint.copy(testIntersects[0].point);
// find intersections
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(interactiveObj, true);
if (intersects.length > 0) {
controls.enabled=false;
if (intersects[0].object.name == 'chair_model') {
container.style.cursor = 'pointer';
chair_selected = true;
//oldIntersectPoint.copy(chair_model.position);
chairBox.material.color.set('white');
} else if (intersects[0].object.name == 'sofa_model') {
container.style.cursor = 'pointer';
sofa_selected = true;
//oldIntersectPoint.copy(sofa_model.position);
sofaBox.material.color.set('white');
}
else {
chair_selected = false;
sofa_selected = false;
}
draggable = false;
}
}
function onDocumentMouseUp(event) {
draggable = false;
chair_selected = false;
sofa_selected = false;
chair_rotate = false;
container.style.cursor = 'auto';
controls.enabled=true;
oldIntersectPoint.set(0,0,0);
newIntersectPoint.set(0,0,0);
intersectOffset.set(0,0,0);
chairBox.material.color.set('grey');
sofaBox.material.color.set('grey');
}
function onDocumentMouseMove(event) {
mouse.x = (event.clientX/window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY/window.innerHeight) * 2 + 1;
var deltaX = event.clientX - mouseX;
var deltaY = event.clientY - mouseY;
var testIntersects;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(interactiveObj, true);
if (intersects.length > 0) {
container.style.cursor = 'pointer';
//addRotationLine(intersects[0].object);
} else {
container.style.cursor = 'auto';
}
if (draggable) {
} else if (chair_selected == true) {
testIntersects = raycaster.intersectObjects(groundRaycastObj, true);
if (testIntersects.length > 0) {
var okToMove = true;
chairOldPosition.copy(chair_model.position);
newIntersectPoint.copy(testIntersects[0].point);
intersectOffset.copy(newIntersectPoint);
intersectOffset.sub(oldIntersectPoint);
//uncomment below if you want more precision mouse movements of objects
//intersectOffset.multiplyScalar(0.1);
// store old intersect point for next frame
oldIntersectPoint.copy(newIntersectPoint);
chair_model.position.add(intersectOffset);
chair_model.updateMatrixWorld(true);
//chairBox.updateMatrixWorld(true);
chairBox.update(chair_model);
// default
chairBox.material.color.set('white');
if(chairBox.box.intersectsBox(sofaBox.box)) {
okToMove = false;
chairBox.material.color.set('red');
}
else if(chairBox.box.intersectsBox(wallrightBox.box)) {
okToMove = false;
chairBox.material.color.set('red');
}
else if(chairBox.box.intersectsBox(wallleftBox.box)) {
okToMove = false;
chairBox.material.color.set('red');
}
else if(chairBox.box.intersectsBox(wallfrontBox.box)) {
okToMove = false;
chairBox.material.color.set('red');
}
else if(chairBox.box.intersectsBox(wallbackBox.box)) {
okToMove = false;
chairBox.material.color.set('red');
}
// if NOT ok to move and chair is hitting something,
if (!okToMove) {
// put chair back where it was
chair_model.position.copy(chairOldPosition);
}
}
// clamp chair position to the ground
chair_model.position.y = 0;
} else if (chair_rotate == true) {
rotate_object(chair_model, event);
}
else if (sofa_selected == true) {
testIntersects = raycaster.intersectObjects(groundRaycastObj, true);
if (testIntersects.length > 0) {
var okToMove = true;
sofaOldPosition.copy(sofa_model.position);
newIntersectPoint.copy(testIntersects[0].point);
intersectOffset.copy(newIntersectPoint);
intersectOffset.sub(oldIntersectPoint);
//uncomment below if you want more precision mouse movements of objects
//intersectOffset.multiplyScalar(0.1);
oldIntersectPoint.copy(newIntersectPoint);
sofa_model.position.add(intersectOffset);
sofa_model.updateMatrixWorld(true);
//sofaBox.updateMatrixWorld(true);
sofaBox.update(sofa_model);
// default
sofaBox.material.color.set('white');
if(sofaBox.box.intersectsBox(chairBox.box)) {
okToMove = false;
sofaBox.material.color.set('red');
}
else if(sofaBox.box.intersectsBox(wallrightBox.box)) {
okToMove = false;
sofaBox.material.color.set('red');
}
else if(sofaBox.box.intersectsBox(wallleftBox.box)) {
okToMove = false;
sofaBox.material.color.set('red');
}
else if(sofaBox.box.intersectsBox(wallfrontBox.box)) {
okToMove = false;
sofaBox.material.color.set('red');
}
else if(sofaBox.box.intersectsBox(wallbackBox.box)) {
okToMove = false;
sofaBox.material.color.set('red');
}
// if NOT ok to move and sofa is hitting something,
if (!okToMove) {
// put sofa back where it was
sofa_model.position.copy(sofaOldPosition);
}
}
// clamp sofa position to the ground
sofa_model.position.y = 0;
}
mouseX = event.clientX;
mouseY = event.clientY;
//render(); // no need to render
}
function onDocumentMouseWheel(event) {
// This is automatically handled for you by orbitControls.js,
// but you can't disable zoom on the controls - so don't type controls.enableZoom = false;
//mouseDelta = (-event.wheelDeltaY || event.detail);
//camera.position.z += mouseDelta * 1;
//render(); // no need to render
}
function addRotationLine(objModel) {
var material = new THREE.LineBasicMaterial({
color: 0x0000ff,
linewidth: 6
});
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3(-10, 500, 0),
new THREE.Vector3(1000, 500, 0)
);
var line = new THREE.Line(geometry, material);
objModel.add(line);
}
function rotate_object(object, event) {
mouse.x = (event.clientX/window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY/window.innerHeight) * 2 + 1;
var deltaX = event.clientX - mouseX;
var deltaY = event.clientY - mouseY;
object.rotation.y += deltaX * 0.02;
object.rotation.y += deltaY * 0.01;
}
</script>
</body>
</html>
希望这对你的作品! :)
很抱歉的回复。我有一段时间没有回到这个网站,而我现在只在3月8日才看到你的早期帖子。你是否想重新链接到你的项目(它目前没有被提供,链接没有显示),我我们来看看,谢谢! – erichlof
嗨@ericlof,这里是更新的链接: http://istation-demo.cladev.com/room-final.html。 我们的主要问题是对象的碰撞,我们不希望我们的对象通过其他对象,谢谢 –
嗨@anuj rajput我很乐意提供帮助,但首先,你见过http://stackoverflow.com//34946735/object-moving-in-different-direction-after-rotating-the-plane-three-jsv73/34997947?noredirect = 1#comment59384683_34997947并尝试将我的更改添加到旧的拾取/移动代码中?我问,因为你现在的例子有旧的不正确的拣选/移动行为,这可能会使得碰撞检测调试变得更加困难。 – erichlof