当前位置: 首页 > 知识库问答 >
问题:

三js-导入时可以检测几何体“孤岛”吗?

华俊弼
2023-03-14

我正在将.3DS模型导入Blender 2.72b,然后将它们与三个模型一起导出。js导入/导出插件。这些模型有多个几何“岛”(独立的连接面和顶点组),每个都有自己的材质。我希望能够将每个材质与其对应的孤岛配对,而不必创建单独的三个。几何体对象。经过一番挖掘,我发现了这个问题,建议使用一个3。MeshFaceMaterial可为一个对象实现多个材质。唯一的问题是,该示例中的几何体是一个简单的立方体,而我的模型有数百个面分布在2-5个岛上。

有三个。js是否具有识别网格中几何体“孤岛”的功能?

共有3个答案

连晟
2023-03-14

我认为这是正确的方法:

function unmergeGeometryArray(geometry) {
        // Asumptions:
        // geometry is BufferGeometry 
        // The geometry has no index duplicates (2 equal positions with different index) neither empty triangles, the geometry has been processed with mergeVertices function
        // normal attribute is discarded, can be recomputed after, only color and position attributes are taken into account
        
        const material = new THREE.MeshBasicMaterial({
            side: THREE.DoubleSide,
            vertexColors: THREE.VertexColors
        });
        
        const indexArray = geometry.index.array;
        const positionArray = geometry.attributes.position.array;
        const positionCount = geometry.attributes.position.count;
        const totalTriangles = indexArray.length / 3;
        
        let triangleVisitedArray = new Uint8Array(totalTriangles);
        let indexVisitedArray = new Uint8Array(positionCount);
        let indexToTriangleIndexMap = [];
        
        let missingVertices = positionCount;
        let missingTriangles = totalTriangles;
        
        // Functions:
        function computeTrianglesRecursive(index, out){ 
            //console.log("- start of computeTriangles with index:", index);    
            if (indexVisitedArray[index] === 1 || missingVertices === 0 || missingTriangles === 0) {
                return;
            }       
            indexVisitedArray[index] = 1;
            missingVertices -= 1;       
            let triangleIndexArray = indexToTriangleIndexMap[index];        
            for(let i=0; i<indexToTriangleIndexMap[index].length; i++) {
                let triangleIndex = indexToTriangleIndexMap[index][i];
                if (triangleVisitedArray[triangleIndex] === 0) {
                    triangleVisitedArray[triangleIndex] = 1
                    missingTriangles -= 1;
                    //console.log("-- index: ", index, "; i: ", i, "; triangleIndex: ", triangleIndex);
                    out.push(triangleIndex);
                    childIndex1 = indexArray[triangleIndex*3+1];
                    computeTriangles(childIndex1, out);
                    childIndex2 = indexArray[triangleIndex*3+2];
                    computeTriangles(childIndex2, out);
                }
            }
        }
        
        function computeTriangles(indexTocheck){
            let out = [];
            let startIndex = indexTocheck;  
            let indexToCheckArray = [indexTocheck];
            let i = 0;
            
            while (i<indexToCheckArray.length) {
                let index = indexToCheckArray[i];
                if (indexVisitedArray[index] == 0) {
                    indexVisitedArray[index] = 1;
                    missingVertices -= 1;   
                    let triangleIndexArray = indexToTriangleIndexMap[index];
                    for(let j=0; j<indexToTriangleIndexMap[index].length; j++) {
                        let triangleIndex = indexToTriangleIndexMap[index][j];
                        if (triangleVisitedArray[triangleIndex] === 0) {
                            triangleVisitedArray[triangleIndex] = 1;
                            missingTriangles -= 1;
                            out.push(triangleIndex);
                            let rootIndex = indexArray[triangleIndex*3];
                            let child1Index = indexArray[triangleIndex*3+1];
                            let child2Index = indexArray[triangleIndex*3+2];
                            
                            if (indexToCheckArray.indexOf(rootIndex) === -1) {
                                indexToCheckArray.push(rootIndex);
                            }
                            
                            if (indexToCheckArray.indexOf(child1Index) === -1) {
                                indexToCheckArray.push(child1Index);
                            }
                            
                            if (indexToCheckArray.indexOf(child2Index) === -1) {
                                indexToCheckArray.push(child2Index);
                            }
                        }
                    }
                }
                i +=1;
            }
            return out;
        }
        
        // In the first loop we reorder indices asc order + generate map
        for (triangleIndex=0; triangleIndex<totalTriangles; triangleIndex++) {
            const geoIndex1 = indexArray[triangleIndex*3];
            const geoIndex2 = indexArray[triangleIndex*3+1];
            const geoIndex3 = indexArray[triangleIndex*3+2];
            const triangleIndexVertexArray = [ geoIndex1, geoIndex2, geoIndex3 ].sort(function(a, b) { 
                return a - b; 
            });
            if (indexToTriangleIndexMap[geoIndex1] === undefined) {
                indexToTriangleIndexMap[geoIndex1] = [triangleIndex];
            } else {
                indexToTriangleIndexMap[geoIndex1].push(triangleIndex);
            }
            if (indexToTriangleIndexMap[geoIndex2] === undefined) {
                indexToTriangleIndexMap[geoIndex2] = [triangleIndex];
            } else {
                indexToTriangleIndexMap[geoIndex2].push(triangleIndex);
            }
            if (indexToTriangleIndexMap[geoIndex3] === undefined) {
                indexToTriangleIndexMap[geoIndex3] = [triangleIndex];
            } else {
                indexToTriangleIndexMap[geoIndex3].push(triangleIndex);
            }
            //indexArray[triangleIndex*3] = triangleIndexVertexArray[0];
            //indexArray[triangleIndex*3+1] = triangleIndexVertexArray[1];
            //indexArray[triangleIndex*3+2] = triangleIndexVertexArray[2];
        }
        
        let geometryTriangleArray = [];
        let index = 0;
        while (index<indexToTriangleIndexMap.length && missingVertices>0 && missingTriangles>0){
            let out = [];
            if (indexVisitedArray[index] === 0) {
                out = computeTriangles(index);
            }
            if (out.length > 0) {
                geometryTriangleArray.push(out);
            }
            index += 1;
        }
        
        let geometryArray = [];
        for (let i=0; i<geometryTriangleArray.length; i++) {
            let out = {
                positionArray: [],
                colorArray: [],
                indexArray: [],
                indexMap: [],
                currentIndex: 0
            }
            let triangleArray = geometryTriangleArray[i];
            
            for (let j=0; j<triangleArray.length; j++) {
                let triangleIndex = triangleArray[j];
                let rootIndex = indexArray[triangleIndex*3];
                if (out.indexMap[rootIndex] === undefined) {
                    out.indexMap[rootIndex] = out.currentIndex;
                    // add vertex position and color
                    out.positionArray.push(
                        geometry.attributes.position.array[rootIndex*3],
                        geometry.attributes.position.array[rootIndex*3+1],
                        geometry.attributes.position.array[rootIndex*3+2]
                    );
                    if (geometry.attributes.color != undefined) {
                        out.colorArray.push(
                            geometry.attributes.color.array[rootIndex*3],
                            geometry.attributes.color.array[rootIndex*3+1],
                            geometry.attributes.color.array[rootIndex*3+2]
                        );
                    }
                    out.currentIndex += 1;
                }
                
                let child1Index = indexArray[triangleIndex*3+1];
                if (out.indexMap[child1Index] === undefined) {
                    out.indexMap[child1Index] = out.currentIndex;
                    // add vertex position and color
                    out.positionArray.push(
                        geometry.attributes.position.array[child1Index*3],
                        geometry.attributes.position.array[child1Index*3+1],
                        geometry.attributes.position.array[child1Index*3+2]
                    );
                    if (geometry.attributes.color != undefined) {
                        out.colorArray.push(
                            geometry.attributes.color.array[child1Index*3],
                            geometry.attributes.color.array[child1Index*3+1],
                            geometry.attributes.color.array[child1Index*3+2]
                        );
                    }
                    
                    out.currentIndex += 1;
                }
                
                let child2Index = indexArray[triangleIndex*3+2];
                if (out.indexMap[child2Index] === undefined) {
                    out.indexMap[child2Index] = out.currentIndex;
                    // add vertex position and color
                    out.positionArray.push(
                        geometry.attributes.position.array[child2Index*3],
                        geometry.attributes.position.array[child2Index*3+1],
                        geometry.attributes.position.array[child2Index*3+2]
                    );
                    if (geometry.attributes.color != undefined) {
                        out.colorArray.push(
                            geometry.attributes.color.array[child2Index*3],
                            geometry.attributes.color.array[child2Index*3+1],
                            geometry.attributes.color.array[child2Index*3+2]
                        );
                    }
                    
                    out.currentIndex += 1;
                }
                
                // Add indices:
                out.indexArray.push(out.indexMap[rootIndex], out.indexMap[child1Index], out.indexMap[child2Index]);
            }
            
            const geoPositions = new Float32Array(out.positionArray);
            const geoColors = new Float32Array(out.colorArray);
            const geoIndices = new Uint32Array(out.indexArray);
            const geo = new THREE.BufferGeometry();
            geo.name = "G_" + i;
            geo.index = new THREE.BufferAttribute(geoIndices, 1, false);
            geo.attributes.position = new THREE.BufferAttribute(geoPositions, 3, false);
            geo.attributes.color = new THREE.BufferAttribute(geoColors, 3, true);
            geo.computeBoundingSphere();
            geo.computeBoundingBox();
            geometryArray.push(geo);
        }
        return geometryArray;
    }
