|
@@ -5,6 +5,7 @@ import { FloatType } from '../constants.js';
|
|
|
import { Matrix4 } from '../math/Matrix4.js';
|
|
|
import { Mesh } from './Mesh.js';
|
|
|
import { RGBAFormat } from '../constants.js';
|
|
|
+import { ColorManagement } from '../math/ColorManagement.js';
|
|
|
import { Box3 } from '../math/Box3.js';
|
|
|
import { Sphere } from '../math/Sphere.js';
|
|
|
import { Frustum } from '../math/Frustum.js';
|
|
@@ -160,6 +161,9 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
this._initMatricesTexture();
|
|
|
|
|
|
+ // Local color per geometry by using data texture
|
|
|
+ this._colorsTexture = null;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
_initMatricesTexture() {
|
|
@@ -182,6 +186,19 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ _initColorsTexture() {
|
|
|
+
|
|
|
+ let size = Math.sqrt( this._maxGeometryCount );
|
|
|
+ size = Math.ceil( size );
|
|
|
+
|
|
|
+ const colorsArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
|
|
|
+ const colorsTexture = new DataTexture( colorsArray, size, size, RGBAFormat, FloatType );
|
|
|
+ colorsTexture.colorSpace = ColorManagement.workingColorSpace;
|
|
|
+
|
|
|
+ this._colorsTexture = colorsTexture;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
_initializeGeometry( reference ) {
|
|
|
|
|
|
const geometry = this.geometry;
|
|
@@ -746,6 +763,49 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ setColorAt( geometryId, color ) {
|
|
|
+
|
|
|
+ if ( this._colorsTexture === null ) {
|
|
|
+
|
|
|
+ this._initColorsTexture();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // @TODO: Map geometryId to index of the arrays because
|
|
|
+ // optimize() can make geometryId mismatch the index
|
|
|
+
|
|
|
+ const active = this._active;
|
|
|
+ const colorsTexture = this._colorsTexture;
|
|
|
+ const colorsArray = this._colorsTexture.image.data;
|
|
|
+ const geometryCount = this._geometryCount;
|
|
|
+ if ( geometryId >= geometryCount || active[ geometryId ] === false ) {
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ color.toArray( colorsArray, geometryId * 4 );
|
|
|
+ colorsTexture.needsUpdate = true;
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ getColorAt( geometryId, color ) {
|
|
|
+
|
|
|
+ const active = this._active;
|
|
|
+ const colorsArray = this._colorsTexture.image.data;
|
|
|
+ const geometryCount = this._geometryCount;
|
|
|
+ if ( geometryId >= geometryCount || active[ geometryId ] === false ) {
|
|
|
+
|
|
|
+ return null;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return color.fromArray( colorsArray, geometryId * 4 );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
setVisibleAt( geometryId, value ) {
|
|
|
|
|
|
const visibility = this._visibility;
|
|
@@ -886,6 +946,13 @@ class BatchedMesh extends Mesh {
|
|
|
this._matricesTexture = source._matricesTexture.clone();
|
|
|
this._matricesTexture.image.data = this._matricesTexture.image.slice();
|
|
|
|
|
|
+ if ( this._colorsTexture !== null ) {
|
|
|
+
|
|
|
+ this._colorsTexture = source._colorsTexture.clone();
|
|
|
+ this._colorsTexture.image.data = this._colorsTexture.image.slice();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
return this;
|
|
|
|
|
|
}
|
|
@@ -897,6 +964,14 @@ class BatchedMesh extends Mesh {
|
|
|
|
|
|
this._matricesTexture.dispose();
|
|
|
this._matricesTexture = null;
|
|
|
+
|
|
|
+ if ( this._colorsTexture !== null ) {
|
|
|
+
|
|
|
+ this._colorsTexture.dispose();
|
|
|
+ this._colorsTexture = null;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
return this;
|
|
|
|
|
|
}
|