43 lines
2.2 KiB
TypeScript
43 lines
2.2 KiB
TypeScript
import type { STLImportResult } from "./stl-import";
|
|
|
|
export const STL_EXPORT_SCHEMA_VERSION = 1 as const;
|
|
|
|
export interface STLLossReport {
|
|
schemaVersion: typeof STL_EXPORT_SCHEMA_VERSION;
|
|
operation: "STL_EXPORT_LOSS_REPORT";
|
|
canRoundTrip: boolean;
|
|
warningCount: number;
|
|
warnings: Array<{ code: "STL_MATERIAL_UNSUPPORTED"; severity: "warning"; message: string }>;
|
|
}
|
|
|
|
function writeFloat(view: DataView, offset: number, value: number): void {
|
|
if (!Number.isFinite(value)) throw new Error("STL_EXPORT_NUMBER_INVALID");
|
|
view.setFloat32(offset, value, true);
|
|
}
|
|
|
|
export function exportBinarySTL(document: STLImportResult): ArrayBuffer {
|
|
if (document.schemaVersion !== 1 || document.triangleCount !== document.vertices.length || document.triangleCount !== document.normals.length) throw new Error("STL_EXPORT_DOCUMENT_INVALID");
|
|
const output = new ArrayBuffer(84 + document.triangleCount * 50);
|
|
const bytes = new Uint8Array(output);
|
|
bytes.set(new TextEncoder().encode("Web Blender STL schema 1").subarray(0, 80));
|
|
const view = new DataView(output);
|
|
view.setUint32(80, document.triangleCount, true);
|
|
for (let triangle = 0; triangle < document.triangleCount; triangle++) {
|
|
const offset = 84 + triangle * 50;
|
|
for (let axis = 0; axis < 3; axis++) writeFloat(view, offset + axis * 4, document.normals[triangle][axis]);
|
|
for (let vertex = 0; vertex < 3; vertex++) for (let axis = 0; axis < 3; axis++) writeFloat(view, offset + 12 + vertex * 12 + axis * 4, document.vertices[triangle][vertex][axis]);
|
|
view.setUint16(offset + 48, 0, true);
|
|
}
|
|
return output;
|
|
}
|
|
|
|
export function createSTLLossReport(sourceMaterialCount: number): STLLossReport {
|
|
if (!Number.isSafeInteger(sourceMaterialCount) || sourceMaterialCount < 0) throw new Error("STL_EXPORT_MATERIAL_COUNT_INVALID");
|
|
const warnings = sourceMaterialCount > 0 ? [{
|
|
code: "STL_MATERIAL_UNSUPPORTED" as const,
|
|
severity: "warning" as const,
|
|
message: `STL has no material slots; ${sourceMaterialCount} source material assignments are omitted`,
|
|
}] : [];
|
|
return { schemaVersion: STL_EXPORT_SCHEMA_VERSION, operation: "STL_EXPORT_LOSS_REPORT", canRoundTrip: true, warningCount: warnings.length, warnings };
|
|
}
|