如何在Aframe中使用Three.InstancedMesh

How to use Three.InstancedMesh in Aframe

我正在尝试根据此处的示例使用 ThreeJs InstancedMesh 在 Aframe 中实现实例化:https://github.com/mrdoob/three.js/blob/master/examples/webgl_instancing_dynamic.html

此处相关代码部分:

    init: function() {
        const {count, radius, scale, colors, positions} = this.data;  
        this.start = true;
        this.dummy = new THREE.Object3D();
        this.count = count;
        this.startObject = new THREE.Object3D();
        this.endObject = new THREE.Object3D();
        this.instanceColors = new Float32Array(count * 3);
        this.instanceColorsBase = new Float32Array(this.instanceColors.length);

        this.vertices = [];
        this.rotations = [];
        for ( var i = 0; i < this.data.count; i ++ ) {
            var x = this.data.positions[i][0] * this.data.scale;
            var y = this.data.positions[i][1] * this.data.scale;
            var z = this.data.positions[i][2] * this.data.scale;

            var xEnd = x + this.data.endPositions[i][0] * this.data.scale;
            var yEnd = y + this.data.endPositions[i][1] * this.data.scale;
            var zEnd = z + this.data.endPositions[i][2] * this.data.scale;

            this.vertices.push( x, y, z );
            const rotation = this.getDirection({'x':x,'y':y,'z':z}, 
                                          {'x':xEnd,'y':yEnd,'z':zEnd});
            this.rotations.push(rotation.x, rotation.y, rotation.z);
        }

        let mesh;
        let geometry;
        let material;
        const loader = new THREE.GLTFLoader();
        const el = this.el;
        loader.load("/assets/arrow/arrow.gltf", function ( model ) {
            geometry = model.scene.children[0].children[0].geometry;
           
            geometry.computeVertexNormals();
            geometry.scale( 0.03, 0.03, 0.03 );

            material = new THREE.MeshNormalMaterial();

            mesh = new THREE.InstancedMesh( geometry, material, count );
            mesh.instanceMatrix.setUsage( THREE.DynamicDrawUsage );
            el.object3D.add(mesh);
        } );
        this.el.setAttribute("id", "cells");
    },
    setMatrix: function (start) {
        if (this.mesh) {
            for ( let i = 0; i < this.count; i ++ ) {
                var x = this.data.positions[i][0] * this.data.scale;
                var y = this.data.positions[i][1] * this.data.scale;
                var z = this.data.positions[i][2] * this.data.scale;

                var xEnd = x + this.data.endPositions[i][0] * this.data.scale;
                var yEnd = y + this.data.endPositions[i][1] * this.data.scale;
                var zEnd = z + this.data.endPositions[i][2] * this.data.scale;
                if (start) {
                    this.dummy.position.set(xEnd, yEnd, zEnd);
                } else {
                    this.dummy.position.set(x, y, z);
                }
                this.dummy.rotation.x = this.rotations[i][0];
                this.dummy.rotation.y = this.rotations[i][1];
                this.dummy.rotation.z = this.rotations[i][2];
                this.dummy.updateMatrix();
                this.mesh.setMatrixAt( i, this.dummy.matrix );
            }
            this.mesh.instanceMatrix.needsUpdate = true;
        }
    }
    tick: function() {
        this.setMatrix(this.start);
        this.start = !this.start;
    },

我看不到任何错误或相关消息,但 none 个实例对象正在呈现。不幸的是,我真的没有很好的方法来 post 举个例子。有人知道我做错了什么吗?提前致谢!

注意:似乎正在渲染对象,因为添加此组件时绘制的三角形数量急剧增加。但是,它们在任何地方都不可见,我也无法在 aframe 检查器中找到它们

这是一个非常具体的问题,主题非常广泛,所以:

一般来说,使用THREE.InstancedMeshes很简单,你做对了:

// create an instanced mesh
let iMesh = new THREE.InstancedMesh(geometry, material, count)
element.object3D.add(iMesh)

// manipulate the instances
let mtx = new Matrix4()
// set the position, rotation, scale of the matrix
// ...
// update the instance
iMesh.setMatrixAt(index, mtx);
iMesh.instanceMatrix.needsUpdate = true;

实例化 gltf 模型示例 here


您的代码做了很多事情,如果能将其精简到最低限度会更容易。但我认为只有一个主要问题 - this.model 未在任何地方设置,因此 setMatrix 函数什么都不做。除此之外,您可能需要禁用视锥体剔除 (mesh.frustumCulling = false),或设置边界球体 - 否则当基础对象不在视线范围内时对象

设置后,your code seems to be working