Three.js:如何添加垂直于人脸的对象(正常)? [英] Three.js: How to add an object perpendicular to a face (normal)?

查看:33
本文介绍了Three.js:如何添加垂直于人脸的对象(正常)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试添加一个垂直于我点击的面的框(称为标记").

I'm trying to add a box (called "marker") perpendicular to the face I'm clicking on.

为此,在单击时,我投射了一条射线,如果它击中某物,我将获得法线的相交点值并将它们传输到标记"作为其旋转值.在问这个问题之前,我阅读了这个答案( 如何使用 Three.js 使对象垂直于面部? )但无法使其工作...

To do this, on click, I cast a ray, if it hits something, I get the normal's intersecting point values and transfer them to the "marker" as its rotation values. Before asking this question, I read this answer ( How do I make an object perpendicular to a face with Three.js? ) but could not make it work...

现在,它会在需要的地方添加标记,但在立方体顶部的方向稍有错误.

For now, it adds the marker where it needs to, but with a slightly wrong orientation expect on cube's top.

立方体方向错误且 Y 旋转不受控制

我不明白两件事:1.为什么faceNormalsHelper的方向和intersects[0].face.normal有区别.2. Y 旋转是如何控制的?

I don't understand two things: 1. why there's a difference between the faceNormalsHelper's direction and intersects[0].face.normal. 2. How is the Y rotation controled?

我的错误是什么?为了帮助您帮助我,我制作了一个 Fiddle ( https://jsfiddle.net/jpyncf62/1/ ),这是我用来执行此操作的代码:

What's my mistake? To help you help me, I made a Fiddle ( https://jsfiddle.net/jpyncf62/1/ ) and here's the code I'm using to do that:

function clickDown(e) {
    e.preventDefault();

    raycaster.setFromCamera(mouse, camera);
    var intersects = raycaster.intersectObjects(objects);

    if (intersects.length > 0) {
        var intersect = intersects[0];
        console.log(intersects[0]);
        console.log(console.log(intersects[0].object.name));

        var markerGeo = new THREE.BoxGeometry(1, 6, 1, 1, 1, 1);
        var markerMat = new THREE.MeshLambertMaterial({ color: 0xff0000 });
        var marker = new THREE.Mesh(markerGeo, markerMat);
        marker.name = "marker";
        marker.position.copy(intersect.point);

        marker.lookAt(intersect.face.normal);

        scene.add(marker);
    }
}

谢谢你的帮助!

推荐答案

您正在添加立方体和平面.并给它们位置和旋转.但是为了正确地相交它们的法线,你应该应用矩阵.

You are adding cube and plane. And giving them position and rotation. But for intersecting normals of them correctly, you should apply matrix.

    var container, stats;
    var camera, scene, renderer;
    var objects = [];
    raycaster = new THREE.Raycaster();
    mouse = new THREE.Vector2();

    init();
    animate();

    function init() {
        container = document.getElementById("webgl-output")
        scene = new THREE.Scene();

        camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
        camera.position.set(20, 50,50);
        camera.lookAt( scene.position );

        scene.add ( new THREE.AmbientLight( 0xffffff ) );

        light = new THREE.DirectionalLight( 0xffffff );
        light.position.set( 0, 1, 0 );
        scene.add( light );

        var material = new THREE.MeshLambertMaterial( { color: 0x4fc2c9 } );
        var cube = new THREE.Mesh( new THREE.BoxGeometry( 10, 10, 10, 1, 1, 1 ), material );
        cube.name = "I'm a cube";
        objects.push( cube );
        scene.add( cube );


        cube.position.set( 0, 5, 0 );
        cube.rotation.set( 0, 0, Math.PI / 4);

        applyMatrixOfMesh(cube); // Apply matrix of cube

        // Add helpers after applied matrix
        var faceNormalsHelper = new THREE.FaceNormalsHelper( cube, 1 );
        cube.add( faceNormalsHelper );

        var vertexNormalsHelper = new THREE.VertexNormalsHelper( cube, 1 );
        cube.add( vertexNormalsHelper );

        var planeGeo = new THREE.PlaneGeometry( 60, 20, 1, 1 );
        var planeMat = new THREE.MeshLambertMaterial({ color: 0xffffff });
        var plane = new THREE.Mesh( planeGeo, planeMat );
        plane.position.set(0, 0, 0);
        plane.rotation.x = -0.5 * Math.PI;
        plane.name = "plane01";

        applyMatrixOfMesh(plane); // Apply matrix of plane

                    scene.add( plane );
        objects.push( plane );

        var axes = new THREE.AxisHelper( 20 );
        scene.add( axes );

        renderer = new THREE.WebGLRenderer( { antialias: true });
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setClearColor( 0xeeeeee );
        renderer.setSize( window.innerWidth, window.innerHeight );
        container.appendChild( renderer.domElement );

        document.addEventListener('mousemove', mouseMoving, false);
        document.addEventListener('mousedown', clickDown, false);
    }

    function mouseMoving(e) {
        mouse.x = ( e.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = - ( e.clientY / window.innerHeight ) * 2 + 1;            
        raycaster.setFromCamera( mouse, camera );

        var intersects = raycaster.intersectObjects( scene.children );

        for ( var i = 0; i < intersects.length; i++ ) {
            var posY = intersects[ 0 ].point.y.toFixed(2);
        }
    }

    function clickDown(e) {
        e.preventDefault();

        raycaster.setFromCamera( mouse, camera );
        var intersects = raycaster.intersectObjects( objects );            

        if( intersects.length > 0 ) {
            var intersect = intersects[ 0 ];
            console.log( intersects[ 0 ]);
            console.log( console.log( intersects[ 0 ].face.normal ) );

            var markerGeo = new THREE.BoxGeometry( 1, 1, 6, 1, 1, 1 ); // I changed BoxGeometry
            var markerMat = new THREE.MeshLambertMaterial( { color: 0xff0000 } );
            var marker = new THREE.Mesh( markerGeo, markerMat );
            marker.name = "marker";



            marker.lookAt( intersect.face.normal );  // First look At to normal
            marker.position.copy( intersect.point )  // After give position to marker

            scene.add( marker );
        }
    }

    function applyMatrixOfMesh(mesh) { // You should apply Matrix of cube and plane
        mesh.updateMatrix();
        mesh.geometry.applyMatrix(mesh.matrix);

        mesh.position.set(0, 0, 0);
        mesh.rotation.set(0, 0, 0);
        mesh.updateMatrix();
    }


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

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

代码中有一个名为applyMatrixOfMesh"的函数.您需要将它用于要用于交集的每个THREE.Mesh".

There is a function named 'applyMatrixOfMesh' in code. You need use it for every 'THREE.Mesh' will you use for intersection.

这篇关于Three.js:如何添加垂直于人脸的对象(正常)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