UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

295 lines (294 loc) 11.5 kB
/** * Model2DRenderer * * Renders Minecraft Bedrock geometry models to 2D SVG representations. * Creates icon-style views of entities by projecting 3D geometry onto a 2D plane * and sampling texture data for accurate coloring. * * FEATURES: * --------- * - Orthographic views: front, back, left, right, top, bottom * - Isometric views: iso-front-right, iso-front-left, iso-back-right, iso-back-left * (shows 3 faces at once for realistic 3D-like appearance) * - Built-in unit cube support for standard block rendering * - Proper depth sorting for occlusion (painter's algorithm) * - Direct PNG and TGA texture loading (no browser required) * - Support for bone rotations and bind_pose_rotation * - Configurable scale and output dimensions * - Optional depth shading effects * - Pure Node.js - no Playwright/browser dependency needed * * USAGE: * ------ * // Render a unit cube block (uses built-in geometry): * const svg = Model2DRenderer.renderUnitCubeToSvg({ * viewDirection: 'iso-front-left', * texturePngData: pngBuffer, * outputWidth: 64, * outputHeight: 64 * }); * * // With raw PNG data (handles decoding automatically): * const svg = Model2DRenderer.renderToSvg(geometry, { * viewDirection: 'front', * texturePngData: pngBuffer, // Uint8Array of PNG file contents * outputWidth: 64, * outputHeight: 64, * depthShading: true * }); * * // Isometric view for Minecraft inventory-style 3D appearance: * const svg = Model2DRenderer.renderToSvg(geometry, { * viewDirection: 'iso-front-right', // Shows north + east + up faces * texturePngData: pngBuffer, * outputWidth: 64, * outputHeight: 64 * }); * * // With raw TGA data (async - use renderToSvgAsync): * const svg = await Model2DRenderer.renderToSvgAsync(geometry, { * viewDirection: 'front', * textureTgaData: tgaBuffer, // Uint8Array of TGA file contents * outputWidth: 64, * outputHeight: 64 * }); * * // With any image type (use textureData + textureFileType): * const svg = await Model2DRenderer.renderToSvgAsync(geometry, { * viewDirection: 'front', * textureData: imageBuffer, * textureFileType: 'tga', // or 'png' * outputWidth: 64 * }); * * // With pre-parsed texture pixels: * const svg = Model2DRenderer.renderToSvg(geometry, { * viewDirection: 'front', * texturePixels: { width: 64, height: 64, pixels: rgbaData }, * outputWidth: 64, * outputHeight: 64 * }); * * // Without texture (uses fallback color): * const svg = Model2DRenderer.renderToSvg(geometry, { * viewDirection: 'front', * fallbackColor: '#808080' * }); * * TEXTURE DATA FORMAT: * -------------------- * Option 1: texturePngData - raw PNG file bytes as Uint8Array * - Automatically decoded using pngjs (sync) * - Fast, pure Node.js, no browser needed * * Option 2: textureTgaData - raw TGA file bytes as Uint8Array * - Automatically decoded using @lunapaint/tga-codec (async) * - Use renderToSvgAsync() or renderToDetailedSvgAsync() * * Option 3: textureData + textureFileType - generic image bytes * - Works with 'png' or 'tga' file types * - Use async methods for TGA support * * Option 4: texturePixels - pre-parsed RGBA pixel data * - width: texture width in pixels * - height: texture height in pixels * - pixels: Uint8Array of RGBA values (4 bytes per pixel, row-major) * * LIMITATIONS: * ------------ * - Rotation is handled but heavily rotated cubes may not project perfectly * - No animation support (renders rest pose only) * - Texture filtering is nearest-neighbor (pixel art style) * * Last Updated: December 2025 */ import { IGeometry } from "./IModelGeometry"; import { ViewDirection } from "./ModelGeometryUtilities"; /** * Pre-parsed texture pixel data. */ export interface ITexturePixels { /** Texture width in pixels */ width: number; /** Texture height in pixels */ height: number; /** RGBA pixel data (4 bytes per pixel, row-major order) */ pixels: Uint8Array; } /** * Options for 2D rendering */ export interface IModel2DRenderOptions { /** View direction (default: 'front') */ viewDirection?: ViewDirection; /** Raw PNG file data - will be decoded automatically using pngjs */ texturePngData?: Uint8Array; /** Raw TGA file data - will be decoded automatically */ textureTgaData?: Uint8Array; /** * Raw texture file data with explicit file type. * Alternative to texturePngData/textureTgaData when you have the data and type separately. */ textureData?: Uint8Array; /** File type for textureData ('png' or 'tga') */ textureFileType?: string; /** Pre-parsed texture pixel data (alternative to texturePngData) */ texturePixels?: ITexturePixels; /** Texture width as defined in geometry (for UV mapping, default: from geometry or 64) */ textureWidth?: number; /** Texture height as defined in geometry (for UV mapping, default: from geometry or 64) */ textureHeight?: number; /** Output SVG width in pixels (default: 64) */ outputWidth?: number; /** Output SVG height in pixels (default: 64) */ outputHeight?: number; /** Whether to add depth shading (darker = further away) */ depthShading?: boolean; /** Depth shading intensity (0-1, default: 0.3) */ depthShadingIntensity?: number; /** Background color (default: transparent) */ backgroundColor?: string; /** Padding in pixels around the model (default: 2) */ padding?: number; /** Whether to include secondary faces (sides/top) for 3/4 view effect */ includeSecondaryFaces?: boolean; /** Scale multiplier for output (default: auto-fit) */ scale?: number; /** Fallback color when texture is not available */ fallbackColor?: string; /** * Perspective projection strength (0-1, default: 0 = orthographic). * A value of 0 uses pure orthographic projection (no foreshortening). * A value of 1 uses strong perspective with visible vanishing point effect. * Recommended range: 0.1-0.3 for subtle perspective, 0.5+ for dramatic effect. */ perspectiveStrength?: number; /** * Focal length for perspective projection (default: 100). * Smaller values create more dramatic perspective (wide-angle lens effect). * Larger values create flatter perspective (telephoto lens effect). * Only applies when perspectiveStrength > 0. */ focalLength?: number; /** * Texture sampling resolution per face (default: 1 = single color per face). * Higher values divide each face into a grid for more detailed texture representation. * - 1: Single averaged color per face (fastest, smallest SVG) * - 2: 2x2 grid = 4 samples per face * - 4: 4x4 grid = 16 samples per face (good balance of quality/size) * - 8: 8x8 grid = 64 samples per face (high quality) * Only applies to non-isometric views. Isometric views use single color for cleaner polygons. */ textureSampleResolution?: number; } /** * Static class for rendering Minecraft geometry models to 2D SVG. * Pure Node.js implementation - no browser/Playwright required. */ export default class Model2DRenderer { /** * Standard unit cube geometry (16x16x16 Minecraft units = 1 block). * Can be used directly with renderToSvg for unit cube blocks. */ static readonly UNIT_CUBE_GEOMETRY: IGeometry; /** * Render a unit cube block to SVG. * Convenience method that uses the standard unit cube geometry. * * @param options Rendering options (same as renderToSvg, but geometry is provided) * @returns SVG string */ static renderUnitCubeToSvg(options?: IModel2DRenderOptions): string; /** * Async version of renderUnitCubeToSvg that supports TGA textures. * * @param options Rendering options * @returns SVG string */ static renderUnitCubeToSvgAsync(options?: IModel2DRenderOptions): Promise<string>; /** * Decode PNG data to RGBA pixels using pngjs. * This is a synchronous operation - fast and doesn't require a browser. * Only works in Node.js environment - returns undefined in browser. * * @param pngData Raw PNG file bytes * @returns Decoded texture pixels, or undefined if decoding fails * @deprecated Use ImageCodec.decodePng() directly instead */ static decodePng(pngData: Uint8Array): ITexturePixels | undefined; /** * Decode TGA data to RGBA pixels. * Uses ImageCodec for decoding. * * @param tgaData Raw TGA file bytes * @returns Decoded texture pixels, or undefined if decoding fails * @deprecated Use ImageCodec.decodeTga() directly instead */ static decodeTga(tgaData: Uint8Array): Promise<ITexturePixels | undefined>; /** * Decode image data (PNG or TGA) to RGBA pixels. * Uses ImageCodec for decoding. * * @param data Raw image file bytes * @param fileType File extension ('png' or 'tga') * @returns Decoded texture pixels, or undefined if decoding fails * @deprecated Use ImageCodec.decode() directly instead */ static decodeTexture(data: Uint8Array, fileType: string): Promise<ITexturePixels | undefined>; /** * Render a geometry model to SVG string. * Uses average color sampling per face for efficient rendering. * * @param geometry The geometry definition to render * @param options Rendering options * @returns SVG string */ static renderToSvg(geometry: IGeometry, options?: IModel2DRenderOptions): string; /** * Async version of renderToSvg that supports TGA textures. * Use this when you have a TGA texture that needs to be decoded. * * @param geometry The geometry definition to render * @param options Rendering options (can include textureTgaData or textureData+textureFileType) * @returns SVG string */ static renderToSvgAsync(geometry: IGeometry, options?: IModel2DRenderOptions): Promise<string>; /** * Render a geometry model to SVG with per-pixel texture sampling. * Creates a more detailed rendering by sampling texture for each output pixel. * * @param geometry The geometry definition to render * @param options Rendering options * @returns SVG string with detailed pixel rendering */ static renderToDetailedSvg(geometry: IGeometry, options?: IModel2DRenderOptions): string; /** * Async version of renderToDetailedSvg that supports TGA textures. * Use this when you have a TGA texture that needs to be decoded. * * @param geometry The geometry definition to render * @param options Rendering options (can include textureTgaData or textureData+textureFileType) * @returns SVG string with detailed pixel rendering */ static renderToDetailedSvgAsync(geometry: IGeometry, options?: IModel2DRenderOptions): Promise<string>; /** * Sample a single pixel from the texture. */ private static _sampleTexturePixel; /** * Sample the average color from a texture region. */ private static _sampleTextureAverageColor; /** * Apply shading to a color. */ private static _shadeColor; /** * Calculate auto scale to fit geometry in output dimensions. */ private static _calculateAutoScale; /** * Get the 2D bounding box of projected faces. */ private static _getProjectedBounds; }