庄飞
2023-03-14

我尝试使用函数,但仍然不精确,它生成的几何图形比未连接的几何图形多:

如果有人能看一下,那就太棒了。

function groupGeometryIntoNonConnectedGeometries(geometry) {
        const material = new THREE.MeshBasicMaterial({
            side: THREE.DoubleSide,
            vertexColors: THREE.VertexColors
        });
        let geometryArray = [];
        const indexArray = geometry.index.array;
        const positionArray = geometry.attributes.position.array;
        const positionCount = geometry.attributes.position.count;
        const color = new THREE.Vector3(geometry.attributes.color.array[0], geometry.attributes.color.array[1], geometry.attributes.color.array[2]);
        const totalTriangles = indexArray.length / 3;
        let geometryCount = 0;
        let indexValueAlreadyVisited = new Uint8Array(indexArray.length);   
        let structure = [];
            /*
             * indexValue: {
             *  child: [ [indexval0, indexval1], [] ],
             *  parent: null
             * }
             */
        // Initialize Structure:
        for (var vextexIdx=0; vextexIdx<positionCount; vextexIdx++) {
            structure[vextexIdx] = {
                child: [],
                parent: null
            }
        }   
        
        for (idx=0; idx<totalTriangles; idx++) {
            const geoIndex1 = indexArray[idx*3];
            const geoIndex2 = indexArray[idx*3+1];
            const geoIndex3 = indexArray[idx*3+2];
            const triangleIndexVertexArray = [ geoIndex1, geoIndex2, geoIndex3 ].sort(function(a, b) { 
                return a - b; 
            });
            structure[ triangleIndexVertexArray[0] ].child.push(triangleIndexVertexArray[1], triangleIndexVertexArray[2]);
            structure[ triangleIndexVertexArray[1] ].parent = triangleIndexVertexArray[0];
            structure[ triangleIndexVertexArray[2] ].parent = triangleIndexVertexArray[0];              
        }
        let count = 0;
        let currentCount = 0;
        let geometryStructureArray = [];
        
        for (let strIdx=0; strIdx<structure.length; strIdx++) {
            if (structure[strIdx].parent == null) {
                currentCount = count;
                geometryStructureArray[currentCount] = {
                    name: "G_" + currentCount,
                    indexMap: {},
                    currentIndex: 0,
                    indexArray: [],
                    positionArray: [],
                    colorArray: []
                };
                count += 1;
            }
            if (structure[strIdx].child.length > 0) {
                const childLen = structure[strIdx].child.length / 2;
                for (let childIdx=0; childIdx<childLen; childIdx++) {
                    const vertexIndex0 = strIdx;
                    const vertexIndex1 = structure[strIdx].child[childIdx*2];
                    const vertexIndex2 = structure[strIdx].child[childIdx*2+1];
                    const v0 = new THREE.Vector3( positionArray[strIdx*3], positionArray[strIdx*3+1], positionArray[strIdx*3+2] );
                    const v1 = new THREE.Vector3( positionArray[vertexIndex1*3], positionArray[vertexIndex1*3+1], positionArray[vertexIndex1*3+2] );
                    const v2 = new THREE.Vector3( positionArray[vertexIndex2*3], positionArray[vertexIndex2*3+1], positionArray[vertexIndex2*3+2] );
                    
                    // check vertex0
                    if (geometryStructureArray[currentCount].indexMap[vertexIndex0] == undefined) {
                        geometryStructureArray[currentCount].indexMap[vertexIndex0] = geometryStructureArray[currentCount].currentIndex;
                        geometryStructureArray[currentCount].indexArray.push(geometryStructureArray[currentCount].currentIndex);
                        geometryStructureArray[currentCount].positionArray.push(v0.x, v0.y, v0.z);
                        geometryStructureArray[currentCount].colorArray.push(color.x, color.y, color.z);
                        geometryStructureArray[currentCount].currentIndex += 1;
                    } else {
                        geometryStructureArray[currentCount].indexArray.push(geometryStructureArray[currentCount].indexMap[vertexIndex0]);
                    }
                    
                    // check vertex1
                    if (geometryStructureArray[currentCount].indexMap[vertexIndex1] == undefined) {
                        geometryStructureArray[currentCount].indexMap[vertexIndex1] = geometryStructureArray[currentCount].currentIndex;
                        geometryStructureArray[currentCount].indexArray.push(geometryStructureArray[currentCount].currentIndex);
                        geometryStructureArray[currentCount].positionArray.push(v1.x, v1.y, v1.z);
                        geometryStructureArray[currentCount].colorArray.push(color.x, color.y, color.z);
                        geometryStructureArray[currentCount].currentIndex += 1;
                    } else {
                        geometryStructureArray[currentCount].indexArray.push(geometryStructureArray[currentCount].indexMap[vertexIndex1]);
                    }
                    
                    // check vertex1
                    if (geometryStructureArray[currentCount].indexMap[vertexIndex2] == undefined) {
                        geometryStructureArray[currentCount].indexMap[vertexIndex2] = geometryStructureArray[currentCount].currentIndex;
                        geometryStructureArray[currentCount].indexArray.push(geometryStructureArray[currentCount].currentIndex);
                        geometryStructureArray[currentCount].positionArray.push(v2.x, v2.y, v2.z);
                        geometryStructureArray[currentCount].colorArray.push(color.x, color.y, color.z);
                        geometryStructureArray[currentCount].currentIndex += 1;
                    } else {
                        geometryStructureArray[currentCount].indexArray.push(geometryStructureArray[currentCount].indexMap[vertexIndex2]);
                    }
                    
                }
            }   
        }
        
        // Convert to geometryArray:
        const geometryStructureArrayLen = geometryStructureArray.length;
        const object3d = new THREE.Object3D();
        
        for (let geoIdx=0; geoIdx<geometryStructureArrayLen; geoIdx++) {
            const geo = new THREE.BufferGeometry();
            geo.name = "G_" + geoIdx;
            const geoPositions = new Float32Array(geometryStructureArray[geoIdx].positionArray);
            const geoColors = new Float32Array(geometryStructureArray[geoIdx].colorArray);
            const geoIndices = new Uint32Array(geometryStructureArray[geoIdx].indexArray);
            //console.log(geoIdx, "geoPositions: ", geoPositions);
            //console.log(geoIdx, "geoColors: ", geoColors);
            //console.log(geoIdx, "geoIndices: ", geoIndices);
            geo.index = new THREE.BufferAttribute(geoIndices, 1, false);
            
            geo.attributes.position = new THREE.BufferAttribute(geoPositions, 3, false);
            geo.attributes.color = new THREE.BufferAttribute(geoColors, 3, true);
            geo.computeBoundingSphere();
            geo.computeBoundingBox();
            
            const mesh = new THREE.Mesh(geo, material);
            mesh.name = "M_" + geoIdx;
            object3d.add(mesh);
        }
        //return [structure, geometryStructureArray, object3d, count];
        return object3d;
    }

