我使用collada loader加载模型。加载器返回一个Object3D,#34; dae",包含许多子网格物体。我想实例化父母" dae"对象多次没有重复网格。我可以使用dae.clone()吗?
换句话说:我希望制作浅色副本,这些副本都有自己的变换矩阵,但共享相同的几何体。什么是最有效的方法?
答案 0 :(得分:7)
默认情况下Object3D.clone()
会创建一个深层副本。我们来看看source
clone: function ( object, recursive ) {
if ( object === undefined ) object = new THREE.Object3D();
if ( recursive === undefined ) recursive = true;
object.name = this.name;
object.up.copy( this.up );
object.position.copy( this.position );
object.quaternion.copy( this.quaternion );
object.scale.copy( this.scale );
object.renderDepth = this.renderDepth;
object.rotationAutoUpdate = this.rotationAutoUpdate;
object.matrix.copy( this.matrix );
object.matrixWorld.copy( this.matrixWorld );
object.matrixAutoUpdate = this.matrixAutoUpdate;
object.matrixWorldNeedsUpdate = this.matrixWorldNeedsUpdate;
object.visible = this.visible;
object.castShadow = this.castShadow;
object.receiveShadow = this.receiveShadow;
object.frustumCulled = this.frustumCulled;
object.userData = JSON.parse( JSON.stringify( this.userData ) );
if ( recursive === true ) {
for ( var i = 0; i < this.children.length; i ++ ) {
var child = this.children[ i ];
object.add( child.clone() );
}
}
return object;
}
我们可以看到clone
函数接受两个可选参数:
Object3D
克隆到的对象。所以是的,可以制作关于Object3D.children
的浅拷贝,但这不是你想要的(基于你的评论)。
我相信您实际上可以使用Object3D.clone()
的默认行为来获取您所追求的内容。 Mesh.clone()
不会克隆Geometry
和Material
属性。
THREE.Mesh.prototype.clone = function ( object ) {
if ( object === undefined ) object = new THREE.Mesh( this.geometry, this.material );
THREE.Object3D.prototype.clone.call( this, object );
return object;
};
答案 1 :(得分:2)
这里有一些我用来深入克隆对象材料的函数。您可以根据需要对其进行修改
另请考虑以下信息:https://github.com/mrdoob/three.js/issues/5754
/** Gives the aptitude for an object3D to clone recursively with its material cloned (normal clone does not clone material)*/
THREE.Object3D.prototype.GdeepCloneMaterials = function() {
var object = this.clone( new THREE.Object3D(), false );
for ( var i = 0; i < this.children.length; i++ ) {
var child = this.children[ i ];
if ( child.GdeepCloneMaterials ) {
object.add( child.GdeepCloneMaterials() );
} else {
object.add( child.clone() );
}
}
return object;
};
THREE.Mesh.prototype.GdeepCloneMaterials = function( object, recursive ) {
if ( object === undefined ) {
object = new THREE.Mesh( this.geometry, this.material.clone() );
}
THREE.Object3D.prototype.GdeepCloneMaterials.call( this, object, recursive );
return object;
};
答案 2 :(得分:1)
three.js Object3D.clone()
将不创建几何和材质的深层副本。它将引用克隆对象的几何形状和材料。
您可以在 three.module.js 中看到它:
Mesh.prototype = ... {
...,
copy: function ( source ) {
Object3D.prototype.copy.call( this, source );
...
>>>>>>> this.material = source.material; <<<<<<<
>>>>>>> this.geometry = source.geometry; <<<<<<<
return this;
}
...
}
因此,关于OP的问题:是的,您可以只使用dae.clone()
。
对于包含几何图形和材质的深层克隆,只需更改上述{{1}}函数的两行即可:
Mesh.prototype.copy()
请记住,这是一个性能问题,因为three.js必须为每个object3D(包括所有网格)计算单独的几何。
答案 3 :(得分:0)
您可以参考copy
中的clone
和Object3D
方法来深深克隆网格物体材料。
首先,在三种方法中扩展了两个新方法:
THREE.Object3D.prototype.deepClone = function ( recursive ) {
return new this.constructor().deepCopy( this, recursive );
},
THREE.Object3D.prototype.deepCopy = function( source, recursive ) {
if ( recursive === undefined ) recursive = true;
this.name = source.name;
this.up.copy( source.up );
this.position.copy( source.position );
this.quaternion.copy( source.quaternion );
this.scale.copy( source.scale );
this.matrix.copy( source.matrix );
this.matrixWorld.copy( source.matrixWorld );
if(source.material){
//changed
this.material = source.material.clone()
}
if(source.geometry){
//changed
this.geometry = source.geometry.clone()
}
this.matrixAutoUpdate = source.matrixAutoUpdate;
this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
this.layers.mask = source.layers.mask;
this.visible = source.visible;
this.castShadow = source.castShadow;
this.receiveShadow = source.receiveShadow;
this.frustumCulled = source.frustumCulled;
this.renderOrder = source.renderOrder;
this.userData = JSON.parse( JSON.stringify( source.userData ) );
if ( recursive === true ) {
for ( var i = 0; i < source.children.length; i ++ ) {
var child = source.children[ i ];
this.add( child.deepClone() ); //changed
}
}
return this;
}
第二,当您想深度克隆名为originalObj
的Object3D或场景时,只需执行var newObj = originalObj.deepClone()