three-zoo 0.4.7 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/BiFovCamera.ts","../src/Bounds.ts","../src/GeometryHasher.ts","../src/SceneTraversal.ts","../src/InstanceAssembler.ts","../node_modules/three/examples/jsm/utils/SkeletonUtils.js","../src/SceneProcessor.ts","../src/SkinnedMeshBaker.ts","../src/Sun.ts"],"sourcesContent":["import type { Box3, BufferAttribute, SkinnedMesh } from \"three\";\nimport { MathUtils, PerspectiveCamera, Vector3 } from \"three\";\n\nconst DEFAULT_HORIZONTAL_FOV = 90;\nconst DEFAULT_VERTICAL_FOV = 90;\nconst DEFAULT_ASPECT = 1;\nconst DEFAULT_NEAR = 1;\nconst DEFAULT_FAR = 1000;\n\nconst MIN_FOV = 1;\nconst MAX_FOV = 179;\n\n/**\n * A camera that supports independent horizontal and vertical FOV settings.\n * Extends Three.js PerspectiveCamera to allow separate control over horizontal\n * and vertical fields of view.\n */\nexport class BiFovCamera extends PerspectiveCamera {\n private horizontalFovInternal: number;\n private verticalFovInternal: number;\n\n /**\n * @param horizontalFov - Horizontal FOV in degrees (90° default)\n * @param verticalFov - Vertical FOV in degrees (90° default)\n * @param aspect - Width/height ratio (1 default)\n * @param near - Near clipping plane (1 default)\n * @param far - Far clipping plane (1000 default)\n */\n constructor(\n horizontalFov = DEFAULT_HORIZONTAL_FOV,\n verticalFov = DEFAULT_VERTICAL_FOV,\n aspect = DEFAULT_ASPECT,\n near = DEFAULT_NEAR,\n far = DEFAULT_FAR,\n ) {\n super(verticalFov, aspect, near, far);\n this.horizontalFovInternal = horizontalFov;\n this.verticalFovInternal = verticalFov;\n this.updateProjectionMatrix();\n }\n\n /** Current horizontal FOV in degrees */\n public get horizontalFov(): number {\n return this.horizontalFovInternal;\n }\n\n /** Current vertical FOV in degrees */\n public get verticalFov(): number {\n return this.verticalFovInternal;\n }\n\n /** Set horizontal FOV in degrees (clamped between 1° and 179°) */\n public set horizontalFov(value: number) {\n this.horizontalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /** Set vertical FOV in degrees (clamped between 1° and 179°) */\n public set verticalFov(value: number) {\n this.verticalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Update both horizontal and vertical FOV\n * @param horizontal - Horizontal FOV in degrees\n * @param vertical - Vertical FOV in degrees\n */\n public setFov(horizontal: number, vertical: number): void {\n this.horizontalFovInternal = MathUtils.clamp(horizontal, MIN_FOV, MAX_FOV);\n this.verticalFovInternal = MathUtils.clamp(vertical, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Copy FOV settings from another BiFovCamera\n * @param source - Camera to copy from\n */\n public copyFovSettings(source: BiFovCamera): void {\n this.horizontalFovInternal = source.horizontalFov;\n this.verticalFovInternal = source.verticalFov;\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates the projection matrix based on FOV settings and aspect ratio.\n * In landscape: preserves horizontal FOV\n * In portrait: preserves vertical FOV\n */\n public override updateProjectionMatrix(): void {\n if (this.aspect > 1) {\n // Landscape orientation: preserve horizontal FOV\n const radians = MathUtils.degToRad(this.horizontalFovInternal);\n this.fov = MathUtils.radToDeg(\n Math.atan(Math.tan(radians / 2) / this.aspect) * 2,\n );\n } else {\n // Portrait orientation: preserve vertical FOV\n this.fov = this.verticalFovInternal;\n }\n\n super.updateProjectionMatrix();\n }\n\n /** Get actual horizontal FOV after aspect ratio adjustments */\n public getEffectiveHorizontalFov(): number {\n if (this.aspect >= 1) {\n return this.horizontalFovInternal;\n }\n const verticalRadians = MathUtils.degToRad(this.verticalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(verticalRadians / 2) * this.aspect) * 2,\n );\n }\n\n /** Get actual vertical FOV after aspect ratio adjustments */\n public getEffectiveVerticalFov(): number {\n if (this.aspect < 1) {\n return this.verticalFovInternal;\n }\n const horizontalRadians = MathUtils.degToRad(this.horizontalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2,\n );\n }\n\n public fitPointsVerticalFov(vertices: Vector3[]): void {\n const up = new Vector3(0, 1, 0).applyQuaternion(this.quaternion);\n\n let maxVerticalAngle = 0;\n\n for (const vertex of vertices) {\n const vertexToCam = this.position.clone().sub(vertex);\n const vertexDirection = vertexToCam.normalize();\n\n const verticalAngle =\n Math.asin(Math.abs(vertexDirection.dot(up))) *\n Math.sign(vertexDirection.dot(up));\n\n if (Math.abs(verticalAngle) > maxVerticalAngle) {\n maxVerticalAngle = Math.abs(verticalAngle);\n }\n }\n\n const requiredFov = MathUtils.radToDeg(2 * maxVerticalAngle);\n\n this.verticalFovInternal = MathUtils.clamp(requiredFov, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n public fitBoxVerticalFov(box: Box3): void {\n this.fitPointsVerticalFov([\n new Vector3(box.min.x, box.min.y, box.min.z),\n new Vector3(box.min.x, box.min.y, box.max.z),\n new Vector3(box.min.x, box.max.y, box.min.z),\n new Vector3(box.min.x, box.max.y, box.max.z),\n new Vector3(box.max.x, box.min.y, box.min.z),\n new Vector3(box.max.x, box.min.y, box.max.z),\n new Vector3(box.max.x, box.max.y, box.min.z),\n new Vector3(box.max.x, box.max.y, box.max.z),\n ]);\n }\n\n public fitSkinnedMeshVerticalFov(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const target = new Vector3();\n\n const points = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n this.fitPointsVerticalFov(points);\n }\n\n public lookAtCenterOfMass(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes.position as BufferAttribute;\n const target = new Vector3();\n const points: Vector3[] = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n const findMainCluster = (points: Vector3[], iterations = 3): Vector3 => {\n if (points.length === 0) {\n return new Vector3();\n }\n\n let center = points[Math.floor(points.length / 2)].clone();\n\n for (let i = 0; i < iterations; i++) {\n let total = new Vector3();\n let count = 0;\n\n for (const point of points) {\n if (\n point.distanceTo(center) < point.distanceTo(total) ||\n count === 0\n ) {\n total.add(point);\n count++;\n }\n }\n\n if (count > 0) {\n center = total.divideScalar(count);\n }\n }\n\n return center;\n };\n\n const centerOfMass = findMainCluster(points);\n this.lookAt(centerOfMass);\n }\n\n public override clone(): this {\n const camera = new BiFovCamera(\n this.horizontalFovInternal,\n this.verticalFovInternal,\n this.aspect,\n this.near,\n this.far,\n ) as this;\n\n camera.copy(this, true);\n return camera;\n }\n}\n","import type { BufferAttribute, Object3D, SkinnedMesh } from \"three\";\nimport { Box3, Vector3 } from \"three\";\n\n/**\n * Box3 with additional convenience methods for width, height, depth, etc.\n */\nexport class Bounds extends Box3 {\n /** Temporary vector for calculations */\n private readonly tempVector3A: Vector3 = new Vector3();\n\n constructor(object?: Object3D) {\n super();\n if (object) {\n this.setFromObject(object);\n }\n }\n\n /** Width (x-axis length) */\n public get width(): number {\n return this.max.x - this.min.x;\n }\n\n /** Height (y-axis length) */\n public get height(): number {\n return this.max.y - this.min.y;\n }\n\n /** Depth (z-axis length) */\n public get depth(): number {\n return this.max.z - this.min.z;\n }\n\n /** Length of the box's diagonal */\n public get diagonal(): number {\n return this.tempVector3A.subVectors(this.max, this.min).length();\n }\n\n public setFromSkinnedMesh(skinnedMesh: SkinnedMesh): Bounds {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const geometry = skinnedMesh.geometry;\n const position = geometry.attributes[\"position\"] as BufferAttribute;\n const target = new Vector3();\n\n const points = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n this.setFromPoints(points);\n return this;\n }\n\n /** Volume (width * height * depth) */\n public getVolume(): number {\n return this.width * this.height * this.depth;\n }\n\n /** Surface area (sum of all six faces) */\n public getSurfaceArea(): number {\n const w = this.width;\n const h = this.height;\n const d = this.depth;\n return 2 * (w * h + h * d + d * w);\n }\n}\n","import type { BufferGeometry } from \"three\";\n\nconst POSITION_COMPONENT_COUNT = 3;\nconst NORMAL_COMPONENT_COUNT = 3;\n\n/**\n * Internal utility to identify identical geometries.\n * @internal\n */\nexport class GeometryHasher {\n /**\n * Creates a hash for a geometry based on its vertex data.\n * Vertices that differ by less than tolerance are considered the same.\n *\n * @param geometry - Geometry to hash\n * @param tolerance - How close vertices need to be to count as identical\n * @returns Hash string that's the same for matching geometries\n * @internal\n */\n public static getGeometryHash(\n geometry: BufferGeometry,\n tolerance: number,\n ): string {\n const position = geometry.attributes[\"position\"];\n\n const positionArray = position.array;\n const positionHashParts: string[] = [];\n\n // Sample vertex positions with tolerance\n for (let i = 0; i < positionArray.length; i += POSITION_COMPONENT_COUNT) {\n const x = Math.round(positionArray[i] / tolerance);\n const y = Math.round(positionArray[i + 1] / tolerance);\n const z = Math.round(positionArray[i + 2] / tolerance);\n positionHashParts.push(`${x},${y},${z}`);\n }\n\n // Hash normal data if available\n const normal = geometry.attributes[\"normal\"];\n const normalHashParts: string[] = [];\n\n const normalArray = normal.array;\n for (let i = 0; i < normalArray.length; i += NORMAL_COMPONENT_COUNT) {\n const x = Math.round(normalArray[i] / tolerance);\n const y = Math.round(normalArray[i + 1] / tolerance);\n const z = Math.round(normalArray[i + 2] / tolerance);\n normalHashParts.push(`${x},${y},${z}`);\n }\n\n // Combine position and normal hashes\n const positionHash = positionHashParts.join(\"|\");\n const normalHash = normalHashParts.join(\"|\");\n\n return `${positionHash}#${normalHash}`;\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { Mesh } from \"three\";\n\n/** Constructor type for type-safe scene traversal */\nexport type Constructor<T> = abstract new (...args: never[]) => T;\n\n/** Find and modify objects in a Three.js scene */\nexport class SceneTraversal {\n /** Find first object with exact name match */\n public static getObjectByName(\n object: Object3D,\n name: string,\n ): Object3D | null {\n if (object.name === name) {\n return object;\n }\n\n for (const child of object.children) {\n const result = SceneTraversal.getObjectByName(child, name);\n if (result) {\n return result;\n }\n }\n\n return null;\n }\n\n /** Find first material with exact name match */\n public static getMaterialByName(\n object: Object3D,\n name: string,\n ): Material | null {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name === name) {\n return material;\n }\n }\n } else if (object.material.name === name) {\n return object.material;\n }\n }\n\n for (const child of object.children) {\n const material = SceneTraversal.getMaterialByName(child, name);\n if (material) {\n return material;\n }\n }\n\n return null;\n }\n\n /** Process all objects of a specific type */\n public static enumerateObjectsByType<T>(\n object: Object3D,\n type: Constructor<T>,\n callback: (instance: T) => void,\n ): void {\n if (object instanceof type) {\n callback(object);\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateObjectsByType(child, type, callback);\n }\n }\n\n /** Process all materials in meshes */\n public static enumerateMaterials(\n object: Object3D,\n callback: (material: Material) => void,\n ): void {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n callback(material);\n }\n } else {\n callback(object.material);\n }\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateMaterials(child, callback);\n }\n }\n\n /** Find all objects whose names match a pattern */\n public static filterObjects(\n object: Object3D,\n filter: RegExp | ((object: Object3D) => boolean),\n ): Object3D[] {\n let result: Object3D[] = [];\n\n if (typeof filter === \"function\") {\n if (filter(object)) {\n result.push(object);\n }\n } else {\n if (object.name && filter.test(object.name)) {\n result.push(object);\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterObjects(child, filter));\n }\n\n return result;\n }\n\n /** Find all materials whose names match a pattern */\n public static filterMaterials(object: Object3D, name: RegExp): Material[] {\n let result: Material[] = [];\n\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name && name.test(material.name)) {\n result.push(material);\n }\n }\n } else {\n if (object.material.name && name.test(object.material.name)) {\n result.push(object.material);\n }\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterMaterials(child, name));\n }\n\n return result;\n }\n\n /** Set shadow properties on meshes */\n public static setShadowRecursive(\n object: Object3D,\n castShadow = true,\n receiveShadow = true,\n filter?: (object: Object3D) => boolean,\n ): void {\n if (object instanceof Mesh || \"isMesh\" in object) {\n (object as Mesh).castShadow = castShadow;\n (object as Mesh).receiveShadow = receiveShadow;\n }\n\n for (const child of object.children) {\n SceneTraversal.setShadowRecursive(\n child,\n castShadow,\n receiveShadow,\n filter,\n );\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { InstancedMesh, Mesh } from \"three\";\nimport { GeometryHasher } from \"./GeometryHasher\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\nconst MIN_INSTANCE_COUNT = 2;\nconst DEFAULT_TOLERANCE = 1e-6;\n\n/** A group of meshes that can be instanced together */\ninterface MeshDescription {\n /** List of meshes */\n meshes: Mesh[];\n /** Materials to use */\n materials: Material[];\n /** Should cast shadows */\n castShadow: boolean;\n /** Should receive shadows */\n receiveShadow: boolean;\n}\n\n/** Configuration for instance assembly */\nexport interface InstanceAssemblerOptions {\n /** Filter which meshes to include */\n filter: (child: Mesh) => boolean;\n\n /** How close vertices need to be to count as identical */\n geometryTolerance: number;\n}\n\n/**\n * Combines identical meshes into instanced versions for better performance.\n * Meshes are considered identical if they share the same geometry and materials.\n */\nexport class InstanceAssembler {\n /**\n * Find meshes that can be instanced and combine them.\n * Only processes meshes that:\n * - Have no children\n * - Pass the filter function (if any)\n * - Share geometry with at least one other mesh\n *\n * @param container - Object containing meshes to process\n * @param options - Optional settings\n */\n public static assemble(\n container: Object3D,\n options: Partial<InstanceAssemblerOptions> = {},\n ): void {\n const dictionary = new Map<string, MeshDescription>();\n const instances: InstancedMesh[] = [];\n\n const tolerance = options.geometryTolerance ?? DEFAULT_TOLERANCE;\n const geometryHashes = new Map<string, string>();\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n if (\n child.children.length === 0 &&\n (!options.filter || options.filter(child))\n ) {\n const materials = Array.isArray(child.material)\n ? child.material\n : [child.material];\n\n let geometryHash = geometryHashes.get(child.geometry.uuid);\n if (!geometryHash) {\n geometryHash = GeometryHasher.getGeometryHash(\n child.geometry,\n tolerance,\n );\n geometryHashes.set(child.geometry.uuid, geometryHash);\n }\n\n const materialKey = materials.map((m) => m.uuid).join(\",\");\n const compositeKey = `${geometryHash}|${materialKey}`;\n\n const entry = dictionary.get(compositeKey) ?? {\n meshes: [],\n materials,\n castShadow: false,\n receiveShadow: false,\n };\n\n if (child.castShadow) {\n entry.castShadow = true;\n }\n\n if (child.receiveShadow) {\n entry.receiveShadow = true;\n }\n\n entry.meshes.push(child);\n dictionary.set(compositeKey, entry);\n }\n });\n\n for (const descriptor of dictionary.values()) {\n if (descriptor.meshes.length < MIN_INSTANCE_COUNT) {\n continue;\n }\n const { meshes, materials, castShadow, receiveShadow } = descriptor;\n\n const sortedMeshes = meshes.sort((a, b) => a.name.localeCompare(b.name));\n const defaultMesh = sortedMeshes[0];\n\n const instancedMesh = new InstancedMesh(\n defaultMesh.geometry,\n materials.length === 1 ? materials[0] : materials,\n sortedMeshes.length,\n );\n\n instancedMesh.name = defaultMesh.name;\n instancedMesh.castShadow = castShadow;\n instancedMesh.receiveShadow = receiveShadow;\n\n for (let i = 0; i < sortedMeshes.length; i++) {\n const mesh = sortedMeshes[i];\n mesh.updateWorldMatrix(true, false);\n instancedMesh.setMatrixAt(i, mesh.matrixWorld);\n instancedMesh.userData[mesh.uuid] = mesh.userData;\n }\n\n instancedMesh.instanceMatrix.needsUpdate = true;\n instances.push(instancedMesh);\n\n for (const mesh of sortedMeshes) {\n mesh.parent?.remove(mesh);\n }\n }\n\n if (instances.length > 0) {\n container.add(...instances);\n }\n }\n}\n","import {\n\tAnimationClip,\n\tAnimationMixer,\n\tMatrix4,\n\tQuaternion,\n\tQuaternionKeyframeTrack,\n\tSkeletonHelper,\n\tVector3,\n\tVectorKeyframeTrack\n} from 'three';\n\n/**\n * @module SkeletonUtils\n * @three_import import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js';\n */\n\nfunction getBoneName( bone, options ) {\n\n\tif ( options.getBoneName !== undefined ) {\n\n\t\treturn options.getBoneName( bone );\n\n\t}\n\n\treturn options.names[ bone.name ];\n\n}\n\n/**\n * Retargets the skeleton from the given source 3D object to the\n * target 3D object.\n *\n * @param {Object3D} target - The target 3D object.\n * @param {Object3D} source - The source 3D object.\n * @param {module:SkeletonUtils~RetargetOptions} options - The options.\n */\nfunction retarget( target, source, options = {} ) {\n\n\tconst quat = new Quaternion(),\n\t\tscale = new Vector3(),\n\t\trelativeMatrix = new Matrix4(),\n\t\tglobalMatrix = new Matrix4();\n\n\toptions.preserveBoneMatrix = options.preserveBoneMatrix !== undefined ? options.preserveBoneMatrix : true;\n\toptions.preserveBonePositions = options.preserveBonePositions !== undefined ? options.preserveBonePositions : true;\n\toptions.useTargetMatrix = options.useTargetMatrix !== undefined ? options.useTargetMatrix : false;\n\toptions.hip = options.hip !== undefined ? options.hip : 'hip';\n\toptions.hipInfluence = options.hipInfluence !== undefined ? options.hipInfluence : new Vector3( 1, 1, 1 );\n\toptions.scale = options.scale !== undefined ? options.scale : 1;\n\toptions.names = options.names || {};\n\n\tconst sourceBones = source.isObject3D ? source.skeleton.bones : getBones( source ),\n\t\tbones = target.isObject3D ? target.skeleton.bones : getBones( target );\n\n\tlet bone, name, boneTo,\n\t\tbonesPosition;\n\n\t// reset bones\n\n\tif ( target.isObject3D ) {\n\n\t\ttarget.skeleton.pose();\n\n\t} else {\n\n\t\toptions.useTargetMatrix = true;\n\t\toptions.preserveBoneMatrix = false;\n\n\t}\n\n\tif ( options.preserveBonePositions ) {\n\n\t\tbonesPosition = [];\n\n\t\tfor ( let i = 0; i < bones.length; i ++ ) {\n\n\t\t\tbonesPosition.push( bones[ i ].position.clone() );\n\n\t\t}\n\n\t}\n\n\tif ( options.preserveBoneMatrix ) {\n\n\t\t// reset matrix\n\n\t\ttarget.updateMatrixWorld();\n\n\t\ttarget.matrixWorld.identity();\n\n\t\t// reset children matrix\n\n\t\tfor ( let i = 0; i < target.children.length; ++ i ) {\n\n\t\t\ttarget.children[ i ].updateMatrixWorld( true );\n\n\t\t}\n\n\t}\n\n\tfor ( let i = 0; i < bones.length; ++ i ) {\n\n\t\tbone = bones[ i ];\n\t\tname = getBoneName( bone, options );\n\n\t\tboneTo = getBoneByName( name, sourceBones );\n\n\t\tglobalMatrix.copy( bone.matrixWorld );\n\n\t\tif ( boneTo ) {\n\n\t\t\tboneTo.updateMatrixWorld();\n\n\t\t\tif ( options.useTargetMatrix ) {\n\n\t\t\t\trelativeMatrix.copy( boneTo.matrixWorld );\n\n\t\t\t} else {\n\n\t\t\t\trelativeMatrix.copy( target.matrixWorld ).invert();\n\t\t\t\trelativeMatrix.multiply( boneTo.matrixWorld );\n\n\t\t\t}\n\n\t\t\t// ignore scale to extract rotation\n\n\t\t\tscale.setFromMatrixScale( relativeMatrix );\n\t\t\trelativeMatrix.scale( scale.set( 1 / scale.x, 1 / scale.y, 1 / scale.z ) );\n\n\t\t\t// apply to global matrix\n\n\t\t\tglobalMatrix.makeRotationFromQuaternion( quat.setFromRotationMatrix( relativeMatrix ) );\n\n\t\t\tif ( target.isObject3D ) {\n\n\t\t\t\tif ( options.localOffsets ) {\n\n\t\t\t\t\tif ( options.localOffsets[ bone.name ] ) {\n\n\t\t\t\t\t\tglobalMatrix.multiply( options.localOffsets[ bone.name ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tglobalMatrix.copyPosition( relativeMatrix );\n\n\t\t}\n\n\t\tif ( name === options.hip ) {\n\n\t\t\tglobalMatrix.elements[ 12 ] *= options.scale * options.hipInfluence.x;\n\t\t\tglobalMatrix.elements[ 13 ] *= options.scale * options.hipInfluence.y;\n\t\t\tglobalMatrix.elements[ 14 ] *= options.scale * options.hipInfluence.z;\n\n\t\t\tif ( options.hipPosition !== undefined ) {\n\n\t\t\t\tglobalMatrix.elements[ 12 ] += options.hipPosition.x * options.scale;\n\t\t\t\tglobalMatrix.elements[ 13 ] += options.hipPosition.y * options.scale;\n\t\t\t\tglobalMatrix.elements[ 14 ] += options.hipPosition.z * options.scale;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( bone.parent ) {\n\n\t\t\tbone.matrix.copy( bone.parent.matrixWorld ).invert();\n\t\t\tbone.matrix.multiply( globalMatrix );\n\n\t\t} else {\n\n\t\t\tbone.matrix.copy( globalMatrix );\n\n\t\t}\n\n\t\tbone.matrix.decompose( bone.position, bone.quaternion, bone.scale );\n\n\t\tbone.updateMatrixWorld();\n\n\t}\n\n\tif ( options.preserveBonePositions ) {\n\n\t\tfor ( let i = 0; i < bones.length; ++ i ) {\n\n\t\t\tbone = bones[ i ];\n\t\t\tname = getBoneName( bone, options ) || bone.name;\n\n\t\t\tif ( name !== options.hip ) {\n\n\t\t\t\tbone.position.copy( bonesPosition[ i ] );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tif ( options.preserveBoneMatrix ) {\n\n\t\t// restore matrix\n\n\t\ttarget.updateMatrixWorld( true );\n\n\t}\n\n}\n\n/**\n * Retargets the animation clip of the source object to the\n * target 3D object.\n *\n * @param {Object3D} target - The target 3D object.\n * @param {Object3D} source - The source 3D object.\n * @param {AnimationClip} clip - The animation clip.\n * @param {module:SkeletonUtils~RetargetOptions} options - The options.\n * @return {AnimationClip} The retargeted animation clip.\n */\nfunction retargetClip( target, source, clip, options = {} ) {\n\n\toptions.useFirstFramePosition = options.useFirstFramePosition !== undefined ? options.useFirstFramePosition : false;\n\n\t// Calculate the fps from the source clip based on the track with the most frames, unless fps is already provided.\n\toptions.fps = options.fps !== undefined ? options.fps : ( Math.max( ...clip.tracks.map( track => track.times.length ) ) / clip.duration );\n\toptions.names = options.names || [];\n\n\tif ( ! source.isObject3D ) {\n\n\t\tsource = getHelperFromSkeleton( source );\n\n\t}\n\n\tconst numFrames = Math.round( clip.duration * ( options.fps / 1000 ) * 1000 ),\n\t\tdelta = clip.duration / ( numFrames - 1 ),\n\t\tconvertedTracks = [],\n\t\tmixer = new AnimationMixer( source ),\n\t\tbones = getBones( target.skeleton ),\n\t\tboneDatas = [];\n\n\tlet positionOffset,\n\t\tbone, boneTo, boneData,\n\t\tname;\n\n\tmixer.clipAction( clip ).play();\n\n\t// trim\n\n\tlet start = 0, end = numFrames;\n\n\tif ( options.trim !== undefined ) {\n\n\t\tstart = Math.round( options.trim[ 0 ] * options.fps );\n\t\tend = Math.min( Math.round( options.trim[ 1 ] * options.fps ), numFrames ) - start;\n\n\t\tmixer.update( options.trim[ 0 ] );\n\n\t} else {\n\n\t\tmixer.update( 0 );\n\n\t}\n\n\tsource.updateMatrixWorld();\n\n\t//\n\n\tfor ( let frame = 0; frame < end; ++ frame ) {\n\n\t\tconst time = frame * delta;\n\n\t\tretarget( target, source, options );\n\n\t\tfor ( let j = 0; j < bones.length; ++ j ) {\n\n\t\t\tbone = bones[ j ];\n\t\t\tname = getBoneName( bone, options ) || bone.name;\n\t\t\tboneTo = getBoneByName( name, source.skeleton );\n\n\t\t\tif ( boneTo ) {\n\n\t\t\t\tboneData = boneDatas[ j ] = boneDatas[ j ] || { bone: bone };\n\n\t\t\t\tif ( options.hip === name ) {\n\n\t\t\t\t\tif ( ! boneData.pos ) {\n\n\t\t\t\t\t\tboneData.pos = {\n\t\t\t\t\t\t\ttimes: new Float32Array( end ),\n\t\t\t\t\t\t\tvalues: new Float32Array( end * 3 )\n\t\t\t\t\t\t};\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( options.useFirstFramePosition ) {\n\n\t\t\t\t\t\tif ( frame === 0 ) {\n\n\t\t\t\t\t\t\tpositionOffset = bone.position.clone();\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbone.position.sub( positionOffset );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tboneData.pos.times[ frame ] = time;\n\n\t\t\t\t\tbone.position.toArray( boneData.pos.values, frame * 3 );\n\n\t\t\t\t}\n\n\t\t\t\tif ( ! boneData.quat ) {\n\n\t\t\t\t\tboneData.quat = {\n\t\t\t\t\t\ttimes: new Float32Array( end ),\n\t\t\t\t\t\tvalues: new Float32Array( end * 4 )\n\t\t\t\t\t};\n\n\t\t\t\t}\n\n\t\t\t\tboneData.quat.times[ frame ] = time;\n\n\t\t\t\tbone.quaternion.toArray( boneData.quat.values, frame * 4 );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( frame === end - 2 ) {\n\n\t\t\t// last mixer update before final loop iteration\n\t\t\t// make sure we do not go over or equal to clip duration\n\t\t\tmixer.update( delta - 0.0000001 );\n\n\t\t} else {\n\n\t\t\tmixer.update( delta );\n\n\t\t}\n\n\t\tsource.updateMatrixWorld();\n\n\t}\n\n\tfor ( let i = 0; i < boneDatas.length; ++ i ) {\n\n\t\tboneData = boneDatas[ i ];\n\n\t\tif ( boneData ) {\n\n\t\t\tif ( boneData.pos ) {\n\n\t\t\t\tconvertedTracks.push( new VectorKeyframeTrack(\n\t\t\t\t\t'.bones[' + boneData.bone.name + '].position',\n\t\t\t\t\tboneData.pos.times,\n\t\t\t\t\tboneData.pos.values\n\t\t\t\t) );\n\n\t\t\t}\n\n\t\t\tconvertedTracks.push( new QuaternionKeyframeTrack(\n\t\t\t\t'.bones[' + boneData.bone.name + '].quaternion',\n\t\t\t\tboneData.quat.times,\n\t\t\t\tboneData.quat.values\n\t\t\t) );\n\n\t\t}\n\n\t}\n\n\tmixer.uncacheAction( clip );\n\n\treturn new AnimationClip( clip.name, - 1, convertedTracks );\n\n}\n\n/**\n * Clones the given 3D object and its descendants, ensuring that any `SkinnedMesh` instances are\n * correctly associated with their bones. Bones are also cloned, and must be descendants of the\n * object passed to this method. Other data, like geometries and materials, are reused by reference.\n *\n * @param {Object3D} source - The 3D object to clone.\n * @return {Object3D} The cloned 3D object.\n */\nfunction clone( source ) {\n\n\tconst sourceLookup = new Map();\n\tconst cloneLookup = new Map();\n\n\tconst clone = source.clone();\n\n\tparallelTraverse( source, clone, function ( sourceNode, clonedNode ) {\n\n\t\tsourceLookup.set( clonedNode, sourceNode );\n\t\tcloneLookup.set( sourceNode, clonedNode );\n\n\t} );\n\n\tclone.traverse( function ( node ) {\n\n\t\tif ( ! node.isSkinnedMesh ) return;\n\n\t\tconst clonedMesh = node;\n\t\tconst sourceMesh = sourceLookup.get( node );\n\t\tconst sourceBones = sourceMesh.skeleton.bones;\n\n\t\tclonedMesh.skeleton = sourceMesh.skeleton.clone();\n\t\tclonedMesh.bindMatrix.copy( sourceMesh.bindMatrix );\n\n\t\tclonedMesh.skeleton.bones = sourceBones.map( function ( bone ) {\n\n\t\t\treturn cloneLookup.get( bone );\n\n\t\t} );\n\n\t\tclonedMesh.bind( clonedMesh.skeleton, clonedMesh.bindMatrix );\n\n\t} );\n\n\treturn clone;\n\n}\n\n// internal helper\n\nfunction getBoneByName( name, skeleton ) {\n\n\tfor ( let i = 0, bones = getBones( skeleton ); i < bones.length; i ++ ) {\n\n\t\tif ( name === bones[ i ].name )\n\n\t\t\treturn bones[ i ];\n\n\t}\n\n}\n\nfunction getBones( skeleton ) {\n\n\treturn Array.isArray( skeleton ) ? skeleton : skeleton.bones;\n\n}\n\n\nfunction getHelperFromSkeleton( skeleton ) {\n\n\tconst source = new SkeletonHelper( skeleton.bones[ 0 ] );\n\tsource.skeleton = skeleton;\n\n\treturn source;\n\n}\n\nfunction parallelTraverse( a, b, callback ) {\n\n\tcallback( a, b );\n\n\tfor ( let i = 0; i < a.children.length; i ++ ) {\n\n\t\tparallelTraverse( a.children[ i ], b.children[ i ], callback );\n\n\t}\n\n}\n\n/**\n * Retarget options of `SkeletonUtils`.\n *\n * @typedef {Object} module:SkeletonUtils~RetargetOptions\n * @property {boolean} [useFirstFramePosition=false] - Whether to use the position of the first frame or not.\n * @property {number} [fps] - The FPS of the clip.\n * @property {Object<string,string>} [names] - A dictionary for mapping target to source bone names.\n * @property {function(string):string} [getBoneName] - A function for mapping bone names. Alternative to `names`.\n * @property {Array<number>} [trim] - Whether to trim the clip or not. If set the array should hold two values for the start and end.\n * @property {boolean} [preserveBoneMatrix=true] - Whether to preserve bone matrices or not.\n * @property {boolean} [preserveBonePositions=true] - Whether to preserve bone positions or not.\n * @property {boolean} [useTargetMatrix=false] - Whether to use the target matrix or not.\n * @property {string} [hip='hip'] - The name of the source's hip bone.\n * @property {Vector3} [hipInfluence=(1,1,1)] - The hip influence.\n * @property {number} [scale=1] - The scale.\n **/\n\nexport {\n\tretarget,\n\tretargetClip,\n\tclone,\n};\n","import type { Material, Object3D } from \"three\";\nimport { FrontSide, Mesh } from \"three\";\nimport { clone } from \"three/examples/jsm/utils/SkeletonUtils.js\";\nimport { InstanceAssembler } from \"./InstanceAssembler\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\n/** Options for scene post-processing */\nexport interface SceneProcessorOptions {\n /** Clone the input asset before processing? */\n cloneAsset: boolean;\n\n /** Combine identical meshes into instances? */\n assembleInstances: boolean;\n\n /** Names matching these patterns will cast shadows */\n castShadowRegExp: RegExp;\n\n /** Names matching these patterns will receive shadows */\n receiveShadowRegExp: RegExp;\n\n /** Names matching these patterns will be transparent */\n transparentMaterialRegExp: RegExp;\n\n /** Names matching these patterns won't write to depth buffer */\n noDepthWriteMaterialRegExp: RegExp;\n\n /** Names matching these patterns will be alpha tested */\n alphaTestMaterialRegExp: RegExp;\n\n /** Names matching these patterns will be alpha hashed */\n alphaHashMaterialRegExp: RegExp;\n}\n\n/** Post-processes a scene based on name patterns */\nexport class SceneProcessor {\n /**\n * Process a scene to set up materials and shadows.\n *\n * @param object - Scene to process\n * @param options - How to process the scene\n * @returns Processed scene root objects\n */\n public static process(\n object: Object3D,\n options: Partial<SceneProcessorOptions>,\n ): Object3D[] {\n const container = options.cloneAsset !== false ? clone(object) : object;\n\n if (options.assembleInstances !== false) {\n InstanceAssembler.assemble(container);\n }\n\n SceneTraversal.enumerateMaterials(container, (material: Material) => {\n material.transparent =\n options.transparentMaterialRegExp?.test(material.name) ?? false;\n material.depthWrite = !(\n options.noDepthWriteMaterialRegExp?.test(material.name) ?? false\n );\n material.alphaTest = options.alphaTestMaterialRegExp?.test(material.name)\n ? 0.5\n : 0;\n material.alphaHash =\n options.alphaHashMaterialRegExp?.test(material.name) ?? false;\n material.side = FrontSide;\n material.forceSinglePass = true;\n material.depthTest = true;\n });\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n child.castShadow = options.castShadowRegExp?.test(child.name) ?? false;\n child.receiveShadow =\n options.receiveShadowRegExp?.test(child.name) ?? false;\n });\n\n return container.children;\n }\n}\n","import type { AnimationClip, Object3D, SkinnedMesh } from \"three\";\nimport { AnimationMixer, BufferAttribute, Mesh, Vector3 } from \"three\";\n\n/** Number of components per vertex */\nconst COMPONENT_COUNT = 3;\n\n/** Convert skinned meshes to regular static meshes */\nexport class SkinnedMeshBaker {\n /**\n * Convert a skinned mesh to a regular mesh in its current pose.\n * The resulting mesh will have no bones but look identical.\n * \n * @param skinnedMesh - Mesh to convert\n * @returns Static mesh with baked vertex positions\n */\n public static bakePose(skinnedMesh: SkinnedMesh): Mesh {\n const bakedGeometry = skinnedMesh.geometry.clone();\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const newPositions = new Float32Array(position.count * COMPONENT_COUNT);\n const target = new Vector3();\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n newPositions[i * COMPONENT_COUNT + 0] = target.x;\n newPositions[i * COMPONENT_COUNT + 1] = target.y;\n newPositions[i * COMPONENT_COUNT + 2] = target.z;\n }\n\n bakedGeometry.setAttribute(\n \"position\",\n new BufferAttribute(newPositions, COMPONENT_COUNT),\n );\n bakedGeometry.computeVertexNormals();\n bakedGeometry.deleteAttribute(\"skinIndex\");\n bakedGeometry.deleteAttribute(\"skinWeight\");\n\n const mesh = new Mesh(bakedGeometry, skinnedMesh.material);\n mesh.name = skinnedMesh.name;\n return mesh;\n }\n\n /**\n * Bake a single frame from an animation into a static mesh.\n * \n * @param armature - Root object with bones (usually from GLTF)\n * @param skinnedMesh - Mesh to convert\n * @param timeOffset - Time in seconds within the animation\n * @param clip - Animation to get the pose from\n * @returns Static mesh with baked vertex positions\n */\n public static bakeAnimationFrame(\n armature: Object3D,\n skinnedMesh: SkinnedMesh,\n timeOffset: number,\n clip: AnimationClip,\n ): Mesh {\n const mixer = new AnimationMixer(armature);\n const action = mixer.clipAction(clip);\n action.play();\n mixer.setTime(timeOffset);\n\n armature.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n return this.bakePose(skinnedMesh);\n }\n}","import type { Texture } from \"three\";\nimport { Box3, DirectionalLight, RGBAFormat, Spherical, Vector3 } from \"three\";\n\nconst RGBA_CHANNEL_COUNT = 4;\nconst RGB_CHANNEL_COUNT = 3;\n\nconst LUMINANCE_R = 0.2126;\nconst LUMINANCE_G = 0.7152;\nconst LUMINANCE_B = 0.0722;\n\n/** A directional light with spherical positioning controls */\nexport class Sun extends DirectionalLight {\n /** Internal vectors to avoid garbage collection */\n private readonly tempVector3D0 = new Vector3();\n private readonly tempVector3D1 = new Vector3();\n private readonly tempVector3D2 = new Vector3();\n private readonly tempVector3D3 = new Vector3();\n private readonly tempVector3D4 = new Vector3();\n private readonly tempVector3D5 = new Vector3();\n private readonly tempVector3D6 = new Vector3();\n private readonly tempVector3D7 = new Vector3();\n private readonly tempBox3 = new Box3();\n private readonly tempSpherical = new Spherical();\n\n /** Distance from the light to its target */\n public get distance(): number {\n return this.position.length();\n }\n\n /** Vertical angle from the ground in radians */\n public get elevation(): number {\n return this.tempSpherical.setFromVector3(this.position).phi;\n }\n\n /** Horizontal angle around the target in radians */\n public get azimuth(): number {\n return this.tempSpherical.setFromVector3(this.position).theta;\n }\n\n /** Set distance while keeping current angles */\n public set distance(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n value,\n this.tempSpherical.phi,\n this.tempSpherical.theta,\n );\n }\n\n /** Set elevation while keeping current distance and azimuth */\n public set elevation(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n value,\n this.tempSpherical.theta,\n );\n }\n\n /** Set azimuth while keeping current distance and elevation */\n public set azimuth(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n this.tempSpherical.phi,\n value,\n );\n }\n\n /** Configure shadows to cover all corners of a bounding box */\n public setShadowMapFromBox3(box3: Box3): void {\n const camera = this.shadow.camera;\n\n this.target.updateWorldMatrix(true, false);\n this.lookAt(this.target.getWorldPosition(this.tempVector3D0));\n\n this.updateWorldMatrix(true, false);\n\n const points: Vector3[] = [\n this.tempVector3D0.set(box3.min.x, box3.min.y, box3.min.z),\n this.tempVector3D1.set(box3.min.x, box3.min.y, box3.max.z),\n this.tempVector3D2.set(box3.min.x, box3.max.y, box3.min.z),\n this.tempVector3D3.set(box3.min.x, box3.max.y, box3.max.z),\n this.tempVector3D4.set(box3.max.x, box3.min.y, box3.min.z),\n this.tempVector3D5.set(box3.max.x, box3.min.y, box3.max.z),\n this.tempVector3D6.set(box3.max.x, box3.max.y, box3.min.z),\n this.tempVector3D7.set(box3.max.x, box3.max.y, box3.max.z),\n ];\n\n const inverseMatrix = this.matrixWorld.clone().invert();\n\n for (const point of points) {\n point.applyMatrix4(inverseMatrix);\n }\n\n const newBox3 = this.tempBox3.setFromPoints(points);\n\n camera.left = newBox3.min.x;\n camera.bottom = newBox3.min.y;\n camera.near = -newBox3.max.z;\n\n camera.right = newBox3.max.x;\n camera.top = newBox3.max.y;\n camera.far = -newBox3.min.z;\n\n camera.updateWorldMatrix(true, false);\n camera.updateProjectionMatrix();\n }\n\n /** Set light direction based on brightest point in an HDR texture */\n public setDirectionFromHDR(texture: Texture, distance = 1): void {\n const data = texture.image.data;\n const width = texture.image.width;\n const height = texture.image.height;\n\n let maxLuminance = 0;\n let maxIndex = 0;\n\n // Find brightest pixel\n\n const step =\n texture.format === RGBAFormat ? RGBA_CHANNEL_COUNT : RGB_CHANNEL_COUNT;\n for (let i = 0; i < data.length; i += step) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const luminance = LUMINANCE_R * r + LUMINANCE_G * g + LUMINANCE_B * b;\n if (luminance > maxLuminance) {\n maxLuminance = luminance;\n maxIndex = i;\n }\n }\n\n // Convert to spherical coordinates\n const pixelIndex = maxIndex / step;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n\n const u = x / width;\n const v = y / height;\n\n const elevation = v * Math.PI;\n const azimuth = u * -Math.PI * 2 - Math.PI / 2;\n\n this.position.setFromSphericalCoords(distance, elevation, azimuth);\n }\n}\n"],"names":[],"mappings":"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","x_google_ignoreList":[5]}
1
+ {"version":3,"file":"index.js","sources":["../src/DualFovCamera.ts","../src/SceneTraversal.ts","../src/SkinnedMeshBaker.ts","../src/Sun.ts"],"sourcesContent":["import type { Box3, BufferAttribute, SkinnedMesh } from \"three\";\nimport { MathUtils, PerspectiveCamera, Vector3 } from \"three\";\n\n/** Default horizontal field of view in degrees */\nconst DEFAULT_HORIZONTAL_FOV = 90;\n/** Default vertical field of view in degrees */\nconst DEFAULT_VERTICAL_FOV = 90;\n/** Default aspect ratio (width/height) */\nconst DEFAULT_ASPECT = 1;\n/** Default near clipping plane distance */\nconst DEFAULT_NEAR = 1;\n/** Default far clipping plane distance */\nconst DEFAULT_FAR = 1000;\n\n/** Minimum allowed field of view in degrees */\nconst MIN_FOV = 1;\n/** Maximum allowed field of view in degrees */\nconst MAX_FOV = 179;\n\n/**\n * A camera that supports independent horizontal and vertical FOV settings.\n * Extends Three.js PerspectiveCamera to allow separate control over horizontal\n * and vertical fields of view.\n */\nexport class DualFovCamera extends PerspectiveCamera {\n /** Internal storage for horizontal field of view in degrees */\n private horizontalFovInternal: number;\n /** Internal storage for vertical field of view in degrees */\n private verticalFovInternal: number;\n\n /**\n * Creates a new DualFovCamera instance with independent horizontal and vertical FOV control.\n *\n * @param horizontalFov - Horizontal field of view in degrees. Must be between 1° and 179°. Defaults to 90°.\n * @param verticalFov - Vertical field of view in degrees. Must be between 1° and 179°. Defaults to 90°.\n * @param aspect - Camera aspect ratio (width/height). Defaults to 1.\n * @param near - Near clipping plane distance. Must be greater than 0. Defaults to 1.\n * @param far - Far clipping plane distance. Must be greater than near plane. Defaults to 1000.\n */\n constructor(\n horizontalFov = DEFAULT_HORIZONTAL_FOV,\n verticalFov = DEFAULT_VERTICAL_FOV,\n aspect = DEFAULT_ASPECT,\n near = DEFAULT_NEAR,\n far = DEFAULT_FAR,\n ) {\n super(verticalFov, aspect, near, far);\n this.horizontalFovInternal = horizontalFov;\n this.verticalFovInternal = verticalFov;\n this.updateProjectionMatrix();\n }\n\n /**\n * Gets the current horizontal field of view in degrees.\n *\n * @returns The horizontal FOV value between 1° and 179°\n */\n public get horizontalFov(): number {\n return this.horizontalFovInternal;\n }\n\n /**\n * Gets the current vertical field of view in degrees.\n *\n * @returns The vertical FOV value between 1° and 179°\n */\n public get verticalFov(): number {\n return this.verticalFovInternal;\n }\n\n /**\n * Sets the horizontal field of view in degrees.\n *\n * @param value - The horizontal FOV value in degrees. Will be clamped between 1° and 179°.\n */\n public set horizontalFov(value: number) {\n this.horizontalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Sets the vertical field of view in degrees.\n *\n * @param value - The vertical FOV value in degrees. Will be clamped between 1° and 179°.\n */\n public set verticalFov(value: number) {\n this.verticalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates both horizontal and vertical field of view values simultaneously.\n *\n * @param horizontal - Horizontal FOV in degrees. Will be clamped between 1° and 179°.\n * @param vertical - Vertical FOV in degrees. Will be clamped between 1° and 179°.\n */\n public setFov(horizontal: number, vertical: number): void {\n this.horizontalFovInternal = MathUtils.clamp(horizontal, MIN_FOV, MAX_FOV);\n this.verticalFovInternal = MathUtils.clamp(vertical, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Copies the field of view settings from another DualFovCamera instance.\n *\n * @param source - The DualFovCamera instance to copy FOV settings from.\n */\n public copyFovSettings(source: DualFovCamera): void {\n this.horizontalFovInternal = source.horizontalFov;\n this.verticalFovInternal = source.verticalFov;\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates the projection matrix based on current FOV settings and aspect ratio.\n *\n * The behavior differs based on orientation:\n * - **Landscape mode (aspect > 1)**: Preserves horizontal FOV, calculates vertical FOV\n * - **Portrait mode (aspect ≤ 1)**: Preserves vertical FOV, calculates horizontal FOV\n *\n * This method is automatically called when FOV values or aspect ratio changes.\n *\n * @override\n */\n public override updateProjectionMatrix(): void {\n if (this.aspect > 1) {\n // Landscape orientation: preserve horizontal FOV\n const radians = MathUtils.degToRad(this.horizontalFovInternal);\n this.fov = MathUtils.radToDeg(\n Math.atan(Math.tan(radians / 2) / this.aspect) * 2,\n );\n } else {\n // Portrait orientation: preserve vertical FOV\n this.fov = this.verticalFovInternal;\n }\n\n super.updateProjectionMatrix();\n }\n\n /**\n * Gets the actual horizontal field of view after aspect ratio adjustments.\n *\n * In landscape mode, this returns the set horizontal FOV.\n * In portrait mode, this calculates the actual horizontal FOV based on the vertical FOV and aspect ratio.\n *\n * @returns The actual horizontal FOV in degrees\n */\n public getActualHorizontalFov(): number {\n if (this.aspect >= 1) {\n return this.horizontalFovInternal;\n }\n const verticalRadians = MathUtils.degToRad(this.verticalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(verticalRadians / 2) * this.aspect) * 2,\n );\n }\n\n /**\n * Gets the actual vertical field of view after aspect ratio adjustments.\n *\n * In portrait mode, this returns the set vertical FOV.\n * In landscape mode, this calculates the actual vertical FOV based on the horizontal FOV and aspect ratio.\n *\n * @returns The actual vertical FOV in degrees\n */\n public getActualVerticalFov(): number {\n if (this.aspect < 1) {\n return this.verticalFovInternal;\n }\n const horizontalRadians = MathUtils.degToRad(this.horizontalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2,\n );\n }\n\n /**\n * Adjusts the vertical field of view to fit all specified points within the camera's view.\n *\n * This method calculates the required vertical FOV to ensure all provided vertices\n * are visible within the vertical bounds of the camera's frustum.\n *\n * @param vertices - Array of 3D points (in world coordinates) that should fit within the camera's vertical view\n */\n public fitVerticalFovToPoints(vertices: Vector3[]): void {\n const up = new Vector3(0, 1, 0).applyQuaternion(this.quaternion);\n\n let maxVerticalAngle = 0;\n\n for (const vertex of vertices) {\n const vertexToCam = this.position.clone().sub(vertex);\n const vertexDirection = vertexToCam.normalize();\n\n const verticalAngle =\n Math.asin(Math.abs(vertexDirection.dot(up))) *\n Math.sign(vertexDirection.dot(up));\n\n if (Math.abs(verticalAngle) > maxVerticalAngle) {\n maxVerticalAngle = Math.abs(verticalAngle);\n }\n }\n\n const requiredFov = MathUtils.radToDeg(2 * maxVerticalAngle);\n\n this.verticalFovInternal = MathUtils.clamp(requiredFov, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Adjusts the vertical field of view to fit a bounding box within the camera's view.\n *\n * This method calculates the required vertical FOV to ensure the entire bounding box\n * is visible within the vertical bounds of the camera's frustum.\n *\n * @param box - The 3D bounding box (in world coordinates) that should fit within the camera's vertical view\n */\n public fitVerticalFovToBox(box: Box3): void {\n this.fitVerticalFovToPoints([\n new Vector3(box.min.x, box.min.y, box.min.z),\n new Vector3(box.min.x, box.min.y, box.max.z),\n new Vector3(box.min.x, box.max.y, box.min.z),\n new Vector3(box.min.x, box.max.y, box.max.z),\n new Vector3(box.max.x, box.min.y, box.min.z),\n new Vector3(box.max.x, box.min.y, box.max.z),\n new Vector3(box.max.x, box.max.y, box.min.z),\n new Vector3(box.max.x, box.max.y, box.max.z),\n ]);\n }\n\n /**\n * Adjusts the vertical field of view to fit a skinned mesh within the camera's view.\n *\n * This method updates the mesh's skeleton, applies bone transformations to all vertices,\n * and then calculates the required vertical FOV to ensure the entire deformed mesh\n * is visible within the vertical bounds of the camera's frustum.\n *\n * @param skinnedMesh - The skinned mesh (with active skeleton) that should fit within the camera's vertical view\n */\n public fitVerticalFovToMesh(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const target = new Vector3();\n\n const points = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n this.fitVerticalFovToPoints(points);\n }\n\n /**\n * Points the camera to look at the center of mass of a skinned mesh.\n *\n * This method updates the mesh's skeleton, applies bone transformations to all vertices,\n * calculates the center of mass using a clustering algorithm, and then orients the camera\n * to look at that point.\n *\n * The center of mass calculation uses an iterative clustering approach to find the\n * main concentration of vertices, which provides better results than a simple average\n * for complex meshes.\n *\n * @param skinnedMesh - The skinned mesh (with active skeleton) whose center of mass should be the camera's target\n */\n public lookAtMeshCenterOfMass(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes.position as BufferAttribute;\n const target = new Vector3();\n const points: Vector3[] = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n /**\n * Finds the main cluster center of a set of 3D points using iterative refinement.\n *\n * @param points - Array of 3D points to cluster\n * @param iterations - Number of refinement iterations to perform\n * @returns The calculated center point of the main cluster\n */\n const findMainCluster = (points: Vector3[], iterations = 3): Vector3 => {\n if (points.length === 0) {\n return new Vector3();\n }\n\n let center = points[Math.floor(points.length / 2)].clone();\n\n for (let i = 0; i < iterations; i++) {\n let total = new Vector3();\n let count = 0;\n\n for (const point of points) {\n if (\n point.distanceTo(center) < point.distanceTo(total) ||\n count === 0\n ) {\n total.add(point);\n count++;\n }\n }\n\n if (count > 0) {\n center = total.divideScalar(count);\n }\n }\n\n return center;\n };\n\n const centerOfMass = findMainCluster(points);\n this.lookAt(centerOfMass);\n }\n\n /**\n * Creates a deep copy of this DualFovCamera instance.\n *\n * The cloned camera will have identical FOV settings, position, rotation,\n * and all other camera properties.\n *\n * @returns A new DualFovCamera instance that is an exact copy of this one\n * @override\n */\n public override clone(): this {\n const camera = new DualFovCamera(\n this.horizontalFovInternal,\n this.verticalFovInternal,\n this.aspect,\n this.near,\n this.far,\n ) as this;\n\n camera.copy(this, true);\n return camera;\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { Mesh } from \"three\";\n\n/**\n * Constructor type for type-safe scene traversal operations.\n *\n * This type represents any constructor function that can be used to create instances of type T.\n * It's used for runtime type checking when filtering objects by their constructor type.\n *\n * @template T - The type that the constructor creates\n */\nexport type Constructor<T> = abstract new (...args: never[]) => T;\n\n/**\n * Utility class for finding and modifying objects in a Three.js scene graph.\n *\n * This class provides static methods for traversing Three.js scene hierarchies,\n * searching for specific objects or materials, and performing batch operations\n * on collections of scene objects.\n *\n * All methods perform depth-first traversal of the scene graph starting from\n * the provided root object and recursively processing all children.\n */\nexport class SceneTraversal {\n /**\n * Finds the first object in the scene hierarchy with an exact name match.\n *\n * Performs a depth-first search through the scene graph starting from the provided\n * root object. Returns the first object encountered whose name property exactly\n * matches the search string.\n *\n * @param object - The root Object3D to start searching from\n * @param name - The exact name to search for (case-sensitive)\n * @returns The first matching Object3D, or null if no match is found\n\n */\n public static getObjectByName(\n object: Object3D,\n name: string,\n ): Object3D | null {\n if (object.name === name) {\n return object;\n }\n\n for (const child of object.children) {\n const result = SceneTraversal.getObjectByName(child, name);\n if (result) {\n return result;\n }\n }\n\n return null;\n }\n\n /**\n * Finds the first material in the scene hierarchy with an exact name match.\n *\n * Performs a depth-first search through the scene graph, examining materials\n * attached to Mesh objects. Handles both single materials and material arrays.\n * Returns the first material encountered whose name property exactly matches\n * the search string.\n *\n * @param object - The root Object3D to start searching from\n * @param name - The exact material name to search for (case-sensitive)\n * @returns The first matching Material, or null if no match is found\n\n */\n public static getMaterialByName(\n object: Object3D,\n name: string,\n ): Material | null {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name === name) {\n return material;\n }\n }\n } else if (object.material.name === name) {\n return object.material;\n }\n }\n\n for (const child of object.children) {\n const material = SceneTraversal.getMaterialByName(child, name);\n if (material) {\n return material;\n }\n }\n\n return null;\n }\n\n /**\n * Processes all objects of a specific type in the scene hierarchy.\n *\n * Performs a depth-first traversal and executes the provided callback function\n * for every object that is an instance of the specified type. This is useful\n * for batch operations on specific object types (e.g., all lights, all meshes, etc.).\n *\n * @template T - The type of objects to process\n * @param object - The root Object3D to start searching from\n * @param type - The constructor/class to filter by (e.g., DirectionalLight, Mesh)\n * @param callback - Function to execute for each matching object instance\n\n */\n public static enumerateObjectsByType<T>(\n object: Object3D,\n type: Constructor<T>,\n callback: (instance: T) => void,\n ): void {\n if (object instanceof type) {\n callback(object);\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateObjectsByType(child, type, callback);\n }\n }\n\n /**\n * Processes all materials found in mesh objects within the scene hierarchy.\n *\n * Performs a depth-first traversal, finding all Mesh objects and executing\n * the provided callback function for each material. Handles both single\n * materials and material arrays properly.\n *\n * @param object - The root Object3D to start searching from\n * @param callback - Function to execute for each material found\n\n */\n public static enumerateMaterials(\n object: Object3D,\n callback: (material: Material) => void,\n ): void {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n callback(material);\n }\n } else {\n callback(object.material);\n }\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateMaterials(child, callback);\n }\n }\n\n /**\n * Finds all objects in the scene hierarchy that match the specified filter criteria.\n *\n * Performs a depth-first search and collects all objects that either match\n * a regular expression pattern (applied to the object's name) or satisfy\n * a custom predicate function.\n *\n * @param object - The root Object3D to start searching from\n * @param filter - Either a RegExp to test against object names, or a predicate function\n * @returns Array of all matching Object3D instances\n\n */\n public static filterObjects(\n object: Object3D,\n filter: RegExp | ((object: Object3D) => boolean),\n ): Object3D[] {\n let result: Object3D[] = [];\n\n if (typeof filter === \"function\") {\n if (filter(object)) {\n result.push(object);\n }\n } else {\n if (object.name && filter.test(object.name)) {\n result.push(object);\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterObjects(child, filter));\n }\n\n return result;\n }\n\n /**\n * Finds all materials in the scene hierarchy whose names match a regular expression pattern.\n *\n * Performs a depth-first search through all Mesh objects and collects materials\n * whose name property matches the provided regular expression. Handles both\n * single materials and material arrays properly.\n *\n * @param object - The root Object3D to start searching from\n * @param name - Regular expression pattern to test against material names\n * @returns Array of all matching Material instances\n\n */\n public static filterMaterials(object: Object3D, name: RegExp): Material[] {\n let result: Material[] = [];\n\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name && name.test(material.name)) {\n result.push(material);\n }\n }\n } else {\n if (object.material.name && name.test(object.material.name)) {\n result.push(object.material);\n }\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterMaterials(child, name));\n }\n\n return result;\n }\n\n /**\n * Finds all objects (mesh users) that use materials with names matching a regular expression pattern.\n *\n * Performs a depth-first search through all Mesh objects and collects the mesh objects\n * whose materials have names that match the provided regular expression. This is useful\n * for finding all objects that use specific material types or naming patterns.\n *\n * @param object - The root Object3D to start searching from\n * @param materialName - Regular expression pattern to test against material names\n * @returns Array of all Mesh objects that use materials with matching names\n */\n public static findMaterialUsers(\n object: Object3D,\n materialName: RegExp,\n ): Mesh[] {\n let result: Mesh[] = [];\n\n if (object instanceof Mesh) {\n let hasMatchingMaterial = false;\n\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name && materialName.test(material.name)) {\n hasMatchingMaterial = true;\n break;\n }\n }\n } else {\n if (object.material.name && materialName.test(object.material.name)) {\n hasMatchingMaterial = true;\n }\n }\n\n if (hasMatchingMaterial) {\n result.push(object);\n }\n }\n\n for (const child of object.children) {\n result = result.concat(\n SceneTraversal.findMaterialUsers(child, materialName),\n );\n }\n\n return result;\n }\n}\n","import type { AnimationClip, Object3D, SkinnedMesh } from \"three\";\nimport { AnimationMixer, BufferAttribute, Mesh, Vector3 } from \"three\";\n\n/** Number of components per vertex */\nconst COMPONENT_COUNT = 3;\n\n/** Convert skinned meshes to regular static meshes */\nexport class SkinnedMeshBaker {\n /**\n * Convert a skinned mesh to a regular mesh in its current pose.\n * The resulting mesh will have no bones but look identical.\n * \n * @param skinnedMesh - Mesh to convert\n * @returns Static mesh with baked vertex positions\n */\n public static bakePose(skinnedMesh: SkinnedMesh): Mesh {\n const bakedGeometry = skinnedMesh.geometry.clone();\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const newPositions = new Float32Array(position.count * COMPONENT_COUNT);\n const target = new Vector3();\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n newPositions[i * COMPONENT_COUNT + 0] = target.x;\n newPositions[i * COMPONENT_COUNT + 1] = target.y;\n newPositions[i * COMPONENT_COUNT + 2] = target.z;\n }\n\n bakedGeometry.setAttribute(\n \"position\",\n new BufferAttribute(newPositions, COMPONENT_COUNT),\n );\n bakedGeometry.computeVertexNormals();\n bakedGeometry.deleteAttribute(\"skinIndex\");\n bakedGeometry.deleteAttribute(\"skinWeight\");\n\n const mesh = new Mesh(bakedGeometry, skinnedMesh.material);\n mesh.name = skinnedMesh.name;\n return mesh;\n }\n\n /**\n * Bake a single frame from an animation into a static mesh.\n * \n * @param armature - Root object with bones (usually from GLTF)\n * @param skinnedMesh - Mesh to convert\n * @param timeOffset - Time in seconds within the animation\n * @param clip - Animation to get the pose from\n * @returns Static mesh with baked vertex positions\n */\n public static bakeAnimationFrame(\n armature: Object3D,\n skinnedMesh: SkinnedMesh,\n timeOffset: number,\n clip: AnimationClip,\n ): Mesh {\n const mixer = new AnimationMixer(armature);\n const action = mixer.clipAction(clip);\n action.play();\n mixer.setTime(timeOffset);\n\n armature.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n return this.bakePose(skinnedMesh);\n }\n}","import type { Texture } from \"three\";\nimport { Box3, DirectionalLight, RGBAFormat, Spherical, Vector3 } from \"three\";\n\n/** Number of color channels in RGBA format */\nconst RGBA_CHANNEL_COUNT = 4;\n/** Number of color channels in RGB format */\nconst RGB_CHANNEL_COUNT = 3;\n\n/** Red channel weight for luminance calculation (ITU-R BT.709) */\nconst LUMINANCE_R = 0.2126;\n/** Green channel weight for luminance calculation (ITU-R BT.709) */\nconst LUMINANCE_G = 0.7152;\n/** Blue channel weight for luminance calculation (ITU-R BT.709) */\nconst LUMINANCE_B = 0.0722;\n\n/**\n * A directional light with spherical positioning controls and advanced shadow mapping.\n *\n * Extends Three.js DirectionalLight to provide intuitive spherical coordinate control\n * (distance, elevation, azimuth) and automatic shadow map configuration for bounding boxes.\n * Also supports automatic sun direction calculation from HDR environment maps.\n */\nexport class Sun extends DirectionalLight {\n /** Internal vectors to avoid garbage collection during calculations */\n private readonly tempVector3D0 = new Vector3();\n private readonly tempVector3D1 = new Vector3();\n private readonly tempVector3D2 = new Vector3();\n private readonly tempVector3D3 = new Vector3();\n private readonly tempVector3D4 = new Vector3();\n private readonly tempVector3D5 = new Vector3();\n private readonly tempVector3D6 = new Vector3();\n private readonly tempVector3D7 = new Vector3();\n private readonly tempBox3 = new Box3();\n private readonly tempSpherical = new Spherical();\n\n /**\n * Gets the distance from the light to its target (origin).\n *\n * @returns The distance in world units\n */\n public get distance(): number {\n return this.position.length();\n }\n\n /**\n * Gets the elevation angle (vertical angle from the horizontal plane).\n *\n * @returns The elevation angle in radians (0 = horizontal, π/2 = directly above)\n */\n public get elevation(): number {\n return this.tempSpherical.setFromVector3(this.position).phi;\n }\n\n /**\n * Gets the azimuth angle (horizontal rotation around the target).\n *\n * @returns The azimuth angle in radians (0 = positive X axis, π/2 = positive Z axis)\n */\n public get azimuth(): number {\n return this.tempSpherical.setFromVector3(this.position).theta;\n }\n\n /**\n * Sets the distance while preserving current elevation and azimuth angles.\n *\n * @param value - The new distance in world units\n */\n public set distance(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n value,\n this.tempSpherical.phi,\n this.tempSpherical.theta,\n );\n }\n\n /**\n * Sets the elevation angle while preserving current distance and azimuth.\n *\n * @param value - The new elevation angle in radians (0 = horizontal, π/2 = directly above)\n */\n public set elevation(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n value,\n this.tempSpherical.theta,\n );\n }\n\n /**\n * Sets the azimuth angle while preserving current distance and elevation.\n *\n * @param value - The new azimuth angle in radians (0 = positive X axis, π/2 = positive Z axis)\n */\n public set azimuth(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n this.tempSpherical.phi,\n value,\n );\n }\n\n /**\n * Configures the shadow camera to optimally cover a bounding box.\n *\n * This method automatically adjusts the directional light's shadow camera frustum\n * to perfectly encompass the provided bounding box, ensuring efficient shadow map\n * usage and eliminating shadow clipping issues.\n *\n * @param box3 - The 3D bounding box to cover with shadows\n */\n public configureShadowsForBoundingBox(box3: Box3): void {\n const camera = this.shadow.camera;\n\n this.target.updateWorldMatrix(true, false);\n this.lookAt(this.target.getWorldPosition(this.tempVector3D0));\n\n this.updateWorldMatrix(true, false);\n\n const points: Vector3[] = [\n this.tempVector3D0.set(box3.min.x, box3.min.y, box3.min.z),\n this.tempVector3D1.set(box3.min.x, box3.min.y, box3.max.z),\n this.tempVector3D2.set(box3.min.x, box3.max.y, box3.min.z),\n this.tempVector3D3.set(box3.min.x, box3.max.y, box3.max.z),\n this.tempVector3D4.set(box3.max.x, box3.min.y, box3.min.z),\n this.tempVector3D5.set(box3.max.x, box3.min.y, box3.max.z),\n this.tempVector3D6.set(box3.max.x, box3.max.y, box3.min.z),\n this.tempVector3D7.set(box3.max.x, box3.max.y, box3.max.z),\n ];\n\n const inverseMatrix = this.matrixWorld.clone().invert();\n\n for (const point of points) {\n point.applyMatrix4(inverseMatrix);\n }\n\n const newBox3 = this.tempBox3.setFromPoints(points);\n\n camera.left = newBox3.min.x;\n camera.bottom = newBox3.min.y;\n camera.near = -newBox3.max.z;\n\n camera.right = newBox3.max.x;\n camera.top = newBox3.max.y;\n camera.far = -newBox3.min.z;\n\n camera.updateWorldMatrix(true, false);\n camera.updateProjectionMatrix();\n }\n\n /**\n * Sets the sun's direction based on the brightest point in an HDR environment map.\n *\n * This method analyzes an HDR texture to find the pixel with the highest luminance\n * value and positions the sun to shine from that direction. This is useful for\n * creating realistic lighting that matches HDR environment maps.\n *\n * @param texture - The HDR texture to analyze (must have image data available)\n * @param distance - The distance to place the sun from the origin (defaults to 1)\n */\n public setDirectionFromHDRTexture(texture: Texture, distance = 1): void {\n const data = texture.image.data;\n const width = texture.image.width;\n const height = texture.image.height;\n\n let maxLuminance = 0;\n let maxIndex = 0;\n\n // Find brightest pixel\n\n const step =\n texture.format === RGBAFormat ? RGBA_CHANNEL_COUNT : RGB_CHANNEL_COUNT;\n for (let i = 0; i < data.length; i += step) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const luminance = LUMINANCE_R * r + LUMINANCE_G * g + LUMINANCE_B * b;\n if (luminance > maxLuminance) {\n maxLuminance = luminance;\n maxIndex = i;\n }\n }\n\n // Convert to spherical coordinates\n const pixelIndex = maxIndex / step;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n\n const u = x / width;\n const v = y / height;\n\n const elevation = v * Math.PI;\n const azimuth = u * -Math.PI * 2 - Math.PI / 2;\n\n this.position.setFromSphericalCoords(distance, elevation, azimuth);\n }\n}\n"],"names":[],"mappings":"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"}
package/dist/index.min.js CHANGED
@@ -1,2 +1,2 @@
1
- import{PerspectiveCamera as t,MathUtils as s,Vector3 as i,Box3 as e,Mesh as n,InstancedMesh as o,FrontSide as r,BufferAttribute as h,AnimationMixer as a,DirectionalLight as c,Spherical as l,RGBAFormat as f}from"three";const u=179;class v extends t{constructor(t=90,s=90,i=1,e=1,n=1e3){super(s,i,e,n),this.horizontalFovInternal=t,this.verticalFovInternal=s,this.updateProjectionMatrix()}get horizontalFov(){return this.horizontalFovInternal}get verticalFov(){return this.verticalFovInternal}set horizontalFov(t){this.horizontalFovInternal=s.clamp(t,1,u),this.updateProjectionMatrix()}set verticalFov(t){this.verticalFovInternal=s.clamp(t,1,u),this.updateProjectionMatrix()}setFov(t,i){this.horizontalFovInternal=s.clamp(t,1,u),this.verticalFovInternal=s.clamp(i,1,u),this.updateProjectionMatrix()}copyFovSettings(t){this.horizontalFovInternal=t.horizontalFov,this.verticalFovInternal=t.verticalFov,this.updateProjectionMatrix()}updateProjectionMatrix(){if(this.aspect>1){const t=s.degToRad(this.horizontalFovInternal);this.fov=s.radToDeg(2*Math.atan(Math.tan(t/2)/this.aspect))}else this.fov=this.verticalFovInternal;super.updateProjectionMatrix()}getEffectiveHorizontalFov(){if(this.aspect>=1)return this.horizontalFovInternal;const t=s.degToRad(this.verticalFovInternal);return s.radToDeg(2*Math.atan(Math.tan(t/2)*this.aspect))}getEffectiveVerticalFov(){if(this.aspect<1)return this.verticalFovInternal;const t=s.degToRad(this.horizontalFovInternal);return s.radToDeg(2*Math.atan(Math.tan(t/2)/this.aspect))}fitPointsVerticalFov(t){const e=new i(0,1,0).applyQuaternion(this.quaternion);let n=0;for(const s of t){const t=this.position.clone().sub(s).normalize(),i=Math.asin(Math.abs(t.dot(e)))*Math.sign(t.dot(e));Math.abs(i)>n&&(n=Math.abs(i))}const o=s.radToDeg(2*n);this.verticalFovInternal=s.clamp(o,1,u),this.updateProjectionMatrix()}fitBoxVerticalFov(t){this.fitPointsVerticalFov([new i(t.min.x,t.min.y,t.min.z),new i(t.min.x,t.min.y,t.max.z),new i(t.min.x,t.max.y,t.min.z),new i(t.min.x,t.max.y,t.max.z),new i(t.max.x,t.min.y,t.min.z),new i(t.max.x,t.min.y,t.max.z),new i(t.max.x,t.max.y,t.min.z),new i(t.max.x,t.max.y,t.max.z)])}fitSkinnedMeshVerticalFov(t){t.updateWorldMatrix(!0,!0),t.skeleton.update();const s=t.geometry.attributes.position,e=new i,n=[];for(let i=0;i<s.count;i++)e.fromBufferAttribute(s,i),t.applyBoneTransform(i,e),n.push(e.clone());this.fitPointsVerticalFov(n)}lookAtCenterOfMass(t){t.updateWorldMatrix(!0,!0),t.skeleton.update();const s=t.geometry.attributes.position,e=new i,n=[];for(let i=0;i<s.count;i++)e.fromBufferAttribute(s,i),t.applyBoneTransform(i,e),n.push(e.clone());const o=((t,s=3)=>{if(0===t.length)return new i;let e=t[Math.floor(t.length/2)].clone();for(let n=0;n<s;n++){let s=new i,n=0;for(const i of t)(i.distanceTo(e)<i.distanceTo(s)||0===n)&&(s.add(i),n++);n>0&&(e=s.divideScalar(n))}return e})(n);this.lookAt(o)}clone(){const t=new v(this.horizontalFovInternal,this.verticalFovInternal,this.aspect,this.near,this.far);return t.copy(this,!0),t}}class w extends e{constructor(t){super(),this.tempVector3A=new i,t&&this.setFromObject(t)}get width(){return this.max.x-this.min.x}get height(){return this.max.y-this.min.y}get depth(){return this.max.z-this.min.z}get diagonal(){return this.tempVector3A.subVectors(this.max,this.min).length()}setFromSkinnedMesh(t){t.updateWorldMatrix(!0,!0),t.skeleton.update();const s=t.geometry.attributes.position,e=new i,n=[];for(let i=0;i<s.count;i++)e.fromBufferAttribute(s,i),t.applyBoneTransform(i,e),n.push(e.clone());return this.setFromPoints(n),this}getVolume(){return this.width*this.height*this.depth}getSurfaceArea(){const t=this.width,s=this.height,i=this.depth;return 2*(t*s+s*i+i*t)}}class d{static getGeometryHash(t,s){const i=t.attributes.position.array,e=[];for(let t=0;t<i.length;t+=3)e.push(`${Math.round(i[t]/s)},${Math.round(i[t+1]/s)},${Math.round(i[t+2]/s)}`);const n=[],o=t.attributes.normal.array;for(let t=0;t<o.length;t+=3)n.push(`${Math.round(o[t]/s)},${Math.round(o[t+1]/s)},${Math.round(o[t+2]/s)}`);return`${e.join("|")}#${n.join("|")}`}}class M{static getObjectByName(t,s){if(t.name===s)return t;for(const i of t.children){const t=M.getObjectByName(i,s);if(t)return t}return null}static getMaterialByName(t,s){if(t instanceof n)if(Array.isArray(t.material)){for(const i of t.material)if(i.name===s)return i}else if(t.material.name===s)return t.material;for(const i of t.children){const t=M.getMaterialByName(i,s);if(t)return t}return null}static enumerateObjectsByType(t,s,i){t instanceof s&&i(t);for(const e of t.children)M.enumerateObjectsByType(e,s,i)}static enumerateMaterials(t,s){if(t instanceof n)if(Array.isArray(t.material))for(const i of t.material)s(i);else s(t.material);for(const i of t.children)M.enumerateMaterials(i,s)}static filterObjects(t,s){let i=[];"function"==typeof s?s(t)&&i.push(t):t.name&&s.test(t.name)&&i.push(t);for(const e of t.children)i=i.concat(M.filterObjects(e,s));return i}static filterMaterials(t,s){let i=[];if(t instanceof n)if(Array.isArray(t.material))for(const e of t.material)e.name&&s.test(e.name)&&i.push(e);else t.material.name&&s.test(t.material.name)&&i.push(t.material);for(const e of t.children)i=i.concat(M.filterMaterials(e,s));return i}static setShadowRecursive(t,s=!0,i=!0,e){(t instanceof n||"isMesh"in t)&&(t.castShadow=s,t.receiveShadow=i);for(const n of t.children)M.setShadowRecursive(n,s,i,e)}}class g{static assemble(t,s={}){var i,e;const r=new Map,h=[],a=null!==(i=s.geometryTolerance)&&void 0!==i?i:1e-6,c=new Map;M.enumerateObjectsByType(t,n,(t=>{var i;if(0===t.children.length&&(!s.filter||s.filter(t))){const s=Array.isArray(t.material)?t.material:[t.material];let e=c.get(t.geometry.uuid);e||(e=d.getGeometryHash(t.geometry,a),c.set(t.geometry.uuid,e));const n=`${e}|${s.map((t=>t.uuid)).join(",")}`,o=null!==(i=r.get(n))&&void 0!==i?i:{meshes:[],materials:s,castShadow:!1,receiveShadow:!1};t.castShadow&&(o.castShadow=!0),t.receiveShadow&&(o.receiveShadow=!0),o.meshes.push(t),r.set(n,o)}}));for(const t of r.values()){if(t.meshes.length<2)continue;const{meshes:s,materials:i,castShadow:n,receiveShadow:r}=t,a=s.sort(((t,s)=>t.name.localeCompare(s.name))),c=a[0],l=new o(c.geometry,1===i.length?i[0]:i,a.length);l.name=c.name,l.castShadow=n,l.receiveShadow=r;for(let t=0;t<a.length;t++){const s=a[t];s.updateWorldMatrix(!0,!1),l.setMatrixAt(t,s.matrixWorld),l.userData[s.uuid]=s.userData}l.instanceMatrix.needsUpdate=!0,h.push(l);for(const t of a)null===(e=t.parent)||void 0===e||e.remove(t)}h.length>0&&t.add(...h)}}function m(t){const s=new Map,i=new Map,e=t.clone();return p(t,e,(function(t,e){s.set(e,t),i.set(t,e)})),e.traverse((function(t){if(!t.isSkinnedMesh)return;const e=t,n=s.get(t),o=n.skeleton.bones;e.skeleton=n.skeleton.clone(),e.bindMatrix.copy(n.bindMatrix),e.skeleton.bones=o.map((function(t){return i.get(t)})),e.bind(e.skeleton,e.bindMatrix)})),e}function p(t,s,i){i(t,s);for(let e=0;e<t.children.length;e++)p(t.children[e],s.children[e],i)}class F{static process(t,s){const i=!1!==s.cloneAsset?m(t):t;return!1!==s.assembleInstances&&g.assemble(i),M.enumerateMaterials(i,(t=>{var i,e,n,o,h,a,c;t.transparent=null!==(e=null===(i=s.transparentMaterialRegExp)||void 0===i?void 0:i.test(t.name))&&void 0!==e&&e,t.depthWrite=!(null!==(o=null===(n=s.noDepthWriteMaterialRegExp)||void 0===n?void 0:n.test(t.name))&&void 0!==o&&o),t.alphaTest=(null===(h=s.alphaTestMaterialRegExp)||void 0===h?void 0:h.test(t.name))?.5:0,t.alphaHash=null!==(c=null===(a=s.alphaHashMaterialRegExp)||void 0===a?void 0:a.test(t.name))&&void 0!==c&&c,t.side=r,t.forceSinglePass=!0,t.depthTest=!0})),M.enumerateObjectsByType(i,n,(t=>{var i,e,n,o;t.castShadow=null!==(e=null===(i=s.castShadowRegExp)||void 0===i?void 0:i.test(t.name))&&void 0!==e&&e,t.receiveShadow=null!==(o=null===(n=s.receiveShadowRegExp)||void 0===n?void 0:n.test(t.name))&&void 0!==o&&o})),i.children}}class y{static bakePose(t){const s=t.geometry.clone(),e=s.attributes.position,o=new Float32Array(3*e.count),r=new i;for(let s=0;s<e.count;s++)r.fromBufferAttribute(e,s),t.applyBoneTransform(s,r),o[3*s+0]=r.x,o[3*s+1]=r.y,o[3*s+2]=r.z;s.setAttribute("position",new h(o,3)),s.computeVertexNormals(),s.deleteAttribute("skinIndex"),s.deleteAttribute("skinWeight");const a=new n(s,t.material);return a.name=t.name,a}static bakeAnimationFrame(t,s,i,e){const n=new a(t);return n.clipAction(e).play(),n.setTime(i),t.updateWorldMatrix(!0,!0),s.skeleton.update(),this.bakePose(s)}}class S extends c{constructor(){super(...arguments),this.tempVector3D0=new i,this.tempVector3D1=new i,this.tempVector3D2=new i,this.tempVector3D3=new i,this.tempVector3D4=new i,this.tempVector3D5=new i,this.tempVector3D6=new i,this.tempVector3D7=new i,this.tempBox3=new e,this.tempSpherical=new l}get distance(){return this.position.length()}get elevation(){return this.tempSpherical.setFromVector3(this.position).phi}get azimuth(){return this.tempSpherical.setFromVector3(this.position).theta}set distance(t){this.tempSpherical.setFromVector3(this.position),this.position.setFromSphericalCoords(t,this.tempSpherical.phi,this.tempSpherical.theta)}set elevation(t){this.tempSpherical.setFromVector3(this.position),this.position.setFromSphericalCoords(this.tempSpherical.radius,t,this.tempSpherical.theta)}set azimuth(t){this.tempSpherical.setFromVector3(this.position),this.position.setFromSphericalCoords(this.tempSpherical.radius,this.tempSpherical.phi,t)}setShadowMapFromBox3(t){const s=this.shadow.camera;this.target.updateWorldMatrix(!0,!1),this.lookAt(this.target.getWorldPosition(this.tempVector3D0)),this.updateWorldMatrix(!0,!1);const i=[this.tempVector3D0.set(t.min.x,t.min.y,t.min.z),this.tempVector3D1.set(t.min.x,t.min.y,t.max.z),this.tempVector3D2.set(t.min.x,t.max.y,t.min.z),this.tempVector3D3.set(t.min.x,t.max.y,t.max.z),this.tempVector3D4.set(t.max.x,t.min.y,t.min.z),this.tempVector3D5.set(t.max.x,t.min.y,t.max.z),this.tempVector3D6.set(t.max.x,t.max.y,t.min.z),this.tempVector3D7.set(t.max.x,t.max.y,t.max.z)],e=this.matrixWorld.clone().invert();for(const t of i)t.applyMatrix4(e);const n=this.tempBox3.setFromPoints(i);s.left=n.min.x,s.bottom=n.min.y,s.near=-n.max.z,s.right=n.max.x,s.top=n.max.y,s.far=-n.min.z,s.updateWorldMatrix(!0,!1),s.updateProjectionMatrix()}setDirectionFromHDR(t,s=1){const i=t.image.data,e=t.image.width,n=t.image.height;let o=0,r=0;const h=t.format===f?4:3;for(let t=0;t<i.length;t+=h){const s=.2126*i[t]+.7152*i[t+1]+.0722*i[t+2];s>o&&(o=s,r=t)}const a=r/h,c=a%e;this.position.setFromSphericalCoords(s,Math.floor(a/e)/n*Math.PI,c/e*-Math.PI*2-Math.PI/2)}}export{v as BiFovCamera,w as Bounds,g as InstanceAssembler,F as SceneProcessor,M as SceneTraversal,y as SkinnedMeshBaker,S as Sun};
1
+ import{PerspectiveCamera as t,MathUtils as s,Vector3 as i,Mesh as e,BufferAttribute as n,AnimationMixer as o,DirectionalLight as r,Box3 as h,Spherical as a,RGBAFormat as c}from"three";const f=179;class l extends t{constructor(t=90,s=90,i=1,e=1,n=1e3){super(s,i,e,n),this.t=t,this.i=s,this.updateProjectionMatrix()}get horizontalFov(){return this.t}get verticalFov(){return this.i}set horizontalFov(t){this.t=s.clamp(t,1,f),this.updateProjectionMatrix()}set verticalFov(t){this.i=s.clamp(t,1,f),this.updateProjectionMatrix()}setFov(t,i){this.t=s.clamp(t,1,f),this.i=s.clamp(i,1,f),this.updateProjectionMatrix()}copyFovSettings(t){this.t=t.horizontalFov,this.i=t.verticalFov,this.updateProjectionMatrix()}updateProjectionMatrix(){if(this.aspect>1){const t=s.degToRad(this.t);this.fov=s.radToDeg(2*Math.atan(Math.tan(t/2)/this.aspect))}else this.fov=this.i;super.updateProjectionMatrix()}getActualHorizontalFov(){if(this.aspect>=1)return this.t;const t=s.degToRad(this.i);return s.radToDeg(2*Math.atan(Math.tan(t/2)*this.aspect))}getActualVerticalFov(){if(1>this.aspect)return this.i;const t=s.degToRad(this.t);return s.radToDeg(2*Math.atan(Math.tan(t/2)/this.aspect))}fitVerticalFovToPoints(t){const e=new i(0,1,0).applyQuaternion(this.quaternion);let n=0;for(const s of t){const t=this.position.clone().sub(s).normalize(),i=Math.asin(Math.abs(t.dot(e)))*Math.sign(t.dot(e));Math.abs(i)>n&&(n=Math.abs(i))}const o=s.radToDeg(2*n);this.i=s.clamp(o,1,f),this.updateProjectionMatrix()}fitVerticalFovToBox(t){this.fitVerticalFovToPoints([new i(t.min.x,t.min.y,t.min.z),new i(t.min.x,t.min.y,t.max.z),new i(t.min.x,t.max.y,t.min.z),new i(t.min.x,t.max.y,t.max.z),new i(t.max.x,t.min.y,t.min.z),new i(t.max.x,t.min.y,t.max.z),new i(t.max.x,t.max.y,t.min.z),new i(t.max.x,t.max.y,t.max.z)])}fitVerticalFovToMesh(t){t.updateWorldMatrix(!0,!0),t.skeleton.update();const s=t.geometry.attributes.position,e=new i,n=[];for(let i=0;s.count>i;i++)e.fromBufferAttribute(s,i),t.applyBoneTransform(i,e),n.push(e.clone());this.fitVerticalFovToPoints(n)}lookAtMeshCenterOfMass(t){t.updateWorldMatrix(!0,!0),t.skeleton.update();const s=t.geometry.attributes.position,e=new i,n=[];for(let i=0;s.count>i;i++)e.fromBufferAttribute(s,i),t.applyBoneTransform(i,e),n.push(e.clone());const o=((t,s=3)=>{if(0===t.length)return new i;let e=t[Math.floor(t.length/2)].clone();for(let n=0;s>n;n++){let s=new i,n=0;for(const i of t)(i.distanceTo(e)<i.distanceTo(s)||0===n)&&(s.add(i),n++);n>0&&(e=s.divideScalar(n))}return e})(n);this.lookAt(o)}clone(){const t=new l(this.t,this.i,this.aspect,this.near,this.far);return t.copy(this,!0),t}}class u{static getObjectByName(t,s){if(t.name===s)return t;for(const i of t.children){const t=u.getObjectByName(i,s);if(t)return t}return null}static getMaterialByName(t,s){if(t instanceof e)if(Array.isArray(t.material)){for(const i of t.material)if(i.name===s)return i}else if(t.material.name===s)return t.material;for(const i of t.children){const t=u.getMaterialByName(i,s);if(t)return t}return null}static enumerateObjectsByType(t,s,i){t instanceof s&&i(t);for(const e of t.children)u.enumerateObjectsByType(e,s,i)}static enumerateMaterials(t,s){if(t instanceof e)if(Array.isArray(t.material))for(const i of t.material)s(i);else s(t.material);for(const i of t.children)u.enumerateMaterials(i,s)}static filterObjects(t,s){let i=[];"function"==typeof s?s(t)&&i.push(t):t.name&&s.test(t.name)&&i.push(t);for(const e of t.children)i=i.concat(u.filterObjects(e,s));return i}static filterMaterials(t,s){let i=[];if(t instanceof e)if(Array.isArray(t.material))for(const e of t.material)e.name&&s.test(e.name)&&i.push(e);else t.material.name&&s.test(t.material.name)&&i.push(t.material);for(const e of t.children)i=i.concat(u.filterMaterials(e,s));return i}static findMaterialUsers(t,s){let i=[];if(t instanceof e){let e=!1;if(Array.isArray(t.material)){for(const i of t.material)if(i.name&&s.test(i.name)){e=!0;break}}else t.material.name&&s.test(t.material.name)&&(e=!0);e&&i.push(t)}for(const e of t.children)i=i.concat(u.findMaterialUsers(e,s));return i}}class w{static bakePose(t){const s=t.geometry.clone(),o=s.attributes.position,r=new Float32Array(3*o.count),h=new i;for(let s=0;o.count>s;s++)h.fromBufferAttribute(o,s),t.applyBoneTransform(s,h),r[3*s+0]=h.x,r[3*s+1]=h.y,r[3*s+2]=h.z;s.setAttribute("position",new n(r,3)),s.computeVertexNormals(),s.deleteAttribute("skinIndex"),s.deleteAttribute("skinWeight");const a=new e(s,t.material);return a.name=t.name,a}static bakeAnimationFrame(t,s,i,e){const n=new o(t);return n.clipAction(e).play(),n.setTime(i),t.updateWorldMatrix(!0,!0),s.skeleton.update(),this.bakePose(s)}}class M extends r{constructor(){super(...arguments),this.o=new i,this.h=new i,this.l=new i,this.u=new i,this.M=new i,this.v=new i,this.F=new i,this.m=new i,this.p=new h,this.A=new a}get distance(){return this.position.length()}get elevation(){return this.A.setFromVector3(this.position).phi}get azimuth(){return this.A.setFromVector3(this.position).theta}set distance(t){this.A.setFromVector3(this.position),this.position.setFromSphericalCoords(t,this.A.phi,this.A.theta)}set elevation(t){this.A.setFromVector3(this.position),this.position.setFromSphericalCoords(this.A.radius,t,this.A.theta)}set azimuth(t){this.A.setFromVector3(this.position),this.position.setFromSphericalCoords(this.A.radius,this.A.phi,t)}configureShadowsForBoundingBox(t){const s=this.shadow.camera;this.target.updateWorldMatrix(!0,!1),this.lookAt(this.target.getWorldPosition(this.o)),this.updateWorldMatrix(!0,!1);const i=[this.o.set(t.min.x,t.min.y,t.min.z),this.h.set(t.min.x,t.min.y,t.max.z),this.l.set(t.min.x,t.max.y,t.min.z),this.u.set(t.min.x,t.max.y,t.max.z),this.M.set(t.max.x,t.min.y,t.min.z),this.v.set(t.max.x,t.min.y,t.max.z),this.F.set(t.max.x,t.max.y,t.min.z),this.m.set(t.max.x,t.max.y,t.max.z)],e=this.matrixWorld.clone().invert();for(const t of i)t.applyMatrix4(e);const n=this.p.setFromPoints(i);s.left=n.min.x,s.bottom=n.min.y,s.near=-n.max.z,s.right=n.max.x,s.top=n.max.y,s.far=-n.min.z,s.updateWorldMatrix(!0,!1),s.updateProjectionMatrix()}setDirectionFromHDRTexture(t,s=1){const i=t.image.data,e=t.image.width,n=t.image.height;let o=0,r=0;const h=t.format===c?4:3;for(let t=0;i.length>t;t+=h){const s=.2126*i[t]+.7152*i[t+1]+.0722*i[t+2];s>o&&(o=s,r=t)}const a=r/h,f=a%e;this.position.setFromSphericalCoords(s,Math.floor(a/e)/n*Math.PI,f/e*-Math.PI*2-Math.PI/2)}}export{l as DualFovCamera,u as SceneTraversal,w as SkinnedMeshBaker,M as Sun};
2
2
  //# sourceMappingURL=index.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.min.js","sources":["../src/BiFovCamera.ts","../src/Bounds.ts","../src/GeometryHasher.ts","../src/SceneTraversal.ts","../src/InstanceAssembler.ts","../node_modules/three/examples/jsm/utils/SkeletonUtils.js","../src/SceneProcessor.ts","../src/SkinnedMeshBaker.ts","../src/Sun.ts"],"sourcesContent":["import type { Box3, BufferAttribute, SkinnedMesh } from \"three\";\nimport { MathUtils, PerspectiveCamera, Vector3 } from \"three\";\n\nconst DEFAULT_HORIZONTAL_FOV = 90;\nconst DEFAULT_VERTICAL_FOV = 90;\nconst DEFAULT_ASPECT = 1;\nconst DEFAULT_NEAR = 1;\nconst DEFAULT_FAR = 1000;\n\nconst MIN_FOV = 1;\nconst MAX_FOV = 179;\n\n/**\n * A camera that supports independent horizontal and vertical FOV settings.\n * Extends Three.js PerspectiveCamera to allow separate control over horizontal\n * and vertical fields of view.\n */\nexport class BiFovCamera extends PerspectiveCamera {\n private horizontalFovInternal: number;\n private verticalFovInternal: number;\n\n /**\n * @param horizontalFov - Horizontal FOV in degrees (90° default)\n * @param verticalFov - Vertical FOV in degrees (90° default)\n * @param aspect - Width/height ratio (1 default)\n * @param near - Near clipping plane (1 default)\n * @param far - Far clipping plane (1000 default)\n */\n constructor(\n horizontalFov = DEFAULT_HORIZONTAL_FOV,\n verticalFov = DEFAULT_VERTICAL_FOV,\n aspect = DEFAULT_ASPECT,\n near = DEFAULT_NEAR,\n far = DEFAULT_FAR,\n ) {\n super(verticalFov, aspect, near, far);\n this.horizontalFovInternal = horizontalFov;\n this.verticalFovInternal = verticalFov;\n this.updateProjectionMatrix();\n }\n\n /** Current horizontal FOV in degrees */\n public get horizontalFov(): number {\n return this.horizontalFovInternal;\n }\n\n /** Current vertical FOV in degrees */\n public get verticalFov(): number {\n return this.verticalFovInternal;\n }\n\n /** Set horizontal FOV in degrees (clamped between 1° and 179°) */\n public set horizontalFov(value: number) {\n this.horizontalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /** Set vertical FOV in degrees (clamped between 1° and 179°) */\n public set verticalFov(value: number) {\n this.verticalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Update both horizontal and vertical FOV\n * @param horizontal - Horizontal FOV in degrees\n * @param vertical - Vertical FOV in degrees\n */\n public setFov(horizontal: number, vertical: number): void {\n this.horizontalFovInternal = MathUtils.clamp(horizontal, MIN_FOV, MAX_FOV);\n this.verticalFovInternal = MathUtils.clamp(vertical, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Copy FOV settings from another BiFovCamera\n * @param source - Camera to copy from\n */\n public copyFovSettings(source: BiFovCamera): void {\n this.horizontalFovInternal = source.horizontalFov;\n this.verticalFovInternal = source.verticalFov;\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates the projection matrix based on FOV settings and aspect ratio.\n * In landscape: preserves horizontal FOV\n * In portrait: preserves vertical FOV\n */\n public override updateProjectionMatrix(): void {\n if (this.aspect > 1) {\n // Landscape orientation: preserve horizontal FOV\n const radians = MathUtils.degToRad(this.horizontalFovInternal);\n this.fov = MathUtils.radToDeg(\n Math.atan(Math.tan(radians / 2) / this.aspect) * 2,\n );\n } else {\n // Portrait orientation: preserve vertical FOV\n this.fov = this.verticalFovInternal;\n }\n\n super.updateProjectionMatrix();\n }\n\n /** Get actual horizontal FOV after aspect ratio adjustments */\n public getEffectiveHorizontalFov(): number {\n if (this.aspect >= 1) {\n return this.horizontalFovInternal;\n }\n const verticalRadians = MathUtils.degToRad(this.verticalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(verticalRadians / 2) * this.aspect) * 2,\n );\n }\n\n /** Get actual vertical FOV after aspect ratio adjustments */\n public getEffectiveVerticalFov(): number {\n if (this.aspect < 1) {\n return this.verticalFovInternal;\n }\n const horizontalRadians = MathUtils.degToRad(this.horizontalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2,\n );\n }\n\n public fitPointsVerticalFov(vertices: Vector3[]): void {\n const up = new Vector3(0, 1, 0).applyQuaternion(this.quaternion);\n\n let maxVerticalAngle = 0;\n\n for (const vertex of vertices) {\n const vertexToCam = this.position.clone().sub(vertex);\n const vertexDirection = vertexToCam.normalize();\n\n const verticalAngle =\n Math.asin(Math.abs(vertexDirection.dot(up))) *\n Math.sign(vertexDirection.dot(up));\n\n if (Math.abs(verticalAngle) > maxVerticalAngle) {\n maxVerticalAngle = Math.abs(verticalAngle);\n }\n }\n\n const requiredFov = MathUtils.radToDeg(2 * maxVerticalAngle);\n\n this.verticalFovInternal = MathUtils.clamp(requiredFov, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n public fitBoxVerticalFov(box: Box3): void {\n this.fitPointsVerticalFov([\n new Vector3(box.min.x, box.min.y, box.min.z),\n new Vector3(box.min.x, box.min.y, box.max.z),\n new Vector3(box.min.x, box.max.y, box.min.z),\n new Vector3(box.min.x, box.max.y, box.max.z),\n new Vector3(box.max.x, box.min.y, box.min.z),\n new Vector3(box.max.x, box.min.y, box.max.z),\n new Vector3(box.max.x, box.max.y, box.min.z),\n new Vector3(box.max.x, box.max.y, box.max.z),\n ]);\n }\n\n public fitSkinnedMeshVerticalFov(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const target = new Vector3();\n\n const points = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n this.fitPointsVerticalFov(points);\n }\n\n public lookAtCenterOfMass(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes.position as BufferAttribute;\n const target = new Vector3();\n const points: Vector3[] = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n const findMainCluster = (points: Vector3[], iterations = 3): Vector3 => {\n if (points.length === 0) {\n return new Vector3();\n }\n\n let center = points[Math.floor(points.length / 2)].clone();\n\n for (let i = 0; i < iterations; i++) {\n let total = new Vector3();\n let count = 0;\n\n for (const point of points) {\n if (\n point.distanceTo(center) < point.distanceTo(total) ||\n count === 0\n ) {\n total.add(point);\n count++;\n }\n }\n\n if (count > 0) {\n center = total.divideScalar(count);\n }\n }\n\n return center;\n };\n\n const centerOfMass = findMainCluster(points);\n this.lookAt(centerOfMass);\n }\n\n public override clone(): this {\n const camera = new BiFovCamera(\n this.horizontalFovInternal,\n this.verticalFovInternal,\n this.aspect,\n this.near,\n this.far,\n ) as this;\n\n camera.copy(this, true);\n return camera;\n }\n}\n","import type { BufferAttribute, Object3D, SkinnedMesh } from \"three\";\nimport { Box3, Vector3 } from \"three\";\n\n/**\n * Box3 with additional convenience methods for width, height, depth, etc.\n */\nexport class Bounds extends Box3 {\n /** Temporary vector for calculations */\n private readonly tempVector3A: Vector3 = new Vector3();\n\n constructor(object?: Object3D) {\n super();\n if (object) {\n this.setFromObject(object);\n }\n }\n\n /** Width (x-axis length) */\n public get width(): number {\n return this.max.x - this.min.x;\n }\n\n /** Height (y-axis length) */\n public get height(): number {\n return this.max.y - this.min.y;\n }\n\n /** Depth (z-axis length) */\n public get depth(): number {\n return this.max.z - this.min.z;\n }\n\n /** Length of the box's diagonal */\n public get diagonal(): number {\n return this.tempVector3A.subVectors(this.max, this.min).length();\n }\n\n public setFromSkinnedMesh(skinnedMesh: SkinnedMesh): Bounds {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const geometry = skinnedMesh.geometry;\n const position = geometry.attributes[\"position\"] as BufferAttribute;\n const target = new Vector3();\n\n const points = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n this.setFromPoints(points);\n return this;\n }\n\n /** Volume (width * height * depth) */\n public getVolume(): number {\n return this.width * this.height * this.depth;\n }\n\n /** Surface area (sum of all six faces) */\n public getSurfaceArea(): number {\n const w = this.width;\n const h = this.height;\n const d = this.depth;\n return 2 * (w * h + h * d + d * w);\n }\n}\n","import type { BufferGeometry } from \"three\";\n\nconst POSITION_COMPONENT_COUNT = 3;\nconst NORMAL_COMPONENT_COUNT = 3;\n\n/**\n * Internal utility to identify identical geometries.\n * @internal\n */\nexport class GeometryHasher {\n /**\n * Creates a hash for a geometry based on its vertex data.\n * Vertices that differ by less than tolerance are considered the same.\n *\n * @param geometry - Geometry to hash\n * @param tolerance - How close vertices need to be to count as identical\n * @returns Hash string that's the same for matching geometries\n * @internal\n */\n public static getGeometryHash(\n geometry: BufferGeometry,\n tolerance: number,\n ): string {\n const position = geometry.attributes[\"position\"];\n\n const positionArray = position.array;\n const positionHashParts: string[] = [];\n\n // Sample vertex positions with tolerance\n for (let i = 0; i < positionArray.length; i += POSITION_COMPONENT_COUNT) {\n const x = Math.round(positionArray[i] / tolerance);\n const y = Math.round(positionArray[i + 1] / tolerance);\n const z = Math.round(positionArray[i + 2] / tolerance);\n positionHashParts.push(`${x},${y},${z}`);\n }\n\n // Hash normal data if available\n const normal = geometry.attributes[\"normal\"];\n const normalHashParts: string[] = [];\n\n const normalArray = normal.array;\n for (let i = 0; i < normalArray.length; i += NORMAL_COMPONENT_COUNT) {\n const x = Math.round(normalArray[i] / tolerance);\n const y = Math.round(normalArray[i + 1] / tolerance);\n const z = Math.round(normalArray[i + 2] / tolerance);\n normalHashParts.push(`${x},${y},${z}`);\n }\n\n // Combine position and normal hashes\n const positionHash = positionHashParts.join(\"|\");\n const normalHash = normalHashParts.join(\"|\");\n\n return `${positionHash}#${normalHash}`;\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { Mesh } from \"three\";\n\n/** Constructor type for type-safe scene traversal */\nexport type Constructor<T> = abstract new (...args: never[]) => T;\n\n/** Find and modify objects in a Three.js scene */\nexport class SceneTraversal {\n /** Find first object with exact name match */\n public static getObjectByName(\n object: Object3D,\n name: string,\n ): Object3D | null {\n if (object.name === name) {\n return object;\n }\n\n for (const child of object.children) {\n const result = SceneTraversal.getObjectByName(child, name);\n if (result) {\n return result;\n }\n }\n\n return null;\n }\n\n /** Find first material with exact name match */\n public static getMaterialByName(\n object: Object3D,\n name: string,\n ): Material | null {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name === name) {\n return material;\n }\n }\n } else if (object.material.name === name) {\n return object.material;\n }\n }\n\n for (const child of object.children) {\n const material = SceneTraversal.getMaterialByName(child, name);\n if (material) {\n return material;\n }\n }\n\n return null;\n }\n\n /** Process all objects of a specific type */\n public static enumerateObjectsByType<T>(\n object: Object3D,\n type: Constructor<T>,\n callback: (instance: T) => void,\n ): void {\n if (object instanceof type) {\n callback(object);\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateObjectsByType(child, type, callback);\n }\n }\n\n /** Process all materials in meshes */\n public static enumerateMaterials(\n object: Object3D,\n callback: (material: Material) => void,\n ): void {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n callback(material);\n }\n } else {\n callback(object.material);\n }\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateMaterials(child, callback);\n }\n }\n\n /** Find all objects whose names match a pattern */\n public static filterObjects(\n object: Object3D,\n filter: RegExp | ((object: Object3D) => boolean),\n ): Object3D[] {\n let result: Object3D[] = [];\n\n if (typeof filter === \"function\") {\n if (filter(object)) {\n result.push(object);\n }\n } else {\n if (object.name && filter.test(object.name)) {\n result.push(object);\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterObjects(child, filter));\n }\n\n return result;\n }\n\n /** Find all materials whose names match a pattern */\n public static filterMaterials(object: Object3D, name: RegExp): Material[] {\n let result: Material[] = [];\n\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name && name.test(material.name)) {\n result.push(material);\n }\n }\n } else {\n if (object.material.name && name.test(object.material.name)) {\n result.push(object.material);\n }\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterMaterials(child, name));\n }\n\n return result;\n }\n\n /** Set shadow properties on meshes */\n public static setShadowRecursive(\n object: Object3D,\n castShadow = true,\n receiveShadow = true,\n filter?: (object: Object3D) => boolean,\n ): void {\n if (object instanceof Mesh || \"isMesh\" in object) {\n (object as Mesh).castShadow = castShadow;\n (object as Mesh).receiveShadow = receiveShadow;\n }\n\n for (const child of object.children) {\n SceneTraversal.setShadowRecursive(\n child,\n castShadow,\n receiveShadow,\n filter,\n );\n }\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { InstancedMesh, Mesh } from \"three\";\nimport { GeometryHasher } from \"./GeometryHasher\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\nconst MIN_INSTANCE_COUNT = 2;\nconst DEFAULT_TOLERANCE = 1e-6;\n\n/** A group of meshes that can be instanced together */\ninterface MeshDescription {\n /** List of meshes */\n meshes: Mesh[];\n /** Materials to use */\n materials: Material[];\n /** Should cast shadows */\n castShadow: boolean;\n /** Should receive shadows */\n receiveShadow: boolean;\n}\n\n/** Configuration for instance assembly */\nexport interface InstanceAssemblerOptions {\n /** Filter which meshes to include */\n filter: (child: Mesh) => boolean;\n\n /** How close vertices need to be to count as identical */\n geometryTolerance: number;\n}\n\n/**\n * Combines identical meshes into instanced versions for better performance.\n * Meshes are considered identical if they share the same geometry and materials.\n */\nexport class InstanceAssembler {\n /**\n * Find meshes that can be instanced and combine them.\n * Only processes meshes that:\n * - Have no children\n * - Pass the filter function (if any)\n * - Share geometry with at least one other mesh\n *\n * @param container - Object containing meshes to process\n * @param options - Optional settings\n */\n public static assemble(\n container: Object3D,\n options: Partial<InstanceAssemblerOptions> = {},\n ): void {\n const dictionary = new Map<string, MeshDescription>();\n const instances: InstancedMesh[] = [];\n\n const tolerance = options.geometryTolerance ?? DEFAULT_TOLERANCE;\n const geometryHashes = new Map<string, string>();\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n if (\n child.children.length === 0 &&\n (!options.filter || options.filter(child))\n ) {\n const materials = Array.isArray(child.material)\n ? child.material\n : [child.material];\n\n let geometryHash = geometryHashes.get(child.geometry.uuid);\n if (!geometryHash) {\n geometryHash = GeometryHasher.getGeometryHash(\n child.geometry,\n tolerance,\n );\n geometryHashes.set(child.geometry.uuid, geometryHash);\n }\n\n const materialKey = materials.map((m) => m.uuid).join(\",\");\n const compositeKey = `${geometryHash}|${materialKey}`;\n\n const entry = dictionary.get(compositeKey) ?? {\n meshes: [],\n materials,\n castShadow: false,\n receiveShadow: false,\n };\n\n if (child.castShadow) {\n entry.castShadow = true;\n }\n\n if (child.receiveShadow) {\n entry.receiveShadow = true;\n }\n\n entry.meshes.push(child);\n dictionary.set(compositeKey, entry);\n }\n });\n\n for (const descriptor of dictionary.values()) {\n if (descriptor.meshes.length < MIN_INSTANCE_COUNT) {\n continue;\n }\n const { meshes, materials, castShadow, receiveShadow } = descriptor;\n\n const sortedMeshes = meshes.sort((a, b) => a.name.localeCompare(b.name));\n const defaultMesh = sortedMeshes[0];\n\n const instancedMesh = new InstancedMesh(\n defaultMesh.geometry,\n materials.length === 1 ? materials[0] : materials,\n sortedMeshes.length,\n );\n\n instancedMesh.name = defaultMesh.name;\n instancedMesh.castShadow = castShadow;\n instancedMesh.receiveShadow = receiveShadow;\n\n for (let i = 0; i < sortedMeshes.length; i++) {\n const mesh = sortedMeshes[i];\n mesh.updateWorldMatrix(true, false);\n instancedMesh.setMatrixAt(i, mesh.matrixWorld);\n instancedMesh.userData[mesh.uuid] = mesh.userData;\n }\n\n instancedMesh.instanceMatrix.needsUpdate = true;\n instances.push(instancedMesh);\n\n for (const mesh of sortedMeshes) {\n mesh.parent?.remove(mesh);\n }\n }\n\n if (instances.length > 0) {\n container.add(...instances);\n }\n }\n}\n","import {\n\tAnimationClip,\n\tAnimationMixer,\n\tMatrix4,\n\tQuaternion,\n\tQuaternionKeyframeTrack,\n\tSkeletonHelper,\n\tVector3,\n\tVectorKeyframeTrack\n} from 'three';\n\n/**\n * @module SkeletonUtils\n * @three_import import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js';\n */\n\nfunction getBoneName( bone, options ) {\n\n\tif ( options.getBoneName !== undefined ) {\n\n\t\treturn options.getBoneName( bone );\n\n\t}\n\n\treturn options.names[ bone.name ];\n\n}\n\n/**\n * Retargets the skeleton from the given source 3D object to the\n * target 3D object.\n *\n * @param {Object3D} target - The target 3D object.\n * @param {Object3D} source - The source 3D object.\n * @param {module:SkeletonUtils~RetargetOptions} options - The options.\n */\nfunction retarget( target, source, options = {} ) {\n\n\tconst quat = new Quaternion(),\n\t\tscale = new Vector3(),\n\t\trelativeMatrix = new Matrix4(),\n\t\tglobalMatrix = new Matrix4();\n\n\toptions.preserveBoneMatrix = options.preserveBoneMatrix !== undefined ? options.preserveBoneMatrix : true;\n\toptions.preserveBonePositions = options.preserveBonePositions !== undefined ? options.preserveBonePositions : true;\n\toptions.useTargetMatrix = options.useTargetMatrix !== undefined ? options.useTargetMatrix : false;\n\toptions.hip = options.hip !== undefined ? options.hip : 'hip';\n\toptions.hipInfluence = options.hipInfluence !== undefined ? options.hipInfluence : new Vector3( 1, 1, 1 );\n\toptions.scale = options.scale !== undefined ? options.scale : 1;\n\toptions.names = options.names || {};\n\n\tconst sourceBones = source.isObject3D ? source.skeleton.bones : getBones( source ),\n\t\tbones = target.isObject3D ? target.skeleton.bones : getBones( target );\n\n\tlet bone, name, boneTo,\n\t\tbonesPosition;\n\n\t// reset bones\n\n\tif ( target.isObject3D ) {\n\n\t\ttarget.skeleton.pose();\n\n\t} else {\n\n\t\toptions.useTargetMatrix = true;\n\t\toptions.preserveBoneMatrix = false;\n\n\t}\n\n\tif ( options.preserveBonePositions ) {\n\n\t\tbonesPosition = [];\n\n\t\tfor ( let i = 0; i < bones.length; i ++ ) {\n\n\t\t\tbonesPosition.push( bones[ i ].position.clone() );\n\n\t\t}\n\n\t}\n\n\tif ( options.preserveBoneMatrix ) {\n\n\t\t// reset matrix\n\n\t\ttarget.updateMatrixWorld();\n\n\t\ttarget.matrixWorld.identity();\n\n\t\t// reset children matrix\n\n\t\tfor ( let i = 0; i < target.children.length; ++ i ) {\n\n\t\t\ttarget.children[ i ].updateMatrixWorld( true );\n\n\t\t}\n\n\t}\n\n\tfor ( let i = 0; i < bones.length; ++ i ) {\n\n\t\tbone = bones[ i ];\n\t\tname = getBoneName( bone, options );\n\n\t\tboneTo = getBoneByName( name, sourceBones );\n\n\t\tglobalMatrix.copy( bone.matrixWorld );\n\n\t\tif ( boneTo ) {\n\n\t\t\tboneTo.updateMatrixWorld();\n\n\t\t\tif ( options.useTargetMatrix ) {\n\n\t\t\t\trelativeMatrix.copy( boneTo.matrixWorld );\n\n\t\t\t} else {\n\n\t\t\t\trelativeMatrix.copy( target.matrixWorld ).invert();\n\t\t\t\trelativeMatrix.multiply( boneTo.matrixWorld );\n\n\t\t\t}\n\n\t\t\t// ignore scale to extract rotation\n\n\t\t\tscale.setFromMatrixScale( relativeMatrix );\n\t\t\trelativeMatrix.scale( scale.set( 1 / scale.x, 1 / scale.y, 1 / scale.z ) );\n\n\t\t\t// apply to global matrix\n\n\t\t\tglobalMatrix.makeRotationFromQuaternion( quat.setFromRotationMatrix( relativeMatrix ) );\n\n\t\t\tif ( target.isObject3D ) {\n\n\t\t\t\tif ( options.localOffsets ) {\n\n\t\t\t\t\tif ( options.localOffsets[ bone.name ] ) {\n\n\t\t\t\t\t\tglobalMatrix.multiply( options.localOffsets[ bone.name ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tglobalMatrix.copyPosition( relativeMatrix );\n\n\t\t}\n\n\t\tif ( name === options.hip ) {\n\n\t\t\tglobalMatrix.elements[ 12 ] *= options.scale * options.hipInfluence.x;\n\t\t\tglobalMatrix.elements[ 13 ] *= options.scale * options.hipInfluence.y;\n\t\t\tglobalMatrix.elements[ 14 ] *= options.scale * options.hipInfluence.z;\n\n\t\t\tif ( options.hipPosition !== undefined ) {\n\n\t\t\t\tglobalMatrix.elements[ 12 ] += options.hipPosition.x * options.scale;\n\t\t\t\tglobalMatrix.elements[ 13 ] += options.hipPosition.y * options.scale;\n\t\t\t\tglobalMatrix.elements[ 14 ] += options.hipPosition.z * options.scale;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( bone.parent ) {\n\n\t\t\tbone.matrix.copy( bone.parent.matrixWorld ).invert();\n\t\t\tbone.matrix.multiply( globalMatrix );\n\n\t\t} else {\n\n\t\t\tbone.matrix.copy( globalMatrix );\n\n\t\t}\n\n\t\tbone.matrix.decompose( bone.position, bone.quaternion, bone.scale );\n\n\t\tbone.updateMatrixWorld();\n\n\t}\n\n\tif ( options.preserveBonePositions ) {\n\n\t\tfor ( let i = 0; i < bones.length; ++ i ) {\n\n\t\t\tbone = bones[ i ];\n\t\t\tname = getBoneName( bone, options ) || bone.name;\n\n\t\t\tif ( name !== options.hip ) {\n\n\t\t\t\tbone.position.copy( bonesPosition[ i ] );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tif ( options.preserveBoneMatrix ) {\n\n\t\t// restore matrix\n\n\t\ttarget.updateMatrixWorld( true );\n\n\t}\n\n}\n\n/**\n * Retargets the animation clip of the source object to the\n * target 3D object.\n *\n * @param {Object3D} target - The target 3D object.\n * @param {Object3D} source - The source 3D object.\n * @param {AnimationClip} clip - The animation clip.\n * @param {module:SkeletonUtils~RetargetOptions} options - The options.\n * @return {AnimationClip} The retargeted animation clip.\n */\nfunction retargetClip( target, source, clip, options = {} ) {\n\n\toptions.useFirstFramePosition = options.useFirstFramePosition !== undefined ? options.useFirstFramePosition : false;\n\n\t// Calculate the fps from the source clip based on the track with the most frames, unless fps is already provided.\n\toptions.fps = options.fps !== undefined ? options.fps : ( Math.max( ...clip.tracks.map( track => track.times.length ) ) / clip.duration );\n\toptions.names = options.names || [];\n\n\tif ( ! source.isObject3D ) {\n\n\t\tsource = getHelperFromSkeleton( source );\n\n\t}\n\n\tconst numFrames = Math.round( clip.duration * ( options.fps / 1000 ) * 1000 ),\n\t\tdelta = clip.duration / ( numFrames - 1 ),\n\t\tconvertedTracks = [],\n\t\tmixer = new AnimationMixer( source ),\n\t\tbones = getBones( target.skeleton ),\n\t\tboneDatas = [];\n\n\tlet positionOffset,\n\t\tbone, boneTo, boneData,\n\t\tname;\n\n\tmixer.clipAction( clip ).play();\n\n\t// trim\n\n\tlet start = 0, end = numFrames;\n\n\tif ( options.trim !== undefined ) {\n\n\t\tstart = Math.round( options.trim[ 0 ] * options.fps );\n\t\tend = Math.min( Math.round( options.trim[ 1 ] * options.fps ), numFrames ) - start;\n\n\t\tmixer.update( options.trim[ 0 ] );\n\n\t} else {\n\n\t\tmixer.update( 0 );\n\n\t}\n\n\tsource.updateMatrixWorld();\n\n\t//\n\n\tfor ( let frame = 0; frame < end; ++ frame ) {\n\n\t\tconst time = frame * delta;\n\n\t\tretarget( target, source, options );\n\n\t\tfor ( let j = 0; j < bones.length; ++ j ) {\n\n\t\t\tbone = bones[ j ];\n\t\t\tname = getBoneName( bone, options ) || bone.name;\n\t\t\tboneTo = getBoneByName( name, source.skeleton );\n\n\t\t\tif ( boneTo ) {\n\n\t\t\t\tboneData = boneDatas[ j ] = boneDatas[ j ] || { bone: bone };\n\n\t\t\t\tif ( options.hip === name ) {\n\n\t\t\t\t\tif ( ! boneData.pos ) {\n\n\t\t\t\t\t\tboneData.pos = {\n\t\t\t\t\t\t\ttimes: new Float32Array( end ),\n\t\t\t\t\t\t\tvalues: new Float32Array( end * 3 )\n\t\t\t\t\t\t};\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( options.useFirstFramePosition ) {\n\n\t\t\t\t\t\tif ( frame === 0 ) {\n\n\t\t\t\t\t\t\tpositionOffset = bone.position.clone();\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbone.position.sub( positionOffset );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tboneData.pos.times[ frame ] = time;\n\n\t\t\t\t\tbone.position.toArray( boneData.pos.values, frame * 3 );\n\n\t\t\t\t}\n\n\t\t\t\tif ( ! boneData.quat ) {\n\n\t\t\t\t\tboneData.quat = {\n\t\t\t\t\t\ttimes: new Float32Array( end ),\n\t\t\t\t\t\tvalues: new Float32Array( end * 4 )\n\t\t\t\t\t};\n\n\t\t\t\t}\n\n\t\t\t\tboneData.quat.times[ frame ] = time;\n\n\t\t\t\tbone.quaternion.toArray( boneData.quat.values, frame * 4 );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( frame === end - 2 ) {\n\n\t\t\t// last mixer update before final loop iteration\n\t\t\t// make sure we do not go over or equal to clip duration\n\t\t\tmixer.update( delta - 0.0000001 );\n\n\t\t} else {\n\n\t\t\tmixer.update( delta );\n\n\t\t}\n\n\t\tsource.updateMatrixWorld();\n\n\t}\n\n\tfor ( let i = 0; i < boneDatas.length; ++ i ) {\n\n\t\tboneData = boneDatas[ i ];\n\n\t\tif ( boneData ) {\n\n\t\t\tif ( boneData.pos ) {\n\n\t\t\t\tconvertedTracks.push( new VectorKeyframeTrack(\n\t\t\t\t\t'.bones[' + boneData.bone.name + '].position',\n\t\t\t\t\tboneData.pos.times,\n\t\t\t\t\tboneData.pos.values\n\t\t\t\t) );\n\n\t\t\t}\n\n\t\t\tconvertedTracks.push( new QuaternionKeyframeTrack(\n\t\t\t\t'.bones[' + boneData.bone.name + '].quaternion',\n\t\t\t\tboneData.quat.times,\n\t\t\t\tboneData.quat.values\n\t\t\t) );\n\n\t\t}\n\n\t}\n\n\tmixer.uncacheAction( clip );\n\n\treturn new AnimationClip( clip.name, - 1, convertedTracks );\n\n}\n\n/**\n * Clones the given 3D object and its descendants, ensuring that any `SkinnedMesh` instances are\n * correctly associated with their bones. Bones are also cloned, and must be descendants of the\n * object passed to this method. Other data, like geometries and materials, are reused by reference.\n *\n * @param {Object3D} source - The 3D object to clone.\n * @return {Object3D} The cloned 3D object.\n */\nfunction clone( source ) {\n\n\tconst sourceLookup = new Map();\n\tconst cloneLookup = new Map();\n\n\tconst clone = source.clone();\n\n\tparallelTraverse( source, clone, function ( sourceNode, clonedNode ) {\n\n\t\tsourceLookup.set( clonedNode, sourceNode );\n\t\tcloneLookup.set( sourceNode, clonedNode );\n\n\t} );\n\n\tclone.traverse( function ( node ) {\n\n\t\tif ( ! node.isSkinnedMesh ) return;\n\n\t\tconst clonedMesh = node;\n\t\tconst sourceMesh = sourceLookup.get( node );\n\t\tconst sourceBones = sourceMesh.skeleton.bones;\n\n\t\tclonedMesh.skeleton = sourceMesh.skeleton.clone();\n\t\tclonedMesh.bindMatrix.copy( sourceMesh.bindMatrix );\n\n\t\tclonedMesh.skeleton.bones = sourceBones.map( function ( bone ) {\n\n\t\t\treturn cloneLookup.get( bone );\n\n\t\t} );\n\n\t\tclonedMesh.bind( clonedMesh.skeleton, clonedMesh.bindMatrix );\n\n\t} );\n\n\treturn clone;\n\n}\n\n// internal helper\n\nfunction getBoneByName( name, skeleton ) {\n\n\tfor ( let i = 0, bones = getBones( skeleton ); i < bones.length; i ++ ) {\n\n\t\tif ( name === bones[ i ].name )\n\n\t\t\treturn bones[ i ];\n\n\t}\n\n}\n\nfunction getBones( skeleton ) {\n\n\treturn Array.isArray( skeleton ) ? skeleton : skeleton.bones;\n\n}\n\n\nfunction getHelperFromSkeleton( skeleton ) {\n\n\tconst source = new SkeletonHelper( skeleton.bones[ 0 ] );\n\tsource.skeleton = skeleton;\n\n\treturn source;\n\n}\n\nfunction parallelTraverse( a, b, callback ) {\n\n\tcallback( a, b );\n\n\tfor ( let i = 0; i < a.children.length; i ++ ) {\n\n\t\tparallelTraverse( a.children[ i ], b.children[ i ], callback );\n\n\t}\n\n}\n\n/**\n * Retarget options of `SkeletonUtils`.\n *\n * @typedef {Object} module:SkeletonUtils~RetargetOptions\n * @property {boolean} [useFirstFramePosition=false] - Whether to use the position of the first frame or not.\n * @property {number} [fps] - The FPS of the clip.\n * @property {Object<string,string>} [names] - A dictionary for mapping target to source bone names.\n * @property {function(string):string} [getBoneName] - A function for mapping bone names. Alternative to `names`.\n * @property {Array<number>} [trim] - Whether to trim the clip or not. If set the array should hold two values for the start and end.\n * @property {boolean} [preserveBoneMatrix=true] - Whether to preserve bone matrices or not.\n * @property {boolean} [preserveBonePositions=true] - Whether to preserve bone positions or not.\n * @property {boolean} [useTargetMatrix=false] - Whether to use the target matrix or not.\n * @property {string} [hip='hip'] - The name of the source's hip bone.\n * @property {Vector3} [hipInfluence=(1,1,1)] - The hip influence.\n * @property {number} [scale=1] - The scale.\n **/\n\nexport {\n\tretarget,\n\tretargetClip,\n\tclone,\n};\n","import type { Material, Object3D } from \"three\";\nimport { FrontSide, Mesh } from \"three\";\nimport { clone } from \"three/examples/jsm/utils/SkeletonUtils.js\";\nimport { InstanceAssembler } from \"./InstanceAssembler\";\nimport { SceneTraversal } from \"./SceneTraversal\";\n\n/** Options for scene post-processing */\nexport interface SceneProcessorOptions {\n /** Clone the input asset before processing? */\n cloneAsset: boolean;\n\n /** Combine identical meshes into instances? */\n assembleInstances: boolean;\n\n /** Names matching these patterns will cast shadows */\n castShadowRegExp: RegExp;\n\n /** Names matching these patterns will receive shadows */\n receiveShadowRegExp: RegExp;\n\n /** Names matching these patterns will be transparent */\n transparentMaterialRegExp: RegExp;\n\n /** Names matching these patterns won't write to depth buffer */\n noDepthWriteMaterialRegExp: RegExp;\n\n /** Names matching these patterns will be alpha tested */\n alphaTestMaterialRegExp: RegExp;\n\n /** Names matching these patterns will be alpha hashed */\n alphaHashMaterialRegExp: RegExp;\n}\n\n/** Post-processes a scene based on name patterns */\nexport class SceneProcessor {\n /**\n * Process a scene to set up materials and shadows.\n *\n * @param object - Scene to process\n * @param options - How to process the scene\n * @returns Processed scene root objects\n */\n public static process(\n object: Object3D,\n options: Partial<SceneProcessorOptions>,\n ): Object3D[] {\n const container = options.cloneAsset !== false ? clone(object) : object;\n\n if (options.assembleInstances !== false) {\n InstanceAssembler.assemble(container);\n }\n\n SceneTraversal.enumerateMaterials(container, (material: Material) => {\n material.transparent =\n options.transparentMaterialRegExp?.test(material.name) ?? false;\n material.depthWrite = !(\n options.noDepthWriteMaterialRegExp?.test(material.name) ?? false\n );\n material.alphaTest = options.alphaTestMaterialRegExp?.test(material.name)\n ? 0.5\n : 0;\n material.alphaHash =\n options.alphaHashMaterialRegExp?.test(material.name) ?? false;\n material.side = FrontSide;\n material.forceSinglePass = true;\n material.depthTest = true;\n });\n\n SceneTraversal.enumerateObjectsByType(container, Mesh, (child: Mesh) => {\n child.castShadow = options.castShadowRegExp?.test(child.name) ?? false;\n child.receiveShadow =\n options.receiveShadowRegExp?.test(child.name) ?? false;\n });\n\n return container.children;\n }\n}\n","import type { AnimationClip, Object3D, SkinnedMesh } from \"three\";\nimport { AnimationMixer, BufferAttribute, Mesh, Vector3 } from \"three\";\n\n/** Number of components per vertex */\nconst COMPONENT_COUNT = 3;\n\n/** Convert skinned meshes to regular static meshes */\nexport class SkinnedMeshBaker {\n /**\n * Convert a skinned mesh to a regular mesh in its current pose.\n * The resulting mesh will have no bones but look identical.\n * \n * @param skinnedMesh - Mesh to convert\n * @returns Static mesh with baked vertex positions\n */\n public static bakePose(skinnedMesh: SkinnedMesh): Mesh {\n const bakedGeometry = skinnedMesh.geometry.clone();\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const newPositions = new Float32Array(position.count * COMPONENT_COUNT);\n const target = new Vector3();\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n newPositions[i * COMPONENT_COUNT + 0] = target.x;\n newPositions[i * COMPONENT_COUNT + 1] = target.y;\n newPositions[i * COMPONENT_COUNT + 2] = target.z;\n }\n\n bakedGeometry.setAttribute(\n \"position\",\n new BufferAttribute(newPositions, COMPONENT_COUNT),\n );\n bakedGeometry.computeVertexNormals();\n bakedGeometry.deleteAttribute(\"skinIndex\");\n bakedGeometry.deleteAttribute(\"skinWeight\");\n\n const mesh = new Mesh(bakedGeometry, skinnedMesh.material);\n mesh.name = skinnedMesh.name;\n return mesh;\n }\n\n /**\n * Bake a single frame from an animation into a static mesh.\n * \n * @param armature - Root object with bones (usually from GLTF)\n * @param skinnedMesh - Mesh to convert\n * @param timeOffset - Time in seconds within the animation\n * @param clip - Animation to get the pose from\n * @returns Static mesh with baked vertex positions\n */\n public static bakeAnimationFrame(\n armature: Object3D,\n skinnedMesh: SkinnedMesh,\n timeOffset: number,\n clip: AnimationClip,\n ): Mesh {\n const mixer = new AnimationMixer(armature);\n const action = mixer.clipAction(clip);\n action.play();\n mixer.setTime(timeOffset);\n\n armature.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n return this.bakePose(skinnedMesh);\n }\n}","import type { Texture } from \"three\";\nimport { Box3, DirectionalLight, RGBAFormat, Spherical, Vector3 } from \"three\";\n\nconst RGBA_CHANNEL_COUNT = 4;\nconst RGB_CHANNEL_COUNT = 3;\n\nconst LUMINANCE_R = 0.2126;\nconst LUMINANCE_G = 0.7152;\nconst LUMINANCE_B = 0.0722;\n\n/** A directional light with spherical positioning controls */\nexport class Sun extends DirectionalLight {\n /** Internal vectors to avoid garbage collection */\n private readonly tempVector3D0 = new Vector3();\n private readonly tempVector3D1 = new Vector3();\n private readonly tempVector3D2 = new Vector3();\n private readonly tempVector3D3 = new Vector3();\n private readonly tempVector3D4 = new Vector3();\n private readonly tempVector3D5 = new Vector3();\n private readonly tempVector3D6 = new Vector3();\n private readonly tempVector3D7 = new Vector3();\n private readonly tempBox3 = new Box3();\n private readonly tempSpherical = new Spherical();\n\n /** Distance from the light to its target */\n public get distance(): number {\n return this.position.length();\n }\n\n /** Vertical angle from the ground in radians */\n public get elevation(): number {\n return this.tempSpherical.setFromVector3(this.position).phi;\n }\n\n /** Horizontal angle around the target in radians */\n public get azimuth(): number {\n return this.tempSpherical.setFromVector3(this.position).theta;\n }\n\n /** Set distance while keeping current angles */\n public set distance(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n value,\n this.tempSpherical.phi,\n this.tempSpherical.theta,\n );\n }\n\n /** Set elevation while keeping current distance and azimuth */\n public set elevation(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n value,\n this.tempSpherical.theta,\n );\n }\n\n /** Set azimuth while keeping current distance and elevation */\n public set azimuth(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n this.tempSpherical.phi,\n value,\n );\n }\n\n /** Configure shadows to cover all corners of a bounding box */\n public setShadowMapFromBox3(box3: Box3): void {\n const camera = this.shadow.camera;\n\n this.target.updateWorldMatrix(true, false);\n this.lookAt(this.target.getWorldPosition(this.tempVector3D0));\n\n this.updateWorldMatrix(true, false);\n\n const points: Vector3[] = [\n this.tempVector3D0.set(box3.min.x, box3.min.y, box3.min.z),\n this.tempVector3D1.set(box3.min.x, box3.min.y, box3.max.z),\n this.tempVector3D2.set(box3.min.x, box3.max.y, box3.min.z),\n this.tempVector3D3.set(box3.min.x, box3.max.y, box3.max.z),\n this.tempVector3D4.set(box3.max.x, box3.min.y, box3.min.z),\n this.tempVector3D5.set(box3.max.x, box3.min.y, box3.max.z),\n this.tempVector3D6.set(box3.max.x, box3.max.y, box3.min.z),\n this.tempVector3D7.set(box3.max.x, box3.max.y, box3.max.z),\n ];\n\n const inverseMatrix = this.matrixWorld.clone().invert();\n\n for (const point of points) {\n point.applyMatrix4(inverseMatrix);\n }\n\n const newBox3 = this.tempBox3.setFromPoints(points);\n\n camera.left = newBox3.min.x;\n camera.bottom = newBox3.min.y;\n camera.near = -newBox3.max.z;\n\n camera.right = newBox3.max.x;\n camera.top = newBox3.max.y;\n camera.far = -newBox3.min.z;\n\n camera.updateWorldMatrix(true, false);\n camera.updateProjectionMatrix();\n }\n\n /** Set light direction based on brightest point in an HDR texture */\n public setDirectionFromHDR(texture: Texture, distance = 1): void {\n const data = texture.image.data;\n const width = texture.image.width;\n const height = texture.image.height;\n\n let maxLuminance = 0;\n let maxIndex = 0;\n\n // Find brightest pixel\n\n const step =\n texture.format === RGBAFormat ? RGBA_CHANNEL_COUNT : RGB_CHANNEL_COUNT;\n for (let i = 0; i < data.length; i += step) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const luminance = LUMINANCE_R * r + LUMINANCE_G * g + LUMINANCE_B * b;\n if (luminance > maxLuminance) {\n maxLuminance = luminance;\n maxIndex = i;\n }\n }\n\n // Convert to spherical coordinates\n const pixelIndex = maxIndex / step;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n\n const u = x / width;\n const v = y / height;\n\n const elevation = v * Math.PI;\n const azimuth = u * -Math.PI * 2 - Math.PI / 2;\n\n this.position.setFromSphericalCoords(distance, elevation, azimuth);\n }\n}\n"],"names":["MAX_FOV","BiFovCamera","PerspectiveCamera","constructor","horizontalFov","verticalFov","aspect","near","far","super","this","horizontalFovInternal","verticalFovInternal","updateProjectionMatrix","value","MathUtils","clamp","setFov","horizontal","vertical","copyFovSettings","source","radians","degToRad","fov","radToDeg","Math","atan","tan","getEffectiveHorizontalFov","verticalRadians","getEffectiveVerticalFov","horizontalRadians","fitPointsVerticalFov","vertices","up","Vector3","applyQuaternion","quaternion","maxVerticalAngle","vertex","vertexDirection","position","clone","sub","normalize","verticalAngle","asin","abs","dot","sign","requiredFov","fitBoxVerticalFov","box","min","x","y","z","max","fitSkinnedMeshVerticalFov","skinnedMesh","updateWorldMatrix","skeleton","update","geometry","attributes","target","points","i","count","fromBufferAttribute","applyBoneTransform","push","lookAtCenterOfMass","centerOfMass","iterations","length","center","floor","total","point","distanceTo","add","divideScalar","findMainCluster","lookAt","camera","copy","Bounds","Box3","object","tempVector3A","setFromObject","width","height","depth","diagonal","subVectors","setFromSkinnedMesh","setFromPoints","getVolume","getSurfaceArea","w","h","d","GeometryHasher","getGeometryHash","tolerance","positionArray","array","positionHashParts","round","normalHashParts","normalArray","join","SceneTraversal","getObjectByName","name","child","children","result","getMaterialByName","Mesh","Array","isArray","material","enumerateObjectsByType","type","callback","enumerateMaterials","filterObjects","filter","test","concat","filterMaterials","setShadowRecursive","castShadow","receiveShadow","InstanceAssembler","assemble","container","options","dictionary","Map","instances","_a","geometryTolerance","geometryHashes","materials","geometryHash","get","uuid","set","compositeKey","map","m","entry","meshes","descriptor","values","sortedMeshes","sort","a","b","localeCompare","defaultMesh","instancedMesh","InstancedMesh","mesh","setMatrixAt","matrixWorld","userData","instanceMatrix","needsUpdate","_b","parent","remove","sourceLookup","cloneLookup","parallelTraverse","sourceNode","clonedNode","traverse","node","isSkinnedMesh","clonedMesh","sourceMesh","sourceBones","bones","bindMatrix","bone","bind","SceneProcessor","process","cloneAsset","assembleInstances","transparent","transparentMaterialRegExp","depthWrite","_d","_c","noDepthWriteMaterialRegExp","alphaTest","alphaTestMaterialRegExp","_e","alphaHash","_g","_f","alphaHashMaterialRegExp","side","FrontSide","forceSinglePass","depthTest","castShadowRegExp","receiveShadowRegExp","SkinnedMeshBaker","bakePose","bakedGeometry","newPositions","Float32Array","setAttribute","BufferAttribute","computeVertexNormals","deleteAttribute","bakeAnimationFrame","armature","timeOffset","clip","mixer","AnimationMixer","clipAction","play","setTime","Sun","DirectionalLight","tempVector3D0","tempVector3D1","tempVector3D2","tempVector3D3","tempVector3D4","tempVector3D5","tempVector3D6","tempVector3D7","tempBox3","tempSpherical","Spherical","distance","elevation","setFromVector3","phi","azimuth","theta","setFromSphericalCoords","radius","setShadowMapFromBox3","box3","shadow","getWorldPosition","inverseMatrix","invert","applyMatrix4","newBox3","left","bottom","right","top","setDirectionFromHDR","texture","data","image","maxLuminance","maxIndex","step","format","RGBAFormat","luminance","pixelIndex","PI"],"mappings":"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","x_google_ignoreList":[5]}
