three.js 使用geometry.merge() 优化

发布于 2022-09-06 14:56:50 字数 2104 浏览 14 评论 0

第一段是原本画网格的代码 第二段我使用geometry.merge()方法的代码 不知道哪里写错了 不报错 也出不来 请前辈指教

function initObject() {
                //1.在x轴上定义两个点p1 p2
                var geometry = new THREE.Geometry();
                geometry.vertices.push(new THREE.Vector3(-500, 0, 0));
                geometry.vertices.push(new THREE.Vector3(500, 0, 0));
                //2.主要在于这里的算法,从右、下角开始画
                for (var i = 0; i <= 20; i++) {
                    //画横线
                    var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0x000000, opacity: 0.2 }));
                    line.position.z = (i * 50) - 500;
                    scene.add(line);


                    var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0x000000, opacity: 0.2 }));
                    line.position.x = (i * 50) - 500;
                    line.rotation.y = 90 * Math.PI / 180;   //转90度
                    scene.add(line);

                }
            }
function initObject() {  
                var geometry = new THREE.Geometry();  
                var allLine=new THREE.Geometry();
                geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) );  
                geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) ); 
                for ( var i = 0; i <= 20; i ++ ) { 
                    var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
                    line.position.z = ( i * 50 ) - 500;  
                    allLine.merge(line.geometry,line.matrix) 
                    var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
                    line.position.x = ( i * 50 ) - 500;  
                    line.rotation.y = 90 * Math.PI / 180;  
                    allLine.merge(line.geometry,line.matrix)
                }  
                allLineMesh=new THREE.Mesh(allLine,new THREE.MeshBasicMaterial({color:0x000000,side:THREE.DoubleSide}))
                scene.add( allLineMesh );  
            }  

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心在旅行 2022-09-13 14:56:50

(1) 要使用正确的对象类型

这里不能用Mesh,因为这里geometry的点数不满足Mesh的规范,图形是渲染不出来的,Mesh是由小三角面构成,顶点数必须是3的倍数。所以,这里应该用THREE.Line

将:

allLineMesh=new THREE.Mesh(allLine,new THREE.MeshBasicMaterial({color:0x000000,side:THREE.DoubleSide}))

改成:

allLineMesh=new THREE.Line(allLine,new THREE.MeshBasicMaterial({color:0x000000,side:THREE.DoubleSide}))

你会发现有图像出来了,但只有一条直线,下面讲这个问题。

(2)对对象使用变换之后,要手动更新对象变换矩阵

在three.js中,考虑到性能,框架在做变换的时候不会自动更新变换矩阵(其实还有很多东西都不会自动更新,可以参考文档里面定义的xxxNeedsUpdate,computeXXX,updateXXX之类的属性),所以,如果你对对象做了变换之后要用到对象的矩阵,那么你首先需要更新对象的变换矩阵,可以使用Object3D.updateMatrix()方法。

所以,像下面这种写法是不能看到geometry有任何改变的:

var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
line.position.z = ( i * 50 ) - 500; // 这里做了变换,但是没更新变换矩阵
allLine.merge(line.geometry,line.matrix)//使用原始的变换矩阵,于是对象的变换并没有应用到geometry上

可以改成:

var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
line.position.z = ( i * 50 ) - 500;
line.updateMatrix(); // 加了这句
allLine.merge(line.geometry,line.matrix)

现在可以看到图像了,但是你会发现图像很奇怪:

图片描述

这是什么鬼?为什么有那么多交叉线?

其实这和Line类型的绘制策略有关,Line是把vertices的点一个一个连起来的,比如vertices里有四个点[A,B,C,D],那么Line在画的时候,就是A-->B-->C--D,而你想的可能是A-->B,C-->D,简单验证一下,使用下面的函数:

            function initObject(){
                var material = new THREE.LineBasicMaterial({
                    color: 0x0000ff
                });
                var geometry = new THREE.Geometry();
                geometry.vertices.push(
                    new THREE.Vector3( -500, 0, 0 ),
                    new THREE.Vector3( 500, 0, 0 ),
                    new THREE.Vector3( 0, 0, -500 ),
                    new THREE.Vector3( 0, 0, 500 )
                );
                var line = new THREE.Line( geometry, material );
                scene.add( line );
            }

运行的结果如下图:

图片描述

确实是A-->B-->C--D这样连的

(3)利用吸附算法使中间连线吸附到边缘

对于Line的A-->B-->C--D这种画法我们是没办法改变,但是,在这个例子中,我们可以人为的将B-->C边吸附到边缘。比如有个上面四个点的坐标如下:

A:[1,0,0]
B:[-1,0,0]
C:[0,0,1]
D:[0,0,-1]

我们可以人为的插一个点E:
A:[1,0,0]
B:[-1,0,0]
E:[-1,0,1]
C:[0,0,1]
D:[0,0,-1]
使得B-->C由斜线变成了沿着边缘走的斜线:

图片描述

吸附算法如下:

 // 吸附算法
            function adsorb(geometry,compares){
                var vertices =  geometry.vertices;
                var cdt1 = compares[0];
                var cdt2 = compares[1];
                for (var i = 0 ; i < vertices.length-1; i++) {
                    var vertice = vertices[i];
                    var nextVertice = vertices[i+1];
                    if(Math.round(vertice[cdt1]) !== Math.round(nextVertice[cdt1])
                        && Math.round(vertice[cdt2]) !== Math.round(nextVertice[cdt2])){ // 差异超过两个维度
                        var vector = new THREE.Vector3();
                        vector[cdt1] = vertice[cdt1];
                        vector[cdt2] = nextVertice[cdt2];
                        vertices.splice(i+1, 0,vector); // 插入一个点
                        i++;
                    }
                }
                geometry.vertices = vertices;
            }

将吸附算法加入到创建过程中:

 function initObject() {
                var geometry = new THREE.Geometry();
                var allLine=new THREE.Geometry();
                geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) );
                geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) );
                for ( var i = 0; i <= 20; i ++ ) {
                    var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
                    line.position.z = ( i * 50 ) - 500;
                    line.updateMatrix();
                    allLine.merge(line.geometry,line.matrix)
                    var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
                    line.position.x = ( i * 50 ) - 500;
                    line.rotation.y = 90 * Math.PI / 180;
                    line.updateMatrix();
                    allLine.merge(line.geometry,line.matrix)
                }
                adsorb(allLine,["x","z"]);  // 添加这一行
                allLine.verticesNeedUpdate = true;
                allLineMesh=new THREE.Line(allLine,new THREE.MeshBasicMaterial({color:0x000000,side:THREE.DoubleSide}))
                scene.add( allLineMesh );
            }

这样看起来就正确了

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文