From c6a80f9bb8411575a50990e35b9a169c8d409b41 Mon Sep 17 00:00:00 2001 From: Don McCurdy Date: Mon, 22 Nov 2021 14:09:35 -0800 Subject: [PATCH 1/3] BufferAttribute: Support (de)normalization in accessors. Clean up WebGLMorphtargets.js BufferAttribute: Add normalization support for u32, i32, and UintClampedArray --- src/core/BufferAttribute.js | 123 ++++++++++++++++++++--- src/core/InterleavedBufferAttribute.js | 57 ++++++++++- src/math/MathUtils.js | 18 ++++ src/renderers/webgl/WebGLMorphtargets.js | 22 ---- 4 files changed, 178 insertions(+), 42 deletions(-) diff --git a/src/core/BufferAttribute.js b/src/core/BufferAttribute.js index 3d47b0573281d6..36387329478e0e 100644 --- a/src/core/BufferAttribute.js +++ b/src/core/BufferAttribute.js @@ -2,6 +2,7 @@ import { Vector4 } from '../math/Vector4.js'; import { Vector3 } from '../math/Vector3.js'; import { Vector2 } from '../math/Vector2.js'; import { Color } from '../math/Color.js'; +import { denormalize, normalize } from '../math/MathUtils.js'; import { StaticDrawUsage } from '../constants.js'; const _vector = /*@__PURE__*/ new Vector3(); @@ -102,9 +103,19 @@ class BufferAttribute { } - array[ offset ++ ] = color.r; - array[ offset ++ ] = color.g; - array[ offset ++ ] = color.b; + if ( this.normalized ) { + + array[ offset ++ ] = normalize( color.r, array ); + array[ offset ++ ] = normalize( color.g, array ); + array[ offset ++ ] = normalize( color.b, array ); + + } else { + + array[ offset ++ ] = color.r; + array[ offset ++ ] = color.g; + array[ offset ++ ] = color.b; + + } } @@ -128,8 +139,17 @@ class BufferAttribute { } - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; + if ( this.normalized ) { + + array[ offset ++ ] = normalize( vector.x, array ); + array[ offset ++ ] = normalize( vector.y, array ); + + } else { + + array[ offset ++ ] = vector.x; + array[ offset ++ ] = vector.y; + + } } @@ -153,9 +173,19 @@ class BufferAttribute { } - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; + if ( this.normalized ) { + + array[ offset ++ ] = normalize( vector.x, array ); + array[ offset ++ ] = normalize( vector.y, array ); + array[ offset ++ ] = normalize( vector.z, array ); + + } else { + + array[ offset ++ ] = vector.x; + array[ offset ++ ] = vector.y; + array[ offset ++ ] = vector.z; + + } } @@ -179,10 +209,21 @@ class BufferAttribute { } - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - array[ offset ++ ] = vector.w; + if ( this.normalized ) { + + array[ offset ++ ] = normalize( vector.x, array ); + array[ offset ++ ] = normalize( vector.y, array ); + array[ offset ++ ] = normalize( vector.z, array ); + array[ offset ++ ] = normalize( vector.w, array ); + + } else { + + array[ offset ++ ] = vector.x; + array[ offset ++ ] = vector.y; + array[ offset ++ ] = vector.z; + array[ offset ++ ] = vector.w; + + } } @@ -270,6 +311,8 @@ class BufferAttribute { set( value, offset = 0 ) { + if ( this.normalized ) value = normalize( value, this.array ); + this.array.set( value, offset ); return this; @@ -278,12 +321,18 @@ class BufferAttribute { getX( index ) { - return this.array[ index * this.itemSize ]; + let x = this.array[ index * this.itemSize ]; + + if ( this.normalized ) x = denormalize( x, this.array ); + + return x; } setX( index, x ) { + if ( this.normalized ) x = normalize( x, this.array ); + this.array[ index * this.itemSize ] = x; return this; @@ -292,12 +341,18 @@ class BufferAttribute { getY( index ) { - return this.array[ index * this.itemSize + 1 ]; + let y = this.array[ index * this.itemSize + 1 ]; + + if ( this.normalized ) y = denormalize( y, this.array ); + + return y; } setY( index, y ) { + if ( this.normalized ) y = normalize( y, this.array ); + this.array[ index * this.itemSize + 1 ] = y; return this; @@ -306,12 +361,18 @@ class BufferAttribute { getZ( index ) { - return this.array[ index * this.itemSize + 2 ]; + let z = this.array[ index * this.itemSize + 2 ]; + + if ( this.normalized ) z = denormalize( z, this.array ); + + return z; } setZ( index, z ) { + if ( this.normalized ) z = normalize( z, this.array ); + this.array[ index * this.itemSize + 2 ] = z; return this; @@ -320,12 +381,18 @@ class BufferAttribute { getW( index ) { - return this.array[ index * this.itemSize + 3 ]; + let w = this.array[ index * this.itemSize + 3 ]; + + if ( this.normalized ) w = denormalize( w, this.array ); + + return w; } setW( index, w ) { + if ( this.normalized ) w = normalize( w, this.array ); + this.array[ index * this.itemSize + 3 ] = w; return this; @@ -336,6 +403,13 @@ class BufferAttribute { index *= this.itemSize; + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + + } + this.array[ index + 0 ] = x; this.array[ index + 1 ] = y; @@ -347,6 +421,14 @@ class BufferAttribute { index *= this.itemSize; + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + + } + this.array[ index + 0 ] = x; this.array[ index + 1 ] = y; this.array[ index + 2 ] = z; @@ -359,6 +441,15 @@ class BufferAttribute { index *= this.itemSize; + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); + + } + this.array[ index + 0 ] = x; this.array[ index + 1 ] = y; this.array[ index + 2 ] = z; diff --git a/src/core/InterleavedBufferAttribute.js b/src/core/InterleavedBufferAttribute.js index 5010f3d4193500..c7aa7ef30cb096 100644 --- a/src/core/InterleavedBufferAttribute.js +++ b/src/core/InterleavedBufferAttribute.js @@ -1,5 +1,6 @@ import { Vector3 } from '../math/Vector3.js'; import { BufferAttribute } from './BufferAttribute.js'; +import { denormalize, normalize } from '../math/MathUtils.js'; const _vector = /*@__PURE__*/ new Vector3(); @@ -87,6 +88,8 @@ class InterleavedBufferAttribute { setX( index, x ) { + if ( this.normalized ) x = normalize( x, this.array ); + this.data.array[ index * this.data.stride + this.offset ] = x; return this; @@ -95,6 +98,8 @@ class InterleavedBufferAttribute { setY( index, y ) { + if ( this.normalized ) y = normalize( y, this.array ); + this.data.array[ index * this.data.stride + this.offset + 1 ] = y; return this; @@ -103,6 +108,8 @@ class InterleavedBufferAttribute { setZ( index, z ) { + if ( this.normalized ) z = normalize( z, this.array ); + this.data.array[ index * this.data.stride + this.offset + 2 ] = z; return this; @@ -111,6 +118,8 @@ class InterleavedBufferAttribute { setW( index, w ) { + if ( this.normalized ) w = normalize( w, this.array ); + this.data.array[ index * this.data.stride + this.offset + 3 ] = w; return this; @@ -119,25 +128,41 @@ class InterleavedBufferAttribute { getX( index ) { - return this.data.array[ index * this.data.stride + this.offset ]; + let x = this.data.array[ index * this.data.stride + this.offset ]; + + if ( this.normalized ) x = denormalize( x, this.array ); + + return x; } getY( index ) { - return this.data.array[ index * this.data.stride + this.offset + 1 ]; + let y = this.data.array[ index * this.data.stride + this.offset + 1 ]; + + if ( this.normalized ) y = denormalize( y, this.array ); + + return y; } getZ( index ) { - return this.data.array[ index * this.data.stride + this.offset + 2 ]; + let z = this.data.array[ index * this.data.stride + this.offset + 2 ]; + + if ( this.normalized ) z = denormalize( z, this.array ); + + return z; } getW( index ) { - return this.data.array[ index * this.data.stride + this.offset + 3 ]; + let w = this.data.array[ index * this.data.stride + this.offset + 3 ]; + + if ( this.normalized ) w = denormalize( w, this.array ); + + return w; } @@ -145,6 +170,13 @@ class InterleavedBufferAttribute { index = index * this.data.stride + this.offset; + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + + } + this.data.array[ index + 0 ] = x; this.data.array[ index + 1 ] = y; @@ -156,6 +188,14 @@ class InterleavedBufferAttribute { index = index * this.data.stride + this.offset; + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + + } + this.data.array[ index + 0 ] = x; this.data.array[ index + 1 ] = y; this.data.array[ index + 2 ] = z; @@ -168,6 +208,15 @@ class InterleavedBufferAttribute { index = index * this.data.stride + this.offset; + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); + + } + this.data.array[ index + 0 ] = x; this.data.array[ index + 1 ] = y; this.data.array[ index + 2 ] = z; diff --git a/src/math/MathUtils.js b/src/math/MathUtils.js index f64985edf8d892..f2b2368661b5e5 100644 --- a/src/math/MathUtils.js +++ b/src/math/MathUtils.js @@ -235,14 +235,23 @@ function denormalize( value, array ) { return value; + case Uint32Array: + + return value / 4294967295.0; + case Uint16Array: return value / 65535.0; case Uint8Array: + case Uint8ClampedArray: return value / 255.0; + case Int32Array: + + return Math.max( value / 2147483647.0, - 1.0 ); + case Int16Array: return Math.max( value / 32767.0, - 1.0 ); @@ -267,14 +276,23 @@ function normalize( value, array ) { return value; + case Uint32Array: + + return Math.round( value * 4294967295.0 ); + case Uint16Array: return Math.round( value * 65535.0 ); case Uint8Array: + case Uint8ClampedArray: return Math.round( value * 255.0 ); + case Int32Array: + + return Math.round( value * 2147483647.0 ); + case Int16Array: return Math.round( value * 32767.0 ); diff --git a/src/renderers/webgl/WebGLMorphtargets.js b/src/renderers/webgl/WebGLMorphtargets.js index 480110103ba279..4fb585a138b98f 100644 --- a/src/renderers/webgl/WebGLMorphtargets.js +++ b/src/renderers/webgl/WebGLMorphtargets.js @@ -15,22 +15,6 @@ function absNumericalSort( a, b ) { } -function denormalize( morph, attribute ) { - - let denominator = 1; - const array = attribute.isInterleavedBufferAttribute ? attribute.data.array : attribute.array; - - if ( array instanceof Int8Array ) denominator = 127; - else if ( array instanceof Uint8Array ) denominator = 255; - else if ( array instanceof Uint16Array ) denominator = 65535; - else if ( array instanceof Int16Array ) denominator = 32767; - else if ( array instanceof Int32Array ) denominator = 2147483647; - else console.error( 'THREE.WebGLMorphtargets: Unsupported morph attribute data type: ', array ); - - morph.divideScalar( denominator ); - -} - function WebGLMorphtargets( gl, capabilities, textures ) { const influencesList = {}; @@ -114,8 +98,6 @@ function WebGLMorphtargets( gl, capabilities, textures ) { morph.fromBufferAttribute( morphTarget, j ); - if ( morphTarget.normalized === true ) denormalize( morph, morphTarget ); - buffer[ offset + stride + 0 ] = morph.x; buffer[ offset + stride + 1 ] = morph.y; buffer[ offset + stride + 2 ] = morph.z; @@ -127,8 +109,6 @@ function WebGLMorphtargets( gl, capabilities, textures ) { morph.fromBufferAttribute( morphNormal, j ); - if ( morphNormal.normalized === true ) denormalize( morph, morphNormal ); - buffer[ offset + stride + 4 ] = morph.x; buffer[ offset + stride + 5 ] = morph.y; buffer[ offset + stride + 6 ] = morph.z; @@ -140,8 +120,6 @@ function WebGLMorphtargets( gl, capabilities, textures ) { morph.fromBufferAttribute( morphColor, j ); - if ( morphColor.normalized === true ) denormalize( morph, morphColor ); - buffer[ offset + stride + 8 ] = morph.x; buffer[ offset + stride + 9 ] = morph.y; buffer[ offset + stride + 10 ] = morph.z; From 9306797023de88f654fac6e759ecbf81728e64a6 Mon Sep 17 00:00:00 2001 From: Don McCurdy Date: Mon, 15 Aug 2022 21:18:41 -0400 Subject: [PATCH 2/3] Revert changes to MathUtils --- src/math/MathUtils.js | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/math/MathUtils.js b/src/math/MathUtils.js index f2b2368661b5e5..f64985edf8d892 100644 --- a/src/math/MathUtils.js +++ b/src/math/MathUtils.js @@ -235,23 +235,14 @@ function denormalize( value, array ) { return value; - case Uint32Array: - - return value / 4294967295.0; - case Uint16Array: return value / 65535.0; case Uint8Array: - case Uint8ClampedArray: return value / 255.0; - case Int32Array: - - return Math.max( value / 2147483647.0, - 1.0 ); - case Int16Array: return Math.max( value / 32767.0, - 1.0 ); @@ -276,23 +267,14 @@ function normalize( value, array ) { return value; - case Uint32Array: - - return Math.round( value * 4294967295.0 ); - case Uint16Array: return Math.round( value * 65535.0 ); case Uint8Array: - case Uint8ClampedArray: return Math.round( value * 255.0 ); - case Int32Array: - - return Math.round( value * 2147483647.0 ); - case Int16Array: return Math.round( value * 32767.0 ); From 75bcd8f7ecdb375a114ab245641e4c0ea018db0a Mon Sep 17 00:00:00 2001 From: Don McCurdy Date: Mon, 15 Aug 2022 21:22:50 -0400 Subject: [PATCH 3/3] Clean up Color.js --- src/math/Color.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/math/Color.js b/src/math/Color.js index b913958e1bc85c..e9a50547ca32a2 100644 --- a/src/math/Color.js +++ b/src/math/Color.js @@ -580,16 +580,6 @@ class Color { this.g = attribute.getY( index ); this.b = attribute.getZ( index ); - if ( attribute.normalized === true ) { - - // assuming Uint8Array - - this.r /= 255; - this.g /= 255; - this.b /= 255; - - } - return this; }