0

我正在尝试使用 Ray intersect 来确定 2 collada 对象是否发生碰撞。但到目前为止没有成功:(

我的代码http://jsfiddle.net/XqQzF/

        object.updateMatrix();

        // ray
        var f_vector = new THREE.Vector3( 0, 0, -1 );
        var b_vector = new THREE.Vector3( 0, 0, 1 );
        var l_vector = new THREE.Vector3( -1, 0, 0 );
        var r_vector = new THREE.Vector3( 1, 0, 0 );

每次我使用它从最新的 three.js 修订版中删除的东西时。你能在路上帮我吗?

4

2 回答 2

0

我最近更新了我的 three.js 示例集合以与最新版本(撰写本文时为 v56)兼容,其中包括一个碰撞检测示例。查看http://stemkoski.github.com/Three.js/Collision-Detection.html(有关说明,请参见http://stemkoski.github.com/Three.js/#collision-detection)。

您的情况的主要区别是选择模型的中心点作为光线的原点,并选择模型的一组顶点作为光线的端点,因为光线用于碰撞检测。

希望这可以帮助!

于 2013-03-12T21:52:58.883 回答
0

@Lee Stemkoski 答案是好的,当我们不使用 collada 数据时。首先,我知道我们需要分钟。2 网格对象。所以我从 collada 对象中获取了所有 Mesh 对象。我写了两个脚本 - 首先尝试碰撞 2 个 collada 对象。第二次尝试将 collada 对象与墙壁(简单网格)碰撞。在这两种情况下,脚本都无法识别碰撞。那我应该怎么写呢?最后,我尝试在 collada 对象上检测鼠标。这不是关于这个话题,而是类似的问题,所以我写在这里。Dae 文件由 SketchUp 生成。

两个 collada 对象的代码:

 var container;
 var meshs = [];
 var camera, scene, renderer, raycaster;
 var controls;
 var mouse = new THREE.Vector2();
 var dae, dae2;
 var collidableMeshList = [];
 var clock = new THREE.Clock();
 var keyboard = new THREEx.KeyboardState();

 $(document).ready(function() {
     init();
     animate();
 });

 function init() {

     container = document.createElement('div');
     $('.container').append(container);

     camera = new THREE.PerspectiveCamera(45, 500 / 500, 1, 1000);
     group = new THREE.Group();

     scene = new THREE.Scene();

     scene.add(camera);

     camera.position.set(10 * 10, 12 * 10, 16 * 10);

     camera.lookAt(scene.position);

     // Lights

     group.add(new THREE.AmbientLight(0x777777));

     var light = new THREE.DirectionalLight(0xdfebff, 1.25);
     light.position.set(300, 400, 50);
     light.position.multiplyScalar(1.3);

     light.castShadow = true;

     group.add(light);

     renderer = new THREE.WebGLRenderer({
         antialias: true
     });

     renderer.setClearColor(0xcccccc, 1);

     renderer.setSize(500, 500);

     container.appendChild(renderer.domElement);

     controls = new THREE.OrbitControls(camera, renderer.domElement);

     var loader = new THREE.ColladaLoader();
     loader.options.convertUpAxis = true;
     loader.load('./sample.dae', loadDae);

     function loadDae(collada) {
         dae = collada.scene;

         dae.scale.x = 0.5;
         dae.scale.y = 0.3;
         dae.scale.z = 0.3;
         dae.updateMatrix();

         group.add(dae);
     }

     var wallGeometry = new THREE.CubeGeometry(10, 10, 20, 1, 1, 1);
     var wallMaterial = new THREE.MeshBasicMaterial({
         color: 0x8888ff
     });
     var wireMaterial = new THREE.MeshBasicMaterial({
         color: 0x000000,
         wireframe: true
     });

     loader = new THREE.ColladaLoader();
     loader.options.convertUpAxis = true;
     loader.load('./sample.dae', loadDae2);

     function loadDae2(collada) {
         dae2 = collada.scene;

         dae2.scale.x = 0.5;
         dae2.scale.y = 0.3;
         dae2.scale.z = 0.3;
         dae2.updateMatrix();

         dae2.position.set(-40, 0, 0);

         dae2.traverse(function(child) {
             if (child instanceof THREE.Mesh) {
                 collidableMeshList.push(child);
             }
         });
         group.add(dae2);
     }

     group.translateX(-20);
     scene.add(group);

     raycaster = new THREE.Raycaster();

     window.addEventListener('resize', onWindowResize, false);
     window.addEventListener('mousemove', onDocumentMouseMove, false);
 }

 function onDocumentMouseMove(event) {

     event.preventDefault();

     mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
     mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

 }

 function onWindowResize() {

     camera.aspect = 500 / 500;
     camera.updateProjectionMatrix();

     renderer.setSize(500, 500);
 }

 function update() {
     var delta = clock.getDelta();
     var moveDistance = 200 * delta;
     var rotateAngle = Math.PI / 2 * delta;

     if (keyboard.pressed("A"))
         dae.rotation.y += rotateAngle;
     if (keyboard.pressed("D"))
         dae.rotation.y -= rotateAngle;

     if (keyboard.pressed("left"))
         dae.translateX(-moveDistance);
     if (keyboard.pressed("right"))
         dae.translateX(moveDistance);
     if (keyboard.pressed("up"))
         dae.translateZ(-moveDistance);
     if (keyboard.pressed("down"))
         dae.translateZ(moveDistance);

     meshs = [];
     if (typeof dae !== 'undefined') {
         dae.traverse(function(child) {
             if (child instanceof THREE.Mesh) {
                 meshs.push(child);
             }
         });
         $.each(meshs, function(number_mesh, mesh) {
             var originPoint = mesh.position.clone();

             for (var vertexIndex = 0; vertexIndex < mesh.geometry.vertices.length; vertexIndex++) {
                 var localVertex = mesh.geometry.vertices[vertexIndex].clone();
                 var globalVertex = localVertex.applyMatrix4(mesh.matrix);
                 var directionVector = globalVertex.sub(mesh.position);

                 var ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize());
                 var collisionResults = ray.intersectObjects(collidableMeshList);
                 if (collisionResults.length > 0 && collisionResults[0].distance < directionVector.length()) {
                     console.log(" Hit ");
                 }
             }
         });
     }
     controls.update();
 }

 function animate() {

     requestAnimationFrame(animate);
     render();
     update();

 }

 function render() {

     renderer.render(scene, camera);

 }

