|
|
@@ -15714,7 +15714,7 @@ class BatchedMesh extends Mesh {
|
|
|
const batchGeometry = this.geometry;
|
|
|
if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) {
|
|
|
|
|
|
- throw new Error( 'BatchedMesh: All geometries must consistently have "index".' );
|
|
|
+ throw new Error( 'THREE.BatchedMesh: All geometries must consistently have "index".' );
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -15722,7 +15722,7 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
if ( ! geometry.hasAttribute( attributeName ) ) {
|
|
|
|
|
|
- throw new Error( `BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` );
|
|
|
+ throw new Error( `THREE.BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` );
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -15730,7 +15730,7 @@ class BatchedMesh extends Mesh {
|
|
|
const dstAttribute = batchGeometry.getAttribute( attributeName );
|
|
|
if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) {
|
|
|
|
|
|
- throw new Error( 'BatchedMesh: All attributes must have a consistent itemSize and normalized value.' );
|
|
|
+ throw new Error( 'THREE.BatchedMesh: All attributes must have a consistent itemSize and normalized value.' );
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -15738,6 +15738,29 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ validateInstanceId( instanceId ) {
|
|
|
+
|
|
|
+ const instanceInfo = this._instanceInfo;
|
|
|
+ if ( instanceId < 0 || instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
|
+
|
|
|
+ throw new Error( `THREE.BatchedMesh: Invalid instanceId ${instanceId}. Instance is either out of range or has been deleted.` );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ validateGeometryId( geometryId ) {
|
|
|
+
|
|
|
+ const geometryInfoList = this._geometryInfo;
|
|
|
+ if ( geometryId < 0 || geometryId >= geometryInfoList.length || geometryInfoList[ geometryId ].active === false ) {
|
|
|
+
|
|
|
+ throw new Error( `THREE.BatchedMesh: Invalid geometryId ${geometryId}. Geometry is either out of range or has been deleted.` );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
setCustomSort( func ) {
|
|
|
|
|
|
this.customSort = func;
|
|
|
@@ -15802,7 +15825,7 @@ class BatchedMesh extends Mesh {
|
|
|
// ensure we're not over geometry
|
|
|
if ( atCapacity && this._availableInstanceIds.length === 0 ) {
|
|
|
|
|
|
- throw new Error( 'BatchedMesh: Maximum item count reached.' );
|
|
|
+ throw new Error( 'THREE.BatchedMesh: Maximum item count reached.' );
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -15891,7 +15914,7 @@ class BatchedMesh extends Mesh {
|
|
|
geometryInfo.vertexStart + geometryInfo.reservedVertexCount > this._maxVertexCount
|
|
|
) {
|
|
|
|
|
|
- throw new Error( 'BatchedMesh: Reserved space request exceeds the maximum buffer size.' );
|
|
|
+ throw new Error( 'THREE.BatchedMesh: Reserved space request exceeds the maximum buffer size.' );
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -15928,7 +15951,7 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
if ( geometryId >= this._geometryCount ) {
|
|
|
|
|
|
- throw new Error( 'BatchedMesh: Maximum geometry count reached.' );
|
|
|
+ throw new Error( 'THREE.BatchedMesh: Maximum geometry count reached.' );
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -15945,7 +15968,7 @@ class BatchedMesh extends Mesh {
|
|
|
geometry.attributes.position.count > geometryInfo.reservedVertexCount
|
|
|
) {
|
|
|
|
|
|
- throw new Error( 'BatchedMesh: Reserved space not large enough for provided geometry.' );
|
|
|
+ throw new Error( 'THREE.BatchedMesh: Reserved space not large enough for provided geometry.' );
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -16060,14 +16083,9 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
deleteInstance( instanceId ) {
|
|
|
|
|
|
- const instanceInfo = this._instanceInfo;
|
|
|
- if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
|
-
|
|
|
- return this;
|
|
|
-
|
|
|
- }
|
|
|
+ this.validateInstanceId( instanceId );
|
|
|
|
|
|
- instanceInfo[ instanceId ].active = false;
|
|
|
+ this._instanceInfo[ instanceId ].active = false;
|
|
|
this._availableInstanceIds.push( instanceId );
|
|
|
this._visibilityChanged = true;
|
|
|
|
|
|
@@ -16251,15 +16269,10 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
setMatrixAt( instanceId, matrix ) {
|
|
|
|
|
|
- const instanceInfo = this._instanceInfo;
|
|
|
+ this.validateInstanceId( instanceId );
|
|
|
+
|
|
|
const matricesTexture = this._matricesTexture;
|
|
|
const matricesArray = this._matricesTexture.image.data;
|
|
|
- if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
|
-
|
|
|
- return this;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
matrix.toArray( matricesArray, instanceId * 16 );
|
|
|
matricesTexture.needsUpdate = true;
|
|
|
|
|
|
@@ -16269,37 +16282,23 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
getMatrixAt( instanceId, matrix ) {
|
|
|
|
|
|
- const instanceInfo = this._instanceInfo;
|
|
|
- const matricesArray = this._matricesTexture.image.data;
|
|
|
- if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
|
-
|
|
|
- return null;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return matrix.fromArray( matricesArray, instanceId * 16 );
|
|
|
+ this.validateInstanceId( instanceId );
|
|
|
+ return matrix.fromArray( this._matricesTexture.image.data, instanceId * 16 );
|
|
|
|
|
|
}
|
|
|
|
|
|
setColorAt( instanceId, color ) {
|
|
|
|
|
|
+ this.validateInstanceId( instanceId );
|
|
|
+
|
|
|
if ( this._colorsTexture === null ) {
|
|
|
|
|
|
this._initColorsTexture();
|
|
|
|
|
|
}
|
|
|
|
|
|
- const colorsTexture = this._colorsTexture;
|
|
|
- const colorsArray = this._colorsTexture.image.data;
|
|
|
- const instanceInfo = this._instanceInfo;
|
|
|
- if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
|
-
|
|
|
- return this;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- color.toArray( colorsArray, instanceId * 4 );
|
|
|
- colorsTexture.needsUpdate = true;
|
|
|
+ color.toArray( this._colorsTexture.image.data, instanceId * 4 );
|
|
|
+ this._colorsTexture.needsUpdate = true;
|
|
|
|
|
|
return this;
|
|
|
|
|
|
@@ -16307,34 +16306,22 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
getColorAt( instanceId, color ) {
|
|
|
|
|
|
- const colorsArray = this._colorsTexture.image.data;
|
|
|
- const instanceInfo = this._instanceInfo;
|
|
|
- if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
|
-
|
|
|
- return null;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return color.fromArray( colorsArray, instanceId * 4 );
|
|
|
+ this.validateInstanceId( instanceId );
|
|
|
+ return color.fromArray( this._colorsTexture.image.data, instanceId * 4 );
|
|
|
|
|
|
}
|
|
|
|
|
|
setVisibleAt( instanceId, value ) {
|
|
|
|
|
|
- // if the geometry is out of range, not active, or visibility state
|
|
|
- // does not change then return early
|
|
|
- const instanceInfo = this._instanceInfo;
|
|
|
- if (
|
|
|
- instanceId >= instanceInfo.length ||
|
|
|
- instanceInfo[ instanceId ].active === false ||
|
|
|
- instanceInfo[ instanceId ].visible === value
|
|
|
- ) {
|
|
|
+ this.validateInstanceId( instanceId );
|
|
|
+
|
|
|
+ if ( this._instanceInfo[ instanceId ].visible === value ) {
|
|
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
- instanceInfo[ instanceId ].visible = value;
|
|
|
+ this._instanceInfo[ instanceId ].visible = value;
|
|
|
this._visibilityChanged = true;
|
|
|
|
|
|
return this;
|
|
|
@@ -16343,37 +16330,18 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
getVisibleAt( instanceId ) {
|
|
|
|
|
|
- // return early if the geometry is out of range or not active
|
|
|
- const instanceInfo = this._instanceInfo;
|
|
|
- if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
|
-
|
|
|
- return false;
|
|
|
+ this.validateInstanceId( instanceId );
|
|
|
|
|
|
- }
|
|
|
-
|
|
|
- return instanceInfo[ instanceId ].visible;
|
|
|
+ return this._instanceInfo[ instanceId ].visible;
|
|
|
|
|
|
}
|
|
|
|
|
|
setGeometryIdAt( instanceId, geometryId ) {
|
|
|
|
|
|
- // return early if the geometry is out of range or not active
|
|
|
- const instanceInfo = this._instanceInfo;
|
|
|
- const geometryInfoList = this._geometryInfo;
|
|
|
- if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
|
-
|
|
|
- return null;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- // check if the provided geometryId is within the valid range
|
|
|
- if ( geometryId >= geometryInfoList.length || geometryInfoList[ geometryId ].active === false ) {
|
|
|
-
|
|
|
- return null;
|
|
|
+ this.validateInstanceId( instanceId );
|
|
|
+ this.validateGeometryId( geometryId );
|
|
|
|
|
|
- }
|
|
|
-
|
|
|
- instanceInfo[ instanceId ].geometryIndex = geometryId;
|
|
|
+ this._instanceInfo[ instanceId ].geometryIndex = geometryId;
|
|
|
|
|
|
return this;
|
|
|
|
|
|
@@ -16381,24 +16349,15 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
getGeometryIdAt( instanceId ) {
|
|
|
|
|
|
- const instanceInfo = this._instanceInfo;
|
|
|
- if ( instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
|
|
|
+ this.validateInstanceId( instanceId );
|
|
|
|
|
|
- return - 1;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return instanceInfo[ instanceId ].geometryIndex;
|
|
|
+ return this._instanceInfo[ instanceId ].geometryIndex;
|
|
|
|
|
|
}
|
|
|
|
|
|
getGeometryRangeAt( geometryId, target = {} ) {
|
|
|
|
|
|
- if ( geometryId < 0 || geometryId >= this._geometryCount ) {
|
|
|
-
|
|
|
- return null;
|
|
|
-
|
|
|
- }
|
|
|
+ this.validateGeometryId( geometryId );
|
|
|
|
|
|
const geometryInfo = this._geometryInfo[ geometryId ];
|
|
|
target.vertexStart = geometryInfo.vertexStart;
|
|
|
@@ -50170,18 +50129,17 @@ class Animation {
|
|
|
this.nodes = nodes;
|
|
|
this.info = info;
|
|
|
|
|
|
- this.animationLoop = null;
|
|
|
- this.requestId = null;
|
|
|
-
|
|
|
- this._init();
|
|
|
+ this._context = self;
|
|
|
+ this._animationLoop = null;
|
|
|
+ this._requestId = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
- _init() {
|
|
|
+ start() {
|
|
|
|
|
|
const update = ( time, frame ) => {
|
|
|
|
|
|
- this.requestId = self.requestAnimationFrame( update );
|
|
|
+ this._requestId = this._context.requestAnimationFrame( update );
|
|
|
|
|
|
if ( this.info.autoReset === true ) this.info.reset();
|
|
|
|
|
|
@@ -50189,7 +50147,7 @@ class Animation {
|
|
|
|
|
|
this.info.frame = this.nodes.nodeFrame.frameId;
|
|
|
|
|
|
- if ( this.animationLoop !== null ) this.animationLoop( time, frame );
|
|
|
+ if ( this._animationLoop !== null ) this._animationLoop( time, frame );
|
|
|
|
|
|
};
|
|
|
|
|
|
@@ -50197,16 +50155,29 @@ class Animation {
|
|
|
|
|
|
}
|
|
|
|
|
|
- dispose() {
|
|
|
+ stop() {
|
|
|
+
|
|
|
+ this._context.cancelAnimationFrame( this._requestId );
|
|
|
|
|
|
- self.cancelAnimationFrame( this.requestId );
|
|
|
- this.requestId = null;
|
|
|
+ this._requestId = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
setAnimationLoop( callback ) {
|
|
|
|
|
|
- this.animationLoop = callback;
|
|
|
+ this._animationLoop = callback;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ setContext( context ) {
|
|
|
+
|
|
|
+ this._context = context;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ dispose() {
|
|
|
+
|
|
|
+ this.stop();
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -50719,9 +50690,12 @@ class RenderObjects {
|
|
|
|
|
|
renderObject.updateClipping( clippingContext );
|
|
|
|
|
|
- if ( renderObject.version !== material.version || renderObject.needsUpdate ) {
|
|
|
+ // force update if geometry has changed
|
|
|
+ const forceUpdate = renderObject.geometry.id !== renderObject.object.geometry.id;
|
|
|
+
|
|
|
+ if ( forceUpdate || renderObject.version !== material.version || renderObject.needsUpdate ) {
|
|
|
|
|
|
- if ( renderObject.initialCacheKey !== renderObject.getCacheKey() ) {
|
|
|
+ if ( forceUpdate || renderObject.initialCacheKey !== renderObject.getCacheKey() ) {
|
|
|
|
|
|
renderObject.dispose();
|
|
|
|
|
|
@@ -64293,6 +64267,7 @@ class Renderer {
|
|
|
|
|
|
//
|
|
|
|
|
|
+ this._animation.start();
|
|
|
this._initialized = true;
|
|
|
|
|
|
resolve();
|