Repository: mrdoob/three.js (JavaScript)
Date: 2021-09-22 08:38:30+00:00
Task type: Bug Fix

Issue:
Clone cylinderGeometry Creates Geometry
##### Description of the problem

When cloning a cylinderGeometry the clone is a geometry not a cylinderGeometry.
simple fiddle,check the console:  http://jsfiddle.net/momve8hk/

Tested in r72 and i get a cylinderGeometry.
...
##### Three.js version
- [x] r75



Issue discussion:
/ping @Mugen87 

 I ended up just making new cylinder geometries from the parameters object.  Seems to work pretty well.

I think this [line of code](https://github.com/mrdoob/three.js/blob/7e0a78beb9317e580d7fa4da9b5b12be051c6feb/src/core/Geometry.js#L1151) causes the behavior. The implementation of the `Geometry .clone`  will always return an object with type `Geometry`.

@mrdoob Um, what do you think about this approach? Maybe it's better to implement a `clone` method that preserves the type of the object.

So it used to behave like that already... https://github.com/mrdoob/three.js/commit/ae4c5198fdbaafb747e5c3739d4506c5b622c282

I see. So the current implementation avoids other problems in context of cloning geometries...

Given that cylinder geometries are so small is there any benefit in cloning a cylindergeometry vs creating a new cylinder geometry?  It seems like cloning is useful when the geometries are large and need to be loaded from external files.

Yeah, in this case there is no benefit. But the code behaved unexpectedly...


Solution patch:
diff --git a/src/core/BufferGeometry.js b/src/core/BufferGeometry.js
--- a/src/core/BufferGeometry.js
+++ b/src/core/BufferGeometry.js
@@ -1004,31 +1004,7 @@ class BufferGeometry extends EventDispatcher {
 
 	clone() {
 
-		/*
-		 // Handle primitives
-
-		 const parameters = this.parameters;
-
-		 if ( parameters !== undefined ) {
-
-		 const values = [];
-
-		 for ( const key in parameters ) {
-
-		 values.push( parameters[ key ] );
-
-		 }
-
-		 const geometry = Object.create( this.constructor.prototype );
-		 this.constructor.apply( geometry, values );
-		 return geometry;
-
-		 }
-
 		 return new this.constructor().copy( this );
-		 */
-
-		return new BufferGeometry().copy( this );
 
 	}
 
@@ -1133,6 +1109,10 @@ class BufferGeometry extends EventDispatcher {
 
 		this.userData = source.userData;
 
+		// geometry generator parameters
+
+		if ( source.parameters !== undefined ) this.parameters = Object.assign( {}, source.parameters );
+
 		return this;
 
 	}
diff --git a/src/geometries/PolyhedronGeometry.js b/src/geometries/PolyhedronGeometry.js
--- a/src/geometries/PolyhedronGeometry.js
+++ b/src/geometries/PolyhedronGeometry.js
@@ -5,7 +5,7 @@ import { Vector2 } from '../math/Vector2.js';
 
 class PolyhedronGeometry extends BufferGeometry {
 
-	constructor( vertices, indices, radius = 1, detail = 0 ) {
+	constructor( vertices = [], indices = [], radius = 1, detail = 0 ) {
 
 		super();
 


Test patch:
diff --git a/test/unit/utils/qunit-utils.js b/test/unit/utils/qunit-utils.js
--- a/test/unit/utils/qunit-utils.js
+++ b/test/unit/utils/qunit-utils.js
@@ -83,12 +83,10 @@ function checkGeometryClone( geom ) {
 	QUnit.assert.notEqual( copy.uuid, geom.uuid, "clone uuid should differ from original" );
 	QUnit.assert.notEqual( copy.id, geom.id, "clone id should differ from original" );
 
-	var excludedProperties = [ 'parameters', 'widthSegments', 'heightSegments', 'depthSegments' ];
-
-	var differingProp = getDifferingProp( geom, copy, excludedProperties );
+	var differingProp = getDifferingProp( geom, copy );
 	QUnit.assert.ok( differingProp === undefined, 'properties are equal' );
 
-	differingProp = getDifferingProp( copy, geom, excludedProperties );
+	differingProp = getDifferingProp( copy, geom );
 	QUnit.assert.ok( differingProp === undefined, 'properties are equal' );
 
 	// json round trip with clone
@@ -96,9 +94,7 @@ function checkGeometryClone( geom ) {
 
 }
 
-function getDifferingProp( geometryA, geometryB, excludedProperties ) {
-
-	excludedProperties = excludedProperties || [];
+function getDifferingProp( geometryA, geometryB ) {
 
 	var geometryKeys = Object.keys( geometryA );
 	var cloneKeys = Object.keys( geometryB );
@@ -109,8 +105,6 @@ function getDifferingProp( geometryA, geometryB, excludedProperties ) {
 
 		var key = geometryKeys[ i ];
 
-		if ( excludedProperties.indexOf( key ) >= 0 ) continue;
-
 		if ( cloneKeys.indexOf( key ) < 0 ) {
 
 			differingProp = key;
@@ -193,31 +187,6 @@ function checkGeometryJsonRoundtrip( geom ) {
 
 }
 
-// Look for undefined and NaN values in numerical fieds.
-function checkFinite( geom ) {
-
-	var allVerticesAreFinite = true;
-
-	var vertices = geom.vertices || [];
-
-	for ( var i = 0, l = vertices.length; i < l; i ++ ) {
-
-		var v = geom.vertices[ i ];
-
-		if ( ! ( isFinite( v.x ) || isFinite( v.y ) || isFinite( v.z ) ) ) {
-
-			allVerticesAreFinite = false;
-			break;
-
-		}
-
-	}
-
-	// TODO Buffers, normal, etc.
-
-	QUnit.assert.ok( allVerticesAreFinite, "contains only finite coordinates" );
-
-}
 
 // Run common geometry tests.
 function runStdGeometryTests( assert, geometries ) {
@@ -226,8 +195,6 @@ function runStdGeometryTests( assert, geometries ) {
 
 		var geom = geometries[ i ];
 
-		checkFinite( geom );
-
 		// Clone
 		checkGeometryClone( geom );