bbmodel-viewer 0.1.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/LICENSE +21 -0
- package/README.md +148 -0
- package/dist/index.cjs +606 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +221 -0
- package/dist/index.d.ts +221 -0
- package/dist/index.js +581 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/geometry.ts","../src/builder.ts","../src/textures.ts","../src/viewer.ts"],"names":["THREE","THREE2","THREE3","THREE4","OrbitControls"],"mappings":"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","file":"index.cjs","sourcesContent":["import * as THREE from \"three\";\nimport type { BBElement, BBFace, BBMeshFace, Vec2, Vec3 } from \"./types\";\nimport type { MaterialLibrary } from \"./textures\";\n\ntype Corner = [number, number, number];\n\ninterface FaceCorners {\n /** top-left, top-right, bottom-left, bottom-right, as seen from outside. */\n tl: Corner;\n tr: Corner;\n bl: Corner;\n br: Corner;\n}\n\n/**\n * Cube face corners in a right-handed, Y-up space, relative to the element\n * origin. Winding is consistent (outward normals) so a single triangle order\n * works for every face. Derived from Minecraft/Blockbench face orientation:\n * north=-Z, south=+Z, east=+X, west=-X, up=+Y (north to top), down=-Y.\n */\nfunction cubeFaceCorners(\n dir: string,\n x1: number,\n y1: number,\n z1: number,\n x2: number,\n y2: number,\n z2: number,\n): FaceCorners | null {\n switch (dir) {\n case \"south\": // +Z\n return { tl: [x1, y2, z2], tr: [x2, y2, z2], bl: [x1, y1, z2], br: [x2, y1, z2] };\n case \"north\": // -Z\n return { tl: [x2, y2, z1], tr: [x1, y2, z1], bl: [x2, y1, z1], br: [x1, y1, z1] };\n case \"east\": // +X\n return { tl: [x2, y2, z2], tr: [x2, y2, z1], bl: [x2, y1, z2], br: [x2, y1, z1] };\n case \"west\": // -X\n return { tl: [x1, y2, z1], tr: [x1, y2, z2], bl: [x1, y1, z1], br: [x1, y1, z2] };\n case \"up\": // +Y\n return { tl: [x1, y2, z1], tr: [x2, y2, z1], bl: [x1, y2, z2], br: [x2, y2, z2] };\n case \"down\": // -Y\n return { tl: [x1, y1, z2], tr: [x2, y1, z2], bl: [x1, y1, z1], br: [x2, y1, z1] };\n default:\n return null;\n }\n}\n\nconst CUBE_FACE_ORDER = [\"north\", \"east\", \"south\", \"west\", \"up\", \"down\"] as const;\n\n/** Standard Minecraft box-UV layout, used only when a face lacks its own uv. */\nfunction boxUvRect(\n dir: string,\n u: number,\n v: number,\n sx: number,\n sy: number,\n sz: number,\n): [number, number, number, number] | null {\n switch (dir) {\n case \"up\":\n return [u + sz, v, u + sz + sx, v + sz];\n case \"down\":\n return [u + sz + sx, v, u + sz + 2 * sx, v + sz];\n case \"east\":\n return [u, v + sz, u + sz, v + sz + sy];\n case \"north\":\n return [u + sz, v + sz, u + sz + sx, v + sz + sy];\n case \"west\":\n return [u + sz + sx, v + sz, u + 2 * sz + sx, v + sz + sy];\n case \"south\":\n return [u + 2 * sz + sx, v + sz, u + 2 * sz + 2 * sx, v + sz + sy];\n default:\n return null;\n }\n}\n\n/** Corner UVs (v pointing up, as three.js expects) from a pixel-space rect. */\nfunction rectToCornerUvs(\n rect: [number, number, number, number],\n uvWidth: number,\n uvHeight: number,\n rotation = 0,\n): { tl: Vec2; tr: Vec2; bl: Vec2; br: Vec2 } {\n const [u1, v1, u2, v2] = rect;\n const uMin = u1 / uvWidth;\n const uMax = u2 / uvWidth;\n const vTop = 1 - v1 / uvHeight;\n const vBot = 1 - v2 / uvHeight;\n\n let corners = {\n tl: [uMin, vTop] as Vec2,\n tr: [uMax, vTop] as Vec2,\n bl: [uMin, vBot] as Vec2,\n br: [uMax, vBot] as Vec2,\n };\n\n // Apply UV rotation in 90° clockwise steps.\n const steps = (((rotation / 90) % 4) + 4) % 4;\n for (let i = 0; i < steps; i++) {\n corners = { tl: corners.bl, tr: corners.tl, br: corners.tr, bl: corners.br };\n }\n return corners;\n}\n\n/**\n * Accumulates triangles grouped by material into a single indexed-free\n * BufferGeometry, producing a ready-to-render Mesh.\n */\nclass MeshAssembler {\n private readonly positions: number[] = [];\n private readonly uvs: number[] = [];\n private readonly materials: THREE.Material[] = [];\n private readonly materialIndex = new Map<THREE.Material, number>();\n private readonly groups: { start: number; count: number; index: number }[] = [];\n private vertexCount = 0;\n\n private indexOf(material: THREE.Material): number {\n let idx = this.materialIndex.get(material);\n if (idx === undefined) {\n idx = this.materials.length;\n this.materials.push(material);\n this.materialIndex.set(material, idx);\n }\n return idx;\n }\n\n addQuad(c: FaceCorners, uv: { tl: Vec2; tr: Vec2; bl: Vec2; br: Vec2 }, material: THREE.Material) {\n const start = this.vertexCount;\n // Two triangles: (tl, bl, tr) and (tr, bl, br) — outward winding.\n this.pushVertex(c.tl, uv.tl);\n this.pushVertex(c.bl, uv.bl);\n this.pushVertex(c.tr, uv.tr);\n this.pushVertex(c.tr, uv.tr);\n this.pushVertex(c.bl, uv.bl);\n this.pushVertex(c.br, uv.br);\n this.groups.push({ start, count: 6, index: this.indexOf(material) });\n }\n\n addTriangle(p: [Corner, Corner, Corner], uv: [Vec2, Vec2, Vec2], material: THREE.Material) {\n const start = this.vertexCount;\n this.pushVertex(p[0], uv[0]);\n this.pushVertex(p[1], uv[1]);\n this.pushVertex(p[2], uv[2]);\n this.groups.push({ start, count: 3, index: this.indexOf(material) });\n }\n\n private pushVertex(pos: Corner, uv: Vec2) {\n this.positions.push(pos[0], pos[1], pos[2]);\n this.uvs.push(uv[0], uv[1]);\n this.vertexCount++;\n }\n\n build(name: string): THREE.Mesh | null {\n if (this.vertexCount === 0) return null;\n const geometry = new THREE.BufferGeometry();\n geometry.setAttribute(\"position\", new THREE.Float32BufferAttribute(this.positions, 3));\n geometry.setAttribute(\"uv\", new THREE.Float32BufferAttribute(this.uvs, 2));\n for (const g of this.groups) geometry.addGroup(g.start, g.count, g.index);\n geometry.computeVertexNormals();\n\n const material = this.materials.length === 1 ? this.materials[0] : this.materials;\n const mesh = new THREE.Mesh(geometry, material);\n mesh.name = name;\n return mesh;\n }\n}\n\n/**\n * Builds a renderable Mesh for a cube or mesh element, with geometry expressed\n * relative to the element's own origin (the caller places the origin pivot).\n */\nexport function buildElementMesh(\n element: BBElement,\n library: MaterialLibrary,\n): THREE.Mesh | null {\n if (element.type === \"mesh\" && element.vertices) {\n return buildMeshElement(element, library);\n }\n return buildCubeElement(element, library);\n}\n\nfunction buildCubeElement(element: BBElement, library: MaterialLibrary): THREE.Mesh | null {\n const from = element.from ?? [0, 0, 0];\n const to = element.to ?? [0, 0, 0];\n const origin = element.origin ?? [0, 0, 0];\n const inflate = element.inflate ?? 0;\n\n // Absolute cube bounds, expanded by inflate, then made relative to origin.\n const x1 = Math.min(from[0], to[0]) - inflate - origin[0];\n const x2 = Math.max(from[0], to[0]) + inflate - origin[0];\n const y1 = Math.min(from[1], to[1]) - inflate - origin[1];\n const y2 = Math.max(from[1], to[1]) + inflate - origin[1];\n const z1 = Math.min(from[2], to[2]) - inflate - origin[2];\n const z2 = Math.max(from[2], to[2]) + inflate - origin[2];\n\n const sx = Math.abs(to[0] - from[0]);\n const sy = Math.abs(to[1] - from[1]);\n const sz = Math.abs(to[2] - from[2]);\n const uvOffset = element.uv_offset ?? [0, 0];\n\n const faces = element.faces ?? {};\n const assembler = new MeshAssembler();\n\n for (const dir of CUBE_FACE_ORDER) {\n const face = faces[dir] as BBFace | undefined;\n const corners = cubeFaceCorners(dir, x1, y1, z1, x2, y2, z2);\n if (!corners) continue;\n // A face is skipped only when explicitly absent; some models omit `faces`\n // entirely, in which case we still draw all six sides.\n if (element.faces && !face) continue;\n\n const texMeta = library.resolve(face?.texture);\n const material = texMeta ? texMeta.material : library.colorMaterial(element.color ?? 0);\n const uvWidth = texMeta ? texMeta.uvWidth : library.fallbackUvSpace.width;\n const uvHeight = texMeta ? texMeta.uvHeight : library.fallbackUvSpace.height;\n\n const rect =\n face?.uv ??\n boxUvRect(dir, uvOffset[0], uvOffset[1], sx, sy, sz) ??\n [0, 0, uvWidth, uvHeight];\n\n const uv = rectToCornerUvs(rect, uvWidth, uvHeight, face?.rotation ?? 0);\n assembler.addQuad(corners, uv, material);\n }\n\n return assembler.build(element.name ?? \"cube\");\n}\n\nfunction buildMeshElement(element: BBElement, library: MaterialLibrary): THREE.Mesh | null {\n const vertices = element.vertices ?? {};\n const faces = (element.faces ?? {}) as Record<string, BBMeshFace>;\n const assembler = new MeshAssembler();\n\n const posOf = (key: string): Corner | null => {\n const v = vertices[key] as Vec3 | undefined;\n return v ? [v[0], v[1], v[2]] : null;\n };\n\n for (const face of Object.values(faces)) {\n const keys = face.vertices ?? [];\n if (keys.length < 3) continue;\n\n const texMeta = library.resolve(face.texture);\n const material = texMeta ? texMeta.material : library.colorMaterial(element.color ?? 0);\n const uvWidth = texMeta ? texMeta.uvWidth : library.fallbackUvSpace.width;\n const uvHeight = texMeta ? texMeta.uvHeight : library.fallbackUvSpace.height;\n\n const uvOf = (key: string): Vec2 => {\n const raw = face.uv?.[key];\n if (!raw) return [0, 0];\n return [raw[0] / uvWidth, 1 - raw[1] / uvHeight];\n };\n\n // Fan-triangulate tris and quads (Blockbench mesh faces are 3 or 4 verts).\n for (let i = 1; i < keys.length - 1; i++) {\n const a = posOf(keys[0]);\n const b = posOf(keys[i]);\n const c = posOf(keys[i + 1]);\n if (!a || !b || !c) continue;\n assembler.addTriangle(\n [a, b, c],\n [uvOf(keys[0]), uvOf(keys[i]), uvOf(keys[i + 1])],\n material,\n );\n }\n }\n\n return assembler.build(element.name ?? \"mesh\");\n}\n","import * as THREE from \"three\";\nimport type { BBElement, BBModel, BBOutlinerGroup, BBOutlinerNode, Vec3 } from \"./types\";\nimport { buildElementMesh } from \"./geometry\";\nimport { MaterialLibrary } from \"./textures\";\n\nconst EULER_ORDER = \"ZYX\" as const; // Blockbench applies rotations as Rz·Ry·Rx.\nconst ORIGIN: Vec3 = [0, 0, 0];\n\n/**\n * Turns a parsed bbmodel plus its materials into a three.js object graph that\n * mirrors the Blockbench outliner (bones with pivots, nested rotations).\n */\nexport function buildModelObject(model: BBModel, library: MaterialLibrary): THREE.Group {\n const root = new THREE.Group();\n root.name = model.name ?? \"bbmodel\";\n\n const elementsByUuid = new Map<string, BBElement>();\n for (const el of model.elements ?? []) {\n if (el.uuid) elementsByUuid.set(el.uuid, el);\n }\n\n const groupsByUuid = new Map<string, BBOutlinerGroup>();\n for (const g of model.groups ?? []) {\n if (g.uuid) groupsByUuid.set(g.uuid, g);\n }\n\n const usedElements = new Set<string>();\n const visitedGroups = new Set<string>();\n\n const outliner = model.outliner ?? [];\n for (const node of outliner) {\n const built = buildNode(node, ORIGIN);\n if (built) root.add(built);\n }\n\n // Any element not referenced by the outliner is added at the root.\n for (const el of model.elements ?? []) {\n if (el.uuid && usedElements.has(el.uuid)) continue;\n const built = buildElementNode(el, ORIGIN);\n if (built) root.add(built);\n }\n\n return root;\n\n function buildNode(node: BBOutlinerNode, parentOrigin: Vec3): THREE.Object3D | null {\n if (typeof node === \"string\") {\n const element = elementsByUuid.get(node);\n if (element) {\n usedElements.add(node);\n return buildElementNode(element, parentOrigin);\n }\n const group = groupsByUuid.get(node);\n if (group) return buildGroupNode(group, parentOrigin);\n return null;\n }\n return buildGroupNode(node, parentOrigin);\n }\n\n function buildGroupNode(group: BBOutlinerGroup, parentOrigin: Vec3): THREE.Object3D | null {\n if (group.visibility === false) return null;\n if (group.uuid) {\n if (visitedGroups.has(group.uuid)) return null;\n visitedGroups.add(group.uuid);\n }\n\n const origin = group.origin ?? parentOrigin;\n const node = new THREE.Group();\n node.name = group.name ?? \"group\";\n applyTransform(node, origin, parentOrigin, group.rotation);\n\n for (const child of group.children ?? []) {\n const built = buildNode(child, origin);\n if (built) node.add(built);\n }\n return node;\n }\n\n function buildElementNode(element: BBElement, parentOrigin: Vec3): THREE.Object3D | null {\n if (element.visibility === false) return null;\n const mesh = buildElementMesh(element, library);\n if (!mesh) return null;\n\n const origin = element.origin ?? parentOrigin;\n const node = new THREE.Group();\n node.name = element.name ?? \"element\";\n applyTransform(node, origin, parentOrigin, element.rotation);\n node.add(mesh);\n return node;\n }\n}\n\n/** Positions a node at its pivot (relative to the parent pivot) and rotates it. */\nfunction applyTransform(\n node: THREE.Object3D,\n origin: Vec3,\n parentOrigin: Vec3,\n rotation?: Vec3,\n): void {\n node.position.set(\n origin[0] - parentOrigin[0],\n origin[1] - parentOrigin[1],\n origin[2] - parentOrigin[2],\n );\n if (rotation) {\n node.rotation.set(\n THREE.MathUtils.degToRad(rotation[0]),\n THREE.MathUtils.degToRad(rotation[1]),\n THREE.MathUtils.degToRad(rotation[2]),\n EULER_ORDER,\n );\n }\n}\n","import * as THREE from \"three\";\nimport type { BBModel, BBTexture, FaceTextureRef } from \"./types\";\n\n/** Approximation of Blockbench's outliner marker colors, used for untextured faces. */\nconst MARKER_COLORS = [\n \"#8f8f8f\", // 0 - neutral / none\n \"#e0475e\", // 1 - red\n \"#e0a63f\", // 2 - orange\n \"#e5d24a\", // 3 - yellow\n \"#7cd15a\", // 4 - green\n \"#4b9fe0\", // 5 - blue\n \"#8054e0\", // 6 - purple\n \"#e055b0\", // 7 - pink\n];\n\nexport interface MaterialSettings {\n /** Discard fragments whose alpha is below this threshold (crisp pixel edges). */\n alphaTest: number;\n /** Render both sides of every face (safe default for meshes / thin geometry). */\n side: THREE.Side;\n}\n\ninterface TextureMeta {\n material: THREE.MeshLambertMaterial;\n uvWidth: number;\n uvHeight: number;\n}\n\n/**\n * Holds every material + texture created for a model. Faces reference a texture\n * through {@link resolve}; untextured faces fall back to a flat color material.\n */\nexport class MaterialLibrary {\n private readonly byKey = new Map<string, TextureMeta>();\n private readonly colorMaterials = new Map<number, THREE.MeshLambertMaterial>();\n private readonly disposables: (THREE.Material | THREE.Texture)[] = [];\n private readonly fallbackUv: { width: number; height: number };\n\n constructor(\n private readonly model: BBModel,\n private readonly settings: MaterialSettings,\n ) {\n this.fallbackUv = {\n width: model.resolution?.width || 16,\n height: model.resolution?.height || 16,\n };\n }\n\n /**\n * Creates a texture + material per model texture and starts loading their\n * images. Resolves once every image has settled (loaded or failed).\n */\n async load(onProgress?: () => void): Promise<void> {\n const textures = this.model.textures ?? [];\n await Promise.all(\n textures.map((tex, index) => this.createTexture(tex, index, onProgress)),\n );\n }\n\n private async createTexture(\n tex: BBTexture,\n index: number,\n onProgress?: () => void,\n ): Promise<void> {\n const uvWidth = tex.uv_width || tex.width || this.fallbackUv.width;\n const uvHeight = tex.uv_height || tex.height || this.fallbackUv.height;\n\n const texture = new THREE.Texture();\n texture.magFilter = THREE.NearestFilter;\n texture.minFilter = THREE.NearestFilter;\n texture.generateMipmaps = false;\n texture.colorSpace = THREE.SRGBColorSpace;\n texture.name = tex.name ?? `texture_${index}`;\n\n const material = new THREE.MeshLambertMaterial({\n map: texture,\n transparent: true,\n alphaTest: this.settings.alphaTest,\n side: this.settings.side,\n });\n\n const meta: TextureMeta = { material, uvWidth, uvHeight };\n\n // Register under every key a face might use to reference this texture.\n this.byKey.set(String(index), meta);\n if (tex.uuid) this.byKey.set(tex.uuid, meta);\n if (tex.id != null) this.byKey.set(String(tex.id), meta);\n\n this.disposables.push(material, texture);\n\n const src = tex.source || tex.path || tex.relative_path;\n if (!src) return;\n\n try {\n const image = await loadImage(src);\n texture.image = image;\n texture.needsUpdate = true;\n onProgress?.();\n } catch {\n // Leave the material colored/blank if the image cannot be decoded.\n }\n }\n\n /** Resolves a face's texture reference to its material + UV space, if any. */\n resolve(ref: FaceTextureRef): TextureMeta | null {\n if (ref == null || ref === false) return null;\n return this.byKey.get(String(ref)) ?? null;\n }\n\n /** UV space to use when a face has no resolvable texture. */\n get fallbackUvSpace(): { width: number; height: number } {\n return this.fallbackUv;\n }\n\n /** Flat color material for untextured faces, keyed by marker color index. */\n colorMaterial(colorIndex = 0): THREE.MeshLambertMaterial {\n const key = colorIndex % MARKER_COLORS.length;\n let material = this.colorMaterials.get(key);\n if (!material) {\n material = new THREE.MeshLambertMaterial({\n color: new THREE.Color(MARKER_COLORS[key]),\n side: this.settings.side,\n });\n this.colorMaterials.set(key, material);\n this.disposables.push(material);\n }\n return material;\n }\n\n dispose(): void {\n for (const item of this.disposables) item.dispose();\n this.disposables.length = 0;\n this.byKey.clear();\n this.colorMaterials.clear();\n }\n}\n\nfunction loadImage(src: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.crossOrigin = \"anonymous\";\n img.onload = () => resolve(img);\n img.onerror = () => reject(new Error(`Failed to load texture image`));\n img.src = src;\n });\n}\n","import * as THREE from \"three\";\nimport { OrbitControls } from \"three/addons/controls/OrbitControls.js\";\nimport type { BBModel } from \"./types\";\nimport { buildModelObject } from \"./builder\";\nimport { MaterialLibrary } from \"./textures\";\n\nexport interface BBModelViewerOptions {\n /** Scene background. A CSS color, hex number, or `null`/\"transparent\". */\n background?: string | number | null;\n /** Show a ground grid aligned with the model base. Default `true`. */\n grid?: boolean;\n /** Enable orbit/zoom/pan controls. Default `true`. */\n controls?: boolean;\n /** Continuously spin the model. Default `false`. */\n autoRotate?: boolean;\n /** Auto-rotation speed (three.js OrbitControls units). Default `1.0`. */\n autoRotateSpeed?: number;\n /** Camera vertical field of view in degrees. Default `45`. */\n fov?: number;\n /** Ambient light intensity. Default `0.8`. */\n ambientIntensity?: number;\n /** Key directional light intensity. Default `0.55`. */\n directionalIntensity?: number;\n /** Render both faces of every polygon. Default `true` (robust for meshes). */\n doubleSided?: boolean;\n /** Alpha cutoff for transparent texels. Default `0.02`. */\n alphaTest?: number;\n /** MSAA antialiasing. Default `true`. */\n antialias?: boolean;\n /** Device pixel ratio cap. Default `min(devicePixelRatio, 2)`. */\n pixelRatio?: number;\n /** Called after a model finishes loading and is added to the scene. */\n onLoad?: (model: BBModel, object: THREE.Group) => void;\n /** Called when loading/parsing fails. */\n onError?: (error: unknown) => void;\n}\n\nconst DEFAULTS = {\n background: \"#20232a\" as string | number | null,\n grid: true,\n controls: true,\n autoRotate: false,\n autoRotateSpeed: 1.0,\n fov: 45,\n ambientIntensity: 0.8,\n directionalIntensity: 0.55,\n doubleSided: true,\n alphaTest: 0.02,\n antialias: true,\n};\n\n/**\n * Renders Blockbench `.bbmodel` files into a container element with three.js.\n *\n * ```ts\n * const viewer = new BBModelViewer(document.getElementById(\"app\")!);\n * await viewer.load(\"/models/creeper.bbmodel\");\n * ```\n */\nexport class BBModelViewer {\n readonly scene = new THREE.Scene();\n readonly camera: THREE.PerspectiveCamera;\n readonly renderer: THREE.WebGLRenderer;\n readonly controls?: OrbitControls;\n\n private readonly container: HTMLElement;\n private readonly options: Required<Omit<BBModelViewerOptions, \"onLoad\" | \"onError\" | \"pixelRatio\">> &\n Pick<BBModelViewerOptions, \"onLoad\" | \"onError\">;\n\n private modelRoot: THREE.Group | null = null;\n private materials: MaterialLibrary | null = null;\n private gridHelper: THREE.GridHelper | null = null;\n private resizeObserver?: ResizeObserver;\n private frameId = 0;\n private disposed = false;\n private loadToken = 0;\n\n constructor(container: HTMLElement, options: BBModelViewerOptions = {}) {\n this.container = container;\n this.options = { ...DEFAULTS, ...options };\n\n const { width, height } = this.measure();\n const transparent =\n this.options.background === null || this.options.background === \"transparent\";\n\n this.renderer = new THREE.WebGLRenderer({\n antialias: this.options.antialias,\n alpha: transparent,\n });\n this.renderer.setPixelRatio(options.pixelRatio ?? Math.min(window.devicePixelRatio, 2));\n this.renderer.setSize(width, height, false);\n this.renderer.outputColorSpace = THREE.SRGBColorSpace;\n this.container.appendChild(this.renderer.domElement);\n this.renderer.domElement.style.display = \"block\";\n this.renderer.domElement.style.width = \"100%\";\n this.renderer.domElement.style.height = \"100%\";\n\n if (!transparent) {\n this.scene.background = new THREE.Color(this.options.background as string | number);\n }\n\n this.camera = new THREE.PerspectiveCamera(this.options.fov, width / height, 0.1, 10000);\n this.camera.position.set(40, 30, 40);\n\n this.addLights();\n\n if (this.options.controls) {\n this.controls = new OrbitControls(this.camera, this.renderer.domElement);\n this.controls.enableDamping = true;\n this.controls.dampingFactor = 0.08;\n this.controls.autoRotate = this.options.autoRotate;\n this.controls.autoRotateSpeed = this.options.autoRotateSpeed;\n }\n\n this.observeResize();\n this.animate();\n }\n\n /** Fetches a `.bbmodel` file by URL and renders it. */\n async load(url: string, init?: RequestInit): Promise<THREE.Group> {\n try {\n const response = await fetch(url, init);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);\n }\n const data = (await response.json()) as BBModel;\n return await this.loadModel(data);\n } catch (error) {\n this.options.onError?.(error);\n throw error;\n }\n }\n\n /** Reads a `File`/`Blob` (e.g. from an `<input type=\"file\">`) and renders it. */\n async loadFile(file: File | Blob): Promise<THREE.Group> {\n try {\n const text = await file.text();\n const data = JSON.parse(text) as BBModel;\n return await this.loadModel(data);\n } catch (error) {\n this.options.onError?.(error);\n throw error;\n }\n }\n\n /** Renders an already-parsed bbmodel object. */\n async loadModel(data: BBModel): Promise<THREE.Group> {\n const token = ++this.loadToken;\n try {\n const materials = new MaterialLibrary(data, {\n alphaTest: this.options.alphaTest,\n side: this.options.doubleSided ? THREE.DoubleSide : THREE.FrontSide,\n });\n await materials.load();\n\n // A newer load() started while we were awaiting textures — bail out.\n if (token !== this.loadToken || this.disposed) {\n materials.dispose();\n return this.modelRoot ?? new THREE.Group();\n }\n\n this.clear();\n this.materials = materials;\n this.modelRoot = buildModelObject(data, materials);\n this.scene.add(this.modelRoot);\n\n this.frameModel();\n this.options.onLoad?.(data, this.modelRoot);\n return this.modelRoot;\n } catch (error) {\n this.options.onError?.(error);\n throw error;\n }\n }\n\n /** Removes the current model and frees its GPU resources. */\n clear(): void {\n if (this.modelRoot) {\n this.scene.remove(this.modelRoot);\n this.modelRoot.traverse((obj: THREE.Object3D) => {\n if (obj instanceof THREE.Mesh) obj.geometry.dispose();\n });\n this.modelRoot = null;\n }\n if (this.gridHelper) {\n this.scene.remove(this.gridHelper);\n this.gridHelper.geometry.dispose();\n (this.gridHelper.material as THREE.Material).dispose();\n this.gridHelper = null;\n }\n this.materials?.dispose();\n this.materials = null;\n }\n\n /** Recomputes size from the container; call after layout changes if needed. */\n resize(): void {\n const { width, height } = this.measure();\n this.renderer.setSize(width, height, false);\n this.camera.aspect = width / height;\n this.camera.updateProjectionMatrix();\n }\n\n /** Frames the camera on the current model's bounding box. */\n frameModel(): void {\n if (!this.modelRoot) return;\n const box = new THREE.Box3().setFromObject(this.modelRoot);\n if (box.isEmpty()) return;\n\n const size = box.getSize(new THREE.Vector3());\n const center = box.getCenter(new THREE.Vector3());\n const maxDim = Math.max(size.x, size.y, size.z) || 16;\n\n if (this.options.grid) this.addGrid(box, maxDim);\n\n const fov = THREE.MathUtils.degToRad(this.camera.fov);\n const distance = ((maxDim / 2) / Math.tan(fov / 2)) * 1.6;\n\n const dir = new THREE.Vector3(1, 0.75, 1).normalize();\n this.camera.position.copy(center).addScaledVector(dir, distance);\n this.camera.near = Math.max(distance / 100, 0.01);\n this.camera.far = distance * 100;\n this.camera.updateProjectionMatrix();\n\n if (this.controls) {\n this.controls.target.copy(center);\n this.controls.update();\n } else {\n this.camera.lookAt(center);\n }\n }\n\n /** Tears down the renderer, listeners and GPU resources. */\n dispose(): void {\n this.disposed = true;\n cancelAnimationFrame(this.frameId);\n this.resizeObserver?.disconnect();\n this.clear();\n this.controls?.dispose();\n this.renderer.dispose();\n this.renderer.domElement.remove();\n }\n\n // --- internals ---\n\n private addLights(): void {\n const ambient = new THREE.AmbientLight(0xffffff, this.options.ambientIntensity);\n const key = new THREE.DirectionalLight(0xffffff, this.options.directionalIntensity);\n key.position.set(0.6, 1, 0.8);\n const fill = new THREE.DirectionalLight(0xffffff, this.options.directionalIntensity * 0.45);\n fill.position.set(-0.6, -0.2, -0.8);\n this.scene.add(ambient, key, fill);\n }\n\n private addGrid(box: THREE.Box3, maxDim: number): void {\n const cells = Math.max(2, Math.ceil(maxDim / 16));\n const size = cells * 16 * 1.5;\n const divisions = Math.round(size / 16);\n const grid = new THREE.GridHelper(size, divisions, 0x666666, 0x3a3a3a);\n grid.position.set(box.getCenter(new THREE.Vector3()).x, box.min.y, box.getCenter(new THREE.Vector3()).z);\n (grid.material as THREE.Material).transparent = true;\n (grid.material as THREE.Material).opacity = 0.5;\n this.scene.add(grid);\n this.gridHelper = grid;\n }\n\n private observeResize(): void {\n if (typeof ResizeObserver === \"undefined\") return;\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(this.container);\n }\n\n private measure(): { width: number; height: number } {\n const width = this.container.clientWidth || 300;\n const height = this.container.clientHeight || 150;\n return { width, height };\n }\n\n private animate = (): void => {\n if (this.disposed) return;\n this.frameId = requestAnimationFrame(this.animate);\n this.controls?.update();\n this.renderer.render(this.scene, this.camera);\n };\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Minimal, permissive typings for the Blockbench `.bbmodel` / `.json` project
|
|
6
|
+
* format. The format is loose and evolves across Blockbench versions, so most
|
|
7
|
+
* fields are optional and unknown extras are tolerated.
|
|
8
|
+
*/
|
|
9
|
+
type Vec2 = [number, number];
|
|
10
|
+
type Vec3 = [number, number, number];
|
|
11
|
+
/** A texture reference on a face: numeric index, uuid/id string, or none. */
|
|
12
|
+
type FaceTextureRef = number | string | null | false | undefined;
|
|
13
|
+
interface BBFace {
|
|
14
|
+
/** Per-face UV rectangle in texture pixels: `[u_min, v_min, u_max, v_max]`. */
|
|
15
|
+
uv?: [number, number, number, number];
|
|
16
|
+
/** Texture reference (index into `textures`, or its uuid/id). */
|
|
17
|
+
texture?: FaceTextureRef;
|
|
18
|
+
/** UV rotation in degrees (0 / 90 / 180 / 270). */
|
|
19
|
+
rotation?: number;
|
|
20
|
+
}
|
|
21
|
+
interface BBMeshFace {
|
|
22
|
+
/** Ordered vertex keys (3 for a triangle, 4 for a quad). */
|
|
23
|
+
vertices: string[];
|
|
24
|
+
/** Per-vertex UV in texture pixels, keyed by vertex id. */
|
|
25
|
+
uv?: Record<string, Vec2>;
|
|
26
|
+
texture?: FaceTextureRef;
|
|
27
|
+
}
|
|
28
|
+
interface BBElement {
|
|
29
|
+
uuid?: string;
|
|
30
|
+
name?: string;
|
|
31
|
+
type?: "cube" | "mesh" | string;
|
|
32
|
+
/** Marker/outliner color index (0-7). */
|
|
33
|
+
color?: number;
|
|
34
|
+
export?: boolean;
|
|
35
|
+
visibility?: boolean;
|
|
36
|
+
from?: Vec3;
|
|
37
|
+
to?: Vec3;
|
|
38
|
+
origin?: Vec3;
|
|
39
|
+
rotation?: Vec3;
|
|
40
|
+
/** Expands the cube on every axis by this many units. */
|
|
41
|
+
inflate?: number;
|
|
42
|
+
box_uv?: boolean;
|
|
43
|
+
uv_offset?: Vec2;
|
|
44
|
+
faces?: Record<string, BBFace>;
|
|
45
|
+
vertices?: Record<string, Vec3>;
|
|
46
|
+
}
|
|
47
|
+
interface BBOutlinerGroup {
|
|
48
|
+
uuid?: string;
|
|
49
|
+
name?: string;
|
|
50
|
+
origin?: Vec3;
|
|
51
|
+
rotation?: Vec3;
|
|
52
|
+
visibility?: boolean;
|
|
53
|
+
export?: boolean;
|
|
54
|
+
children?: BBOutlinerNode[];
|
|
55
|
+
}
|
|
56
|
+
/** An outliner node is either an element uuid (string) or a nested group. */
|
|
57
|
+
type BBOutlinerNode = string | BBOutlinerGroup;
|
|
58
|
+
interface BBTexture {
|
|
59
|
+
uuid?: string;
|
|
60
|
+
id?: string;
|
|
61
|
+
name?: string;
|
|
62
|
+
path?: string;
|
|
63
|
+
relative_path?: string;
|
|
64
|
+
/** `data:image/...;base64,` payload. Preferred source when present. */
|
|
65
|
+
source?: string;
|
|
66
|
+
width?: number;
|
|
67
|
+
height?: number;
|
|
68
|
+
/** UV coordinate space for this texture (falls back to project resolution). */
|
|
69
|
+
uv_width?: number;
|
|
70
|
+
uv_height?: number;
|
|
71
|
+
render_mode?: string;
|
|
72
|
+
}
|
|
73
|
+
interface BBModel {
|
|
74
|
+
meta?: {
|
|
75
|
+
format_version?: string;
|
|
76
|
+
model_format?: string;
|
|
77
|
+
box_uv?: boolean;
|
|
78
|
+
[k: string]: unknown;
|
|
79
|
+
};
|
|
80
|
+
name?: string;
|
|
81
|
+
/** Project UV resolution used to normalize per-face UV coordinates. */
|
|
82
|
+
resolution?: {
|
|
83
|
+
width: number;
|
|
84
|
+
height: number;
|
|
85
|
+
};
|
|
86
|
+
elements?: BBElement[];
|
|
87
|
+
outliner?: BBOutlinerNode[];
|
|
88
|
+
/** Blockbench 5.0+ stores groups here; still referenced by the outliner tree. */
|
|
89
|
+
groups?: BBOutlinerGroup[];
|
|
90
|
+
textures?: BBTexture[];
|
|
91
|
+
[k: string]: unknown;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface BBModelViewerOptions {
|
|
95
|
+
/** Scene background. A CSS color, hex number, or `null`/"transparent". */
|
|
96
|
+
background?: string | number | null;
|
|
97
|
+
/** Show a ground grid aligned with the model base. Default `true`. */
|
|
98
|
+
grid?: boolean;
|
|
99
|
+
/** Enable orbit/zoom/pan controls. Default `true`. */
|
|
100
|
+
controls?: boolean;
|
|
101
|
+
/** Continuously spin the model. Default `false`. */
|
|
102
|
+
autoRotate?: boolean;
|
|
103
|
+
/** Auto-rotation speed (three.js OrbitControls units). Default `1.0`. */
|
|
104
|
+
autoRotateSpeed?: number;
|
|
105
|
+
/** Camera vertical field of view in degrees. Default `45`. */
|
|
106
|
+
fov?: number;
|
|
107
|
+
/** Ambient light intensity. Default `0.8`. */
|
|
108
|
+
ambientIntensity?: number;
|
|
109
|
+
/** Key directional light intensity. Default `0.55`. */
|
|
110
|
+
directionalIntensity?: number;
|
|
111
|
+
/** Render both faces of every polygon. Default `true` (robust for meshes). */
|
|
112
|
+
doubleSided?: boolean;
|
|
113
|
+
/** Alpha cutoff for transparent texels. Default `0.02`. */
|
|
114
|
+
alphaTest?: number;
|
|
115
|
+
/** MSAA antialiasing. Default `true`. */
|
|
116
|
+
antialias?: boolean;
|
|
117
|
+
/** Device pixel ratio cap. Default `min(devicePixelRatio, 2)`. */
|
|
118
|
+
pixelRatio?: number;
|
|
119
|
+
/** Called after a model finishes loading and is added to the scene. */
|
|
120
|
+
onLoad?: (model: BBModel, object: THREE.Group) => void;
|
|
121
|
+
/** Called when loading/parsing fails. */
|
|
122
|
+
onError?: (error: unknown) => void;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Renders Blockbench `.bbmodel` files into a container element with three.js.
|
|
126
|
+
*
|
|
127
|
+
* ```ts
|
|
128
|
+
* const viewer = new BBModelViewer(document.getElementById("app")!);
|
|
129
|
+
* await viewer.load("/models/creeper.bbmodel");
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
declare class BBModelViewer {
|
|
133
|
+
readonly scene: THREE.Scene;
|
|
134
|
+
readonly camera: THREE.PerspectiveCamera;
|
|
135
|
+
readonly renderer: THREE.WebGLRenderer;
|
|
136
|
+
readonly controls?: OrbitControls;
|
|
137
|
+
private readonly container;
|
|
138
|
+
private readonly options;
|
|
139
|
+
private modelRoot;
|
|
140
|
+
private materials;
|
|
141
|
+
private gridHelper;
|
|
142
|
+
private resizeObserver?;
|
|
143
|
+
private frameId;
|
|
144
|
+
private disposed;
|
|
145
|
+
private loadToken;
|
|
146
|
+
constructor(container: HTMLElement, options?: BBModelViewerOptions);
|
|
147
|
+
/** Fetches a `.bbmodel` file by URL and renders it. */
|
|
148
|
+
load(url: string, init?: RequestInit): Promise<THREE.Group>;
|
|
149
|
+
/** Reads a `File`/`Blob` (e.g. from an `<input type="file">`) and renders it. */
|
|
150
|
+
loadFile(file: File | Blob): Promise<THREE.Group>;
|
|
151
|
+
/** Renders an already-parsed bbmodel object. */
|
|
152
|
+
loadModel(data: BBModel): Promise<THREE.Group>;
|
|
153
|
+
/** Removes the current model and frees its GPU resources. */
|
|
154
|
+
clear(): void;
|
|
155
|
+
/** Recomputes size from the container; call after layout changes if needed. */
|
|
156
|
+
resize(): void;
|
|
157
|
+
/** Frames the camera on the current model's bounding box. */
|
|
158
|
+
frameModel(): void;
|
|
159
|
+
/** Tears down the renderer, listeners and GPU resources. */
|
|
160
|
+
dispose(): void;
|
|
161
|
+
private addLights;
|
|
162
|
+
private addGrid;
|
|
163
|
+
private observeResize;
|
|
164
|
+
private measure;
|
|
165
|
+
private animate;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
interface MaterialSettings {
|
|
169
|
+
/** Discard fragments whose alpha is below this threshold (crisp pixel edges). */
|
|
170
|
+
alphaTest: number;
|
|
171
|
+
/** Render both sides of every face (safe default for meshes / thin geometry). */
|
|
172
|
+
side: THREE.Side;
|
|
173
|
+
}
|
|
174
|
+
interface TextureMeta {
|
|
175
|
+
material: THREE.MeshLambertMaterial;
|
|
176
|
+
uvWidth: number;
|
|
177
|
+
uvHeight: number;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Holds every material + texture created for a model. Faces reference a texture
|
|
181
|
+
* through {@link resolve}; untextured faces fall back to a flat color material.
|
|
182
|
+
*/
|
|
183
|
+
declare class MaterialLibrary {
|
|
184
|
+
private readonly model;
|
|
185
|
+
private readonly settings;
|
|
186
|
+
private readonly byKey;
|
|
187
|
+
private readonly colorMaterials;
|
|
188
|
+
private readonly disposables;
|
|
189
|
+
private readonly fallbackUv;
|
|
190
|
+
constructor(model: BBModel, settings: MaterialSettings);
|
|
191
|
+
/**
|
|
192
|
+
* Creates a texture + material per model texture and starts loading their
|
|
193
|
+
* images. Resolves once every image has settled (loaded or failed).
|
|
194
|
+
*/
|
|
195
|
+
load(onProgress?: () => void): Promise<void>;
|
|
196
|
+
private createTexture;
|
|
197
|
+
/** Resolves a face's texture reference to its material + UV space, if any. */
|
|
198
|
+
resolve(ref: FaceTextureRef): TextureMeta | null;
|
|
199
|
+
/** UV space to use when a face has no resolvable texture. */
|
|
200
|
+
get fallbackUvSpace(): {
|
|
201
|
+
width: number;
|
|
202
|
+
height: number;
|
|
203
|
+
};
|
|
204
|
+
/** Flat color material for untextured faces, keyed by marker color index. */
|
|
205
|
+
colorMaterial(colorIndex?: number): THREE.MeshLambertMaterial;
|
|
206
|
+
dispose(): void;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Turns a parsed bbmodel plus its materials into a three.js object graph that
|
|
211
|
+
* mirrors the Blockbench outliner (bones with pivots, nested rotations).
|
|
212
|
+
*/
|
|
213
|
+
declare function buildModelObject(model: BBModel, library: MaterialLibrary): THREE.Group;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Builds a renderable Mesh for a cube or mesh element, with geometry expressed
|
|
217
|
+
* relative to the element's own origin (the caller places the origin pivot).
|
|
218
|
+
*/
|
|
219
|
+
declare function buildElementMesh(element: BBElement, library: MaterialLibrary): THREE.Mesh | null;
|
|
220
|
+
|
|
221
|
+
export { type BBElement, type BBFace, type BBMeshFace, type BBModel, BBModelViewer, type BBModelViewerOptions, type BBOutlinerGroup, type BBOutlinerNode, type BBTexture, type FaceTextureRef, MaterialLibrary, type MaterialSettings, type Vec2, type Vec3, buildElementMesh, buildModelObject };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Minimal, permissive typings for the Blockbench `.bbmodel` / `.json` project
|
|
6
|
+
* format. The format is loose and evolves across Blockbench versions, so most
|
|
7
|
+
* fields are optional and unknown extras are tolerated.
|
|
8
|
+
*/
|
|
9
|
+
type Vec2 = [number, number];
|
|
10
|
+
type Vec3 = [number, number, number];
|
|
11
|
+
/** A texture reference on a face: numeric index, uuid/id string, or none. */
|
|
12
|
+
type FaceTextureRef = number | string | null | false | undefined;
|
|
13
|
+
interface BBFace {
|
|
14
|
+
/** Per-face UV rectangle in texture pixels: `[u_min, v_min, u_max, v_max]`. */
|
|
15
|
+
uv?: [number, number, number, number];
|
|
16
|
+
/** Texture reference (index into `textures`, or its uuid/id). */
|
|
17
|
+
texture?: FaceTextureRef;
|
|
18
|
+
/** UV rotation in degrees (0 / 90 / 180 / 270). */
|
|
19
|
+
rotation?: number;
|
|
20
|
+
}
|
|
21
|
+
interface BBMeshFace {
|
|
22
|
+
/** Ordered vertex keys (3 for a triangle, 4 for a quad). */
|
|
23
|
+
vertices: string[];
|
|
24
|
+
/** Per-vertex UV in texture pixels, keyed by vertex id. */
|
|
25
|
+
uv?: Record<string, Vec2>;
|
|
26
|
+
texture?: FaceTextureRef;
|
|
27
|
+
}
|
|
28
|
+
interface BBElement {
|
|
29
|
+
uuid?: string;
|
|
30
|
+
name?: string;
|
|
31
|
+
type?: "cube" | "mesh" | string;
|
|
32
|
+
/** Marker/outliner color index (0-7). */
|
|
33
|
+
color?: number;
|
|
34
|
+
export?: boolean;
|
|
35
|
+
visibility?: boolean;
|
|
36
|
+
from?: Vec3;
|
|
37
|
+
to?: Vec3;
|
|
38
|
+
origin?: Vec3;
|
|
39
|
+
rotation?: Vec3;
|
|
40
|
+
/** Expands the cube on every axis by this many units. */
|
|
41
|
+
inflate?: number;
|
|
42
|
+
box_uv?: boolean;
|
|
43
|
+
uv_offset?: Vec2;
|
|
44
|
+
faces?: Record<string, BBFace>;
|
|
45
|
+
vertices?: Record<string, Vec3>;
|
|
46
|
+
}
|
|
47
|
+
interface BBOutlinerGroup {
|
|
48
|
+
uuid?: string;
|
|
49
|
+
name?: string;
|
|
50
|
+
origin?: Vec3;
|
|
51
|
+
rotation?: Vec3;
|
|
52
|
+
visibility?: boolean;
|
|
53
|
+
export?: boolean;
|
|
54
|
+
children?: BBOutlinerNode[];
|
|
55
|
+
}
|
|
56
|
+
/** An outliner node is either an element uuid (string) or a nested group. */
|
|
57
|
+
type BBOutlinerNode = string | BBOutlinerGroup;
|
|
58
|
+
interface BBTexture {
|
|
59
|
+
uuid?: string;
|
|
60
|
+
id?: string;
|
|
61
|
+
name?: string;
|
|
62
|
+
path?: string;
|
|
63
|
+
relative_path?: string;
|
|
64
|
+
/** `data:image/...;base64,` payload. Preferred source when present. */
|
|
65
|
+
source?: string;
|
|
66
|
+
width?: number;
|
|
67
|
+
height?: number;
|
|
68
|
+
/** UV coordinate space for this texture (falls back to project resolution). */
|
|
69
|
+
uv_width?: number;
|
|
70
|
+
uv_height?: number;
|
|
71
|
+
render_mode?: string;
|
|
72
|
+
}
|
|
73
|
+
interface BBModel {
|
|
74
|
+
meta?: {
|
|
75
|
+
format_version?: string;
|
|
76
|
+
model_format?: string;
|
|
77
|
+
box_uv?: boolean;
|
|
78
|
+
[k: string]: unknown;
|
|
79
|
+
};
|
|
80
|
+
name?: string;
|
|
81
|
+
/** Project UV resolution used to normalize per-face UV coordinates. */
|
|
82
|
+
resolution?: {
|
|
83
|
+
width: number;
|
|
84
|
+
height: number;
|
|
85
|
+
};
|
|
86
|
+
elements?: BBElement[];
|
|
87
|
+
outliner?: BBOutlinerNode[];
|
|
88
|
+
/** Blockbench 5.0+ stores groups here; still referenced by the outliner tree. */
|
|
89
|
+
groups?: BBOutlinerGroup[];
|
|
90
|
+
textures?: BBTexture[];
|
|
91
|
+
[k: string]: unknown;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface BBModelViewerOptions {
|
|
95
|
+
/** Scene background. A CSS color, hex number, or `null`/"transparent". */
|
|
96
|
+
background?: string | number | null;
|
|
97
|
+
/** Show a ground grid aligned with the model base. Default `true`. */
|
|
98
|
+
grid?: boolean;
|
|
99
|
+
/** Enable orbit/zoom/pan controls. Default `true`. */
|
|
100
|
+
controls?: boolean;
|
|
101
|
+
/** Continuously spin the model. Default `false`. */
|
|
102
|
+
autoRotate?: boolean;
|
|
103
|
+
/** Auto-rotation speed (three.js OrbitControls units). Default `1.0`. */
|
|
104
|
+
autoRotateSpeed?: number;
|
|
105
|
+
/** Camera vertical field of view in degrees. Default `45`. */
|
|
106
|
+
fov?: number;
|
|
107
|
+
/** Ambient light intensity. Default `0.8`. */
|
|
108
|
+
ambientIntensity?: number;
|
|
109
|
+
/** Key directional light intensity. Default `0.55`. */
|
|
110
|
+
directionalIntensity?: number;
|
|
111
|
+
/** Render both faces of every polygon. Default `true` (robust for meshes). */
|
|
112
|
+
doubleSided?: boolean;
|
|
113
|
+
/** Alpha cutoff for transparent texels. Default `0.02`. */
|
|
114
|
+
alphaTest?: number;
|
|
115
|
+
/** MSAA antialiasing. Default `true`. */
|
|
116
|
+
antialias?: boolean;
|
|
117
|
+
/** Device pixel ratio cap. Default `min(devicePixelRatio, 2)`. */
|
|
118
|
+
pixelRatio?: number;
|
|
119
|
+
/** Called after a model finishes loading and is added to the scene. */
|
|
120
|
+
onLoad?: (model: BBModel, object: THREE.Group) => void;
|
|
121
|
+
/** Called when loading/parsing fails. */
|
|
122
|
+
onError?: (error: unknown) => void;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Renders Blockbench `.bbmodel` files into a container element with three.js.
|
|
126
|
+
*
|
|
127
|
+
* ```ts
|
|
128
|
+
* const viewer = new BBModelViewer(document.getElementById("app")!);
|
|
129
|
+
* await viewer.load("/models/creeper.bbmodel");
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
declare class BBModelViewer {
|
|
133
|
+
readonly scene: THREE.Scene;
|
|
134
|
+
readonly camera: THREE.PerspectiveCamera;
|
|
135
|
+
readonly renderer: THREE.WebGLRenderer;
|
|
136
|
+
readonly controls?: OrbitControls;
|
|
137
|
+
private readonly container;
|
|
138
|
+
private readonly options;
|
|
139
|
+
private modelRoot;
|
|
140
|
+
private materials;
|
|
141
|
+
private gridHelper;
|
|
142
|
+
private resizeObserver?;
|
|
143
|
+
private frameId;
|
|
144
|
+
private disposed;
|
|
145
|
+
private loadToken;
|
|
146
|
+
constructor(container: HTMLElement, options?: BBModelViewerOptions);
|
|
147
|
+
/** Fetches a `.bbmodel` file by URL and renders it. */
|
|
148
|
+
load(url: string, init?: RequestInit): Promise<THREE.Group>;
|
|
149
|
+
/** Reads a `File`/`Blob` (e.g. from an `<input type="file">`) and renders it. */
|
|
150
|
+
loadFile(file: File | Blob): Promise<THREE.Group>;
|
|
151
|
+
/** Renders an already-parsed bbmodel object. */
|
|
152
|
+
loadModel(data: BBModel): Promise<THREE.Group>;
|
|
153
|
+
/** Removes the current model and frees its GPU resources. */
|
|
154
|
+
clear(): void;
|
|
155
|
+
/** Recomputes size from the container; call after layout changes if needed. */
|
|
156
|
+
resize(): void;
|
|
157
|
+
/** Frames the camera on the current model's bounding box. */
|
|
158
|
+
frameModel(): void;
|
|
159
|
+
/** Tears down the renderer, listeners and GPU resources. */
|
|
160
|
+
dispose(): void;
|
|
161
|
+
private addLights;
|
|
162
|
+
private addGrid;
|
|
163
|
+
private observeResize;
|
|
164
|
+
private measure;
|
|
165
|
+
private animate;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
interface MaterialSettings {
|
|
169
|
+
/** Discard fragments whose alpha is below this threshold (crisp pixel edges). */
|
|
170
|
+
alphaTest: number;
|
|
171
|
+
/** Render both sides of every face (safe default for meshes / thin geometry). */
|
|
172
|
+
side: THREE.Side;
|
|
173
|
+
}
|
|
174
|
+
interface TextureMeta {
|
|
175
|
+
material: THREE.MeshLambertMaterial;
|
|
176
|
+
uvWidth: number;
|
|
177
|
+
uvHeight: number;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Holds every material + texture created for a model. Faces reference a texture
|
|
181
|
+
* through {@link resolve}; untextured faces fall back to a flat color material.
|
|
182
|
+
*/
|
|
183
|
+
declare class MaterialLibrary {
|
|
184
|
+
private readonly model;
|
|
185
|
+
private readonly settings;
|
|
186
|
+
private readonly byKey;
|
|
187
|
+
private readonly colorMaterials;
|
|
188
|
+
private readonly disposables;
|
|
189
|
+
private readonly fallbackUv;
|
|
190
|
+
constructor(model: BBModel, settings: MaterialSettings);
|
|
191
|
+
/**
|
|
192
|
+
* Creates a texture + material per model texture and starts loading their
|
|
193
|
+
* images. Resolves once every image has settled (loaded or failed).
|
|
194
|
+
*/
|
|
195
|
+
load(onProgress?: () => void): Promise<void>;
|
|
196
|
+
private createTexture;
|
|
197
|
+
/** Resolves a face's texture reference to its material + UV space, if any. */
|
|
198
|
+
resolve(ref: FaceTextureRef): TextureMeta | null;
|
|
199
|
+
/** UV space to use when a face has no resolvable texture. */
|
|
200
|
+
get fallbackUvSpace(): {
|
|
201
|
+
width: number;
|
|
202
|
+
height: number;
|
|
203
|
+
};
|
|
204
|
+
/** Flat color material for untextured faces, keyed by marker color index. */
|
|
205
|
+
colorMaterial(colorIndex?: number): THREE.MeshLambertMaterial;
|
|
206
|
+
dispose(): void;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Turns a parsed bbmodel plus its materials into a three.js object graph that
|
|
211
|
+
* mirrors the Blockbench outliner (bones with pivots, nested rotations).
|
|
212
|
+
*/
|
|
213
|
+
declare function buildModelObject(model: BBModel, library: MaterialLibrary): THREE.Group;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Builds a renderable Mesh for a cube or mesh element, with geometry expressed
|
|
217
|
+
* relative to the element's own origin (the caller places the origin pivot).
|
|
218
|
+
*/
|
|
219
|
+
declare function buildElementMesh(element: BBElement, library: MaterialLibrary): THREE.Mesh | null;
|
|
220
|
+
|
|
221
|
+
export { type BBElement, type BBFace, type BBMeshFace, type BBModel, BBModelViewer, type BBModelViewerOptions, type BBOutlinerGroup, type BBOutlinerNode, type BBTexture, type FaceTextureRef, MaterialLibrary, type MaterialSettings, type Vec2, type Vec3, buildElementMesh, buildModelObject };
|