Description
BufferGeometry.computeVertexNormals checks if the normal attribute exists and initializes it with the size of the position attribute. If it already exists, it is reused and reset.
|
let normalAttribute = this.getAttribute( 'normal' ); |
|
|
|
if ( normalAttribute === undefined ) { |
|
|
|
normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 ); |
|
this.setAttribute( 'normal', normalAttribute ); |
|
|
|
} else { |
|
|
|
// reset existing normals to zero |
|
|
|
for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) { |
|
|
|
normalAttribute.setXYZ( i, 0, 0, 0 ); |
|
|
|
} |
|
|
|
} |
If you call computeVertexNormals, then change the size of the position attribute (e.g. to reflect changes to the model), and call computeVertexNormals again, the attribute retains its original size, either missing entries (if the position attribute has more entries), or having too many values (if the position attribute is now smaller).
I would expect that after calling computeVertexNormals, the normal attribute has the same size as the position attribute.
Workaround
Check if the position attribute has a different count than the normal attribute and delete the normal attribute before calling computeVertexNormals
Other affected methods
I assume BufferGeometry.computeTangents is also affected.
Reproduction steps
- Create a Buffer Geometry and set the positions attribute
- Call
computeVertexNormals
- Overwrite the positions attribute with a new BufferAttribute of a different size
- Call
computeVertexNormals again
Expected:
The normal attribute has the same size as the new position attribute.
Observed:
The normal attribute has the size of the old position attribute.
Code
import * as THREE from 'three';
const geometry = new THREE.BufferGeometry();
// create a simple triangle (3 vertices)
geometry.setAttribute( 'position', new THREE.BufferAttribute( new Float32Array( [
-1.0, -1.0, 1.0, // v0
1.0, -1.0, 1.0, // v1
1.0, 1.0, 1.0, // v2
] ), 3 ) );
// Creates the `normal` attribute
geometry.computeVertexNormals();
let normalAttr = geometry.getAttribute( 'normal' );
console.log(normalAttr.count); // correctly displays count of 3
// overwrite the position attribute with new values (a square, 6 vertices)
geometry.setAttribute( 'position', new THREE.BufferAttribute( new Float32Array( [
-1.0, -1.0, 1.0, // v0
1.0, -1.0, 1.0, // v1
1.0, 1.0, 1.0, // v2
1.0, 1.0, 1.0, // v3
-1.0, 1.0, 1.0, // v4
-1.0, -1.0, 1.0 // v5
] ), 3 ) );
// Reuses the `normal` attribute created in the first call
geometry.computeVertexNormals();
// should be the same, but just to be safe, retrieve the current normal attribute again
normalAttr = geometry.getAttribute( 'normal' );
console.log(normalAttr.count); // !!! still 3 - but should be 6 !!!
Live example
https://stackblitz.com/edit/typescript-1ofnthap?file=index.ts
Screenshots
No response
Version
0.184.0
Device
Desktop
Browser
Chrome
OS
Windows
Description
BufferGeometry.computeVertexNormalschecks if the normal attribute exists and initializes it with the size of the position attribute. If it already exists, it is reused and reset.three.js/src/core/BufferGeometry.js
Lines 994 to 1011 in d3b629c
If you call
computeVertexNormals, then change the size of the position attribute (e.g. to reflect changes to the model), and callcomputeVertexNormalsagain, the attribute retains its original size, either missing entries (if the position attribute has more entries), or having too many values (if the position attribute is now smaller).I would expect that after calling
computeVertexNormals, thenormalattribute has the same size as thepositionattribute.Workaround
Check if the position attribute has a different count than the normal attribute and delete the normal attribute before calling
computeVertexNormalsOther affected methods
I assume
BufferGeometry.computeTangentsis also affected.Reproduction steps
computeVertexNormalscomputeVertexNormalsagainExpected:
The
normalattribute has the same size as the newpositionattribute.Observed:
The
normalattribute has the size of the oldpositionattribute.Code
Live example
https://stackblitz.com/edit/typescript-1ofnthap?file=index.ts
Screenshots
No response
Version
0.184.0
Device
Desktop
Browser
Chrome
OS
Windows