1
+ {"version":3,"file":"index.min.js","sources":["../src/DualFovCamera.ts","../src/SceneTraversal.ts","../src/SkinnedMeshBaker.ts","../src/Sun.ts"],"sourcesContent":["import type { Box3, BufferAttribute, SkinnedMesh } from \"three\";\nimport { MathUtils, PerspectiveCamera, Vector3 } from \"three\";\n\n/** Default horizontal field of view in degrees */\nconst DEFAULT_HORIZONTAL_FOV = 90;\n/** Default vertical field of view in degrees */\nconst DEFAULT_VERTICAL_FOV = 90;\n/** Default aspect ratio (width/height) */\nconst DEFAULT_ASPECT = 1;\n/** Default near clipping plane distance */\nconst DEFAULT_NEAR = 1;\n/** Default far clipping plane distance */\nconst DEFAULT_FAR = 1000;\n\n/** Minimum allowed field of view in degrees */\nconst MIN_FOV = 1;\n/** Maximum allowed field of view in degrees */\nconst MAX_FOV = 179;\n\n/**\n * A camera that supports independent horizontal and vertical FOV settings.\n * Extends Three.js PerspectiveCamera to allow separate control over horizontal\n * and vertical fields of view.\n */\nexport class DualFovCamera extends PerspectiveCamera {\n /** Internal storage for horizontal field of view in degrees */\n private horizontalFovInternal: number;\n /** Internal storage for vertical field of view in degrees */\n private verticalFovInternal: number;\n\n /**\n * Creates a new DualFovCamera instance with independent horizontal and vertical FOV control.\n *\n * @param horizontalFov - Horizontal field of view in degrees. Must be between 1° and 179°. Defaults to 90°.\n * @param verticalFov - Vertical field of view in degrees. Must be between 1° and 179°. Defaults to 90°.\n * @param aspect - Camera aspect ratio (width/height). Defaults to 1.\n * @param near - Near clipping plane distance. Must be greater than 0. Defaults to 1.\n * @param far - Far clipping plane distance. Must be greater than near plane. Defaults to 1000.\n */\n constructor(\n horizontalFov = DEFAULT_HORIZONTAL_FOV,\n verticalFov = DEFAULT_VERTICAL_FOV,\n aspect = DEFAULT_ASPECT,\n near = DEFAULT_NEAR,\n far = DEFAULT_FAR,\n ) {\n super(verticalFov, aspect, near, far);\n this.horizontalFovInternal = horizontalFov;\n this.verticalFovInternal = verticalFov;\n this.updateProjectionMatrix();\n }\n\n /**\n * Gets the current horizontal field of view in degrees.\n *\n * @returns The horizontal FOV value between 1° and 179°\n */\n public get horizontalFov(): number {\n return this.horizontalFovInternal;\n }\n\n /**\n * Gets the current vertical field of view in degrees.\n *\n * @returns The vertical FOV value between 1° and 179°\n */\n public get verticalFov(): number {\n return this.verticalFovInternal;\n }\n\n /**\n * Sets the horizontal field of view in degrees.\n *\n * @param value - The horizontal FOV value in degrees. Will be clamped between 1° and 179°.\n */\n public set horizontalFov(value: number) {\n this.horizontalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Sets the vertical field of view in degrees.\n *\n * @param value - The vertical FOV value in degrees. Will be clamped between 1° and 179°.\n */\n public set verticalFov(value: number) {\n this.verticalFovInternal = MathUtils.clamp(value, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates both horizontal and vertical field of view values simultaneously.\n *\n * @param horizontal - Horizontal FOV in degrees. Will be clamped between 1° and 179°.\n * @param vertical - Vertical FOV in degrees. Will be clamped between 1° and 179°.\n */\n public setFov(horizontal: number, vertical: number): void {\n this.horizontalFovInternal = MathUtils.clamp(horizontal, MIN_FOV, MAX_FOV);\n this.verticalFovInternal = MathUtils.clamp(vertical, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Copies the field of view settings from another DualFovCamera instance.\n *\n * @param source - The DualFovCamera instance to copy FOV settings from.\n */\n public copyFovSettings(source: DualFovCamera): void {\n this.horizontalFovInternal = source.horizontalFov;\n this.verticalFovInternal = source.verticalFov;\n this.updateProjectionMatrix();\n }\n\n /**\n * Updates the projection matrix based on current FOV settings and aspect ratio.\n *\n * The behavior differs based on orientation:\n * - **Landscape mode (aspect > 1)**: Preserves horizontal FOV, calculates vertical FOV\n * - **Portrait mode (aspect ≤ 1)**: Preserves vertical FOV, calculates horizontal FOV\n *\n * This method is automatically called when FOV values or aspect ratio changes.\n *\n * @override\n */\n public override updateProjectionMatrix(): void {\n if (this.aspect > 1) {\n // Landscape orientation: preserve horizontal FOV\n const radians = MathUtils.degToRad(this.horizontalFovInternal);\n this.fov = MathUtils.radToDeg(\n Math.atan(Math.tan(radians / 2) / this.aspect) * 2,\n );\n } else {\n // Portrait orientation: preserve vertical FOV\n this.fov = this.verticalFovInternal;\n }\n\n super.updateProjectionMatrix();\n }\n\n /**\n * Gets the actual horizontal field of view after aspect ratio adjustments.\n *\n * In landscape mode, this returns the set horizontal FOV.\n * In portrait mode, this calculates the actual horizontal FOV based on the vertical FOV and aspect ratio.\n *\n * @returns The actual horizontal FOV in degrees\n */\n public getActualHorizontalFov(): number {\n if (this.aspect >= 1) {\n return this.horizontalFovInternal;\n }\n const verticalRadians = MathUtils.degToRad(this.verticalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(verticalRadians / 2) * this.aspect) * 2,\n );\n }\n\n /**\n * Gets the actual vertical field of view after aspect ratio adjustments.\n *\n * In portrait mode, this returns the set vertical FOV.\n * In landscape mode, this calculates the actual vertical FOV based on the horizontal FOV and aspect ratio.\n *\n * @returns The actual vertical FOV in degrees\n */\n public getActualVerticalFov(): number {\n if (this.aspect < 1) {\n return this.verticalFovInternal;\n }\n const horizontalRadians = MathUtils.degToRad(this.horizontalFovInternal);\n return MathUtils.radToDeg(\n Math.atan(Math.tan(horizontalRadians / 2) / this.aspect) * 2,\n );\n }\n\n /**\n * Adjusts the vertical field of view to fit all specified points within the camera's view.\n *\n * This method calculates the required vertical FOV to ensure all provided vertices\n * are visible within the vertical bounds of the camera's frustum.\n *\n * @param vertices - Array of 3D points (in world coordinates) that should fit within the camera's vertical view\n */\n public fitVerticalFovToPoints(vertices: Vector3[]): void {\n const up = new Vector3(0, 1, 0).applyQuaternion(this.quaternion);\n\n let maxVerticalAngle = 0;\n\n for (const vertex of vertices) {\n const vertexToCam = this.position.clone().sub(vertex);\n const vertexDirection = vertexToCam.normalize();\n\n const verticalAngle =\n Math.asin(Math.abs(vertexDirection.dot(up))) *\n Math.sign(vertexDirection.dot(up));\n\n if (Math.abs(verticalAngle) > maxVerticalAngle) {\n maxVerticalAngle = Math.abs(verticalAngle);\n }\n }\n\n const requiredFov = MathUtils.radToDeg(2 * maxVerticalAngle);\n\n this.verticalFovInternal = MathUtils.clamp(requiredFov, MIN_FOV, MAX_FOV);\n this.updateProjectionMatrix();\n }\n\n /**\n * Adjusts the vertical field of view to fit a bounding box within the camera's view.\n *\n * This method calculates the required vertical FOV to ensure the entire bounding box\n * is visible within the vertical bounds of the camera's frustum.\n *\n * @param box - The 3D bounding box (in world coordinates) that should fit within the camera's vertical view\n */\n public fitVerticalFovToBox(box: Box3): void {\n this.fitVerticalFovToPoints([\n new Vector3(box.min.x, box.min.y, box.min.z),\n new Vector3(box.min.x, box.min.y, box.max.z),\n new Vector3(box.min.x, box.max.y, box.min.z),\n new Vector3(box.min.x, box.max.y, box.max.z),\n new Vector3(box.max.x, box.min.y, box.min.z),\n new Vector3(box.max.x, box.min.y, box.max.z),\n new Vector3(box.max.x, box.max.y, box.min.z),\n new Vector3(box.max.x, box.max.y, box.max.z),\n ]);\n }\n\n /**\n * Adjusts the vertical field of view to fit a skinned mesh within the camera's view.\n *\n * This method updates the mesh's skeleton, applies bone transformations to all vertices,\n * and then calculates the required vertical FOV to ensure the entire deformed mesh\n * is visible within the vertical bounds of the camera's frustum.\n *\n * @param skinnedMesh - The skinned mesh (with active skeleton) that should fit within the camera's vertical view\n */\n public fitVerticalFovToMesh(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const target = new Vector3();\n\n const points = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n this.fitVerticalFovToPoints(points);\n }\n\n /**\n * Points the camera to look at the center of mass of a skinned mesh.\n *\n * This method updates the mesh's skeleton, applies bone transformations to all vertices,\n * calculates the center of mass using a clustering algorithm, and then orients the camera\n * to look at that point.\n *\n * The center of mass calculation uses an iterative clustering approach to find the\n * main concentration of vertices, which provides better results than a simple average\n * for complex meshes.\n *\n * @param skinnedMesh - The skinned mesh (with active skeleton) whose center of mass should be the camera's target\n */\n public lookAtMeshCenterOfMass(skinnedMesh: SkinnedMesh): void {\n skinnedMesh.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n const bakedGeometry = skinnedMesh.geometry;\n const position = bakedGeometry.attributes.position as BufferAttribute;\n const target = new Vector3();\n const points: Vector3[] = [];\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n points.push(target.clone());\n }\n\n /**\n * Finds the main cluster center of a set of 3D points using iterative refinement.\n *\n * @param points - Array of 3D points to cluster\n * @param iterations - Number of refinement iterations to perform\n * @returns The calculated center point of the main cluster\n */\n const findMainCluster = (points: Vector3[], iterations = 3): Vector3 => {\n if (points.length === 0) {\n return new Vector3();\n }\n\n let center = points[Math.floor(points.length / 2)].clone();\n\n for (let i = 0; i < iterations; i++) {\n let total = new Vector3();\n let count = 0;\n\n for (const point of points) {\n if (\n point.distanceTo(center) < point.distanceTo(total) ||\n count === 0\n ) {\n total.add(point);\n count++;\n }\n }\n\n if (count > 0) {\n center = total.divideScalar(count);\n }\n }\n\n return center;\n };\n\n const centerOfMass = findMainCluster(points);\n this.lookAt(centerOfMass);\n }\n\n /**\n * Creates a deep copy of this DualFovCamera instance.\n *\n * The cloned camera will have identical FOV settings, position, rotation,\n * and all other camera properties.\n *\n * @returns A new DualFovCamera instance that is an exact copy of this one\n * @override\n */\n public override clone(): this {\n const camera = new DualFovCamera(\n this.horizontalFovInternal,\n this.verticalFovInternal,\n this.aspect,\n this.near,\n this.far,\n ) as this;\n\n camera.copy(this, true);\n return camera;\n }\n}\n","import type { Material, Object3D } from \"three\";\nimport { Mesh } from \"three\";\n\n/**\n * Constructor type for type-safe scene traversal operations.\n *\n * This type represents any constructor function that can be used to create instances of type T.\n * It's used for runtime type checking when filtering objects by their constructor type.\n *\n * @template T - The type that the constructor creates\n */\nexport type Constructor<T> = abstract new (...args: never[]) => T;\n\n/**\n * Utility class for finding and modifying objects in a Three.js scene graph.\n *\n * This class provides static methods for traversing Three.js scene hierarchies,\n * searching for specific objects or materials, and performing batch operations\n * on collections of scene objects.\n *\n * All methods perform depth-first traversal of the scene graph starting from\n * the provided root object and recursively processing all children.\n */\nexport class SceneTraversal {\n /**\n * Finds the first object in the scene hierarchy with an exact name match.\n *\n * Performs a depth-first search through the scene graph starting from the provided\n * root object. Returns the first object encountered whose name property exactly\n * matches the search string.\n *\n * @param object - The root Object3D to start searching from\n * @param name - The exact name to search for (case-sensitive)\n * @returns The first matching Object3D, or null if no match is found\n\n */\n public static getObjectByName(\n object: Object3D,\n name: string,\n ): Object3D | null {\n if (object.name === name) {\n return object;\n }\n\n for (const child of object.children) {\n const result = SceneTraversal.getObjectByName(child, name);\n if (result) {\n return result;\n }\n }\n\n return null;\n }\n\n /**\n * Finds the first material in the scene hierarchy with an exact name match.\n *\n * Performs a depth-first search through the scene graph, examining materials\n * attached to Mesh objects. Handles both single materials and material arrays.\n * Returns the first material encountered whose name property exactly matches\n * the search string.\n *\n * @param object - The root Object3D to start searching from\n * @param name - The exact material name to search for (case-sensitive)\n * @returns The first matching Material, or null if no match is found\n\n */\n public static getMaterialByName(\n object: Object3D,\n name: string,\n ): Material | null {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name === name) {\n return material;\n }\n }\n } else if (object.material.name === name) {\n return object.material;\n }\n }\n\n for (const child of object.children) {\n const material = SceneTraversal.getMaterialByName(child, name);\n if (material) {\n return material;\n }\n }\n\n return null;\n }\n\n /**\n * Processes all objects of a specific type in the scene hierarchy.\n *\n * Performs a depth-first traversal and executes the provided callback function\n * for every object that is an instance of the specified type. This is useful\n * for batch operations on specific object types (e.g., all lights, all meshes, etc.).\n *\n * @template T - The type of objects to process\n * @param object - The root Object3D to start searching from\n * @param type - The constructor/class to filter by (e.g., DirectionalLight, Mesh)\n * @param callback - Function to execute for each matching object instance\n\n */\n public static enumerateObjectsByType<T>(\n object: Object3D,\n type: Constructor<T>,\n callback: (instance: T) => void,\n ): void {\n if (object instanceof type) {\n callback(object);\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateObjectsByType(child, type, callback);\n }\n }\n\n /**\n * Processes all materials found in mesh objects within the scene hierarchy.\n *\n * Performs a depth-first traversal, finding all Mesh objects and executing\n * the provided callback function for each material. Handles both single\n * materials and material arrays properly.\n *\n * @param object - The root Object3D to start searching from\n * @param callback - Function to execute for each material found\n\n */\n public static enumerateMaterials(\n object: Object3D,\n callback: (material: Material) => void,\n ): void {\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n callback(material);\n }\n } else {\n callback(object.material);\n }\n }\n\n for (const child of object.children) {\n SceneTraversal.enumerateMaterials(child, callback);\n }\n }\n\n /**\n * Finds all objects in the scene hierarchy that match the specified filter criteria.\n *\n * Performs a depth-first search and collects all objects that either match\n * a regular expression pattern (applied to the object's name) or satisfy\n * a custom predicate function.\n *\n * @param object - The root Object3D to start searching from\n * @param filter - Either a RegExp to test against object names, or a predicate function\n * @returns Array of all matching Object3D instances\n\n */\n public static filterObjects(\n object: Object3D,\n filter: RegExp | ((object: Object3D) => boolean),\n ): Object3D[] {\n let result: Object3D[] = [];\n\n if (typeof filter === \"function\") {\n if (filter(object)) {\n result.push(object);\n }\n } else {\n if (object.name && filter.test(object.name)) {\n result.push(object);\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterObjects(child, filter));\n }\n\n return result;\n }\n\n /**\n * Finds all materials in the scene hierarchy whose names match a regular expression pattern.\n *\n * Performs a depth-first search through all Mesh objects and collects materials\n * whose name property matches the provided regular expression. Handles both\n * single materials and material arrays properly.\n *\n * @param object - The root Object3D to start searching from\n * @param name - Regular expression pattern to test against material names\n * @returns Array of all matching Material instances\n\n */\n public static filterMaterials(object: Object3D, name: RegExp): Material[] {\n let result: Material[] = [];\n\n if (object instanceof Mesh) {\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name && name.test(material.name)) {\n result.push(material);\n }\n }\n } else {\n if (object.material.name && name.test(object.material.name)) {\n result.push(object.material);\n }\n }\n }\n\n for (const child of object.children) {\n result = result.concat(SceneTraversal.filterMaterials(child, name));\n }\n\n return result;\n }\n\n /**\n * Finds all objects (mesh users) that use materials with names matching a regular expression pattern.\n *\n * Performs a depth-first search through all Mesh objects and collects the mesh objects\n * whose materials have names that match the provided regular expression. This is useful\n * for finding all objects that use specific material types or naming patterns.\n *\n * @param object - The root Object3D to start searching from\n * @param materialName - Regular expression pattern to test against material names\n * @returns Array of all Mesh objects that use materials with matching names\n */\n public static findMaterialUsers(\n object: Object3D,\n materialName: RegExp,\n ): Mesh[] {\n let result: Mesh[] = [];\n\n if (object instanceof Mesh) {\n let hasMatchingMaterial = false;\n\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n if (material.name && materialName.test(material.name)) {\n hasMatchingMaterial = true;\n break;\n }\n }\n } else {\n if (object.material.name && materialName.test(object.material.name)) {\n hasMatchingMaterial = true;\n }\n }\n\n if (hasMatchingMaterial) {\n result.push(object);\n }\n }\n\n for (const child of object.children) {\n result = result.concat(\n SceneTraversal.findMaterialUsers(child, materialName),\n );\n }\n\n return result;\n }\n}\n","import type { AnimationClip, Object3D, SkinnedMesh } from \"three\";\nimport { AnimationMixer, BufferAttribute, Mesh, Vector3 } from \"three\";\n\n/** Number of components per vertex */\nconst COMPONENT_COUNT = 3;\n\n/** Convert skinned meshes to regular static meshes */\nexport class SkinnedMeshBaker {\n /**\n * Convert a skinned mesh to a regular mesh in its current pose.\n * The resulting mesh will have no bones but look identical.\n * \n * @param skinnedMesh - Mesh to convert\n * @returns Static mesh with baked vertex positions\n */\n public static bakePose(skinnedMesh: SkinnedMesh): Mesh {\n const bakedGeometry = skinnedMesh.geometry.clone();\n const position = bakedGeometry.attributes[\"position\"] as BufferAttribute;\n const newPositions = new Float32Array(position.count * COMPONENT_COUNT);\n const target = new Vector3();\n\n for (let i = 0; i < position.count; i++) {\n target.fromBufferAttribute(position, i);\n skinnedMesh.applyBoneTransform(i, target);\n newPositions[i * COMPONENT_COUNT + 0] = target.x;\n newPositions[i * COMPONENT_COUNT + 1] = target.y;\n newPositions[i * COMPONENT_COUNT + 2] = target.z;\n }\n\n bakedGeometry.setAttribute(\n \"position\",\n new BufferAttribute(newPositions, COMPONENT_COUNT),\n );\n bakedGeometry.computeVertexNormals();\n bakedGeometry.deleteAttribute(\"skinIndex\");\n bakedGeometry.deleteAttribute(\"skinWeight\");\n\n const mesh = new Mesh(bakedGeometry, skinnedMesh.material);\n mesh.name = skinnedMesh.name;\n return mesh;\n }\n\n /**\n * Bake a single frame from an animation into a static mesh.\n * \n * @param armature - Root object with bones (usually from GLTF)\n * @param skinnedMesh - Mesh to convert\n * @param timeOffset - Time in seconds within the animation\n * @param clip - Animation to get the pose from\n * @returns Static mesh with baked vertex positions\n */\n public static bakeAnimationFrame(\n armature: Object3D,\n skinnedMesh: SkinnedMesh,\n timeOffset: number,\n clip: AnimationClip,\n ): Mesh {\n const mixer = new AnimationMixer(armature);\n const action = mixer.clipAction(clip);\n action.play();\n mixer.setTime(timeOffset);\n\n armature.updateWorldMatrix(true, true);\n skinnedMesh.skeleton.update();\n\n return this.bakePose(skinnedMesh);\n }\n}","import type { Texture } from \"three\";\nimport { Box3, DirectionalLight, RGBAFormat, Spherical, Vector3 } from \"three\";\n\n/** Number of color channels in RGBA format */\nconst RGBA_CHANNEL_COUNT = 4;\n/** Number of color channels in RGB format */\nconst RGB_CHANNEL_COUNT = 3;\n\n/** Red channel weight for luminance calculation (ITU-R BT.709) */\nconst LUMINANCE_R = 0.2126;\n/** Green channel weight for luminance calculation (ITU-R BT.709) */\nconst LUMINANCE_G = 0.7152;\n/** Blue channel weight for luminance calculation (ITU-R BT.709) */\nconst LUMINANCE_B = 0.0722;\n\n/**\n * A directional light with spherical positioning controls and advanced shadow mapping.\n *\n * Extends Three.js DirectionalLight to provide intuitive spherical coordinate control\n * (distance, elevation, azimuth) and automatic shadow map configuration for bounding boxes.\n * Also supports automatic sun direction calculation from HDR environment maps.\n */\nexport class Sun extends DirectionalLight {\n /** Internal vectors to avoid garbage collection during calculations */\n private readonly tempVector3D0 = new Vector3();\n private readonly tempVector3D1 = new Vector3();\n private readonly tempVector3D2 = new Vector3();\n private readonly tempVector3D3 = new Vector3();\n private readonly tempVector3D4 = new Vector3();\n private readonly tempVector3D5 = new Vector3();\n private readonly tempVector3D6 = new Vector3();\n private readonly tempVector3D7 = new Vector3();\n private readonly tempBox3 = new Box3();\n private readonly tempSpherical = new Spherical();\n\n /**\n * Gets the distance from the light to its target (origin).\n *\n * @returns The distance in world units\n */\n public get distance(): number {\n return this.position.length();\n }\n\n /**\n * Gets the elevation angle (vertical angle from the horizontal plane).\n *\n * @returns The elevation angle in radians (0 = horizontal, π/2 = directly above)\n */\n public get elevation(): number {\n return this.tempSpherical.setFromVector3(this.position).phi;\n }\n\n /**\n * Gets the azimuth angle (horizontal rotation around the target).\n *\n * @returns The azimuth angle in radians (0 = positive X axis, π/2 = positive Z axis)\n */\n public get azimuth(): number {\n return this.tempSpherical.setFromVector3(this.position).theta;\n }\n\n /**\n * Sets the distance while preserving current elevation and azimuth angles.\n *\n * @param value - The new distance in world units\n */\n public set distance(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n value,\n this.tempSpherical.phi,\n this.tempSpherical.theta,\n );\n }\n\n /**\n * Sets the elevation angle while preserving current distance and azimuth.\n *\n * @param value - The new elevation angle in radians (0 = horizontal, π/2 = directly above)\n */\n public set elevation(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n value,\n this.tempSpherical.theta,\n );\n }\n\n /**\n * Sets the azimuth angle while preserving current distance and elevation.\n *\n * @param value - The new azimuth angle in radians (0 = positive X axis, π/2 = positive Z axis)\n */\n public set azimuth(value: number) {\n this.tempSpherical.setFromVector3(this.position);\n this.position.setFromSphericalCoords(\n this.tempSpherical.radius,\n this.tempSpherical.phi,\n value,\n );\n }\n\n /**\n * Configures the shadow camera to optimally cover a bounding box.\n *\n * This method automatically adjusts the directional light's shadow camera frustum\n * to perfectly encompass the provided bounding box, ensuring efficient shadow map\n * usage and eliminating shadow clipping issues.\n *\n * @param box3 - The 3D bounding box to cover with shadows\n */\n public configureShadowsForBoundingBox(box3: Box3): void {\n const camera = this.shadow.camera;\n\n this.target.updateWorldMatrix(true, false);\n this.lookAt(this.target.getWorldPosition(this.tempVector3D0));\n\n this.updateWorldMatrix(true, false);\n\n const points: Vector3[] = [\n this.tempVector3D0.set(box3.min.x, box3.min.y, box3.min.z),\n this.tempVector3D1.set(box3.min.x, box3.min.y, box3.max.z),\n this.tempVector3D2.set(box3.min.x, box3.max.y, box3.min.z),\n this.tempVector3D3.set(box3.min.x, box3.max.y, box3.max.z),\n this.tempVector3D4.set(box3.max.x, box3.min.y, box3.min.z),\n this.tempVector3D5.set(box3.max.x, box3.min.y, box3.max.z),\n this.tempVector3D6.set(box3.max.x, box3.max.y, box3.min.z),\n this.tempVector3D7.set(box3.max.x, box3.max.y, box3.max.z),\n ];\n\n const inverseMatrix = this.matrixWorld.clone().invert();\n\n for (const point of points) {\n point.applyMatrix4(inverseMatrix);\n }\n\n const newBox3 = this.tempBox3.setFromPoints(points);\n\n camera.left = newBox3.min.x;\n camera.bottom = newBox3.min.y;\n camera.near = -newBox3.max.z;\n\n camera.right = newBox3.max.x;\n camera.top = newBox3.max.y;\n camera.far = -newBox3.min.z;\n\n camera.updateWorldMatrix(true, false);\n camera.updateProjectionMatrix();\n }\n\n /**\n * Sets the sun's direction based on the brightest point in an HDR environment map.\n *\n * This method analyzes an HDR texture to find the pixel with the highest luminance\n * value and positions the sun to shine from that direction. This is useful for\n * creating realistic lighting that matches HDR environment maps.\n *\n * @param texture - The HDR texture to analyze (must have image data available)\n * @param distance - The distance to place the sun from the origin (defaults to 1)\n */\n public setDirectionFromHDRTexture(texture: Texture, distance = 1): void {\n const data = texture.image.data;\n const width = texture.image.width;\n const height = texture.image.height;\n\n let maxLuminance = 0;\n let maxIndex = 0;\n\n // Find brightest pixel\n\n const step =\n texture.format === RGBAFormat ? RGBA_CHANNEL_COUNT : RGB_CHANNEL_COUNT;\n for (let i = 0; i < data.length; i += step) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const luminance = LUMINANCE_R * r + LUMINANCE_G * g + LUMINANCE_B * b;\n if (luminance > maxLuminance) {\n maxLuminance = luminance;\n maxIndex = i;\n }\n }\n\n // Convert to spherical coordinates\n const pixelIndex = maxIndex / step;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n\n const u = x / width;\n const v = y / height;\n\n const elevation = v * Math.PI;\n const azimuth = u * -Math.PI * 2 - Math.PI / 2;\n\n this.position.setFromSphericalCoords(distance, elevation, azimuth);\n }\n}\n"],"names":["MAX_FOV","DualFovCamera","PerspectiveCamera","constructor","horizontalFov","verticalFov","aspect","near","far","super","this","_private_horizontalFovInternal","_private_verticalFovInternal","updateProjectionMatrix","value","MathUtils","clamp","setFov","horizontal","vertical","copyFovSettings","source","radians","degToRad","fov","radToDeg","Math","atan","tan","getActualHorizontalFov","verticalRadians","getActualVerticalFov","horizontalRadians","fitVerticalFovToPoints","vertices","up","Vector3","applyQuaternion","quaternion","maxVerticalAngle","vertex","vertexDirection","position","clone","sub","normalize","verticalAngle","asin","abs","dot","sign","requiredFov","fitVerticalFovToBox","box","min","x","y","z","max","fitVerticalFovToMesh","skinnedMesh","updateWorldMatrix","skeleton","update","geometry","attributes","target","points","i","count","fromBufferAttribute","applyBoneTransform","push","lookAtMeshCenterOfMass","centerOfMass","iterations","length","center","floor","total","point","distanceTo","add","divideScalar","findMainCluster","lookAt","camera","copy","SceneTraversal","getObjectByName","object","name","child","children","result","getMaterialByName","Mesh","Array","isArray","material","enumerateObjectsByType","type","callback","enumerateMaterials","filterObjects","filter","test","concat","filterMaterials","findMaterialUsers","materialName","hasMatchingMaterial","SkinnedMeshBaker","bakePose","bakedGeometry","newPositions","Float32Array","setAttribute","BufferAttribute","computeVertexNormals","deleteAttribute","mesh","bakeAnimationFrame","armature","timeOffset","clip","mixer","AnimationMixer","clipAction","play","setTime","Sun","DirectionalLight","Box3","Spherical","distance","elevation","_private_tempSpherical","setFromVector3","phi","azimuth","theta","setFromSphericalCoords","radius","configureShadowsForBoundingBox","box3","shadow","getWorldPosition","_private_tempVector3D0","set","_private_tempVector3D1","_private_tempVector3D2","_private_tempVector3D3","_private_tempVector3D4","_private_tempVector3D5","_private_tempVector3D6","_private_tempVector3D7","inverseMatrix","matrixWorld","invert","applyMatrix4","newBox3","_private_tempBox3","setFromPoints","left","bottom","right","top","setDirectionFromHDRTexture","texture","data","image","width","height","maxLuminance","maxIndex","step","format","RGBAFormat","luminance","pixelIndex","PI"],"mappings":"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"}