Skip to content

Commit

Permalink
BufferGeometryUtils: Fixed computeMorphedBufferGeometry()
Browse files Browse the repository at this point in the history
  • Loading branch information
mrdoob committed Jan 13, 2021
1 parent 2591284 commit f21ecaf
Show file tree
Hide file tree
Showing 2 changed files with 324 additions and 12 deletions.
313 changes: 312 additions & 1 deletion examples/js/utils/BufferGeometryUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,6 @@ THREE.BufferGeometryUtils = {
newIndices.push( index.getX( i + 1 ) );
newIndices.push( index.getX( i + 2 ) );


} else {

newIndices.push( index.getX( i + 2 ) );
Expand Down Expand Up @@ -778,6 +777,318 @@ THREE.BufferGeometryUtils = {

}

},

/**
* Calculates the morphed attributes of a morphed/skinned BufferGeometry.
* Helpful for Raytracing or Decals.
* @param {Object3D} object
* @return {Object} An Object with original position/normal attributes and morphed ones.
*/
computeMorphedBufferGeometry: function ( object ) {

if ( ! object ) {

console.error( 'Please provide an object' );
return null;

}

if ( ! object.geometry ) {

console.error( 'Please provide an object with a geometry' );
return null;

}

if ( ! object.geometry.isBufferGeometry ) {

console.error( 'Geometry is not a BufferGeometry' );
return null;

}

var _vA = new THREE.Vector3();
var _vB = new THREE.Vector3();
var _vC = new THREE.Vector3();

var _tempA = new THREE.Vector3();
var _tempB = new THREE.Vector3();
var _tempC = new THREE.Vector3();

var _morphA = new THREE.Vector3();
var _morphB = new THREE.Vector3();
var _morphC = new THREE.Vector3();

function _calculateMorphedAttributeData(
object,
material,
attribute,
morphAttribute,
morphTargetsRelative,
a,
b,
c,
modifiedAttributeArray
) {

_vA.fromBufferAttribute( attribute, a );
_vB.fromBufferAttribute( attribute, b );
_vC.fromBufferAttribute( attribute, c );

var morphInfluences = object.morphTargetInfluences;

if ( material.morphTargets && morphAttribute && morphInfluences ) {

_morphA.set( 0, 0, 0 );
_morphB.set( 0, 0, 0 );
_morphC.set( 0, 0, 0 );

for ( var i = 0, il = morphAttribute.length; i < il; i ++ ) {

var influence = morphInfluences[ i ];
var morphAttribute = morphAttribute[ i ];

if ( influence === 0 ) continue;

_tempA.fromBufferAttribute( morphAttribute, a );
_tempB.fromBufferAttribute( morphAttribute, b );
_tempC.fromBufferAttribute( morphAttribute, c );

if ( morphTargetsRelative ) {

_morphA.addScaledVector( _tempA, influence );
_morphB.addScaledVector( _tempB, influence );
_morphC.addScaledVector( _tempC, influence );

} else {

_morphA.addScaledVector( _tempA.sub( _vA ), influence );
_morphB.addScaledVector( _tempB.sub( _vB ), influence );
_morphC.addScaledVector( _tempC.sub( _vC ), influence );

}

}

_vA.add( _morphA );
_vB.add( _morphB );
_vC.add( _morphC );

}

if ( object.isSkinnedMesh ) {

object.boneTransform( a, _vA );
object.boneTransform( b, _vB );
object.boneTransform( c, _vC );

}

modifiedAttributeArray[ a * 3 + 0 ] = _vA.x;
modifiedAttributeArray[ a * 3 + 1 ] = _vA.y;
modifiedAttributeArray[ a * 3 + 2 ] = _vA.z;
modifiedAttributeArray[ b * 3 + 0 ] = _vB.x;
modifiedAttributeArray[ b * 3 + 1 ] = _vB.y;
modifiedAttributeArray[ b * 3 + 2 ] = _vB.z;
modifiedAttributeArray[ c * 3 + 0 ] = _vC.x;
modifiedAttributeArray[ c * 3 + 1 ] = _vC.y;
modifiedAttributeArray[ c * 3 + 2 ] = _vC.z;

}

var geometry = object.geometry;
var material = object.material;

var a, b, c;
var index = geometry.index;
var positionAttribute = geometry.attributes.position;
var morphPosition = geometry.morphAttributes.position;
var morphTargetsRelative = geometry.morphTargetsRelative;
var normalAttribute = geometry.attributes.normal;
var morphNormal = geometry.morphAttributes.position;

var groups = geometry.groups;
var drawRange = geometry.drawRange;
var i, j, il, jl;
var group, groupMaterial;
var start, end;

var modifiedPosition = new Float32Array( positionAttribute.count * positionAttribute.itemSize );
var modifiedNormal = new Float32Array( normalAttribute.count * normalAttribute.itemSize );

if ( index !== null ) {

// indexed buffer geometry

if ( Array.isArray( material ) ) {

for ( i = 0, il = groups.length; i < il; i ++ ) {

group = groups[ i ];
groupMaterial = material[ group.materialIndex ];

start = Math.max( group.start, drawRange.start );
end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );

for ( j = start, jl = end; j < jl; j += 3 ) {

a = index.getX( j );
b = index.getX( j + 1 );
c = index.getX( j + 2 );

_calculateMorphedAttributeData(
object,
groupMaterial,
positionAttribute,
morphPosition,
morphTargetsRelative,
a, b, c,
modifiedPosition
);

_calculateMorphedAttributeData(
object,
groupMaterial,
normalAttribute,
morphNormal,
morphTargetsRelative,
a, b, c,
modifiedNormal
);

}

}

} else {

start = Math.max( 0, drawRange.start );
end = Math.min( index.count, ( drawRange.start + drawRange.count ) );

for ( i = start, il = end; i < il; i += 3 ) {

a = index.getX( i );
b = index.getX( i + 1 );
c = index.getX( i + 2 );

_calculateMorphedAttributeData(
object,
material,
positionAttribute,
morphPosition,
morphTargetsRelative,
a, b, c,
modifiedPosition
);

_calculateMorphedAttributeData(
object,
material,
normalAttribute,
morphNormal,
morphTargetsRelative,
a, b, c,
modifiedNormal
);

}

}

} else if ( positionAttribute !== undefined ) {

// non-indexed buffer geometry

if ( Array.isArray( material ) ) {

for ( i = 0, il = groups.length; i < il; i ++ ) {

group = groups[ i ];
groupMaterial = material[ group.materialIndex ];

start = Math.max( group.start, drawRange.start );
end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );

for ( j = start, jl = end; j < jl; j += 3 ) {

a = j;
b = j + 1;
c = j + 2;

_calculateMorphedAttributeData(
object,
groupMaterial,
positionAttribute,
morphPosition,
morphTargetsRelative,
a, b, c,
modifiedPosition
);

_calculateMorphedAttributeData(
object,
groupMaterial,
normalAttribute,
morphNormal,
morphTargetsRelative,
a, b, c,
modifiedNormal
);

}

}

} else {

start = Math.max( 0, drawRange.start );
end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );

