Buckets:
| ; | |
| var __defProp = Object.defineProperty; | |
| var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; | |
| var __publicField = (obj, key, value) => { | |
| __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); | |
| return value; | |
| }; | |
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | |
| const THREE = require("three"); | |
| const ID_ATTR_NAME = "_batch_id_"; | |
| const _identityMatrix = /* @__PURE__ */ new THREE.Matrix4(); | |
| const _zeroScaleMatrix = /* @__PURE__ */ (() => new THREE.Matrix4().set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1))(); | |
| const batchingParsVertex = ( | |
| /* glsl */ | |
| ` | |
| #ifdef BATCHING | |
| attribute float ${ID_ATTR_NAME}; | |
| uniform highp sampler2D batchingTexture; | |
| mat4 getBatchingMatrix( const in float i ) { | |
| int size = textureSize( batchingTexture, 0 ).x; | |
| int j = int( i ) * 4; | |
| int x = j % size; | |
| int y = j / size; | |
| vec4 v1 = texelFetch( batchingTexture, ivec2( x, y ), 0 ); | |
| vec4 v2 = texelFetch( batchingTexture, ivec2( x + 1, y ), 0 ); | |
| vec4 v3 = texelFetch( batchingTexture, ivec2( x + 2, y ), 0 ); | |
| vec4 v4 = texelFetch( batchingTexture, ivec2( x + 3, y ), 0 ); | |
| return mat4( v1, v2, v3, v4 ); | |
| } | |
| #endif | |
| ` | |
| ); | |
| const batchingbaseVertex = ( | |
| /* glsl */ | |
| ` | |
| #ifdef BATCHING | |
| mat4 batchingMatrix = getBatchingMatrix( ${ID_ATTR_NAME} ); | |
| #endif | |
| ` | |
| ); | |
| const batchingnormalVertex = ( | |
| /* glsl */ | |
| ` | |
| #ifdef BATCHING | |
| objectNormal = vec4( batchingMatrix * vec4( objectNormal, 0.0 ) ).xyz; | |
| #ifdef USE_TANGENT | |
| objectTangent = vec4( batchingMatrix * vec4( objectTangent, 0.0 ) ).xyz; | |
| #endif | |
| #endif | |
| ` | |
| ); | |
| const batchingVertex = ( | |
| /* glsl */ | |
| ` | |
| #ifdef BATCHING | |
| transformed = ( batchingMatrix * vec4( transformed, 1.0 ) ).xyz; | |
| #endif | |
| ` | |
| ); | |
| function copyAttributeData(src, target, targetOffset = 0) { | |
| const itemSize = target.itemSize; | |
| if (src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor) { | |
| const vertexCount = src.count; | |
| for (let i = 0; i < vertexCount; i++) { | |
| for (let c = 0; c < itemSize; c++) { | |
| target.setComponent(i + targetOffset, c, src.getComponent(i, c)); | |
| } | |
| } | |
| } else { | |
| target.array.set(src.array, targetOffset * itemSize); | |
| } | |
| target.needsUpdate = true; | |
| } | |
| class BatchedMesh extends THREE.Mesh { | |
| constructor(maxGeometryCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material) { | |
| super(new THREE.BufferGeometry(), material); | |
| __publicField(this, "_vertexStarts"); | |
| __publicField(this, "_vertexCounts"); | |
| __publicField(this, "_indexStarts"); | |
| __publicField(this, "_indexCounts"); | |
| __publicField(this, "_reservedRanges"); | |
| __publicField(this, "_visible"); | |
| __publicField(this, "_active"); | |
| __publicField(this, "_maxGeometryCount"); | |
| __publicField(this, "_maxVertexCount"); | |
| __publicField(this, "_maxIndexCount"); | |
| __publicField(this, "_geometryInitialized"); | |
| __publicField(this, "_geometryCount"); | |
| __publicField(this, "_matrices"); | |
| __publicField(this, "_matricesTexture"); | |
| __publicField(this, "_customUniforms"); | |
| this._vertexStarts = []; | |
| this._vertexCounts = []; | |
| this._indexStarts = []; | |
| this._indexCounts = []; | |
| this._reservedRanges = []; | |
| this._visible = []; | |
| this._active = []; | |
| this._maxGeometryCount = maxGeometryCount; | |
| this._maxVertexCount = maxVertexCount; | |
| this._maxIndexCount = maxIndexCount; | |
| this._geometryInitialized = false; | |
| this._geometryCount = 0; | |
| this._matrices = []; | |
| this._matricesTexture = null; | |
| this.frustumCulled = false; | |
| this._customUniforms = { | |
| batchingTexture: { value: null } | |
| }; | |
| this._initMatricesTexture(); | |
| this._initShader(); | |
| this.onBeforeRender = function() { | |
| if (this.material.defines) { | |
| this.material.defines.BATCHING = true; | |
| } | |
| }; | |
| this.onAfterRender = function() { | |
| if (this.material.defines) { | |
| this.material.defines.BATCHING = false; | |
| } | |
| }; | |
| } | |
| _initMatricesTexture() { | |
| let size = Math.sqrt(this._maxGeometryCount * 4); | |
| size = THREE.MathUtils.ceilPowerOfTwo(size); | |
| size = Math.max(size, 4); | |
| const matricesArray = new Float32Array(size * size * 4); | |
| const matricesTexture = new THREE.DataTexture(matricesArray, size, size, THREE.RGBAFormat, THREE.FloatType); | |
| this._matricesTexture = matricesTexture; | |
| this._customUniforms.batchingTexture.value = this._matricesTexture; | |
| } | |
| _initShader() { | |
| const material = this.material; | |
| const currentOnBeforeCompile = material.onBeforeCompile; | |
| const customUniforms = this._customUniforms; | |
| material.onBeforeCompile = function onBeforeCompile(parameters, renderer) { | |
| parameters.vertexShader = parameters.vertexShader.replace("#include <skinning_pars_vertex>", "#include <skinning_pars_vertex>\n" + batchingParsVertex).replace("#include <uv_vertex>", "#include <uv_vertex>\n" + batchingbaseVertex).replace("#include <skinnormal_vertex>", "#include <skinnormal_vertex>\n" + batchingnormalVertex).replace("#include <skinning_vertex>", "#include <skinning_vertex>\n" + batchingVertex); | |
| for (const uniformName in customUniforms) { | |
| parameters.uniforms[uniformName] = customUniforms[uniformName]; | |
| } | |
| currentOnBeforeCompile.call(this, parameters, renderer); | |
| }; | |
| material.defines = material.defines || {}; | |
| material.defines.BATCHING = false; | |
| } | |
| _initializeGeometry(reference) { | |
| const geometry = this.geometry; | |
| const maxVertexCount = this._maxVertexCount; | |
| const maxGeometryCount = this._maxGeometryCount; | |
| const maxIndexCount = this._maxIndexCount; | |
| if (this._geometryInitialized === false) { | |
| for (const attributeName in reference.attributes) { | |
| const srcAttribute = reference.getAttribute(attributeName); | |
| const { array, itemSize, normalized } = srcAttribute; | |
| const dstArray = new array.constructor(maxVertexCount * itemSize); | |
| const dstAttribute = new srcAttribute.constructor(dstArray, itemSize, normalized); | |
| dstAttribute.setUsage(srcAttribute.usage); | |
| geometry.setAttribute(attributeName, dstAttribute); | |
| } | |
| if (reference.getIndex() !== null) { | |
| const indexArray = maxVertexCount > 65536 ? new Uint32Array(maxIndexCount) : new Uint16Array(maxIndexCount); | |
| geometry.setIndex(new THREE.BufferAttribute(indexArray, 1)); | |
| } | |
| const idArray = maxGeometryCount > 65536 ? new Uint32Array(maxVertexCount) : new Uint16Array(maxVertexCount); | |
| geometry.setAttribute(ID_ATTR_NAME, new THREE.BufferAttribute(idArray, 1)); | |
| this._geometryInitialized = true; | |
| } | |
| } | |
| // Make sure the geometry is compatible with the existing combined geometry atributes | |
| _validateGeometry(geometry) { | |
| if (geometry.getAttribute(ID_ATTR_NAME)) { | |
| throw new Error(`BatchedMesh: Geometry cannot use attribute "${ID_ATTR_NAME}"`); | |
| } | |
| const batchGeometry = this.geometry; | |
| if (Boolean(geometry.getIndex()) !== Boolean(batchGeometry.getIndex())) { | |
| throw new Error('BatchedMesh: All geometries must consistently have "index".'); | |
| } | |
| for (const attributeName in batchGeometry.attributes) { | |
| if (attributeName === ID_ATTR_NAME) { | |
| continue; | |
| } | |
| if (!geometry.hasAttribute(attributeName)) { | |
| throw new Error( | |
| `BatchedMesh: Added geometry missing "${attributeName}". All geometries must have consistent attributes.` | |
| ); | |
| } | |
| const srcAttribute = geometry.getAttribute(attributeName); | |
| 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."); | |
| } | |
| } | |
| } | |
| getGeometryCount() { | |
| return this._geometryCount; | |
| } | |
| getVertexCount() { | |
| const reservedRanges = this._reservedRanges; | |
| if (reservedRanges.length === 0) { | |
| return 0; | |
| } else { | |
| const finalRange = reservedRanges[reservedRanges.length - 1]; | |
| return finalRange.vertexStart + finalRange.vertexCount; | |
| } | |
| } | |
| getIndexCount() { | |
| const reservedRanges = this._reservedRanges; | |
| const geometry = this.geometry; | |
| if (geometry.getIndex() === null || reservedRanges.length === 0) { | |
| return 0; | |
| } else { | |
| const finalRange = reservedRanges[reservedRanges.length - 1]; | |
| return finalRange.indexStart + finalRange.indexCount; | |
| } | |
| } | |
| addGeometry(geometry, vertexCount = -1, indexCount = -1) { | |
| this._initializeGeometry(geometry); | |
| this._validateGeometry(geometry); | |
| if (this._geometryCount >= this._maxGeometryCount) { | |
| throw new Error("BatchedMesh: Maximum geometry count reached."); | |
| } | |
| const range = { | |
| vertexStart: -1, | |
| vertexCount: -1, | |
| indexStart: -1, | |
| indexCount: -1 | |
| }; | |
| let lastRange = null; | |
| const reservedRanges = this._reservedRanges; | |
| if (this._geometryCount !== 0) { | |
| lastRange = reservedRanges[reservedRanges.length - 1]; | |
| } | |
| if (vertexCount === -1) { | |
| range.vertexCount = geometry.getAttribute("position").count; | |
| } else { | |
| range.vertexCount = vertexCount; | |
| } | |
| if (lastRange === null) { | |
| range.vertexStart = 0; | |
| } else { | |
| range.vertexStart = lastRange.vertexStart + lastRange.vertexCount; | |
| } | |
| if (geometry.getIndex() !== null) { | |
| if (indexCount === -1) { | |
| range.indexCount = geometry.getIndex().count; | |
| } else { | |
| range.indexCount = indexCount; | |
| } | |
| if (lastRange === null) { | |
| range.indexStart = 0; | |
| } else { | |
| range.indexStart = lastRange.indexStart + lastRange.indexCount; | |
| } | |
| } | |
| if (range.indexStart !== -1 && range.indexStart + range.indexCount > this._maxIndexCount || range.vertexStart + range.vertexCount > this._maxVertexCount) { | |
| throw new Error("BatchedMesh: Reserved space request exceeds the maximum buffer size."); | |
| } | |
| const indexCounts = this._indexCounts; | |
| const indexStarts = this._indexStarts; | |
| const vertexCounts = this._vertexCounts; | |
| const vertexStarts = this._vertexStarts; | |
| const visible = this._visible; | |
| const active = this._active; | |
| const matricesTexture = this._matricesTexture; | |
| const matrices = this._matrices; | |
| const matricesArray = this._matricesTexture.image.data; | |
| visible.push(true); | |
| active.push(true); | |
| const geometryId = this._geometryCount; | |
| this._geometryCount++; | |
| matrices.push(new THREE.Matrix4()); | |
| _identityMatrix.toArray(matricesArray, geometryId * 16); | |
| matricesTexture.needsUpdate = true; | |
| reservedRanges.push(range); | |
| vertexStarts.push(range.vertexStart); | |
| vertexCounts.push(range.vertexCount); | |
| if (geometry.getIndex() !== null) { | |
| indexStarts.push(range.indexCount); | |
| indexCounts.push(range.indexCount); | |
| } | |
| const idAttribute = this.geometry.getAttribute(ID_ATTR_NAME); | |
| for (let i = 0; i < range.vertexCount; i++) { | |
| idAttribute.setX(range.vertexStart + i, geometryId); | |
| } | |
| idAttribute.needsUpdate = true; | |
| this.setGeometryAt(geometryId, geometry); | |
| return geometryId; | |
| } | |
| /** | |
| * @deprecated use `addGeometry` instead. | |
| */ | |
| applyGeometry(geometry) { | |
| return this.addGeometry(geometry); | |
| } | |
| setGeometryAt(id, geometry) { | |
| if (id >= this._geometryCount) { | |
| throw new Error("BatchedMesh: Maximum geometry count reached."); | |
| } | |
| this._validateGeometry(geometry); | |
| const range = this._reservedRanges[id]; | |
| if (geometry.getIndex() !== null && geometry.getIndex().count > range.indexCount || geometry.attributes.position.count > range.vertexCount) { | |
| throw new Error("BatchedMesh: Reserved space not large enough for provided geometry."); | |
| } | |
| const batchGeometry = this.geometry; | |
| const srcPositionAttribute = geometry.getAttribute("position"); | |
| const hasIndex = batchGeometry.getIndex() !== null; | |
| const dstIndex = batchGeometry.getIndex(); | |
| const srcIndex = geometry.getIndex(); | |
| const vertexStart = range.vertexStart; | |
| const vertexCount = range.vertexCount; | |
| for (const attributeName in batchGeometry.attributes) { | |
| if (attributeName === ID_ATTR_NAME) { | |
| continue; | |
| } | |
| const srcAttribute = geometry.getAttribute(attributeName); | |
| const dstAttribute = batchGeometry.getAttribute(attributeName); | |
| copyAttributeData(srcAttribute, dstAttribute, vertexStart); | |
| const itemSize = srcAttribute.itemSize; | |
| for (let i = srcAttribute.count, l = vertexCount; i < l; i++) { | |
| const index = vertexStart + i; | |
| for (let c = 0; c < itemSize; c++) { | |
| dstAttribute.setComponent(index, c, 0); | |
| } | |
| } | |
| dstAttribute.needsUpdate = true; | |
| } | |
| this._vertexCounts[id] = srcPositionAttribute.count; | |
| if (hasIndex) { | |
| const indexStart = range.indexStart; | |
| for (let i = 0; i < srcIndex.count; i++) { | |
| dstIndex.setX(indexStart + i, vertexStart + srcIndex.getX(i)); | |
| } | |
| for (let i = srcIndex.count, l = range.indexCount; i < l; i++) { | |
| dstIndex.setX(indexStart + i, vertexStart); | |
| } | |
| dstIndex.needsUpdate = true; | |
| this._indexCounts[id] = srcIndex.count; | |
| } | |
| return id; | |
| } | |
| deleteGeometry(geometryId) { | |
| const active = this._active; | |
| const matricesTexture = this._matricesTexture; | |
| const matricesArray = matricesTexture.image.data; | |
| if (geometryId >= active.length || active[geometryId] === false) { | |
| return this; | |
| } | |
| active[geometryId] = false; | |
| _zeroScaleMatrix.toArray(matricesArray, geometryId * 16); | |
| matricesTexture.needsUpdate = true; | |
| return this; | |
| } | |
| optimize() { | |
| throw new Error("BatchedMesh: Optimize function not implemented."); | |
| } | |
| setMatrixAt(geometryId, matrix) { | |
| const visible = this._visible; | |
| const active = this._active; | |
| const matricesTexture = this._matricesTexture; | |
| const matrices = this._matrices; | |
| const matricesArray = matricesTexture.image.data; | |
| if (geometryId >= matrices.length || active[geometryId] === false) { | |
| return this; | |
| } | |
| if (visible[geometryId] === true) { | |
| matrix.toArray(matricesArray, geometryId * 16); | |
| matricesTexture.needsUpdate = true; | |
| } | |
| matrices[geometryId].copy(matrix); | |
| return this; | |
| } | |
| getMatrixAt(geometryId, matrix) { | |
| const matrices = this._matrices; | |
| const active = this._active; | |
| if (geometryId >= matrices.length || active[geometryId] === false) { | |
| return matrix; | |
| } | |
| return matrix.copy(matrices[geometryId]); | |
| } | |
| setVisibleAt(geometryId, value) { | |
| const visible = this._visible; | |
| const active = this._active; | |
| const matricesTexture = this._matricesTexture; | |
| const matrices = this._matrices; | |
| const matricesArray = matricesTexture.image.data; | |
| if (geometryId >= visible.length || active[geometryId] === false || visible[geometryId] === value) { | |
| return this; | |
| } | |
| if (value === true) { | |
| matrices[geometryId].toArray(matricesArray, geometryId * 16); | |
| } else { | |
| _zeroScaleMatrix.toArray(matricesArray, geometryId * 16); | |
| } | |
| matricesTexture.needsUpdate = true; | |
| visible[geometryId] = value; | |
| return this; | |
| } | |
| getVisibleAt(geometryId) { | |
| const visible = this._visible; | |
| const active = this._active; | |
| if (geometryId >= visible.length || active[geometryId] === false) { | |
| return false; | |
| } | |
| return visible[geometryId]; | |
| } | |
| raycast() { | |
| console.warn("BatchedMesh: Raycast function not implemented."); | |
| } | |
| copy() { | |
| throw new Error("BatchedMesh: Copy function not implemented."); | |
| } | |
| toJSON() { | |
| throw new Error("BatchedMesh: toJSON function not implemented."); | |
| } | |
| dispose() { | |
| this.geometry.dispose(); | |
| this._matricesTexture.dispose(); | |
| this._matricesTexture = null; | |
| return this; | |
| } | |
| } | |
| exports.BatchedMesh = BatchedMesh; | |
| //# sourceMappingURL=BatchedMesh.cjs.map | |
Xet Storage Details
- Size:
- 15.9 kB
- Xet hash:
- 1eea6d7ee6e5133fe952a7b3a4eb8dcf6744f474371e0e555c86f524146b4b71
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.