首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Three.js -当导入时,我可以检测几何学‘岛’吗?

Three.js -当导入时,我可以检测几何学‘岛’吗?
EN

Stack Overflow用户
提问于 2014-11-10 17:49:10
回答 3查看 405关注 0票数 2

我将.3DS模型导入Blder2.72b,然后使用Three.js导入/导出加载项导出它们。这些模型有多个几何‘岛’(独立的连通面和顶点组),每一个都有自己的材料。我希望能够将每种材料与其对应的岛配对,而不必创建单独的THREE.Geometry对象。经过一番挖掘,我发现了this question,它建议使用THREE.MeshFaceMaterial来实现一个对象的多个材料。唯一的问题是,这个例子中的几何是一个简单的立方体,而我的模型有数百个面分布在2-5个岛屿上。

Three.js是否有识别网格中几何‘岛’的功能?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-11-10 21:01:23

不是的。three.js没有识别网格中几何‘岛’的功能。

在使用MeshFaceMaterial时,WebGLRenderer还是将几何分解成块--每种材料一个块。它这样做是因为WebGL支持每个几何图形一个着色器。

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

如果你愿意的话,你可以把共用一种材料的几何图形合并起来。

three.js r.69号

票数 2
EN

Stack Overflow用户

发布于 2021-06-01 09:59:00

我尝试了一个函数,但仍然不准确,它产生的几何比不连接的几何图形更多:

如果有人能看一看,它会被磨碎的。

代码语言:javascript
运行
复制
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;
    }

诚挚的问候

票数 0
EN

Stack Overflow用户

发布于 2021-09-23 08:26:55

这是我认为正确的方法:

代码语言:javascript
运行
复制
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;
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26849791

复制
相关文章

相似问题

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