Spaces:
Running
Running
import { Vector3 } from '../math/Vector3.js'; | |
import { Box3 } from '../math/Box3.js'; | |
import { EventDispatcher } from './EventDispatcher.js'; | |
import { BufferAttribute, Float32BufferAttribute, Uint16BufferAttribute, Uint32BufferAttribute } from './BufferAttribute.js'; | |
import { Sphere } from '../math/Sphere.js'; | |
import { DirectGeometry } from './DirectGeometry.js'; | |
import { Object3D } from './Object3D.js'; | |
import { Matrix4 } from '../math/Matrix4.js'; | |
import { Matrix3 } from '../math/Matrix3.js'; | |
import { _Math } from '../math/Math.js'; | |
import { arrayMax } from '../utils.js'; | |
/** | |
* @author alteredq / http://alteredqualia.com/ | |
* @author mrdoob / http://mrdoob.com/ | |
*/ | |
var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id | |
function BufferGeometry() { | |
Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } ); | |
this.uuid = _Math.generateUUID(); | |
this.name = ''; | |
this.type = 'BufferGeometry'; | |
this.index = null; | |
this.attributes = {}; | |
this.morphAttributes = {}; | |
this.groups = []; | |
this.boundingBox = null; | |
this.boundingSphere = null; | |
this.drawRange = { start: 0, count: Infinity }; | |
this.userData = {}; | |
} | |
BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { | |
constructor: BufferGeometry, | |
isBufferGeometry: true, | |
getIndex: function () { | |
return this.index; | |
}, | |
setIndex: function ( index ) { | |
if ( Array.isArray( index ) ) { | |
this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); | |
} else { | |
this.index = index; | |
} | |
}, | |
addAttribute: function ( name, attribute ) { | |
if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) { | |
console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); | |
return this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) ); | |
} | |
if ( name === 'index' ) { | |
console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' ); | |
this.setIndex( attribute ); | |
return this; | |
} | |
this.attributes[ name ] = attribute; | |
return this; | |
}, | |
getAttribute: function ( name ) { | |
return this.attributes[ name ]; | |
}, | |
removeAttribute: function ( name ) { | |
delete this.attributes[ name ]; | |
return this; | |
}, | |
addGroup: function ( start, count, materialIndex ) { | |
this.groups.push( { | |
start: start, | |
count: count, | |
materialIndex: materialIndex !== undefined ? materialIndex : 0 | |
} ); | |
}, | |
clearGroups: function () { | |
this.groups = []; | |
}, | |
setDrawRange: function ( start, count ) { | |
this.drawRange.start = start; | |
this.drawRange.count = count; | |
}, | |
applyMatrix: function ( matrix ) { | |
var position = this.attributes.position; | |
if ( position !== undefined ) { | |
matrix.applyToBufferAttribute( position ); | |
position.needsUpdate = true; | |
} | |
var normal = this.attributes.normal; | |
if ( normal !== undefined ) { | |
var normalMatrix = new Matrix3().getNormalMatrix( matrix ); | |
normalMatrix.applyToBufferAttribute( normal ); | |
normal.needsUpdate = true; | |
} | |
var tangent = this.attributes.tangent; | |
if ( tangent !== undefined ) { | |
var normalMatrix = new Matrix3().getNormalMatrix( matrix ); | |
// Tangent is vec4, but the '.w' component is a sign value (+1/-1). | |
normalMatrix.applyToBufferAttribute( tangent ); | |
tangent.needsUpdate = true; | |
} | |
if ( this.boundingBox !== null ) { | |
this.computeBoundingBox(); | |
} | |
if ( this.boundingSphere !== null ) { | |
this.computeBoundingSphere(); | |
} | |
return this; | |
}, | |
rotateX: function () { | |
// rotate geometry around world x-axis | |
var m1 = new Matrix4(); | |
return function rotateX( angle ) { | |
m1.makeRotationX( angle ); | |
this.applyMatrix( m1 ); | |
return this; | |
}; | |
}(), | |
rotateY: function () { | |
// rotate geometry around world y-axis | |
var m1 = new Matrix4(); | |
return function rotateY( angle ) { | |
m1.makeRotationY( angle ); | |
this.applyMatrix( m1 ); | |
return this; | |
}; | |
}(), | |
rotateZ: function () { | |
// rotate geometry around world z-axis | |
var m1 = new Matrix4(); | |
return function rotateZ( angle ) { | |
m1.makeRotationZ( angle ); | |
this.applyMatrix( m1 ); | |
return this; | |
}; | |
}(), | |
translate: function () { | |
// translate geometry | |
var m1 = new Matrix4(); | |
return function translate( x, y, z ) { | |
m1.makeTranslation( x, y, z ); | |
this.applyMatrix( m1 ); | |
return this; | |
}; | |
}(), | |
scale: function () { | |
// scale geometry | |
var m1 = new Matrix4(); | |
return function scale( x, y, z ) { | |
m1.makeScale( x, y, z ); | |
this.applyMatrix( m1 ); | |
return this; | |
}; | |
}(), | |
lookAt: function () { | |
var obj = new Object3D(); | |
return function lookAt( vector ) { | |
obj.lookAt( vector ); | |
obj.updateMatrix(); | |
this.applyMatrix( obj.matrix ); | |
}; | |
}(), | |
center: function () { | |
var offset = new Vector3(); | |
return function center() { | |
this.computeBoundingBox(); | |
this.boundingBox.getCenter( offset ).negate(); | |
this.translate( offset.x, offset.y, offset.z ); | |
return this; | |
}; | |
}(), | |
setFromObject: function ( object ) { | |
// console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this ); | |
var geometry = object.geometry; | |
if ( object.isPoints || object.isLine ) { | |
var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 ); | |
var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 ); | |
this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) ); | |
this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) ); | |
if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) { | |
var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 ); | |
this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) ); | |
} | |
if ( geometry.boundingSphere !== null ) { | |
this.boundingSphere = geometry.boundingSphere.clone(); | |
} | |
if ( geometry.boundingBox !== null ) { | |
this.boundingBox = geometry.boundingBox.clone(); | |
} | |
} else if ( object.isMesh ) { | |
if ( geometry && geometry.isGeometry ) { | |
this.fromGeometry( geometry ); | |
} | |
} | |
return this; | |
}, | |
setFromPoints: function ( points ) { | |
var position = []; | |
for ( var i = 0, l = points.length; i < l; i ++ ) { | |
var point = points[ i ]; | |
position.push( point.x, point.y, point.z || 0 ); | |
} | |
this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); | |
return this; | |
}, | |
updateFromObject: function ( object ) { | |
var geometry = object.geometry; | |
if ( object.isMesh ) { | |
var direct = geometry.__directGeometry; | |
if ( geometry.elementsNeedUpdate === true ) { | |
direct = undefined; | |
geometry.elementsNeedUpdate = false; | |
} | |
if ( direct === undefined ) { | |
return this.fromGeometry( geometry ); | |
} | |
direct.verticesNeedUpdate = geometry.verticesNeedUpdate; | |
direct.normalsNeedUpdate = geometry.normalsNeedUpdate; | |
direct.colorsNeedUpdate = geometry.colorsNeedUpdate; | |
direct.uvsNeedUpdate = geometry.uvsNeedUpdate; | |
direct.groupsNeedUpdate = geometry.groupsNeedUpdate; | |
geometry.verticesNeedUpdate = false; | |
geometry.normalsNeedUpdate = false; | |
geometry.colorsNeedUpdate = false; | |
geometry.uvsNeedUpdate = false; | |
geometry.groupsNeedUpdate = false; | |
geometry = direct; | |
} | |
var attribute; | |
if ( geometry.verticesNeedUpdate === true ) { | |
attribute = this.attributes.position; | |
if ( attribute !== undefined ) { | |
attribute.copyVector3sArray( geometry.vertices ); | |
attribute.needsUpdate = true; | |
} | |
geometry.verticesNeedUpdate = false; | |
} | |
if ( geometry.normalsNeedUpdate === true ) { | |
attribute = this.attributes.normal; | |
if ( attribute !== undefined ) { | |
attribute.copyVector3sArray( geometry.normals ); | |
attribute.needsUpdate = true; | |
} | |
geometry.normalsNeedUpdate = false; | |
} | |
if ( geometry.colorsNeedUpdate === true ) { | |
attribute = this.attributes.color; | |
if ( attribute !== undefined ) { | |
attribute.copyColorsArray( geometry.colors ); | |
attribute.needsUpdate = true; | |
} | |
geometry.colorsNeedUpdate = false; | |
} | |
if ( geometry.uvsNeedUpdate ) { | |
attribute = this.attributes.uv; | |
if ( attribute !== undefined ) { | |
attribute.copyVector2sArray( geometry.uvs ); | |
attribute.needsUpdate = true; | |
} | |
geometry.uvsNeedUpdate = false; | |
} | |
if ( geometry.lineDistancesNeedUpdate ) { | |
attribute = this.attributes.lineDistance; | |
if ( attribute !== undefined ) { | |
attribute.copyArray( geometry.lineDistances ); | |
attribute.needsUpdate = true; | |
} | |
geometry.lineDistancesNeedUpdate = false; | |
} | |
if ( geometry.groupsNeedUpdate ) { | |
geometry.computeGroups( object.geometry ); | |
this.groups = geometry.groups; | |
geometry.groupsNeedUpdate = false; | |
} | |
return this; | |
}, | |
fromGeometry: function ( geometry ) { | |
geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry ); | |
return this.fromDirectGeometry( geometry.__directGeometry ); | |
}, | |
fromDirectGeometry: function ( geometry ) { | |
var positions = new Float32Array( geometry.vertices.length * 3 ); | |
this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) ); | |
if ( geometry.normals.length > 0 ) { | |
var normals = new Float32Array( geometry.normals.length * 3 ); | |
this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) ); | |
} | |
if ( geometry.colors.length > 0 ) { | |
var colors = new Float32Array( geometry.colors.length * 3 ); | |
this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) ); | |
} | |
if ( geometry.uvs.length > 0 ) { | |
var uvs = new Float32Array( geometry.uvs.length * 2 ); | |
this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) ); | |
} | |
if ( geometry.uvs2.length > 0 ) { | |
var uvs2 = new Float32Array( geometry.uvs2.length * 2 ); | |
this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) ); | |
} | |
// groups | |
this.groups = geometry.groups; | |
// morphs | |
for ( var name in geometry.morphTargets ) { | |
var array = []; | |
var morphTargets = geometry.morphTargets[ name ]; | |
for ( var i = 0, l = morphTargets.length; i < l; i ++ ) { | |
var morphTarget = morphTargets[ i ]; | |
var attribute = new Float32BufferAttribute( morphTarget.data.length * 3, 3 ); | |
attribute.name = morphTarget.name; | |
array.push( attribute.copyVector3sArray( morphTarget.data ) ); | |
} | |
this.morphAttributes[ name ] = array; | |
} | |
// skinning | |
if ( geometry.skinIndices.length > 0 ) { | |
var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); | |
this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) ); | |
} | |
if ( geometry.skinWeights.length > 0 ) { | |
var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); | |
this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) ); | |
} | |
// | |
if ( geometry.boundingSphere !== null ) { | |
this.boundingSphere = geometry.boundingSphere.clone(); | |
} | |
if ( geometry.boundingBox !== null ) { | |
this.boundingBox = geometry.boundingBox.clone(); | |
} | |
return this; | |
}, | |
computeBoundingBox: function () { | |
var box = new Box3(); | |
return function computeBoundingBox() { | |
if ( this.boundingBox === null ) { | |
this.boundingBox = new Box3(); | |
} | |
var position = this.attributes.position; | |
var morphAttributesPosition = this.morphAttributes.position; | |
if ( position !== undefined ) { | |
this.boundingBox.setFromBufferAttribute( position ); | |
// process morph attributes if present | |
if ( morphAttributesPosition ) { | |
for ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { | |
var morphAttribute = morphAttributesPosition[ i ]; | |
box.setFromBufferAttribute( morphAttribute ); | |
this.boundingBox.expandByPoint( box.min ); | |
this.boundingBox.expandByPoint( box.max ); | |
} | |
} | |
} else { | |
this.boundingBox.makeEmpty(); | |
} | |
if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { | |
console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); | |
} | |
}; | |
}(), | |
computeBoundingSphere: function () { | |
var box = new Box3(); | |
var boxMorphTargets = new Box3(); | |
var vector = new Vector3(); | |
return function computeBoundingSphere() { | |
if ( this.boundingSphere === null ) { | |
this.boundingSphere = new Sphere(); | |
} | |
var position = this.attributes.position; | |
var morphAttributesPosition = this.morphAttributes.position; | |
if ( position ) { | |
// first, find the center of the bounding sphere | |
var center = this.boundingSphere.center; | |
box.setFromBufferAttribute( position ); | |
// process morph attributes if present | |
if ( morphAttributesPosition ) { | |
for ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { | |
var morphAttribute = morphAttributesPosition[ i ]; | |
boxMorphTargets.setFromBufferAttribute( morphAttribute ); | |
box.expandByPoint( boxMorphTargets.min ); | |
box.expandByPoint( boxMorphTargets.max ); | |
} | |
} | |
box.getCenter( center ); | |
// second, try to find a boundingSphere with a radius smaller than the | |
// boundingSphere of the boundingBox: sqrt(3) smaller in the best case | |
var maxRadiusSq = 0; | |
for ( var i = 0, il = position.count; i < il; i ++ ) { | |
vector.fromBufferAttribute( position, i ); | |
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); | |
} | |
// process morph attributes if present | |
if ( morphAttributesPosition ) { | |
for ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { | |
var morphAttribute = morphAttributesPosition[ i ]; | |
for ( var j = 0, jl = morphAttribute.count; j < jl; j ++ ) { | |
vector.fromBufferAttribute( morphAttribute, i ); | |
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); | |
} | |
} | |
} | |
this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); | |
if ( isNaN( this.boundingSphere.radius ) ) { | |
console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); | |
} | |
} | |
}; | |
}(), | |
computeFaceNormals: function () { | |
// backwards compatibility | |
}, | |
computeVertexNormals: function () { | |
var index = this.index; | |
var attributes = this.attributes; | |
if ( attributes.position ) { | |
var positions = attributes.position.array; | |
if ( attributes.normal === undefined ) { | |
this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) ); | |
} else { | |
// reset existing normals to zero | |
var array = attributes.normal.array; | |
for ( var i = 0, il = array.length; i < il; i ++ ) { | |
array[ i ] = 0; | |
} | |
} | |
var normals = attributes.normal.array; | |
var vA, vB, vC; | |
var pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); | |
var cb = new Vector3(), ab = new Vector3(); | |
// indexed elements | |
if ( index ) { | |
var indices = index.array; | |
for ( var i = 0, il = index.count; i < il; i += 3 ) { | |
vA = indices[ i + 0 ] * 3; | |
vB = indices[ i + 1 ] * 3; | |
vC = indices[ i + 2 ] * 3; | |
pA.fromArray( positions, vA ); | |
pB.fromArray( positions, vB ); | |
pC.fromArray( positions, vC ); | |
cb.subVectors( pC, pB ); | |
ab.subVectors( pA, pB ); | |
cb.cross( ab ); | |
normals[ vA ] += cb.x; | |
normals[ vA + 1 ] += cb.y; | |
normals[ vA + 2 ] += cb.z; | |
normals[ vB ] += cb.x; | |
normals[ vB + 1 ] += cb.y; | |
normals[ vB + 2 ] += cb.z; | |
normals[ vC ] += cb.x; | |
normals[ vC + 1 ] += cb.y; | |
normals[ vC + 2 ] += cb.z; | |
} | |
} else { | |
// non-indexed elements (unconnected triangle soup) | |
for ( var i = 0, il = positions.length; i < il; i += 9 ) { | |
pA.fromArray( positions, i ); | |
pB.fromArray( positions, i + 3 ); | |
pC.fromArray( positions, i + 6 ); | |
cb.subVectors( pC, pB ); | |
ab.subVectors( pA, pB ); | |
cb.cross( ab ); | |
normals[ i ] = cb.x; | |
normals[ i + 1 ] = cb.y; | |
normals[ i + 2 ] = cb.z; | |
normals[ i + 3 ] = cb.x; | |
normals[ i + 4 ] = cb.y; | |
normals[ i + 5 ] = cb.z; | |
normals[ i + 6 ] = cb.x; | |
normals[ i + 7 ] = cb.y; | |
normals[ i + 8 ] = cb.z; | |
} | |
} | |
this.normalizeNormals(); | |
attributes.normal.needsUpdate = true; | |
} | |
}, | |
merge: function ( geometry, offset ) { | |
if ( ! ( geometry && geometry.isBufferGeometry ) ) { | |
console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry ); | |
return; | |
} | |
if ( offset === undefined ) { | |
offset = 0; | |
console.warn( | |
'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. ' | |
+ 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.' | |
); | |
} | |
var attributes = this.attributes; | |
for ( var key in attributes ) { | |
if ( geometry.attributes[ key ] === undefined ) continue; | |
var attribute1 = attributes[ key ]; | |
var attributeArray1 = attribute1.array; | |
var attribute2 = geometry.attributes[ key ]; | |
var attributeArray2 = attribute2.array; | |
var attributeSize = attribute2.itemSize; | |
for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) { | |
attributeArray1[ j ] = attributeArray2[ i ]; | |
} | |
} | |
return this; | |
}, | |
normalizeNormals: function () { | |
var vector = new Vector3(); | |
return function normalizeNormals() { | |
var normals = this.attributes.normal; | |
for ( var i = 0, il = normals.count; i < il; i ++ ) { | |
vector.x = normals.getX( i ); | |
vector.y = normals.getY( i ); | |
vector.z = normals.getZ( i ); | |
vector.normalize(); | |
normals.setXYZ( i, vector.x, vector.y, vector.z ); | |
} | |
}; | |
}(), | |
toNonIndexed: function () { | |
function convertBufferAttribute( attribute, indices ) { | |
var array = attribute.array; | |
var itemSize = attribute.itemSize; | |
var array2 = new array.constructor( indices.length * itemSize ); | |
var index = 0, index2 = 0; | |
for ( var i = 0, l = indices.length; i < l; i ++ ) { | |
index = indices[ i ] * itemSize; | |
for ( var j = 0; j < itemSize; j ++ ) { | |
array2[ index2 ++ ] = array[ index ++ ]; | |
} | |
} | |
return new BufferAttribute( array2, itemSize ); | |
} | |
// | |
if ( this.index === null ) { | |
console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' ); | |
return this; | |
} | |
var geometry2 = new BufferGeometry(); | |
var indices = this.index.array; | |
var attributes = this.attributes; | |
// attributes | |
for ( var name in attributes ) { | |
var attribute = attributes[ name ]; | |
var newAttribute = convertBufferAttribute( attribute, indices ); | |
geometry2.addAttribute( name, newAttribute ); | |
} | |
// morph attributes | |
var morphAttributes = this.morphAttributes; | |
for ( name in morphAttributes ) { | |
var morphArray = []; | |
var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes | |
for ( var i = 0, il = morphAttribute.length; i < il; i ++ ) { | |
var attribute = morphAttribute[ i ]; | |
var newAttribute = convertBufferAttribute( attribute, indices ); | |
morphArray.push( newAttribute ); | |
} | |
geometry2.morphAttributes[ name ] = morphArray; | |
} | |
// groups | |
var groups = this.groups; | |
for ( var i = 0, l = groups.length; i < l; i ++ ) { | |
var group = groups[ i ]; | |
geometry2.addGroup( group.start, group.count, group.materialIndex ); | |
} | |
return geometry2; | |
}, | |
toJSON: function () { | |
var data = { | |
metadata: { | |
version: 4.5, | |
type: 'BufferGeometry', | |
generator: 'BufferGeometry.toJSON' | |
} | |
}; | |
// standard BufferGeometry serialization | |
data.uuid = this.uuid; | |
data.type = this.type; | |
if ( this.name !== '' ) data.name = this.name; | |
if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; | |
if ( this.parameters !== undefined ) { | |
var parameters = this.parameters; | |
for ( var key in parameters ) { | |
if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; | |
} | |
return data; | |
} | |
data.data = { attributes: {} }; | |
var index = this.index; | |
if ( index !== null ) { | |
data.data.index = { | |
type: index.array.constructor.name, | |
array: Array.prototype.slice.call( index.array ) | |
}; | |
} | |
var attributes = this.attributes; | |
for ( var key in attributes ) { | |
var attribute = attributes[ key ]; | |
var attributeData = { | |
itemSize: attribute.itemSize, | |
type: attribute.array.constructor.name, | |
array: Array.prototype.slice.call( attribute.array ), | |
normalized: attribute.normalized | |
}; | |
if ( attribute.name !== '' ) attributeData.name = attribute.name; | |
data.data.attributes[ key ] = attributeData; | |
} | |
var morphAttributes = {}; | |
var hasMorphAttributes = false; | |
for ( var key in this.morphAttributes ) { | |
var attributeArray = this.morphAttributes[ key ]; | |
var array = []; | |
for ( var i = 0, il = attributeArray.length; i < il; i ++ ) { | |
var attribute = attributeArray[ i ]; | |
var attributeData = { | |
itemSize: attribute.itemSize, | |
type: attribute.array.constructor.name, | |
array: Array.prototype.slice.call( attribute.array ), | |
normalized: attribute.normalized | |
}; | |
if ( attribute.name !== '' ) attributeData.name = attribute.name; | |
array.push( attributeData ); | |
} | |
if ( array.length > 0 ) { | |
morphAttributes[ key ] = array; | |
hasMorphAttributes = true; | |
} | |
} | |
if ( hasMorphAttributes ) data.data.morphAttributes = morphAttributes; | |
var groups = this.groups; | |
if ( groups.length > 0 ) { | |
data.data.groups = JSON.parse( JSON.stringify( groups ) ); | |
} | |
var boundingSphere = this.boundingSphere; | |
if ( boundingSphere !== null ) { | |
data.data.boundingSphere = { | |
center: boundingSphere.center.toArray(), | |
radius: boundingSphere.radius | |
}; | |
} | |
return data; | |
}, | |
clone: function () { | |
/* | |
// Handle primitives | |
var parameters = this.parameters; | |
if ( parameters !== undefined ) { | |
var values = []; | |
for ( var key in parameters ) { | |
values.push( parameters[ key ] ); | |
} | |
var geometry = Object.create( this.constructor.prototype ); | |
this.constructor.apply( geometry, values ); | |
return geometry; | |
} | |
return new this.constructor().copy( this ); | |
*/ | |
return new BufferGeometry().copy( this ); | |
}, | |
copy: function ( source ) { | |
var name, i, l; | |
// reset | |
this.index = null; | |
this.attributes = {}; | |
this.morphAttributes = {}; | |
this.groups = []; | |
this.boundingBox = null; | |
this.boundingSphere = null; | |
// name | |
this.name = source.name; | |
// index | |
var index = source.index; | |
if ( index !== null ) { | |
this.setIndex( index.clone() ); | |
} | |
// attributes | |
var attributes = source.attributes; | |
for ( name in attributes ) { | |
var attribute = attributes[ name ]; | |
this.addAttribute( name, attribute.clone() ); | |
} | |
// morph attributes | |
var morphAttributes = source.morphAttributes; | |
for ( name in morphAttributes ) { | |
var array = []; | |
var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes | |
for ( i = 0, l = morphAttribute.length; i < l; i ++ ) { | |
array.push( morphAttribute[ i ].clone() ); | |
} | |
this.morphAttributes[ name ] = array; | |
} | |
// groups | |
var groups = source.groups; | |
for ( i = 0, l = groups.length; i < l; i ++ ) { | |
var group = groups[ i ]; | |
this.addGroup( group.start, group.count, group.materialIndex ); | |
} | |
// bounding box | |
var boundingBox = source.boundingBox; | |
if ( boundingBox !== null ) { | |
this.boundingBox = boundingBox.clone(); | |
} | |
// bounding sphere | |
var boundingSphere = source.boundingSphere; | |
if ( boundingSphere !== null ) { | |
this.boundingSphere = boundingSphere.clone(); | |
} | |
// draw range | |
this.drawRange.start = source.drawRange.start; | |
this.drawRange.count = source.drawRange.count; | |
// user data | |
this.userData = source.userData; | |
return this; | |
}, | |
dispose: function () { | |
this.dispatchEvent( { type: 'dispose' } ); | |
} | |
} ); | |
export { BufferGeometry }; | |