three.js - 使用Projector和Ray选择一个顶点

时间:2012-06-26 10:53:16

标签: javascript three.js

我的总体目标是能够加载一个人体的.obj文件。允许用户选择两个顶点并用标志突出显示它们。然后从原始.obj文件中找到两个顶点的索引,并运行php脚本来测量两个顶点之间的距离。

我尝试了一些approches,但没有运气,通常是选择两个顶点。我当前的方法使用obj加载器,它工作正常,但我无法找到我使用Projector和Ray点击的顶点。它总是返回一个空数组。

到目前为止,这是我的代码,一旦intersects数组不为空,我会尝试从文件中找到最近的顶点,更改对象的颜色并更改单击的面。

<!doctype html>
<html lang="en">
    <head>
        <title>three.js webgl - loaders - OBJ loader</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                font-family: Monospace;
                background-color: white;
                color: #fff;
                margin: 0px;
                overflow: hidden;
            }
            #info {
                color: #fff;
                position: absolute;
                top: 10px;
                width: 100%;
                text-align: center;
                z-index: 100;
                display:block;
            }
            #info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
        </style>
    </head>

<body>
    <script src="javascripts/Three.js"></script>
    <script src="javascripts/OBJLoader.js"></script>

    <script>

        var container, stats;

        var camera, scene, renderer, model;

        var mouseX = 0, mouseY = 0;

        var windowHalfX = window.innerWidth / 2;
        var windowHalfY = window.innerHeight / 2;


        init();
        animate();


        function init() {

            container = document.createElement( 'div' );
            document.body.appendChild( container );

            scene = new THREE.Scene();

            camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 2000 );
            camera.position.z = 1;
            scene.add( camera );
            camera.position.y = -4;

            var ambient = new THREE.AmbientLight( 0x101030 );
            scene.add( ambient );

            var directionalLight = new THREE.DirectionalLight( 0xffeedd );
            directionalLight.position.set( 0, 0, 1 ).normalize();
            scene.add( directionalLight );

            var loader = new THREE.OBJLoader();
            loader.load( "img/originalMeanModel.obj", function ( object ) {
                model = object;
                scene.add( model );
            } );

            // RENDERER
            renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer.domElement );

            document.addEventListener( 'mousemove', onDocumentMouseMove, false );
            document.addEventListener( 'mousedown', onDocumentMouseDown, false );

        }

        function onDocumentMouseDown( event ){

            console.log('Morphable-body-obj: Width '+ window.innerWidth ) ;
            console.log('Morphable-body-obj: Height '+ window.innerHeight) ;

            var vector = new THREE.Vector3 ((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight)*2+1, 0.5);
            var projector = new THREE.Projector();
            projector.unprojectVector(vector, camera);
            var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize());
            var intersects = ray.intersectObject(scene);
            console.log(intersects);
            if (intersects.length > 0)
              {
                var xhr = new XMLHttpRequest();
                xhr.open('GET', '/img/originalMeanModel.obj', false);
                xhr.send(null);
                var text = xhr.responseText;
                var origText = text; 
                var lines = text.split("\n");
                for (i=0; i<6449; i++){
                  lines[i] = lines[i].split(" ");
                }
                var low = Math.sqrt(
                      (Math.pow((intersects[0].point.x - parseFloat(lines[0][1])), 2))+
                      (Math.pow((intersects[0].point.y - parseFloat(lines[0][2])), 2))+
                      (Math.pow((intersects[0].point.z - parseFloat(lines[0][3])), 2))
                    );

                var c = 0;
                for(i=1; i<6449; i++){
                  var temp = Math.sqrt(
                      (Math.pow((intersects[0].point.x - parseFloat(lines[i][1])), 2))+
                      (Math.pow((intersects[0].point.y - parseFloat(lines[i][2])), 2))+
                      (Math.pow((intersects[0].point.z - parseFloat(lines[i][3])), 2))
                  );
                  if(temp < low){
                    low = temp;
                    c=i;
                  }
                }

                console.log(
                  'Mouse coordinates:' + '\nx = ' + intersects[0].point.x + '\ny = ' + intersects[0].point.y + '\nz = ' + intersects[0].point.z +'\n'+
                  'Nearest Vertex' + '\nx= ' + lines[c][1] + '\ny= ' + lines[c][2] + '\nz =' + lines[c][3] + "\n" +
                  'Difference' + '\nx= ' + (intersects[0].point.x - lines[c][1]) + '\ny= ' + (intersects[0].point.y - lines[c][2]) + '\nz= ' + (intersects[0].point.z - lines[c][3]) 
                );

                intersects[0].object.materials[0].color = new THREE.Color( Math.random() * 0xffffff );

                intersects[0].face.color = new THREE.Color(0xffffff);
                intersects[0].object.geometry.colorsNeedUpdate = true;
                intersects[0].object.geometry.dynamic = true;
               }
            else{
                alert('error');
            }
        }

        function onDocumentMouseMove( event ) {
            mouseX = ( event.clientX - windowHalfX ) / 2;
            mouseY = ( event.clientY - windowHalfY ) / 2;
        }

        function animate() {
            requestAnimationFrame( animate );
            render();
        }

        function render() {
            camera.lookAt( scene.position );
            renderer.render( scene, camera );
        }

    </script>

</body>

有问题的.obj文件可以在https://dl.dropbox.com/u/23384412/originalMeanModel.obj

找到

如果有人能指出我正确的方向,那将非常感激。

提前致谢! :)

1 个答案:

答案 0 :(得分:2)

为了解决这个问题,我使用此代码

从obj加载程序返回的对象创建了一个网格
            var loader = new THREE.OBJLoader();
            loader.load( "img/originalMeanModel.obj", function ( object ) {

              object.children[0].geometry.computeFaceNormals();
              var  geometry = object.children[0].geometry;
                      console.log(geometry);
              THREE.GeometryUtils.center(geometry);
              var material = new THREE.MeshLambertMaterial({color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors });
              mesh = new THREE.Mesh(geometry, material);
              model = mesh;
              // model = object;
               scene.add( model );
            } );

然后在执行intersectObject时,我在模型而非场景

上完成
var intersects = ray.intersectObject(model);