for ( i = start, il = end; i < il; i += 3 ) {

a = i;
b = i + 1;
c = i + 2;

_calculateMorphedAttributeData(
object,
material,
positionAttribute,
morphPosition,
morphTargetsRelative,
a, b, c,
modifiedPosition
);

_calculateMorphedAttributeData(
object,
material,
normalAttribute,
morphNormal,
morphTargetsRelative,
a, b, c,
modifiedNormal
);

}

}

}

var morphedPositionAttribute = new THREE.Float32BufferAttribute( modifiedPosition, 3 );
var morphedNormalAttribute = new THREE.Float32BufferAttribute( modifiedNormal, 3 );

return {

positionAttribute: positionAttribute,
normalAttribute: normalAttribute,
morphedPositionAttribute: morphedPositionAttribute,
morphedNormalAttribute: morphedNormalAttribute

};

}

};
23 changes: 12 additions & 11 deletions examples/jsm/utils/BufferGeometryUtils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
BufferAttribute,
BufferGeometry,
Float32BufferAttribute,
InterleavedBuffer,
InterleavedBufferAttribute,
TriangleFanDrawMode,
Expand Down Expand Up @@ -820,17 +821,17 @@ var BufferGeometryUtils = {

}

var _vA = new THREE.Vector3();
var _vB = new THREE.Vector3();
var _vC = new THREE.Vector3();
var _vA = new Vector3();
var _vB = new Vector3();
var _vC = new Vector3();

var _tempA = new THREE.Vector3();
var _tempB = new THREE.Vector3();
var _tempC = new THREE.Vector3();
var _tempA = new Vector3();
var _tempB = new Vector3();
var _tempC = new Vector3();

var _morphA = new THREE.Vector3();
var _morphB = new THREE.Vector3();
var _morphC = new THREE.Vector3();
var _morphA = new Vector3();
var _morphB = new Vector3();
var _morphC = new Vector3();

function _calculateMorphedAttributeData(
object,
Expand Down Expand Up @@ -1089,8 +1090,8 @@ var BufferGeometryUtils = {

}

var morphedPositionAttribute = new THREE.Float32BufferAttribute( modifiedPosition, 3 );
var morphedNormalAttribute = new THREE.Float32BufferAttribute( modifiedNormal, 3 );
var morphedPositionAttribute = new Float32BufferAttribute( modifiedPosition, 3 );
var morphedNormalAttribute = new Float32BufferAttribute( modifiedNormal, 3 );

return {

Expand Down

0 comments on commit f21ecaf

Please sign in to comment.