顺致敬意,

谷翰飞
2023-03-14

不,three.js没有识别网格中几何“岛屿”的功能

使用MeshFaceMaterial时,WebGLRenderer会将几何体分解为块,每种材质一块。这是因为WebGL支持每个几何体一个着色器。

我不会合并所有几何体,然后使用MeshFaceMaterial,只会让渲染器将单个几何体分开。

如果愿意,可以合并共享单个材质的几何图形。

三js r.69

 类似资料:
  • 问题内容: (PostgreSQL 8.4) 我对SQL的空白和孤岛做了很好的介绍,但是我仍然有一个问题。许多孤岛检测CTE基于时间戳的运行顺序和一些标志,这些标志在更改时会破坏序列。但是,如果“中断”条件稍微复杂些怎么办? 在这种情况下,表示设备,并且为或。我想选择的记录,,,并具有以下逻辑。 10转为OFF-正确结束序列,忽略行 11接通-确定,新序列,包括在SELECT中 11开启-重复,忽

  • 我想与您分享一个我必须在ANTLR4中实现的岛屿解决方案。 > 语言的结构。我必须为其编写语法的语言是从PL/SQL派生出来的,带有一些附加的构造。我在这里不做更多的详细说明,因为这与主题无关。 该语言定义了一个特殊的命令,其结构如下: 。 我的解决办法是: 任何反馈都是非常欢迎的!问候,沃尔夫冈·哈默

  • 问题内容: 谁能解释垃圾收集 隔离岛 的概念吗? 问题答案: 对象A引用对象B。对象B引用对象A。任何其他对象都没有引用对象A和对象B。那是一个孤立的孤岛。 基本上,隔离孤岛是一组相互引用的对象,但是应用程序中的任何活动对象都不会引用它们。严格来说,即使是单个未引用的对象也都是孤立的孤岛。 编辑评论:

  • 经过大量的努力,我已经设法破解了一个perl脚本,它使用PDF::Create为标签打印机创建pdf标签。该脚本现在可以完美地满足我的需求,但字体的选择有限。我已经用gnome-font-查看器安装了一个真正的字体(我正在使用Debian Stretch)。 根据PDF::Create的文档:一个名为“BaseFont”(Courier,Courier-Bold,Courier-BoldObliq

  • 问题内容: jQuery是否有办法检测到同时按下了多个键? 是否有其他方法可以同时检测两个键? 问题答案: 为了检测按住多个键,请使用和事件。

  • 问题内容: 我正在基于此页面使用脚本标签长轮询技术实现Comet 。 一个问题(我认为没有解决方案)是“厄运的th子”-浏览器继续将文档永远显示为“正在加载”,并使工具栏上的“停止”按钮保持启用状态。这种品牌的意义,因为该文件 是 仍然加载,虽然它的效果并不理想,我想我可以住在一起。 但是,第二个问题是,如果用户实际单击“停止”,则浏览器将停止加载我的脚本标签,并且我必须依靠超时来重新启动Come

  • 问题内容: 我一直在使用Chromedriver测试Selenium,但我注意到,即使根本没有自动化功能,某些页面也可以检测到您正在使用Selenium。即使当我只是通过Selenium和Xephyr使用chrome手动浏览时,我也经常得到一个页面,指出检测到可疑活动。我已经检查了用户代理和浏览器指纹,它们与普通的chrome浏览器完全相同。 当我以普通的chrome浏览到这些站点时,一切正常,但

  • 几何体组件为实体提供基本形状。这个 primitive属性定义常规形状。在计算机图形学中,几何基元是不可分的基本形状。通常还定义一个材质组件来创建完整的网孔(Mesh)。 目录 基础属性 每种几何图形类型都具有以下属性: 属性 描述 默认值 buffer 将几何体转换为BufferGeometry以减少内存使用,但代价是更难操作。 true primitive 几何体的名称(例如,下面列出的几何体