Three.js - 我可以在导入时检测几何'岛'吗?

时间:2014-11-10 17:49:11

标签: three.js

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

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

2 个答案:

答案 0 :(得分:2)

没有。 three.js没有用于识别网格中几何体“孤岛”的功能。

使用MeshFaceMaterial时,WebGLRenderer无论如何都会将几何体分成几个块 - 每个材质都有一个块。这样做是因为WebGL支持每个几何体一个着色器。

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

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

three.js r.69

答案 1 :(得分:0)

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

如果有人可以看看它,那就太好了。

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;
    }

最好的问候