collada + 墙(网格)的代码:

var container;
var meshs = [];
var camera, scene, renderer, raycaster;
var controls;
var mouse = new THREE.Vector2();
var dae;
var collidableMeshList = [];
var clock = new THREE.Clock();
var keyboard = new THREEx.KeyboardState();

$(document).ready(function() {
    init();
    animate();
});

function init() {

    container = document.createElement('div');
    $('.container').append(container);

    camera = new THREE.PerspectiveCamera(45, 500 / 500, 1, 1000);
    group = new THREE.Group();

    scene = new THREE.Scene();

    scene.add(camera);

    camera.position.set(10 * 10, 12 * 10, 16 * 10);

    camera.lookAt(scene.position);

    // Lights

    group.add(new THREE.AmbientLight(0x777777));

    var light = new THREE.DirectionalLight(0xdfebff, 1.25);
    light.position.set(300, 400, 50);
    light.position.multiplyScalar(1.3);

    light.castShadow = true;

    group.add(light);

    renderer = new THREE.WebGLRenderer({
        antialias: true
    });

    renderer.setClearColor(0xcccccc, 1);

    renderer.setSize(500, 500);

    container.appendChild(renderer.domElement);

    controls = new THREE.OrbitControls(camera, renderer.domElement);

    var loader = new THREE.ColladaLoader();
    loader.options.convertUpAxis = true;
    loader.load('./sample.dae', loadDae);

    function loadDae(collada) {
        dae = collada.scene;

        dae.scale.x = 0.5;
        dae.scale.y = 0.3;
        dae.scale.z = 0.3;
        dae.updateMatrix();

        group.add(dae);
    }

    var wallGeometry = new THREE.CubeGeometry(10, 10, 20, 1, 1, 1);
    var wallMaterial = new THREE.MeshBasicMaterial({
        color: 0x8888ff
    });
    var wireMaterial = new THREE.MeshBasicMaterial({
        color: 0x000000,
        wireframe: true
    });

    var wall = new THREE.Mesh(wallGeometry, wallMaterial);
    wall.position.set(-40, 5, -10);
    group.add(wall);
    collidableMeshList.push(wall);
    var wall = new THREE.Mesh(wallGeometry, wireMaterial);
    wall.position.set(-40, 5, -10);
    group.add(wall);

    group.translateX(-20);
    scene.add(group);

    raycaster = new THREE.Raycaster();

    window.addEventListener('resize', onWindowResize, false);
    window.addEventListener('mousemove', onDocumentMouseMove, false);
}

