【问题标题】:Raycasting hard-faces of a mesh -- Three.js光线投射网格的硬面——Three.js
【发布时间】:2016-09-19 08:47:35
【问题描述】:

我在 three.js 中创建了一个盒子

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 100, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set(5, 5, 10);

var geo = new THREE.BoxGeometry(5,2,5);

var mat = new THREE.MeshBasicMaterial({color:0xff0ff0, wireframe:false, vertexColors: THREE.FaceColors});

var mesh = new THREE.Mesh( geo, mat);
scene.add(mesh);

var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.render(scene, camera);

之后我想将光线投射到鼠标悬停的立方体面上。因此我创建了这个函数

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();

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

    raycaster.setFromCamera( mouse, camera );   

    var intersects = raycaster.intersectObject( mesh);

    for ( var i = 0; i < intersects.length; i++ ) {
        intersects[ i ].face.color.setHex( 0xDDC2A3);
        mesh.geometry.colorsNeedUpdate = true;
    }

    renderer.render( scene, camera );
}

window.addEventListener( 'mousemove', onMouseMove, false );

几乎工作正常。我的意思是,它改变了半张脸的颜色。要知道,BoxGeometry() 创建的网格有 12 个Face3。我想要完整的脸硬脸Face4,由Face3+Face3塑造。知道我该如何做到这一点吗?

【问题讨论】:

  • 对于框,您可以循环 geometry.faces 并找到与您选择的面法线方向相同的所有面。
  • @uhura 对我来说太老套了
  • @uhura 的回答相当不错。没有寻找/选择面孔的神奇方法。您需要 A) 遍历面并确定需要选择的面,B) 在您需要的结构中预先计算面索引图,或者 C) 使用 6 个单独的网格(每个网格一个侧面。)顺便说一句,Face4 已从 ThreeJS 中删除。
  • Face4 被移除了?在看到您的评论之前,我一直在考虑将 Face4 添加到源代码中。我想知道为什么它被你删除了。
  • @jjkk 是的,来自 ThreeJS r59 -> r60 “Face4 已被移除。使用 2 Face3 来模拟它。” ...我不确定为什么,我认为通常 3D 图形库/硬件针对几何中的三角形面进行了优化。也许开发人员认为 Face4 的负担太大了,因为你可以用 Face4 做任何事情,你也可以用 Face3 做。 (不幸的是,您的具体示例除外。)

标签: javascript three.js


【解决方案1】:

仅适用于现成的非缓冲区几何图形,例如 .. BoxGeometry、SphereGeometry、CircleGeometry 等...

var intersects = raycaster.intersectObject( mesh);

for ( var i = 0; i < intersects.length; i++ ) {

    var faceIndex = intersects[i].faceIndex;

    if(faceIndex == 0 || (faceIndex % 2) == 0) {
        intersects[i].object.geometry.faces[faceIndex].color.setHex( 0xD1B3B3);
        intersects[i].object.geometry.faces[faceIndex + 1].color.setHex( 0xD1B3B3);
        intersects[i].object.geometry.colorsNeedUpdate = true;

    }else {
        intersects[i].object.geometry.faces[faceIndex].color.setHex( 0xD1B3B3);
        intersects[i].object.geometry.faces[faceIndex - 1].color.setHex( 0xD1B3B3);
        intersects[i].object.geometry.colorsNeedUpdate = true;
    }

}

renderer.render(scene, camera);

【讨论】:

    【解决方案2】:

    在您的具体示例中,假设您使用的是默认的盒子几何形状,并且我们知道每边有 2 个面,以特定的方向/顺序包装,您应该能够将这两个面中的每一个配对在一起像这样:

    var facesPerSide = 2;
    for ( var i = 0; i < intersects.length; i++ ) {
        var side = Math.floor(intersects[i].faceIndex/facesPerSide);
        for(var j=0;j<facesPerSide;j++) {
            mesh.geometry.faces[side*facesPerSide+j].color.setHex(0xDDC2A3);
        }
        mesh.geometry.colorsNeedUpdate = true;
    }
    

    编辑:显然,如果使用可变数量的线段来表示宽度/高度/深度,或者使用非柏拉图立体几何,它会变得更加复杂。

    【讨论】:

      猜你喜欢
      • 2020-03-07
      • 2016-06-19
      • 1970-01-01
      • 2017-12-06
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 2021-07-05
      • 2014-03-01
      相关资源
      最近更新 更多