首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Raycaster改变Three.js网格人脸颜色

用Raycaster改变Three.js网格人脸颜色
EN

Stack Overflow用户
提问于 2020-07-15 12:35:29
回答 1查看 932关注 0票数 1

目前,我正在开发一个web应用程序,当这些面孔被雷克斯特(鼠标)悬停时,应该给它们另一种颜色。

我目前有一个工作的.stl查看器和轨道控制到位。

使用已知的工作.stl文件看我的github下载并运行我的代码。您可以非常轻松地运行它,只需要一个活动服务器(这在例如VSCode中很容易实现,请参阅自述文件)。

目前,它可以很好地改变整个对象的颜色,但是当我尝试使用raycaster的intersects改变面部颜色时(就像更改对象的属性一样),它不起作用。我已经读过了,你必须把vertexColors: THREE.VertexColors添加到你的材料属性中。

我可以看到颜色值正在变化(在脸的颜色属性上使用console.log ),当我更改intersects[i].face.color.setHex(0x0f0f0f)时,它会改变为一个不同的腐蚀值。但视觉表情并没有改变。

我想我错过了什么或者忽略了什么,但我似乎无法弄清楚。

我现在的代码是:

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3d viewer tjalle</title>
    <link rel="stylesheet" type="text/css" href="../style/render.css">
</head>

<body>
    <script src="https://rawcdn.githack.com/mrdoob/three.js/r117/build/three.min.js"></script>
    <script src="https://rawcdn.githack.com/mrdoob/three.js/r117/examples/js/loaders/STLLoader.js"></script>
    <script src="https://rawcdn.githack.com/mrdoob/three.js/r117/examples/js/controls/OrbitControls.js"></script>

    <script>
        function init() {
            var raycaster = new THREE.Raycaster();
            var mouse = new THREE.Vector2();
            document.addEventListener('mousemove', onMouseMove, false);


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

            // Setup some basic stuff
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0xdddddd);


            // Setup Camera 
            camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 5000);

            // Setup renerer and add to page
            renderer = new THREE.WebGLRenderer({
                antialias: true
            });
            renderer.setSize(window.innerWidth, window.innerHeight);

            document.body.appendChild(renderer.domElement);


            window.addEventListener('resize', onWindowResize, false);

            function onWindowResize() {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize(window.innerWidth, window.innerHeight);

            }

            // Setup Camera Position
            camera.rotation.y = 45 / 180 * Math.PI;
            camera.position.x = 800;
            camera.position.y = 100;
            camera.position.z = 1000;

            // Add Camera Control through orbit.js
            let controls = new THREE.OrbitControls(camera, renderer.domElement);

            // Add some basic ambient lighting (Does light all parts equally and does not cast shadows)
            hlight = new THREE.AmbientLight(0xffffff, 5.3);
            scene.add(hlight);


            //Add some point lights to simulate real lights
            light = new THREE.PointLight(0xffffff, 1, 10000);
            light.position.set(0, 300, 500);
            scene.add(light);

            controls.update();
            // Animation Script
            function animate() {
                raycaster.setFromCamera(mouse, camera);
                // scene.children[2].material.color.set(0x1313)
                // calculate objects intersecting the picking ray
                var intersects = raycaster.intersectObjects(scene.children);
                
                for (var i = 0; i < intersects.length; i++) {
                    // changes whole object to red
                    // intersects[i].object.material.color.set(0xff0000);
                    intersects[i].face.color.setHex(0x0f0f0f)

                }
                if (intersects.length > 1) {
                    console.log(intersects[1].face.color);
                }


                renderer.render(scene, camera);
                requestAnimationFrame(animate);
            }

            // Setup GLTF Loader and load in car
            let loader = new THREE.STLLoader();
            loader.load('example.stl', function (geometry) {

                // console.log(gltf);
                var material = new THREE.MeshLambertMaterial({
                    color: 0x1313,
                    wireframe: false,
                    transparent: false,
                    vertexColors: THREE.vertexColors
                });
                var mesh = new THREE.Mesh(geometry, material);
                mesh.castShadow = true;
                mesh.receiveShadow = true;
                mesh.position.set(0, 0, 0);
                mesh.name = 'Tjalle\'s Mesh'

                scene.add(mesh);
                renderer.render(scene, camera)
                animate();
                console.log("Scene: ",)
                console.log(mesh)
            });


        }

        // Call method for starting init
        init();
    </script>

</body>

</html>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-15 16:38:17

交集对象的face属性是只读的.这意味着即使你修改了它,实际的几何数据也不会被更新。

请记住,您使用的是BufferGeometry,它通过顶点数据表示几何图形。没有像遗留Geometry类那样的面子抽象。因此,如果您想修改每个脸的颜色,您必须确保在您的几何图形中没有人脸定义共享顶点。换句话说,只有在非索引几何学中才能做到这一点。幸运的是,STLLoader只返回非索引的几何图形。

实际顶点颜色数据存储在颜色缓冲区属性中。您可以通过const colorAttribute = geometry.getAttribute( 'color' );访问它。您必须更新此缓冲区属性中的颜色值,以实现您的预期功能。这方面的模式是:

代码语言:javascript
复制
const face = intersects[ 0 ].face;
const color = new THREE.Color( Math.random() * 0xffffff ); // random color

const colorAttribute = geometry.getAttribute( 'color' );

colorAttribute.setXYZ( face.a, color.r, color.g, color.b );
colorAttribute.setXYZ( face.b, color.r, color.g, color.b );
colorAttribute.setXYZ( face.c, color.r, color.g, color.b );

colorAttribute.needsUpdate = true;

STLLoader不一定会产生颜色缓冲区属性,因此如果缺少颜色缓冲区属性,您可能必须创建一个属性。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62914985

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档