function onDocumentMouseMove(event) {

    event.preventDefault();

    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

}

function onWindowResize() {

    camera.aspect = 500 / 500;
    camera.updateProjectionMatrix();

    renderer.setSize(500, 500);
}

function update() {
    var delta = clock.getDelta();
    var moveDistance = 200 * delta;
    var rotateAngle = Math.PI / 2 * delta;

    if (keyboard.pressed("A"))
        dae.rotation.y += rotateAngle;
    if (keyboard.pressed("D"))
        dae.rotation.y -= rotateAngle;

    if (keyboard.pressed("left"))
        dae.translateX(-moveDistance);
    if (keyboard.pressed("right"))
        dae.translateX(moveDistance);
    if (keyboard.pressed("up"))
        dae.translateZ(-moveDistance);
    if (keyboard.pressed("down"))
        dae.translateZ(moveDistance);

    meshs = [];
    if (typeof dae !== 'undefined') {
        dae.traverse(function(child) {
            if (child instanceof THREE.Mesh) {
                meshs.push(child);
            }
        });
        $.each(meshs, function(number_mesh, mesh) {
            var originPoint = mesh.position.clone();

            for (var vertexIndex = 0; vertexIndex < mesh.geometry.vertices.length; vertexIndex++) {
                var localVertex = mesh.geometry.vertices[vertexIndex].clone();
                var globalVertex = localVertex.applyMatrix4(mesh.matrix);
                var directionVector = globalVertex.sub(mesh.position);

                var ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize());
                var collisionResults = ray.intersectObjects(collidableMeshList);
                if (collisionResults.length > 0 && collisionResults[0].distance < directionVector.length()) {
                    console.log(" Hit ");
                }
            }
        });
    }
    controls.update();
}

function animate() {

    requestAnimationFrame(animate);
    render();
    update();

}

function render() {

    renderer.render(scene, camera);

}

检测 collada 对象上的鼠标。短代码版本:

var meshs = [],
    raycaster,
    mouse = new THREE.Vector2();
...
function init() {
    ...
    function loadDae(collada) {
        dae = collada.scene;
        dae.scale.x = 0.5;
        dae.scale.y = 0.3;
        dae.scale.z = 0.3;
        dae.updateMatrix();
        group.add(dae);
        dae.traverse(function(child) {
            if (child instanceof THREE.Mesh) {
                meshs.push(child);
            }
        });
    }

    var loader = new THREE.ColladaLoader();

    loader.options.convertUpAxis = true;
    loader.load('./sample.dae', loadDae);
    raycaster = new THREE.Raycaster();
    window.addEventListener('mousemove', onDocumentMouseMove, false);
    ...
}
...
function onDocumentMouseMove(event) {

    event.preventDefault();

    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

}

function render() {
    raycaster.setFromCamera(mouse, camera);

    if (group.children.length === 5) {
        var intersects = raycaster.intersectObjects(meshs);

        if (intersects.length > 0) {
            console.log(" Hit ");
        }
    }
    renderer.render(scene, camera);
}
...

一般 - 是的,它有效,但会抛出一些 $meshs 错误。

类型错误:未定义不是对象(评估“O”)

three.min.js:8304
cthree.min.js:3544
intersectObjectsthree.min.js:3609:144

为什么以及如何识别哪个网格对于 intersectObjects 是正确的,而哪个不是?

于 2016-02-04T18:06:00.580 回答