"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const uv1 = require("../_polyfill/uv1.cjs");
class ColladaExporter {
constructor() {
__publicField(this, "options");
__publicField(this, "geometryInfo");
__publicField(this, "materialMap");
__publicField(this, "imageMap");
__publicField(this, "textures");
__publicField(this, "libraryImages");
__publicField(this, "libraryGeometries");
__publicField(this, "libraryEffects");
__publicField(this, "libraryMaterials");
__publicField(this, "canvas");
__publicField(this, "ctx");
__publicField(this, "transMat");
__publicField(this, "getFuncs", ["getX", "getY", "getZ", "getW"]);
this.options = {
version: "1.4.1",
author: null,
textureDirectory: "",
upAxis: "Y_UP",
unitName: null,
unitMeter: null
};
this.geometryInfo = /* @__PURE__ */ new WeakMap();
this.materialMap = /* @__PURE__ */ new WeakMap();
this.imageMap = /* @__PURE__ */ new WeakMap();
this.textures = [];
this.libraryImages = [];
this.libraryGeometries = [];
this.libraryEffects = [];
this.libraryMaterials = [];
this.canvas = null;
this.ctx = null;
this.transMat = null;
}
parse(object, onDone, options = {}) {
this.options = { ...this.options, ...options };
if (this.options.upAxis.match(/^[XYZ]_UP$/) === null) {
console.error("ColladaExporter: Invalid upAxis: valid values are X_UP, Y_UP or Z_UP.");
return null;
}
if (this.options.unitName !== null && this.options.unitMeter === null) {
console.error("ColladaExporter: unitMeter needs to be specified if unitName is specified.");
return null;
}
if (this.options.unitMeter !== null && this.options.unitName === null) {
console.error("ColladaExporter: unitName needs to be specified if unitMeter is specified.");
return null;
}
if (this.options.textureDirectory !== "") {
this.options.textureDirectory = `${this.options.textureDirectory}/`.replace(/\\/g, "/").replace(/\/+/g, "/");
}
if (this.options.version !== "1.4.1" && this.options.version !== "1.5.0") {
console.warn(`ColladaExporter : Version ${this.options.version} not supported for export. Only 1.4.1 and 1.5.0.`);
return null;
}
const libraryVisualScenes = this.processObject(object);
const specLink = this.options.version === "1.4.1" ? "http://www.collada.org/2005/11/COLLADASchema" : "https://www.khronos.org/collada/";
let dae = `${``}three.js Collada Exporter${this.options.author !== null ? `${this.options.author}` : ""}${`${(/* @__PURE__ */ new Date()).toISOString()}`}${`${(/* @__PURE__ */ new Date()).toISOString()}`}Y_UP`;
dae += `${this.libraryImages.join("")}`;
dae += `${this.libraryEffects.join("")}`;
dae += `${this.libraryMaterials.join("")}`;
dae += `${this.libraryGeometries.join("")}`;
dae += `${libraryVisualScenes}`;
dae += '';
dae += "";
const res = {
data: this.format(dae),
textures: this.textures
};
if (typeof onDone === "function") {
requestAnimationFrame(() => onDone(res));
}
return res;
}
// Convert the urdf xml into a well-formatted, indented format
format(urdf) {
var _a, _b;
const IS_END_TAG = /^<\//;
const IS_SELF_CLOSING = /(\?>$)|(\/>$)/;
const HAS_TEXT = /<[^>]+>[^<]*<\/[^<]+>/;
const pad = (ch, num) => num > 0 ? ch + pad(ch, num - 1) : "";
let tagnum = 0;
return (_b = (_a = urdf.match(/(<[^>]+>[^<]+<\/[^<]+>)|(<[^>]+>)/g)) == null ? void 0 : _a.map((tag) => {
if (!HAS_TEXT.test(tag) && !IS_SELF_CLOSING.test(tag) && IS_END_TAG.test(tag)) {
tagnum--;
}
const res = `${pad(" ", tagnum)}${tag}`;
if (!HAS_TEXT.test(tag) && !IS_SELF_CLOSING.test(tag) && !IS_END_TAG.test(tag)) {
tagnum++;
}
return res;
}).join("\n")) != null ? _b : "";
}
// Convert an image into a png format for saving
base64ToBuffer(str) {
const b = atob(str);
const buf = new Uint8Array(b.length);
for (let i = 0, l = buf.length; i < l; i++) {
buf[i] = b.charCodeAt(i);
}
return buf;
}
imageToData(image, ext) {
var _a;
this.canvas = this.canvas || document.createElement("canvas");
this.ctx = this.ctx || this.canvas.getContext("2d");
this.canvas.width = image.width instanceof SVGAnimatedLength ? 0 : image.width;
this.canvas.height = image.height instanceof SVGAnimatedLength ? 0 : image.height;
(_a = this.ctx) == null ? void 0 : _a.drawImage(image, 0, 0);
const base64data = this.canvas.toDataURL(`image/${ext}`, 1).replace(/^data:image\/(png|jpg);base64,/, "");
return this.base64ToBuffer(base64data);
}
// gets the attribute array. Generate a new array if the attribute is interleaved
attrBufferToArray(attr) {
if (attr instanceof THREE.InterleavedBufferAttribute && attr.isInterleavedBufferAttribute) {
const TypedArrayConstructor = attr.array.constructor;
const arr = new TypedArrayConstructor(attr.count * attr.itemSize);
const size = attr.itemSize;
for (let i = 0, l = attr.count; i < l; i++) {
for (let j = 0; j < size; j++) {
arr[i * size + j] = attr[this.getFuncs[j]](i);
}
}
return arr;
} else {
return attr.array;
}
}
// Returns an array of the same type starting at the `st` index,
// and `ct` length
subArray(arr, st, ct) {
if (Array.isArray(arr)) {
return arr.slice(st, st + ct);
} else {
const TypedArrayConstructor = arr.constructor;
return new TypedArrayConstructor(arr.buffer, st * arr.BYTES_PER_ELEMENT, ct);
}
}
// Returns the string for a geometry's attribute
getAttribute(attr, name, params, type) {
const array = this.attrBufferToArray(attr);
const res = Array.isArray(array) ? `${`` + array.join(" ")}${``}${params.map((n) => ``).join("")}` : "";
return res;
}
// Returns the string for a node's transform information
getTransform(o) {
o.updateMatrix();
this.transMat = this.transMat || new THREE.Matrix4();
this.transMat.copy(o.matrix);
this.transMat.transpose();
return `${this.transMat.toArray().join(" ")}`;
}
// Process the given piece of geometry into the geometry library
// Returns the mesh id
processGeometry(g) {
let info = this.geometryInfo.get(g);
if (!info) {
const bufferGeometry = g;
if (!bufferGeometry.isBufferGeometry) {
throw new Error("THREE.ColladaExporter: Geometry is not of type THREE.BufferGeometry.");
}
const meshid = `Mesh${this.libraryGeometries.length + 1}`;
const indexCount = bufferGeometry.index ? bufferGeometry.index.count * bufferGeometry.index.itemSize : bufferGeometry.attributes.position.count;
const groups = bufferGeometry.groups != null && bufferGeometry.groups.length !== 0 ? bufferGeometry.groups : [{ start: 0, count: indexCount, materialIndex: 0 }];
const gname = g.name ? ` name="${g.name}"` : "";
let gnode = ``;
const posName = `${meshid}-position`;
const vertName = `${meshid}-vertices`;
gnode += this.getAttribute(bufferGeometry.attributes.position, posName, ["X", "Y", "Z"], "float");
gnode += ``;
let triangleInputs = ``;
if ("normal" in bufferGeometry.attributes) {
const normName = `${meshid}-normal`;
gnode += this.getAttribute(bufferGeometry.attributes.normal, normName, ["X", "Y", "Z"], "float");
triangleInputs += ``;
}
if ("uv" in bufferGeometry.attributes) {
const uvName = `${meshid}-texcoord`;
gnode += this.getAttribute(bufferGeometry.attributes.uv, uvName, ["S", "T"], "float");
triangleInputs += ``;
}
if (uv1.UV1 in bufferGeometry.attributes) {
const uvName = `${meshid}-texcoord2`;
gnode += this.getAttribute(bufferGeometry.attributes[uv1.UV1], uvName, ["S", "T"], "float");
triangleInputs += ``;
}
if ("color" in bufferGeometry.attributes) {
const colName = `${meshid}-color`;
gnode += this.getAttribute(bufferGeometry.attributes.color, colName, ["X", "Y", "Z"], "uint8");
triangleInputs += ``;
}
let indexArray = null;
if (bufferGeometry.index) {
indexArray = this.attrBufferToArray(bufferGeometry.index);
} else {
indexArray = new Array(indexCount);
for (let i = 0, l = indexArray.length; i < l && Array.isArray(indexArray); i++)
indexArray[i] = i;
}
for (let i = 0, l = groups.length; i < l; i++) {
const group = groups[i];
const subarr = this.subArray(indexArray, group.start, group.count);
const polycount = subarr.length / 3;
gnode += ``;
gnode += triangleInputs;
gnode += `${subarr.join(" ")}
`;
gnode += "";
}
gnode += "";
this.libraryGeometries.push(gnode);
info = { meshid, bufferGeometry };
this.geometryInfo.set(g, info);
}
return info;
}
// Process the given texture into the image library
// Returns the image library
processTexture(tex) {
let texid = this.imageMap.get(tex);
if (texid == null) {
texid = `image-${this.libraryImages.length + 1}`;
const ext = "png";
const name = tex.name || texid;
let imageNode = ``;
if (this.options.version === "1.5.0") {
imageNode += `[${this.options.textureDirectory}${name}.${ext}]`;
} else {
imageNode += `${this.options.textureDirectory}${name}.${ext}`;
}
imageNode += "";
this.libraryImages.push(imageNode);
this.imageMap.set(tex, texid);
this.textures.push({
directory: this.options.textureDirectory,
name,
ext,
data: this.imageToData(tex.image, ext),
original: tex
});
}
return texid;
}
// Process the given material into the material and effect libraries
// Returns the material id
processMaterial(m) {
let matid = this.materialMap.get(m);
if (matid == null) {
matid = `Mat${this.libraryEffects.length + 1}`;
let type = "phong";
if (m instanceof THREE.MeshLambertMaterial) {
type = "lambert";
} else if (m instanceof THREE.MeshBasicMaterial) {
type = "constant";
if (m.map !== null) {
console.warn("ColladaExporter: Texture maps not supported with MeshBasicMaterial.");
}
}
if (m instanceof THREE.MeshPhongMaterial) {
const emissive = m.emissive ? m.emissive : new THREE.Color(0, 0, 0);
const diffuse = m.color ? m.color : new THREE.Color(0, 0, 0);
const specular = m.specular ? m.specular : new THREE.Color(1, 1, 1);
const shininess = m.shininess || 0;
const reflectivity = m.reflectivity || 0;
let transparencyNode = "";
if (m.transparent) {
transparencyNode += `${m.map ? '' : "1"}`;
if (m.opacity < 1) {
transparencyNode += `${m.opacity}`;
}
}
const techniqueNode = `${`<${type}>`}${m.emissiveMap ? '' : `${emissive.r} ${emissive.g} ${emissive.b} 1`}${type !== "constant" ? `${m.map ? '' : `${diffuse.r} ${diffuse.g} ${diffuse.b} 1`}` : ""}${type !== "constant" ? `${m.normalMap ? '' : ""}` : ""}${type === "phong" ? `${`${specular.r} ${specular.g} ${specular.b} 1`}${m.specularMap ? '' : `${shininess}`}` : ""}${`${diffuse.r} ${diffuse.g} ${diffuse.b} 1`}${`${reflectivity}`}${transparencyNode}${`${type}>`}`;
const effectnode = `${``}${m.map ? `${`${this.processTexture(
m.map
)}`}diffuse-surface` : ""}${m.specularMap ? `${`${this.processTexture(
m.specularMap
)}`}specular-surface` : ""}${m.emissiveMap ? `${`${this.processTexture(
m.emissiveMap
)}`}emissive-surface` : ""}${m.normalMap ? `${`${this.processTexture(
m.normalMap
)}`}bump-surface` : ""}${techniqueNode}${m.side === THREE.DoubleSide ? '1' : ""}`;
const materialName = m.name ? ` name="${m.name}"` : "";
const materialNode = ``;
this.libraryMaterials.push(materialNode);
this.libraryEffects.push(effectnode);
this.materialMap.set(m, matid);
}
}
return matid;
}
// Recursively process the object into a scene
processObject(o) {
let node = ``;
node += this.getTransform(o);
const a = new THREE.Mesh();
a.geometry;
if (o instanceof THREE.Mesh && o.isMesh && o.geometry !== null) {
const geomInfo = this.processGeometry(o.geometry);
const meshid = geomInfo.meshid;
const geometry = geomInfo.bufferGeometry;
let matids = null;
let matidsArray;
const mat = o.material || new THREE.MeshBasicMaterial();
const materials = Array.isArray(mat) ? mat : [mat];
if (geometry.groups.length > materials.length) {
matidsArray = new Array(geometry.groups.length);
} else {
matidsArray = new Array(materials.length);
}
matids = matidsArray.fill(null).map((_, i) => this.processMaterial(materials[i % materials.length]));
node += `${`` + (matids != null ? `${matids.map(
(id, i) => `${``}`
).join("")}` : "")}`;
}
o.children.forEach((c) => node += this.processObject(c));
node += "";
return node;
}
}
exports.ColladaExporter = ColladaExporter;
//# sourceMappingURL=ColladaExporter.cjs.map