简体   繁体   English

Three.js:如何添加垂直于面部的对象(法线)?

[英]Three.js: How to add an object perpendicular to a face (normal)?

I'm trying to add a box (called "marker") perpendicular to the face I'm clicking on. 我试图添加一个垂直于我单击的脸的框(称为“标记”)。

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... 在问这个问题之前,我先阅读了这个答案( 如何使用Three.js使对象垂直于面部? ),但无法使其正常工作...

For now, it adds the marker where it needs to, but with a slightly wrong orientation expect on cube's top. 目前,它在需要的地方添加了标记,但是在多维数据集的顶部预期方向略有错误。

Wrong orientation on cube and uncontroled Y rotation 立方体方向错误和Y旋转不受控制

I don't understand two things: 1. why there's a difference between the faceNormalsHelper's direction and intersects[0].face.normal. 我不明白两件事:1.为什么faceNormalsHelper的方向和相交[0] .face.normal之间存在差异。 2. How is the Y rotation controled? 2.如何控制Y旋转?

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: 为了帮助您,我制作了一个小提琴( https://jsfiddle.net/jpyncf62/1/ ),这是我用来执行此操作的代码:

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);
    }
}

Thanks for me help! 谢谢我的帮助!

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 );
    }

There is a function named 'applyMatrixOfMesh' in code. 代码中有一个名为“ applyMatrixOfMesh”的函数。 You need use it for every 'THREE.Mesh' will you use for intersection. 您需要将其用于每个“三”网格,以用于交集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM