Favivon - Correção

This commit is contained in:
2026-05-30 19:59:39 -03:00
parent 76ddaa815d
commit d7dfd221f0
32859 changed files with 5459654 additions and 404 deletions
+803
View File
@@ -0,0 +1,803 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const _taskCache = /* @__PURE__ */ new WeakMap();
class Rhino3dmLoader extends THREE.Loader {
constructor(manager) {
super(manager);
this.libraryPath = "";
this.libraryPending = null;
this.libraryBinary = null;
this.libraryConfig = {};
this.url = "";
this.workerLimit = 4;
this.workerPool = [];
this.workerNextTaskID = 1;
this.workerSourceURL = "";
this.workerConfig = {};
this.materials = [];
}
setLibraryPath(path) {
this.libraryPath = path;
return this;
}
setWorkerLimit(workerLimit) {
this.workerLimit = workerLimit;
return this;
}
load(url, onLoad, onProgress, onError) {
const loader = new THREE.FileLoader(this.manager);
loader.setPath(this.path);
loader.setResponseType("arraybuffer");
loader.setRequestHeader(this.requestHeader);
this.url = url;
loader.load(
url,
(buffer) => {
if (_taskCache.has(buffer)) {
const cachedTask = _taskCache.get(buffer);
return cachedTask.promise.then(onLoad).catch(onError);
}
this.decodeObjects(buffer, url).then(onLoad).catch(onError);
},
onProgress,
onError
);
}
debug() {
console.log(
"Task load: ",
this.workerPool.map((worker) => worker._taskLoad)
);
}
decodeObjects(buffer, url) {
let worker;
let taskID;
const taskCost = buffer.byteLength;
const objectPending = this._getWorker(taskCost).then((_worker) => {
worker = _worker;
taskID = this.workerNextTaskID++;
return new Promise((resolve, reject) => {
worker._callbacks[taskID] = { resolve, reject };
worker.postMessage({ type: "decode", id: taskID, buffer }, [buffer]);
});
}).then((message) => this._createGeometry(message.data));
objectPending.catch(() => true).then(() => {
if (worker && taskID) {
this._releaseTask(worker, taskID);
}
});
_taskCache.set(buffer, {
url,
promise: objectPending
});
return objectPending;
}
parse(data, onLoad, onError) {
this.decodeObjects(data, "").then(onLoad).catch(onError);
}
_compareMaterials(material) {
const mat = {};
mat.name = material.name;
mat.color = {};
mat.color.r = material.color.r;
mat.color.g = material.color.g;
mat.color.b = material.color.b;
mat.type = material.type;
for (let i = 0; i < this.materials.length; i++) {
const m = this.materials[i];
const _mat = {};
_mat.name = m.name;
_mat.color = {};
_mat.color.r = m.color.r;
_mat.color.g = m.color.g;
_mat.color.b = m.color.b;
_mat.type = m.type;
if (JSON.stringify(mat) === JSON.stringify(_mat)) {
return m;
}
}
this.materials.push(material);
return material;
}
_createMaterial(material) {
if (material === void 0) {
return new THREE.MeshStandardMaterial({
color: new THREE.Color(1, 1, 1),
metalness: 0.8,
name: "default",
side: 2
});
}
const _diffuseColor = material.diffuseColor;
const diffusecolor = new THREE.Color(_diffuseColor.r / 255, _diffuseColor.g / 255, _diffuseColor.b / 255);
if (_diffuseColor.r === 0 && _diffuseColor.g === 0 && _diffuseColor.b === 0) {
diffusecolor.r = 1;
diffusecolor.g = 1;
diffusecolor.b = 1;
}
const mat = new THREE.MeshStandardMaterial({
color: diffusecolor,
name: material.name,
side: 2,
transparent: material.transparency > 0 ? true : false,
opacity: 1 - material.transparency
});
const textureLoader = new THREE.TextureLoader();
for (let i = 0; i < material.textures.length; i++) {
const texture = material.textures[i];
if (texture.image !== null) {
const map = textureLoader.load(texture.image);
switch (texture.type) {
case "Diffuse":
mat.map = map;
break;
case "Bump":
mat.bumpMap = map;
break;
case "Transparency":
mat.alphaMap = map;
mat.transparent = true;
break;
case "Emap":
mat.envMap = map;
break;
}
}
}
return mat;
}
_createGeometry(data) {
const object = new THREE.Object3D();
const instanceDefinitionObjects = [];
const instanceDefinitions = [];
const instanceReferences = [];
object.userData["layers"] = data.layers;
object.userData["groups"] = data.groups;
object.userData["settings"] = data.settings;
object.userData["objectType"] = "File3dm";
object.userData["materials"] = null;
object.name = this.url;
let objects = data.objects;
const materials = data.materials;
for (let i = 0; i < objects.length; i++) {
const obj = objects[i];
const attributes = obj.attributes;
switch (obj.objectType) {
case "InstanceDefinition":
instanceDefinitions.push(obj);
break;
case "InstanceReference":
instanceReferences.push(obj);
break;
default:
let _object;
if (attributes.materialIndex >= 0) {
const rMaterial = materials[attributes.materialIndex];
let material = this._createMaterial(rMaterial);
material = this._compareMaterials(material);
_object = this._createObject(obj, material);
} else {
const material = this._createMaterial();
_object = this._createObject(obj, material);
}
if (_object === void 0) {
continue;
}
const layer = data.layers[attributes.layerIndex];
_object.visible = layer ? data.layers[attributes.layerIndex].visible : true;
if (attributes.isInstanceDefinitionObject) {
instanceDefinitionObjects.push(_object);
} else {
object.add(_object);
}
break;
}
}
for (let i = 0; i < instanceDefinitions.length; i++) {
const iDef = instanceDefinitions[i];
objects = [];
for (let j = 0; j < iDef.attributes.objectIds.length; j++) {
const objId = iDef.attributes.objectIds[j];
for (let p = 0; p < instanceDefinitionObjects.length; p++) {
const idoId = instanceDefinitionObjects[p].userData.attributes.id;
if (objId === idoId) {
objects.push(instanceDefinitionObjects[p]);
}
}
}
for (let j = 0; j < instanceReferences.length; j++) {
const iRef = instanceReferences[j];
if (iRef.geometry.parentIdefId === iDef.attributes.id) {
const iRefObject = new THREE.Object3D();
const xf = iRef.geometry.xform.array;
const matrix = new THREE.Matrix4();
matrix.set(
xf[0],
xf[1],
xf[2],
xf[3],
xf[4],
xf[5],
xf[6],
xf[7],
xf[8],
xf[9],
xf[10],
xf[11],
xf[12],
xf[13],
xf[14],
xf[15]
);
iRefObject.applyMatrix4(matrix);
for (let p = 0; p < objects.length; p++) {
iRefObject.add(objects[p].clone(true));
}
object.add(iRefObject);
}
}
}
object.userData["materials"] = this.materials;
return object;
}
_createObject(obj, mat) {
const loader = new THREE.BufferGeometryLoader();
const attributes = obj.attributes;
let geometry, material, _color, color;
switch (obj.objectType) {
case "Point":
case "PointSet":
geometry = loader.parse(obj.geometry);
if (geometry.attributes.hasOwnProperty("color")) {
material = new THREE.PointsMaterial({ vertexColors: true, sizeAttenuation: false, size: 2 });
} else {
_color = attributes.drawColor;
color = new THREE.Color(_color.r / 255, _color.g / 255, _color.b / 255);
material = new THREE.PointsMaterial({ color, sizeAttenuation: false, size: 2 });
}
material = this._compareMaterials(material);
const points = new THREE.Points(geometry, material);
points.userData["attributes"] = attributes;
points.userData["objectType"] = obj.objectType;
if (attributes.name) {
points.name = attributes.name;
}
return points;
case "Mesh":
case "Extrusion":
case "SubD":
case "Brep":
if (obj.geometry === null)
return;
geometry = loader.parse(obj.geometry);
if (geometry.attributes.hasOwnProperty("color")) {
mat.vertexColors = true;
}
if (mat === null) {
mat = this._createMaterial();
mat = this._compareMaterials(mat);
}
const mesh = new THREE.Mesh(geometry, mat);
mesh.castShadow = attributes.castsShadows;
mesh.receiveShadow = attributes.receivesShadows;
mesh.userData["attributes"] = attributes;
mesh.userData["objectType"] = obj.objectType;
if (attributes.name) {
mesh.name = attributes.name;
}
return mesh;
case "Curve":
geometry = loader.parse(obj.geometry);
_color = attributes.drawColor;
color = new THREE.Color(_color.r / 255, _color.g / 255, _color.b / 255);
material = new THREE.LineBasicMaterial({ color });
material = this._compareMaterials(material);
const lines = new THREE.Line(geometry, material);
lines.userData["attributes"] = attributes;
lines.userData["objectType"] = obj.objectType;
if (attributes.name) {
lines.name = attributes.name;
}
return lines;
case "TextDot":
geometry = obj.geometry;
const ctx = document.createElement("canvas").getContext("2d");
const font = `${geometry.fontHeight}px ${geometry.fontFace}`;
ctx.font = font;
const width = ctx.measureText(geometry.text).width + 10;
const height = geometry.fontHeight + 10;
const r = window.devicePixelRatio;
ctx.canvas.width = width * r;
ctx.canvas.height = height * r;
ctx.canvas.style.width = width + "px";
ctx.canvas.style.height = height + "px";
ctx.setTransform(r, 0, 0, r, 0, 0);
ctx.font = font;
ctx.textBaseline = "middle";
ctx.textAlign = "center";
color = attributes.drawColor;
ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${color.a})`;
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = "white";
ctx.fillText(geometry.text, width / 2, height / 2);
const texture = new THREE.CanvasTexture(ctx.canvas);
texture.minFilter = THREE.LinearFilter;
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.wrapT = THREE.ClampToEdgeWrapping;
material = new THREE.SpriteMaterial({ map: texture, depthTest: false });
const sprite = new THREE.Sprite(material);
sprite.position.set(geometry.point[0], geometry.point[1], geometry.point[2]);
sprite.scale.set(width / 10, height / 10, 1);
sprite.userData["attributes"] = attributes;
sprite.userData["objectType"] = obj.objectType;
if (attributes.name) {
sprite.name = attributes.name;
}
return sprite;
case "Light":
geometry = obj.geometry;
let light;
if (geometry.isDirectionalLight) {
light = new THREE.DirectionalLight();
light.castShadow = attributes.castsShadows;
light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]);
light.target.position.set(geometry.direction[0], geometry.direction[1], geometry.direction[2]);
light.shadow.normalBias = 0.1;
} else if (geometry.isPointLight) {
light = new THREE.PointLight();
light.castShadow = attributes.castsShadows;
light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]);
light.shadow.normalBias = 0.1;
} else if (geometry.isRectangularLight) {
light = new THREE.RectAreaLight();
const width2 = Math.abs(geometry.width[2]);
const height2 = Math.abs(geometry.length[0]);
light.position.set(geometry.location[0] - height2 / 2, geometry.location[1], geometry.location[2] - width2 / 2);
light.height = height2;
light.width = width2;
light.lookAt(new THREE.Vector3(geometry.direction[0], geometry.direction[1], geometry.direction[2]));
} else if (geometry.isSpotLight) {
light = new THREE.SpotLight();
light.castShadow = attributes.castsShadows;
light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]);
light.target.position.set(geometry.direction[0], geometry.direction[1], geometry.direction[2]);
light.angle = geometry.spotAngleRadians;
light.shadow.normalBias = 0.1;
} else if (geometry.isLinearLight) {
console.warn("THREE.3DMLoader: No conversion exists for linear lights.");
return;
}
if (light) {
light.intensity = geometry.intensity;
_color = geometry.diffuse;
color = new THREE.Color(_color.r / 255, _color.g / 255, _color.b / 255);
light.color = color;
light.userData["attributes"] = attributes;
light.userData["objectType"] = obj.objectType;
}
return light;
}
}
_initLibrary() {
if (!this.libraryPending) {
const jsLoader = new THREE.FileLoader(this.manager);
jsLoader.setPath(this.libraryPath);
const jsContent = new Promise((resolve, reject) => {
jsLoader.load("rhino3dm.js", resolve, void 0, reject);
});
const binaryLoader = new THREE.FileLoader(this.manager);
binaryLoader.setPath(this.libraryPath);
binaryLoader.setResponseType("arraybuffer");
const binaryContent = new Promise((resolve, reject) => {
binaryLoader.load("rhino3dm.wasm", resolve, void 0, reject);
});
this.libraryPending = Promise.all([jsContent, binaryContent]).then(([jsContent2, binaryContent2]) => {
this.libraryConfig.wasmBinary = binaryContent2;
const fn = Rhino3dmWorker.toString();
const body = [
"/* rhino3dm.js */",
jsContent2,
"/* worker */",
fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"))
].join("\n");
this.workerSourceURL = URL.createObjectURL(new Blob([body]));
});
}
return this.libraryPending;
}
_getWorker(taskCost) {
return this._initLibrary().then(() => {
if (this.workerPool.length < this.workerLimit) {
const worker2 = new Worker(this.workerSourceURL);
worker2._callbacks = {};
worker2._taskCosts = {};
worker2._taskLoad = 0;
worker2.postMessage({
type: "init",
libraryConfig: this.libraryConfig
});
worker2.onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "decode":
worker2._callbacks[message.id].resolve(message);
break;
case "error":
worker2._callbacks[message.id].reject(message);
break;
default:
console.error('THREE.Rhino3dmLoader: Unexpected message, "' + message.type + '"');
}
};
this.workerPool.push(worker2);
} else {
this.workerPool.sort(function(a, b) {
return a._taskLoad > b._taskLoad ? -1 : 1;
});
}
const worker = this.workerPool[this.workerPool.length - 1];
worker._taskLoad += taskCost;
return worker;
});
}
_releaseTask(worker, taskID) {
worker._taskLoad -= worker._taskCosts[taskID];
delete worker._callbacks[taskID];
delete worker._taskCosts[taskID];
}
dispose() {
for (let i = 0; i < this.workerPool.length; ++i) {
this.workerPool[i].terminate();
}
this.workerPool.length = 0;
return this;
}
}
function Rhino3dmWorker() {
let libraryPending;
let libraryConfig;
let rhino;
onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "init":
libraryConfig = message.libraryConfig;
const wasmBinary = libraryConfig.wasmBinary;
let RhinoModule;
libraryPending = new Promise(function(resolve) {
RhinoModule = { wasmBinary, onRuntimeInitialized: resolve };
rhino3dm(RhinoModule);
}).then(() => {
rhino = RhinoModule;
});
break;
case "decode":
const buffer = message.buffer;
libraryPending.then(() => {
const data = decodeObjects(rhino, buffer);
self.postMessage({ type: "decode", id: message.id, data });
});
break;
}
};
function decodeObjects(rhino2, buffer) {
const arr = new Uint8Array(buffer);
const doc = rhino2.File3dm.fromByteArray(arr);
const objects = [];
const materials = [];
const layers = [];
const views = [];
const namedViews = [];
const groups = [];
const objs = doc.objects();
const cnt = objs.count;
for (let i = 0; i < cnt; i++) {
const _object = objs.get(i);
const object = extractObjectData(_object, doc);
_object.delete();
if (object) {
objects.push(object);
}
}
for (let i = 0; i < doc.instanceDefinitions().count(); i++) {
const idef = doc.instanceDefinitions().get(i);
const idefAttributes = extractProperties(idef);
idefAttributes.objectIds = idef.getObjectIds();
objects.push({ geometry: null, attributes: idefAttributes, objectType: "InstanceDefinition" });
}
const textureTypes = [
// rhino.TextureType.Bitmap,
rhino2.TextureType.Diffuse,
rhino2.TextureType.Bump,
rhino2.TextureType.Transparency,
rhino2.TextureType.Opacity,
rhino2.TextureType.Emap
];
const pbrTextureTypes = [
rhino2.TextureType.PBR_BaseColor,
rhino2.TextureType.PBR_Subsurface,
rhino2.TextureType.PBR_SubsurfaceScattering,
rhino2.TextureType.PBR_SubsurfaceScatteringRadius,
rhino2.TextureType.PBR_Metallic,
rhino2.TextureType.PBR_Specular,
rhino2.TextureType.PBR_SpecularTint,
rhino2.TextureType.PBR_Roughness,
rhino2.TextureType.PBR_Anisotropic,
rhino2.TextureType.PBR_Anisotropic_Rotation,
rhino2.TextureType.PBR_Sheen,
rhino2.TextureType.PBR_SheenTint,
rhino2.TextureType.PBR_Clearcoat,
rhino2.TextureType.PBR_ClearcoatBump,
rhino2.TextureType.PBR_ClearcoatRoughness,
rhino2.TextureType.PBR_OpacityIor,
rhino2.TextureType.PBR_OpacityRoughness,
rhino2.TextureType.PBR_Emission,
rhino2.TextureType.PBR_AmbientOcclusion,
rhino2.TextureType.PBR_Displacement
];
for (let i = 0; i < doc.materials().count(); i++) {
const _material = doc.materials().get(i);
const _pbrMaterial = _material.physicallyBased();
let material = extractProperties(_material);
const textures = [];
for (let j = 0; j < textureTypes.length; j++) {
const _texture = _material.getTexture(textureTypes[j]);
if (_texture) {
let textureType = textureTypes[j].constructor.name;
textureType = textureType.substring(12, textureType.length);
const texture = { type: textureType };
const image = doc.getEmbeddedFileAsBase64(_texture.fileName);
if (image) {
texture.image = "data:image/png;base64," + image;
} else {
console.warn(`THREE.3DMLoader: Image for ${textureType} texture not embedded in file.`);
texture.image = null;
}
textures.push(texture);
_texture.delete();
}
}
material.textures = textures;
if (_pbrMaterial.supported) {
console.log("pbr true");
for (let j = 0; j < pbrTextureTypes.length; j++) {
const _texture = _material.getTexture(textureTypes[j]);
if (_texture) {
const image = doc.getEmbeddedFileAsBase64(_texture.fileName);
let textureType = textureTypes[j].constructor.name;
textureType = textureType.substring(12, textureType.length);
const texture = { type: textureType, image: "data:image/png;base64," + image };
textures.push(texture);
_texture.delete();
}
}
const pbMaterialProperties = extractProperties(_material.physicallyBased());
material = Object.assign(pbMaterialProperties, material);
}
materials.push(material);
_material.delete();
_pbrMaterial.delete();
}
for (let i = 0; i < doc.layers().count(); i++) {
const _layer = doc.layers().get(i);
const layer = extractProperties(_layer);
layers.push(layer);
_layer.delete();
}
for (let i = 0; i < doc.views().count(); i++) {
const _view = doc.views().get(i);
const view = extractProperties(_view);
views.push(view);
_view.delete();
}
for (let i = 0; i < doc.namedViews().count(); i++) {
const _namedView = doc.namedViews().get(i);
const namedView = extractProperties(_namedView);
namedViews.push(namedView);
_namedView.delete();
}
for (let i = 0; i < doc.groups().count(); i++) {
const _group = doc.groups().get(i);
const group = extractProperties(_group);
groups.push(group);
_group.delete();
}
const settings = extractProperties(doc.settings());
doc.delete();
return { objects, materials, layers, views, namedViews, groups, settings };
}
function extractObjectData(object, doc) {
const _geometry = object.geometry();
const _attributes = object.attributes();
let objectType = _geometry.objectType;
let geometry, attributes, position, data, mesh;
switch (objectType) {
case rhino.ObjectType.Curve:
const pts = curveToPoints(_geometry, 100);
position = {};
attributes = {};
data = {};
position.itemSize = 3;
position.type = "Float32Array";
position.array = [];
for (let j = 0; j < pts.length; j++) {
position.array.push(pts[j][0]);
position.array.push(pts[j][1]);
position.array.push(pts[j][2]);
}
attributes.position = position;
data.attributes = attributes;
geometry = { data };
break;
case rhino.ObjectType.Point:
const pt = _geometry.location;
position = {};
const color = {};
attributes = {};
data = {};
position.itemSize = 3;
position.type = "Float32Array";
position.array = [pt[0], pt[1], pt[2]];
const _color = _attributes.drawColor(doc);
color.itemSize = 3;
color.type = "Float32Array";
color.array = [_color.r / 255, _color.g / 255, _color.b / 255];
attributes.position = position;
attributes.color = color;
data.attributes = attributes;
geometry = { data };
break;
case rhino.ObjectType.PointSet:
case rhino.ObjectType.Mesh:
geometry = _geometry.toThreejsJSON();
break;
case rhino.ObjectType.Brep:
const faces = _geometry.faces();
mesh = new rhino.Mesh();
for (let faceIndex = 0; faceIndex < faces.count; faceIndex++) {
const face = faces.get(faceIndex);
const _mesh = face.getMesh(rhino.MeshType.Any);
if (_mesh) {
mesh.append(_mesh);
_mesh.delete();
}
face.delete();
}
if (mesh.faces().count > 0) {
mesh.compact();
geometry = mesh.toThreejsJSON();
faces.delete();
}
mesh.delete();
break;
case rhino.ObjectType.Extrusion:
mesh = _geometry.getMesh(rhino.MeshType.Any);
if (mesh) {
geometry = mesh.toThreejsJSON();
mesh.delete();
}
break;
case rhino.ObjectType.TextDot:
geometry = extractProperties(_geometry);
break;
case rhino.ObjectType.Light:
geometry = extractProperties(_geometry);
break;
case rhino.ObjectType.InstanceReference:
geometry = extractProperties(_geometry);
geometry.xform = extractProperties(_geometry.xform);
geometry.xform.array = _geometry.xform.toFloatArray(true);
break;
case rhino.ObjectType.SubD:
_geometry.subdivide(3);
mesh = rhino.Mesh.createFromSubDControlNet(_geometry);
if (mesh) {
geometry = mesh.toThreejsJSON();
mesh.delete();
}
break;
default:
console.warn(`THREE.3DMLoader: TODO: Implement ${objectType.constructor.name}`);
break;
}
if (geometry) {
attributes = extractProperties(_attributes);
attributes.geometry = extractProperties(_geometry);
if (_attributes.groupCount > 0) {
attributes.groupIds = _attributes.getGroupList();
}
if (_attributes.userStringCount > 0) {
attributes.userStrings = _attributes.getUserStrings();
}
if (_geometry.userStringCount > 0) {
attributes.geometry.userStrings = _geometry.getUserStrings();
}
attributes.drawColor = _attributes.drawColor(doc);
objectType = objectType.constructor.name;
objectType = objectType.substring(11, objectType.length);
return { geometry, attributes, objectType };
} else {
console.warn(`THREE.3DMLoader: ${objectType.constructor.name} has no associated mesh geometry.`);
}
}
function extractProperties(object) {
const result = {};
for (const property in object) {
const value = object[property];
if (typeof value !== "function") {
if (typeof value === "object" && value !== null && value.hasOwnProperty("constructor")) {
result[property] = { name: value.constructor.name, value: value.value };
} else {
result[property] = value;
}
}
}
return result;
}
function curveToPoints(curve, pointLimit) {
let pointCount = pointLimit;
let rc = [];
const ts = [];
if (curve instanceof rhino.LineCurve) {
return [curve.pointAtStart, curve.pointAtEnd];
}
if (curve instanceof rhino.PolylineCurve) {
pointCount = curve.pointCount;
for (let i = 0; i < pointCount; i++) {
rc.push(curve.point(i));
}
return rc;
}
if (curve instanceof rhino.PolyCurve) {
const segmentCount = curve.segmentCount;
for (let i = 0; i < segmentCount; i++) {
const segment = curve.segmentCurve(i);
const segmentArray = curveToPoints(segment, pointCount);
rc = rc.concat(segmentArray);
segment.delete();
}
return rc;
}
if (curve instanceof rhino.ArcCurve) {
pointCount = Math.floor(curve.angleDegrees / 5);
pointCount = pointCount < 2 ? 2 : pointCount;
}
if (curve instanceof rhino.NurbsCurve && curve.degree === 1) {
const pLine = curve.tryGetPolyline();
for (let i = 0; i < pLine.count; i++) {
rc.push(pLine.get(i));
}
pLine.delete();
return rc;
}
const domain = curve.domain;
const divisions = pointCount - 1;
for (let j = 0; j < pointCount; j++) {
const t = domain[0] + j / divisions * (domain[1] - domain[0]);
if (t === domain[0] || t === domain[1]) {
ts.push(t);
continue;
}
const tan = curve.tangentAt(t);
const prevTan = curve.tangentAt(ts.slice(-1)[0]);
const tS = tan[0] * tan[0] + tan[1] * tan[1] + tan[2] * tan[2];
const ptS = prevTan[0] * prevTan[0] + prevTan[1] * prevTan[1] + prevTan[2] * prevTan[2];
const denominator = Math.sqrt(tS * ptS);
let angle;
if (denominator === 0) {
angle = Math.PI / 2;
} else {
const theta = (tan.x * prevTan.x + tan.y * prevTan.y + tan.z * prevTan.z) / denominator;
angle = Math.acos(Math.max(-1, Math.min(1, theta)));
}
if (angle < 0.1)
continue;
ts.push(t);
}
rc = ts.map((t) => curve.pointAt(t));
return rc;
}
}
exports.Rhino3dmLoader = Rhino3dmLoader;
//# sourceMappingURL=3DMLoader.cjs.map
File diff suppressed because one or more lines are too long
+17
View File
@@ -0,0 +1,17 @@
import { Loader, LoadingManager, Object3D } from 'three'
export class Rhino3dmLoader extends Loader {
constructor(manager?: LoadingManager)
load(
url: string,
onLoad: (object: Object3D) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Object3D>
parse(data: ArrayBufferLike, onLoad: (object: Object3D) => void, onError?: (event: ErrorEvent) => void): void
setLibraryPath(path: string): Rhino3dmLoader
setWorkerLimit(workerLimit: number): Rhino3dmLoader
dispose(): Rhino3dmLoader
}
+803
View File
@@ -0,0 +1,803 @@
import { Loader, FileLoader, MeshStandardMaterial, Color, TextureLoader, Object3D, Matrix4, BufferGeometryLoader, DirectionalLight, PointLight, RectAreaLight, Vector3, SpotLight, CanvasTexture, LinearFilter, ClampToEdgeWrapping, SpriteMaterial, Sprite, LineBasicMaterial, Line, Mesh, PointsMaterial, Points } from "three";
const _taskCache = /* @__PURE__ */ new WeakMap();
class Rhino3dmLoader extends Loader {
constructor(manager) {
super(manager);
this.libraryPath = "";
this.libraryPending = null;
this.libraryBinary = null;
this.libraryConfig = {};
this.url = "";
this.workerLimit = 4;
this.workerPool = [];
this.workerNextTaskID = 1;
this.workerSourceURL = "";
this.workerConfig = {};
this.materials = [];
}
setLibraryPath(path) {
this.libraryPath = path;
return this;
}
setWorkerLimit(workerLimit) {
this.workerLimit = workerLimit;
return this;
}
load(url, onLoad, onProgress, onError) {
const loader = new FileLoader(this.manager);
loader.setPath(this.path);
loader.setResponseType("arraybuffer");
loader.setRequestHeader(this.requestHeader);
this.url = url;
loader.load(
url,
(buffer) => {
if (_taskCache.has(buffer)) {
const cachedTask = _taskCache.get(buffer);
return cachedTask.promise.then(onLoad).catch(onError);
}
this.decodeObjects(buffer, url).then(onLoad).catch(onError);
},
onProgress,
onError
);
}
debug() {
console.log(
"Task load: ",
this.workerPool.map((worker) => worker._taskLoad)
);
}
decodeObjects(buffer, url) {
let worker;
let taskID;
const taskCost = buffer.byteLength;
const objectPending = this._getWorker(taskCost).then((_worker) => {
worker = _worker;
taskID = this.workerNextTaskID++;
return new Promise((resolve, reject) => {
worker._callbacks[taskID] = { resolve, reject };
worker.postMessage({ type: "decode", id: taskID, buffer }, [buffer]);
});
}).then((message) => this._createGeometry(message.data));
objectPending.catch(() => true).then(() => {
if (worker && taskID) {
this._releaseTask(worker, taskID);
}
});
_taskCache.set(buffer, {
url,
promise: objectPending
});
return objectPending;
}
parse(data, onLoad, onError) {
this.decodeObjects(data, "").then(onLoad).catch(onError);
}
_compareMaterials(material) {
const mat = {};
mat.name = material.name;
mat.color = {};
mat.color.r = material.color.r;
mat.color.g = material.color.g;
mat.color.b = material.color.b;
mat.type = material.type;
for (let i = 0; i < this.materials.length; i++) {
const m = this.materials[i];
const _mat = {};
_mat.name = m.name;
_mat.color = {};
_mat.color.r = m.color.r;
_mat.color.g = m.color.g;
_mat.color.b = m.color.b;
_mat.type = m.type;
if (JSON.stringify(mat) === JSON.stringify(_mat)) {
return m;
}
}
this.materials.push(material);
return material;
}
_createMaterial(material) {
if (material === void 0) {
return new MeshStandardMaterial({
color: new Color(1, 1, 1),
metalness: 0.8,
name: "default",
side: 2
});
}
const _diffuseColor = material.diffuseColor;
const diffusecolor = new Color(_diffuseColor.r / 255, _diffuseColor.g / 255, _diffuseColor.b / 255);
if (_diffuseColor.r === 0 && _diffuseColor.g === 0 && _diffuseColor.b === 0) {
diffusecolor.r = 1;
diffusecolor.g = 1;
diffusecolor.b = 1;
}
const mat = new MeshStandardMaterial({
color: diffusecolor,
name: material.name,
side: 2,
transparent: material.transparency > 0 ? true : false,
opacity: 1 - material.transparency
});
const textureLoader = new TextureLoader();
for (let i = 0; i < material.textures.length; i++) {
const texture = material.textures[i];
if (texture.image !== null) {
const map = textureLoader.load(texture.image);
switch (texture.type) {
case "Diffuse":
mat.map = map;
break;
case "Bump":
mat.bumpMap = map;
break;
case "Transparency":
mat.alphaMap = map;
mat.transparent = true;
break;
case "Emap":
mat.envMap = map;
break;
}
}
}
return mat;
}
_createGeometry(data) {
const object = new Object3D();
const instanceDefinitionObjects = [];
const instanceDefinitions = [];
const instanceReferences = [];
object.userData["layers"] = data.layers;
object.userData["groups"] = data.groups;
object.userData["settings"] = data.settings;
object.userData["objectType"] = "File3dm";
object.userData["materials"] = null;
object.name = this.url;
let objects = data.objects;
const materials = data.materials;
for (let i = 0; i < objects.length; i++) {
const obj = objects[i];
const attributes = obj.attributes;
switch (obj.objectType) {
case "InstanceDefinition":
instanceDefinitions.push(obj);
break;
case "InstanceReference":
instanceReferences.push(obj);
break;
default:
let _object;
if (attributes.materialIndex >= 0) {
const rMaterial = materials[attributes.materialIndex];
let material = this._createMaterial(rMaterial);
material = this._compareMaterials(material);
_object = this._createObject(obj, material);
} else {
const material = this._createMaterial();
_object = this._createObject(obj, material);
}
if (_object === void 0) {
continue;
}
const layer = data.layers[attributes.layerIndex];
_object.visible = layer ? data.layers[attributes.layerIndex].visible : true;
if (attributes.isInstanceDefinitionObject) {
instanceDefinitionObjects.push(_object);
} else {
object.add(_object);
}
break;
}
}
for (let i = 0; i < instanceDefinitions.length; i++) {
const iDef = instanceDefinitions[i];
objects = [];
for (let j = 0; j < iDef.attributes.objectIds.length; j++) {
const objId = iDef.attributes.objectIds[j];
for (let p = 0; p < instanceDefinitionObjects.length; p++) {
const idoId = instanceDefinitionObjects[p].userData.attributes.id;
if (objId === idoId) {
objects.push(instanceDefinitionObjects[p]);
}
}
}
for (let j = 0; j < instanceReferences.length; j++) {
const iRef = instanceReferences[j];
if (iRef.geometry.parentIdefId === iDef.attributes.id) {
const iRefObject = new Object3D();
const xf = iRef.geometry.xform.array;
const matrix = new Matrix4();
matrix.set(
xf[0],
xf[1],
xf[2],
xf[3],
xf[4],
xf[5],
xf[6],
xf[7],
xf[8],
xf[9],
xf[10],
xf[11],
xf[12],
xf[13],
xf[14],
xf[15]
);
iRefObject.applyMatrix4(matrix);
for (let p = 0; p < objects.length; p++) {
iRefObject.add(objects[p].clone(true));
}
object.add(iRefObject);
}
}
}
object.userData["materials"] = this.materials;
return object;
}
_createObject(obj, mat) {
const loader = new BufferGeometryLoader();
const attributes = obj.attributes;
let geometry, material, _color, color;
switch (obj.objectType) {
case "Point":
case "PointSet":
geometry = loader.parse(obj.geometry);
if (geometry.attributes.hasOwnProperty("color")) {
material = new PointsMaterial({ vertexColors: true, sizeAttenuation: false, size: 2 });
} else {
_color = attributes.drawColor;
color = new Color(_color.r / 255, _color.g / 255, _color.b / 255);
material = new PointsMaterial({ color, sizeAttenuation: false, size: 2 });
}
material = this._compareMaterials(material);
const points = new Points(geometry, material);
points.userData["attributes"] = attributes;
points.userData["objectType"] = obj.objectType;
if (attributes.name) {
points.name = attributes.name;
}
return points;
case "Mesh":
case "Extrusion":
case "SubD":
case "Brep":
if (obj.geometry === null)
return;
geometry = loader.parse(obj.geometry);
if (geometry.attributes.hasOwnProperty("color")) {
mat.vertexColors = true;
}
if (mat === null) {
mat = this._createMaterial();
mat = this._compareMaterials(mat);
}
const mesh = new Mesh(geometry, mat);
mesh.castShadow = attributes.castsShadows;
mesh.receiveShadow = attributes.receivesShadows;
mesh.userData["attributes"] = attributes;
mesh.userData["objectType"] = obj.objectType;
if (attributes.name) {
mesh.name = attributes.name;
}
return mesh;
case "Curve":
geometry = loader.parse(obj.geometry);
_color = attributes.drawColor;
color = new Color(_color.r / 255, _color.g / 255, _color.b / 255);
material = new LineBasicMaterial({ color });
material = this._compareMaterials(material);
const lines = new Line(geometry, material);
lines.userData["attributes"] = attributes;
lines.userData["objectType"] = obj.objectType;
if (attributes.name) {
lines.name = attributes.name;
}
return lines;
case "TextDot":
geometry = obj.geometry;
const ctx = document.createElement("canvas").getContext("2d");
const font = `${geometry.fontHeight}px ${geometry.fontFace}`;
ctx.font = font;
const width = ctx.measureText(geometry.text).width + 10;
const height = geometry.fontHeight + 10;
const r = window.devicePixelRatio;
ctx.canvas.width = width * r;
ctx.canvas.height = height * r;
ctx.canvas.style.width = width + "px";
ctx.canvas.style.height = height + "px";
ctx.setTransform(r, 0, 0, r, 0, 0);
ctx.font = font;
ctx.textBaseline = "middle";
ctx.textAlign = "center";
color = attributes.drawColor;
ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${color.a})`;
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = "white";
ctx.fillText(geometry.text, width / 2, height / 2);
const texture = new CanvasTexture(ctx.canvas);
texture.minFilter = LinearFilter;
texture.wrapS = ClampToEdgeWrapping;
texture.wrapT = ClampToEdgeWrapping;
material = new SpriteMaterial({ map: texture, depthTest: false });
const sprite = new Sprite(material);
sprite.position.set(geometry.point[0], geometry.point[1], geometry.point[2]);
sprite.scale.set(width / 10, height / 10, 1);
sprite.userData["attributes"] = attributes;
sprite.userData["objectType"] = obj.objectType;
if (attributes.name) {
sprite.name = attributes.name;
}
return sprite;
case "Light":
geometry = obj.geometry;
let light;
if (geometry.isDirectionalLight) {
light = new DirectionalLight();
light.castShadow = attributes.castsShadows;
light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]);
light.target.position.set(geometry.direction[0], geometry.direction[1], geometry.direction[2]);
light.shadow.normalBias = 0.1;
} else if (geometry.isPointLight) {
light = new PointLight();
light.castShadow = attributes.castsShadows;
light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]);
light.shadow.normalBias = 0.1;
} else if (geometry.isRectangularLight) {
light = new RectAreaLight();
const width2 = Math.abs(geometry.width[2]);
const height2 = Math.abs(geometry.length[0]);
light.position.set(geometry.location[0] - height2 / 2, geometry.location[1], geometry.location[2] - width2 / 2);
light.height = height2;
light.width = width2;
light.lookAt(new Vector3(geometry.direction[0], geometry.direction[1], geometry.direction[2]));
} else if (geometry.isSpotLight) {
light = new SpotLight();
light.castShadow = attributes.castsShadows;
light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]);
light.target.position.set(geometry.direction[0], geometry.direction[1], geometry.direction[2]);
light.angle = geometry.spotAngleRadians;
light.shadow.normalBias = 0.1;
} else if (geometry.isLinearLight) {
console.warn("THREE.3DMLoader: No conversion exists for linear lights.");
return;
}
if (light) {
light.intensity = geometry.intensity;
_color = geometry.diffuse;
color = new Color(_color.r / 255, _color.g / 255, _color.b / 255);
light.color = color;
light.userData["attributes"] = attributes;
light.userData["objectType"] = obj.objectType;
}
return light;
}
}
_initLibrary() {
if (!this.libraryPending) {
const jsLoader = new FileLoader(this.manager);
jsLoader.setPath(this.libraryPath);
const jsContent = new Promise((resolve, reject) => {
jsLoader.load("rhino3dm.js", resolve, void 0, reject);
});
const binaryLoader = new FileLoader(this.manager);
binaryLoader.setPath(this.libraryPath);
binaryLoader.setResponseType("arraybuffer");
const binaryContent = new Promise((resolve, reject) => {
binaryLoader.load("rhino3dm.wasm", resolve, void 0, reject);
});
this.libraryPending = Promise.all([jsContent, binaryContent]).then(([jsContent2, binaryContent2]) => {
this.libraryConfig.wasmBinary = binaryContent2;
const fn = Rhino3dmWorker.toString();
const body = [
"/* rhino3dm.js */",
jsContent2,
"/* worker */",
fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"))
].join("\n");
this.workerSourceURL = URL.createObjectURL(new Blob([body]));
});
}
return this.libraryPending;
}
_getWorker(taskCost) {
return this._initLibrary().then(() => {
if (this.workerPool.length < this.workerLimit) {
const worker2 = new Worker(this.workerSourceURL);
worker2._callbacks = {};
worker2._taskCosts = {};
worker2._taskLoad = 0;
worker2.postMessage({
type: "init",
libraryConfig: this.libraryConfig
});
worker2.onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "decode":
worker2._callbacks[message.id].resolve(message);
break;
case "error":
worker2._callbacks[message.id].reject(message);
break;
default:
console.error('THREE.Rhino3dmLoader: Unexpected message, "' + message.type + '"');
}
};
this.workerPool.push(worker2);
} else {
this.workerPool.sort(function(a, b) {
return a._taskLoad > b._taskLoad ? -1 : 1;
});
}
const worker = this.workerPool[this.workerPool.length - 1];
worker._taskLoad += taskCost;
return worker;
});
}
_releaseTask(worker, taskID) {
worker._taskLoad -= worker._taskCosts[taskID];
delete worker._callbacks[taskID];
delete worker._taskCosts[taskID];
}
dispose() {
for (let i = 0; i < this.workerPool.length; ++i) {
this.workerPool[i].terminate();
}
this.workerPool.length = 0;
return this;
}
}
function Rhino3dmWorker() {
let libraryPending;
let libraryConfig;
let rhino;
onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "init":
libraryConfig = message.libraryConfig;
const wasmBinary = libraryConfig.wasmBinary;
let RhinoModule;
libraryPending = new Promise(function(resolve) {
RhinoModule = { wasmBinary, onRuntimeInitialized: resolve };
rhino3dm(RhinoModule);
}).then(() => {
rhino = RhinoModule;
});
break;
case "decode":
const buffer = message.buffer;
libraryPending.then(() => {
const data = decodeObjects(rhino, buffer);
self.postMessage({ type: "decode", id: message.id, data });
});
break;
}
};
function decodeObjects(rhino2, buffer) {
const arr = new Uint8Array(buffer);
const doc = rhino2.File3dm.fromByteArray(arr);
const objects = [];
const materials = [];
const layers = [];
const views = [];
const namedViews = [];
const groups = [];
const objs = doc.objects();
const cnt = objs.count;
for (let i = 0; i < cnt; i++) {
const _object = objs.get(i);
const object = extractObjectData(_object, doc);
_object.delete();
if (object) {
objects.push(object);
}
}
for (let i = 0; i < doc.instanceDefinitions().count(); i++) {
const idef = doc.instanceDefinitions().get(i);
const idefAttributes = extractProperties(idef);
idefAttributes.objectIds = idef.getObjectIds();
objects.push({ geometry: null, attributes: idefAttributes, objectType: "InstanceDefinition" });
}
const textureTypes = [
// rhino.TextureType.Bitmap,
rhino2.TextureType.Diffuse,
rhino2.TextureType.Bump,
rhino2.TextureType.Transparency,
rhino2.TextureType.Opacity,
rhino2.TextureType.Emap
];
const pbrTextureTypes = [
rhino2.TextureType.PBR_BaseColor,
rhino2.TextureType.PBR_Subsurface,
rhino2.TextureType.PBR_SubsurfaceScattering,
rhino2.TextureType.PBR_SubsurfaceScatteringRadius,
rhino2.TextureType.PBR_Metallic,
rhino2.TextureType.PBR_Specular,
rhino2.TextureType.PBR_SpecularTint,
rhino2.TextureType.PBR_Roughness,
rhino2.TextureType.PBR_Anisotropic,
rhino2.TextureType.PBR_Anisotropic_Rotation,
rhino2.TextureType.PBR_Sheen,
rhino2.TextureType.PBR_SheenTint,
rhino2.TextureType.PBR_Clearcoat,
rhino2.TextureType.PBR_ClearcoatBump,
rhino2.TextureType.PBR_ClearcoatRoughness,
rhino2.TextureType.PBR_OpacityIor,
rhino2.TextureType.PBR_OpacityRoughness,
rhino2.TextureType.PBR_Emission,
rhino2.TextureType.PBR_AmbientOcclusion,
rhino2.TextureType.PBR_Displacement
];
for (let i = 0; i < doc.materials().count(); i++) {
const _material = doc.materials().get(i);
const _pbrMaterial = _material.physicallyBased();
let material = extractProperties(_material);
const textures = [];
for (let j = 0; j < textureTypes.length; j++) {
const _texture = _material.getTexture(textureTypes[j]);
if (_texture) {
let textureType = textureTypes[j].constructor.name;
textureType = textureType.substring(12, textureType.length);
const texture = { type: textureType };
const image = doc.getEmbeddedFileAsBase64(_texture.fileName);
if (image) {
texture.image = "data:image/png;base64," + image;
} else {
console.warn(`THREE.3DMLoader: Image for ${textureType} texture not embedded in file.`);
texture.image = null;
}
textures.push(texture);
_texture.delete();
}
}
material.textures = textures;
if (_pbrMaterial.supported) {
console.log("pbr true");
for (let j = 0; j < pbrTextureTypes.length; j++) {
const _texture = _material.getTexture(textureTypes[j]);
if (_texture) {
const image = doc.getEmbeddedFileAsBase64(_texture.fileName);
let textureType = textureTypes[j].constructor.name;
textureType = textureType.substring(12, textureType.length);
const texture = { type: textureType, image: "data:image/png;base64," + image };
textures.push(texture);
_texture.delete();
}
}
const pbMaterialProperties = extractProperties(_material.physicallyBased());
material = Object.assign(pbMaterialProperties, material);
}
materials.push(material);
_material.delete();
_pbrMaterial.delete();
}
for (let i = 0; i < doc.layers().count(); i++) {
const _layer = doc.layers().get(i);
const layer = extractProperties(_layer);
layers.push(layer);
_layer.delete();
}
for (let i = 0; i < doc.views().count(); i++) {
const _view = doc.views().get(i);
const view = extractProperties(_view);
views.push(view);
_view.delete();
}
for (let i = 0; i < doc.namedViews().count(); i++) {
const _namedView = doc.namedViews().get(i);
const namedView = extractProperties(_namedView);
namedViews.push(namedView);
_namedView.delete();
}
for (let i = 0; i < doc.groups().count(); i++) {
const _group = doc.groups().get(i);
const group = extractProperties(_group);
groups.push(group);
_group.delete();
}
const settings = extractProperties(doc.settings());
doc.delete();
return { objects, materials, layers, views, namedViews, groups, settings };
}
function extractObjectData(object, doc) {
const _geometry = object.geometry();
const _attributes = object.attributes();
let objectType = _geometry.objectType;
let geometry, attributes, position, data, mesh;
switch (objectType) {
case rhino.ObjectType.Curve:
const pts = curveToPoints(_geometry, 100);
position = {};
attributes = {};
data = {};
position.itemSize = 3;
position.type = "Float32Array";
position.array = [];
for (let j = 0; j < pts.length; j++) {
position.array.push(pts[j][0]);
position.array.push(pts[j][1]);
position.array.push(pts[j][2]);
}
attributes.position = position;
data.attributes = attributes;
geometry = { data };
break;
case rhino.ObjectType.Point:
const pt = _geometry.location;
position = {};
const color = {};
attributes = {};
data = {};
position.itemSize = 3;
position.type = "Float32Array";
position.array = [pt[0], pt[1], pt[2]];
const _color = _attributes.drawColor(doc);
color.itemSize = 3;
color.type = "Float32Array";
color.array = [_color.r / 255, _color.g / 255, _color.b / 255];
attributes.position = position;
attributes.color = color;
data.attributes = attributes;
geometry = { data };
break;
case rhino.ObjectType.PointSet:
case rhino.ObjectType.Mesh:
geometry = _geometry.toThreejsJSON();
break;
case rhino.ObjectType.Brep:
const faces = _geometry.faces();
mesh = new rhino.Mesh();
for (let faceIndex = 0; faceIndex < faces.count; faceIndex++) {
const face = faces.get(faceIndex);
const _mesh = face.getMesh(rhino.MeshType.Any);
if (_mesh) {
mesh.append(_mesh);
_mesh.delete();
}
face.delete();
}
if (mesh.faces().count > 0) {
mesh.compact();
geometry = mesh.toThreejsJSON();
faces.delete();
}
mesh.delete();
break;
case rhino.ObjectType.Extrusion:
mesh = _geometry.getMesh(rhino.MeshType.Any);
if (mesh) {
geometry = mesh.toThreejsJSON();
mesh.delete();
}
break;
case rhino.ObjectType.TextDot:
geometry = extractProperties(_geometry);
break;
case rhino.ObjectType.Light:
geometry = extractProperties(_geometry);
break;
case rhino.ObjectType.InstanceReference:
geometry = extractProperties(_geometry);
geometry.xform = extractProperties(_geometry.xform);
geometry.xform.array = _geometry.xform.toFloatArray(true);
break;
case rhino.ObjectType.SubD:
_geometry.subdivide(3);
mesh = rhino.Mesh.createFromSubDControlNet(_geometry);
if (mesh) {
geometry = mesh.toThreejsJSON();
mesh.delete();
}
break;
default:
console.warn(`THREE.3DMLoader: TODO: Implement ${objectType.constructor.name}`);
break;
}
if (geometry) {
attributes = extractProperties(_attributes);
attributes.geometry = extractProperties(_geometry);
if (_attributes.groupCount > 0) {
attributes.groupIds = _attributes.getGroupList();
}
if (_attributes.userStringCount > 0) {
attributes.userStrings = _attributes.getUserStrings();
}
if (_geometry.userStringCount > 0) {
attributes.geometry.userStrings = _geometry.getUserStrings();
}
attributes.drawColor = _attributes.drawColor(doc);
objectType = objectType.constructor.name;
objectType = objectType.substring(11, objectType.length);
return { geometry, attributes, objectType };
} else {
console.warn(`THREE.3DMLoader: ${objectType.constructor.name} has no associated mesh geometry.`);
}
}
function extractProperties(object) {
const result = {};
for (const property in object) {
const value = object[property];
if (typeof value !== "function") {
if (typeof value === "object" && value !== null && value.hasOwnProperty("constructor")) {
result[property] = { name: value.constructor.name, value: value.value };
} else {
result[property] = value;
}
}
}
return result;
}
function curveToPoints(curve, pointLimit) {
let pointCount = pointLimit;
let rc = [];
const ts = [];
if (curve instanceof rhino.LineCurve) {
return [curve.pointAtStart, curve.pointAtEnd];
}
if (curve instanceof rhino.PolylineCurve) {
pointCount = curve.pointCount;
for (let i = 0; i < pointCount; i++) {
rc.push(curve.point(i));
}
return rc;
}
if (curve instanceof rhino.PolyCurve) {
const segmentCount = curve.segmentCount;
for (let i = 0; i < segmentCount; i++) {
const segment = curve.segmentCurve(i);
const segmentArray = curveToPoints(segment, pointCount);
rc = rc.concat(segmentArray);
segment.delete();
}
return rc;
}
if (curve instanceof rhino.ArcCurve) {
pointCount = Math.floor(curve.angleDegrees / 5);
pointCount = pointCount < 2 ? 2 : pointCount;
}
if (curve instanceof rhino.NurbsCurve && curve.degree === 1) {
const pLine = curve.tryGetPolyline();
for (let i = 0; i < pLine.count; i++) {
rc.push(pLine.get(i));
}
pLine.delete();
return rc;
}
const domain = curve.domain;
const divisions = pointCount - 1;
for (let j = 0; j < pointCount; j++) {
const t = domain[0] + j / divisions * (domain[1] - domain[0]);
if (t === domain[0] || t === domain[1]) {
ts.push(t);
continue;
}
const tan = curve.tangentAt(t);
const prevTan = curve.tangentAt(ts.slice(-1)[0]);
const tS = tan[0] * tan[0] + tan[1] * tan[1] + tan[2] * tan[2];
const ptS = prevTan[0] * prevTan[0] + prevTan[1] * prevTan[1] + prevTan[2] * prevTan[2];
const denominator = Math.sqrt(tS * ptS);
let angle;
if (denominator === 0) {
angle = Math.PI / 2;
} else {
const theta = (tan.x * prevTan.x + tan.y * prevTan.y + tan.z * prevTan.z) / denominator;
angle = Math.acos(Math.max(-1, Math.min(1, theta)));
}
if (angle < 0.1)
continue;
ts.push(t);
}
rc = ts.map((t) => curve.pointAt(t));
return rc;
}
}
export {
Rhino3dmLoader
};
//# sourceMappingURL=3DMLoader.js.map
File diff suppressed because one or more lines are too long
+853
View File
@@ -0,0 +1,853 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const fflate = require("fflate");
const LoaderUtils = require("../_polyfill/LoaderUtils.cjs");
class ThreeMFLoader extends THREE.Loader {
constructor(manager) {
super(manager);
this.availableExtensions = [];
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader = new THREE.FileLoader(scope.manager);
loader.setPath(scope.path);
loader.setResponseType("arraybuffer");
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
function(buffer) {
try {
onLoad(scope.parse(buffer));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(data) {
const scope = this;
const textureLoader = new THREE.TextureLoader(this.manager);
function loadDocument(data2) {
let zip = null;
let file = null;
let relsName;
let modelRelsName;
const modelPartNames = [];
const texturesPartNames = [];
let modelRels;
const modelParts = {};
const printTicketParts = {};
const texturesParts = {};
const otherParts = {};
try {
zip = fflate.unzipSync(new Uint8Array(data2));
} catch (e) {
if (e instanceof ReferenceError) {
console.error("THREE.3MFLoader: fflate missing and file is compressed.");
return null;
}
}
for (file in zip) {
if (file.match(/\_rels\/.rels$/)) {
relsName = file;
} else if (file.match(/3D\/_rels\/.*\.model\.rels$/)) {
modelRelsName = file;
} else if (file.match(/^3D\/.*\.model$/)) {
modelPartNames.push(file);
} else if (file.match(/^3D\/Metadata\/.*\.xml$/))
;
else if (file.match(/^3D\/Textures?\/.*/)) {
texturesPartNames.push(file);
} else if (file.match(/^3D\/Other\/.*/))
;
}
const relsView = zip[relsName];
const relsFileText = LoaderUtils.decodeText(relsView);
const rels = parseRelsXml(relsFileText);
if (modelRelsName) {
const relsView2 = zip[modelRelsName];
const relsFileText2 = LoaderUtils.decodeText(relsView2);
modelRels = parseRelsXml(relsFileText2);
}
for (let i = 0; i < modelPartNames.length; i++) {
const modelPart = modelPartNames[i];
const view = zip[modelPart];
const fileText = LoaderUtils.decodeText(view);
const xmlData = new DOMParser().parseFromString(fileText, "application/xml");
if (xmlData.documentElement.nodeName.toLowerCase() !== "model") {
console.error("THREE.3MFLoader: Error loading 3MF - no 3MF document found: ", modelPart);
}
const modelNode = xmlData.querySelector("model");
const extensions = {};
for (let i2 = 0; i2 < modelNode.attributes.length; i2++) {
const attr = modelNode.attributes[i2];
if (attr.name.match(/^xmlns:(.+)$/)) {
extensions[attr.value] = RegExp.$1;
}
}
const modelData = parseModelNode(modelNode);
modelData["xml"] = modelNode;
if (0 < Object.keys(extensions).length) {
modelData["extensions"] = extensions;
}
modelParts[modelPart] = modelData;
}
for (let i = 0; i < texturesPartNames.length; i++) {
const texturesPartName = texturesPartNames[i];
texturesParts[texturesPartName] = zip[texturesPartName].buffer;
}
return {
rels,
modelRels,
model: modelParts,
printTicket: printTicketParts,
texture: texturesParts,
other: otherParts
};
}
function parseRelsXml(relsFileText) {
const relationships = [];
const relsXmlData = new DOMParser().parseFromString(relsFileText, "application/xml");
const relsNodes = relsXmlData.querySelectorAll("Relationship");
for (let i = 0; i < relsNodes.length; i++) {
const relsNode = relsNodes[i];
const relationship = {
target: relsNode.getAttribute("Target"),
//required
id: relsNode.getAttribute("Id"),
//required
type: relsNode.getAttribute("Type")
//required
};
relationships.push(relationship);
}
return relationships;
}
function parseMetadataNodes(metadataNodes) {
const metadataData = {};
for (let i = 0; i < metadataNodes.length; i++) {
const metadataNode = metadataNodes[i];
const name = metadataNode.getAttribute("name");
const validNames = [
"Title",
"Designer",
"Description",
"Copyright",
"LicenseTerms",
"Rating",
"CreationDate",
"ModificationDate"
];
if (0 <= validNames.indexOf(name)) {
metadataData[name] = metadataNode.textContent;
}
}
return metadataData;
}
function parseBasematerialsNode(basematerialsNode) {
const basematerialsData = {
id: basematerialsNode.getAttribute("id"),
// required
basematerials: []
};
const basematerialNodes = basematerialsNode.querySelectorAll("base");
for (let i = 0; i < basematerialNodes.length; i++) {
const basematerialNode = basematerialNodes[i];
const basematerialData = parseBasematerialNode(basematerialNode);
basematerialData.index = i;
basematerialsData.basematerials.push(basematerialData);
}
return basematerialsData;
}
function parseTexture2DNode(texture2DNode) {
const texture2dData = {
id: texture2DNode.getAttribute("id"),
// required
path: texture2DNode.getAttribute("path"),
// required
contenttype: texture2DNode.getAttribute("contenttype"),
// required
tilestyleu: texture2DNode.getAttribute("tilestyleu"),
tilestylev: texture2DNode.getAttribute("tilestylev"),
filter: texture2DNode.getAttribute("filter")
};
return texture2dData;
}
function parseTextures2DGroupNode(texture2DGroupNode) {
const texture2DGroupData = {
id: texture2DGroupNode.getAttribute("id"),
// required
texid: texture2DGroupNode.getAttribute("texid"),
// required
displaypropertiesid: texture2DGroupNode.getAttribute("displaypropertiesid")
};
const tex2coordNodes = texture2DGroupNode.querySelectorAll("tex2coord");
const uvs = [];
for (let i = 0; i < tex2coordNodes.length; i++) {
const tex2coordNode = tex2coordNodes[i];
const u = tex2coordNode.getAttribute("u");
const v = tex2coordNode.getAttribute("v");
uvs.push(parseFloat(u), parseFloat(v));
}
texture2DGroupData["uvs"] = new Float32Array(uvs);
return texture2DGroupData;
}
function parseColorGroupNode(colorGroupNode) {
const colorGroupData = {
id: colorGroupNode.getAttribute("id"),
// required
displaypropertiesid: colorGroupNode.getAttribute("displaypropertiesid")
};
const colorNodes = colorGroupNode.querySelectorAll("color");
const colors = [];
const colorObject = new THREE.Color();
for (let i = 0; i < colorNodes.length; i++) {
const colorNode = colorNodes[i];
const color = colorNode.getAttribute("color");
colorObject.setStyle(color.substring(0, 7));
colorObject.convertSRGBToLinear();
colors.push(colorObject.r, colorObject.g, colorObject.b);
}
colorGroupData["colors"] = new Float32Array(colors);
return colorGroupData;
}
function parseMetallicDisplaypropertiesNode(metallicDisplaypropetiesNode) {
const metallicDisplaypropertiesData = {
id: metallicDisplaypropetiesNode.getAttribute("id")
// required
};
const metallicNodes = metallicDisplaypropetiesNode.querySelectorAll("pbmetallic");
const metallicData = [];
for (let i = 0; i < metallicNodes.length; i++) {
const metallicNode = metallicNodes[i];
metallicData.push({
name: metallicNode.getAttribute("name"),
// required
metallicness: parseFloat(metallicNode.getAttribute("metallicness")),
// required
roughness: parseFloat(metallicNode.getAttribute("roughness"))
// required
});
}
metallicDisplaypropertiesData.data = metallicData;
return metallicDisplaypropertiesData;
}
function parseBasematerialNode(basematerialNode) {
const basematerialData = {};
basematerialData["name"] = basematerialNode.getAttribute("name");
basematerialData["displaycolor"] = basematerialNode.getAttribute("displaycolor");
basematerialData["displaypropertiesid"] = basematerialNode.getAttribute("displaypropertiesid");
return basematerialData;
}
function parseMeshNode(meshNode) {
const meshData = {};
const vertices = [];
const vertexNodes = meshNode.querySelectorAll("vertices vertex");
for (let i = 0; i < vertexNodes.length; i++) {
const vertexNode = vertexNodes[i];
const x = vertexNode.getAttribute("x");
const y = vertexNode.getAttribute("y");
const z = vertexNode.getAttribute("z");
vertices.push(parseFloat(x), parseFloat(y), parseFloat(z));
}
meshData["vertices"] = new Float32Array(vertices);
const triangleProperties = [];
const triangles = [];
const triangleNodes = meshNode.querySelectorAll("triangles triangle");
for (let i = 0; i < triangleNodes.length; i++) {
const triangleNode = triangleNodes[i];
const v1 = triangleNode.getAttribute("v1");
const v2 = triangleNode.getAttribute("v2");
const v3 = triangleNode.getAttribute("v3");
const p1 = triangleNode.getAttribute("p1");
const p2 = triangleNode.getAttribute("p2");
const p3 = triangleNode.getAttribute("p3");
const pid = triangleNode.getAttribute("pid");
const triangleProperty = {};
triangleProperty["v1"] = parseInt(v1, 10);
triangleProperty["v2"] = parseInt(v2, 10);
triangleProperty["v3"] = parseInt(v3, 10);
triangles.push(triangleProperty["v1"], triangleProperty["v2"], triangleProperty["v3"]);
if (p1) {
triangleProperty["p1"] = parseInt(p1, 10);
}
if (p2) {
triangleProperty["p2"] = parseInt(p2, 10);
}
if (p3) {
triangleProperty["p3"] = parseInt(p3, 10);
}
if (pid) {
triangleProperty["pid"] = pid;
}
if (0 < Object.keys(triangleProperty).length) {
triangleProperties.push(triangleProperty);
}
}
meshData["triangleProperties"] = triangleProperties;
meshData["triangles"] = new Uint32Array(triangles);
return meshData;
}
function parseComponentsNode(componentsNode) {
const components = [];
const componentNodes = componentsNode.querySelectorAll("component");
for (let i = 0; i < componentNodes.length; i++) {
const componentNode = componentNodes[i];
const componentData = parseComponentNode(componentNode);
components.push(componentData);
}
return components;
}
function parseComponentNode(componentNode) {
const componentData = {};
componentData["objectId"] = componentNode.getAttribute("objectid");
const transform = componentNode.getAttribute("transform");
if (transform) {
componentData["transform"] = parseTransform(transform);
}
return componentData;
}
function parseTransform(transform) {
const t = [];
transform.split(" ").forEach(function(s) {
t.push(parseFloat(s));
});
const matrix = new THREE.Matrix4();
matrix.set(t[0], t[3], t[6], t[9], t[1], t[4], t[7], t[10], t[2], t[5], t[8], t[11], 0, 0, 0, 1);
return matrix;
}
function parseObjectNode(objectNode) {
const objectData = {
type: objectNode.getAttribute("type")
};
const id = objectNode.getAttribute("id");
if (id) {
objectData["id"] = id;
}
const pid = objectNode.getAttribute("pid");
if (pid) {
objectData["pid"] = pid;
}
const pindex = objectNode.getAttribute("pindex");
if (pindex) {
objectData["pindex"] = pindex;
}
const thumbnail = objectNode.getAttribute("thumbnail");
if (thumbnail) {
objectData["thumbnail"] = thumbnail;
}
const partnumber = objectNode.getAttribute("partnumber");
if (partnumber) {
objectData["partnumber"] = partnumber;
}
const name = objectNode.getAttribute("name");
if (name) {
objectData["name"] = name;
}
const meshNode = objectNode.querySelector("mesh");
if (meshNode) {
objectData["mesh"] = parseMeshNode(meshNode);
}
const componentsNode = objectNode.querySelector("components");
if (componentsNode) {
objectData["components"] = parseComponentsNode(componentsNode);
}
return objectData;
}
function parseResourcesNode(resourcesNode) {
const resourcesData = {};
resourcesData["basematerials"] = {};
const basematerialsNodes = resourcesNode.querySelectorAll("basematerials");
for (let i = 0; i < basematerialsNodes.length; i++) {
const basematerialsNode = basematerialsNodes[i];
const basematerialsData = parseBasematerialsNode(basematerialsNode);
resourcesData["basematerials"][basematerialsData["id"]] = basematerialsData;
}
resourcesData["texture2d"] = {};
const textures2DNodes = resourcesNode.querySelectorAll("texture2d");
for (let i = 0; i < textures2DNodes.length; i++) {
const textures2DNode = textures2DNodes[i];
const texture2DData = parseTexture2DNode(textures2DNode);
resourcesData["texture2d"][texture2DData["id"]] = texture2DData;
}
resourcesData["colorgroup"] = {};
const colorGroupNodes = resourcesNode.querySelectorAll("colorgroup");
for (let i = 0; i < colorGroupNodes.length; i++) {
const colorGroupNode = colorGroupNodes[i];
const colorGroupData = parseColorGroupNode(colorGroupNode);
resourcesData["colorgroup"][colorGroupData["id"]] = colorGroupData;
}
resourcesData["pbmetallicdisplayproperties"] = {};
const pbmetallicdisplaypropertiesNodes = resourcesNode.querySelectorAll("pbmetallicdisplayproperties");
for (let i = 0; i < pbmetallicdisplaypropertiesNodes.length; i++) {
const pbmetallicdisplaypropertiesNode = pbmetallicdisplaypropertiesNodes[i];
const pbmetallicdisplaypropertiesData = parseMetallicDisplaypropertiesNode(pbmetallicdisplaypropertiesNode);
resourcesData["pbmetallicdisplayproperties"][pbmetallicdisplaypropertiesData["id"]] = pbmetallicdisplaypropertiesData;
}
resourcesData["texture2dgroup"] = {};
const textures2DGroupNodes = resourcesNode.querySelectorAll("texture2dgroup");
for (let i = 0; i < textures2DGroupNodes.length; i++) {
const textures2DGroupNode = textures2DGroupNodes[i];
const textures2DGroupData = parseTextures2DGroupNode(textures2DGroupNode);
resourcesData["texture2dgroup"][textures2DGroupData["id"]] = textures2DGroupData;
}
resourcesData["object"] = {};
const objectNodes = resourcesNode.querySelectorAll("object");
for (let i = 0; i < objectNodes.length; i++) {
const objectNode = objectNodes[i];
const objectData = parseObjectNode(objectNode);
resourcesData["object"][objectData["id"]] = objectData;
}
return resourcesData;
}
function parseBuildNode(buildNode) {
const buildData = [];
const itemNodes = buildNode.querySelectorAll("item");
for (let i = 0; i < itemNodes.length; i++) {
const itemNode = itemNodes[i];
const buildItem = {
objectId: itemNode.getAttribute("objectid")
};
const transform = itemNode.getAttribute("transform");
if (transform) {
buildItem["transform"] = parseTransform(transform);
}
buildData.push(buildItem);
}
return buildData;
}
function parseModelNode(modelNode) {
const modelData = { unit: modelNode.getAttribute("unit") || "millimeter" };
const metadataNodes = modelNode.querySelectorAll("metadata");
if (metadataNodes) {
modelData["metadata"] = parseMetadataNodes(metadataNodes);
}
const resourcesNode = modelNode.querySelector("resources");
if (resourcesNode) {
modelData["resources"] = parseResourcesNode(resourcesNode);
}
const buildNode = modelNode.querySelector("build");
if (buildNode) {
modelData["build"] = parseBuildNode(buildNode);
}
return modelData;
}
function buildTexture(texture2dgroup, objects2, modelData, textureData) {
const texid = texture2dgroup.texid;
const texture2ds = modelData.resources.texture2d;
const texture2d = texture2ds[texid];
if (texture2d) {
const data2 = textureData[texture2d.path];
const type = texture2d.contenttype;
const blob = new Blob([data2], { type });
const sourceURI = URL.createObjectURL(blob);
const texture = textureLoader.load(sourceURI, function() {
URL.revokeObjectURL(sourceURI);
});
if ("colorSpace" in texture)
texture.colorSpace = "srgb";
else
texture.encoding = 3001;
switch (texture2d.tilestyleu) {
case "wrap":
texture.wrapS = THREE.RepeatWrapping;
break;
case "mirror":
texture.wrapS = THREE.MirroredRepeatWrapping;
break;
case "none":
case "clamp":
texture.wrapS = THREE.ClampToEdgeWrapping;
break;
default:
texture.wrapS = THREE.RepeatWrapping;
}
switch (texture2d.tilestylev) {
case "wrap":
texture.wrapT = THREE.RepeatWrapping;
break;
case "mirror":
texture.wrapT = THREE.MirroredRepeatWrapping;
break;
case "none":
case "clamp":
texture.wrapT = THREE.ClampToEdgeWrapping;
break;
default:
texture.wrapT = THREE.RepeatWrapping;
}
switch (texture2d.filter) {
case "auto":
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearMipmapLinearFilter;
break;
case "linear":
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearFilter;
break;
case "nearest":
texture.magFilter = THREE.NearestFilter;
texture.minFilter = THREE.NearestFilter;
break;
default:
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearMipmapLinearFilter;
}
return texture;
} else {
return null;
}
}
function buildBasematerialsMeshes(basematerials, triangleProperties, meshData, objects2, modelData, textureData, objectData) {
const objectPindex = objectData.pindex;
const materialMap = {};
for (let i = 0, l = triangleProperties.length; i < l; i++) {
const triangleProperty = triangleProperties[i];
const pindex = triangleProperty.p1 !== void 0 ? triangleProperty.p1 : objectPindex;
if (materialMap[pindex] === void 0)
materialMap[pindex] = [];
materialMap[pindex].push(triangleProperty);
}
const keys = Object.keys(materialMap);
const meshes = [];
for (let i = 0, l = keys.length; i < l; i++) {
const materialIndex = keys[i];
const trianglePropertiesProps = materialMap[materialIndex];
const basematerialData = basematerials.basematerials[materialIndex];
const material = getBuild(basematerialData, objects2, modelData, textureData, objectData, buildBasematerial);
const geometry = new THREE.BufferGeometry();
const positionData = [];
const vertices = meshData.vertices;
for (let j = 0, jl = trianglePropertiesProps.length; j < jl; j++) {
const triangleProperty = trianglePropertiesProps[j];
positionData.push(vertices[triangleProperty.v1 * 3 + 0]);
positionData.push(vertices[triangleProperty.v1 * 3 + 1]);
positionData.push(vertices[triangleProperty.v1 * 3 + 2]);
positionData.push(vertices[triangleProperty.v2 * 3 + 0]);
positionData.push(vertices[triangleProperty.v2 * 3 + 1]);
positionData.push(vertices[triangleProperty.v2 * 3 + 2]);
positionData.push(vertices[triangleProperty.v3 * 3 + 0]);
positionData.push(vertices[triangleProperty.v3 * 3 + 1]);
positionData.push(vertices[triangleProperty.v3 * 3 + 2]);
}
geometry.setAttribute("position", new THREE.Float32BufferAttribute(positionData, 3));
const mesh = new THREE.Mesh(geometry, material);
meshes.push(mesh);
}
return meshes;
}
function buildTexturedMesh(texture2dgroup, triangleProperties, meshData, objects2, modelData, textureData, objectData) {
const geometry = new THREE.BufferGeometry();
const positionData = [];
const uvData = [];
const vertices = meshData.vertices;
const uvs = texture2dgroup.uvs;
for (let i = 0, l = triangleProperties.length; i < l; i++) {
const triangleProperty = triangleProperties[i];
positionData.push(vertices[triangleProperty.v1 * 3 + 0]);
positionData.push(vertices[triangleProperty.v1 * 3 + 1]);
positionData.push(vertices[triangleProperty.v1 * 3 + 2]);
positionData.push(vertices[triangleProperty.v2 * 3 + 0]);
positionData.push(vertices[triangleProperty.v2 * 3 + 1]);
positionData.push(vertices[triangleProperty.v2 * 3 + 2]);
positionData.push(vertices[triangleProperty.v3 * 3 + 0]);
positionData.push(vertices[triangleProperty.v3 * 3 + 1]);
positionData.push(vertices[triangleProperty.v3 * 3 + 2]);
uvData.push(uvs[triangleProperty.p1 * 2 + 0]);
uvData.push(uvs[triangleProperty.p1 * 2 + 1]);
uvData.push(uvs[triangleProperty.p2 * 2 + 0]);
uvData.push(uvs[triangleProperty.p2 * 2 + 1]);
uvData.push(uvs[triangleProperty.p3 * 2 + 0]);
uvData.push(uvs[triangleProperty.p3 * 2 + 1]);
}
geometry.setAttribute("position", new THREE.Float32BufferAttribute(positionData, 3));
geometry.setAttribute("uv", new THREE.Float32BufferAttribute(uvData, 2));
const texture = getBuild(texture2dgroup, objects2, modelData, textureData, objectData, buildTexture);
const material = new THREE.MeshPhongMaterial({ map: texture, flatShading: true });
const mesh = new THREE.Mesh(geometry, material);
return mesh;
}
function buildVertexColorMesh(colorgroup, triangleProperties, meshData, objects2, modelData, objectData) {
const geometry = new THREE.BufferGeometry();
const positionData = [];
const colorData = [];
const vertices = meshData.vertices;
const colors = colorgroup.colors;
for (let i = 0, l = triangleProperties.length; i < l; i++) {
const triangleProperty = triangleProperties[i];
const v1 = triangleProperty.v1;
const v2 = triangleProperty.v2;
const v3 = triangleProperty.v3;
positionData.push(vertices[v1 * 3 + 0]);
positionData.push(vertices[v1 * 3 + 1]);
positionData.push(vertices[v1 * 3 + 2]);
positionData.push(vertices[v2 * 3 + 0]);
positionData.push(vertices[v2 * 3 + 1]);
positionData.push(vertices[v2 * 3 + 2]);
positionData.push(vertices[v3 * 3 + 0]);
positionData.push(vertices[v3 * 3 + 1]);
positionData.push(vertices[v3 * 3 + 2]);
const p1 = triangleProperty.p1 !== void 0 ? triangleProperty.p1 : objectData.pindex;
const p2 = triangleProperty.p2 !== void 0 ? triangleProperty.p2 : p1;
const p3 = triangleProperty.p3 !== void 0 ? triangleProperty.p3 : p1;
colorData.push(colors[p1 * 3 + 0]);
colorData.push(colors[p1 * 3 + 1]);
colorData.push(colors[p1 * 3 + 2]);
colorData.push(colors[p2 * 3 + 0]);
colorData.push(colors[p2 * 3 + 1]);
colorData.push(colors[p2 * 3 + 2]);
colorData.push(colors[p3 * 3 + 0]);
colorData.push(colors[p3 * 3 + 1]);
colorData.push(colors[p3 * 3 + 2]);
}
geometry.setAttribute("position", new THREE.Float32BufferAttribute(positionData, 3));
geometry.setAttribute("color", new THREE.Float32BufferAttribute(colorData, 3));
const material = new THREE.MeshPhongMaterial({ vertexColors: true, flatShading: true });
const mesh = new THREE.Mesh(geometry, material);
return mesh;
}
function buildDefaultMesh(meshData) {
const geometry = new THREE.BufferGeometry();
geometry.setIndex(new THREE.BufferAttribute(meshData["triangles"], 1));
geometry.setAttribute("position", new THREE.BufferAttribute(meshData["vertices"], 3));
const material = new THREE.MeshPhongMaterial({ color: 11184895, flatShading: true });
const mesh = new THREE.Mesh(geometry, material);
return mesh;
}
function buildMeshes(resourceMap, meshData, objects2, modelData, textureData, objectData) {
const keys = Object.keys(resourceMap);
const meshes = [];
for (let i = 0, il = keys.length; i < il; i++) {
const resourceId = keys[i];
const triangleProperties = resourceMap[resourceId];
const resourceType = getResourceType(resourceId, modelData);
switch (resourceType) {
case "material":
const basematerials = modelData.resources.basematerials[resourceId];
const newMeshes = buildBasematerialsMeshes(
basematerials,
triangleProperties,
meshData,
objects2,
modelData,
textureData,
objectData
);
for (let j = 0, jl = newMeshes.length; j < jl; j++) {
meshes.push(newMeshes[j]);
}
break;
case "texture":
const texture2dgroup = modelData.resources.texture2dgroup[resourceId];
meshes.push(
buildTexturedMesh(
texture2dgroup,
triangleProperties,
meshData,
objects2,
modelData,
textureData,
objectData
)
);
break;
case "vertexColors":
const colorgroup = modelData.resources.colorgroup[resourceId];
meshes.push(buildVertexColorMesh(colorgroup, triangleProperties, meshData, objects2, modelData, objectData));
break;
case "default":
meshes.push(buildDefaultMesh(meshData));
break;
default:
console.error("THREE.3MFLoader: Unsupported resource type.");
}
}
return meshes;
}
function getResourceType(pid, modelData) {
if (modelData.resources.texture2dgroup[pid] !== void 0) {
return "texture";
} else if (modelData.resources.basematerials[pid] !== void 0) {
return "material";
} else if (modelData.resources.colorgroup[pid] !== void 0) {
return "vertexColors";
} else if (pid === "default") {
return "default";
} else {
return void 0;
}
}
function analyzeObject(modelData, meshData, objectData) {
const resourceMap = {};
const triangleProperties = meshData["triangleProperties"];
const objectPid = objectData.pid;
for (let i = 0, l = triangleProperties.length; i < l; i++) {
const triangleProperty = triangleProperties[i];
let pid = triangleProperty.pid !== void 0 ? triangleProperty.pid : objectPid;
if (pid === void 0)
pid = "default";
if (resourceMap[pid] === void 0)
resourceMap[pid] = [];
resourceMap[pid].push(triangleProperty);
}
return resourceMap;
}
function buildGroup(meshData, objects2, modelData, textureData, objectData) {
const group = new THREE.Group();
const resourceMap = analyzeObject(modelData, meshData, objectData);
const meshes = buildMeshes(resourceMap, meshData, objects2, modelData, textureData, objectData);
for (let i = 0, l = meshes.length; i < l; i++) {
group.add(meshes[i]);
}
return group;
}
function applyExtensions(extensions, meshData, modelXml) {
if (!extensions) {
return;
}
const availableExtensions = [];
const keys = Object.keys(extensions);
for (let i = 0; i < keys.length; i++) {
const ns = keys[i];
for (let j = 0; j < scope.availableExtensions.length; j++) {
const extension = scope.availableExtensions[j];
if (extension.ns === ns) {
availableExtensions.push(extension);
}
}
}
for (let i = 0; i < availableExtensions.length; i++) {
const extension = availableExtensions[i];
extension.apply(modelXml, extensions[extension["ns"]], meshData);
}
}
function getBuild(data2, objects2, modelData, textureData, objectData, builder) {
if (data2.build !== void 0)
return data2.build;
data2.build = builder(data2, objects2, modelData, textureData, objectData);
return data2.build;
}
function buildBasematerial(materialData, objects2, modelData) {
let material;
const displaypropertiesid = materialData.displaypropertiesid;
const pbmetallicdisplayproperties = modelData.resources.pbmetallicdisplayproperties;
if (displaypropertiesid !== null && pbmetallicdisplayproperties[displaypropertiesid] !== void 0) {
const pbmetallicdisplayproperty = pbmetallicdisplayproperties[displaypropertiesid];
const metallicData = pbmetallicdisplayproperty.data[materialData.index];
material = new THREE.MeshStandardMaterial({
flatShading: true,
roughness: metallicData.roughness,
metalness: metallicData.metallicness
});
} else {
material = new THREE.MeshPhongMaterial({ flatShading: true });
}
material.name = materialData.name;
const displaycolor = materialData.displaycolor;
const color = displaycolor.substring(0, 7);
material.color.setStyle(color);
material.color.convertSRGBToLinear();
if (displaycolor.length === 9) {
material.opacity = parseInt(displaycolor.charAt(7) + displaycolor.charAt(8), 16) / 255;
}
return material;
}
function buildComposite(compositeData, objects2, modelData, textureData) {
const composite = new THREE.Group();
for (let j = 0; j < compositeData.length; j++) {
const component = compositeData[j];
let build2 = objects2[component.objectId];
if (build2 === void 0) {
buildObject(component.objectId, objects2, modelData, textureData);
build2 = objects2[component.objectId];
}
const object3D = build2.clone();
const transform = component.transform;
if (transform) {
object3D.applyMatrix4(transform);
}
composite.add(object3D);
}
return composite;
}
function buildObject(objectId, objects2, modelData, textureData) {
const objectData = modelData["resources"]["object"][objectId];
if (objectData["mesh"]) {
const meshData = objectData["mesh"];
const extensions = modelData["extensions"];
const modelXml = modelData["xml"];
applyExtensions(extensions, meshData, modelXml);
objects2[objectData.id] = getBuild(meshData, objects2, modelData, textureData, objectData, buildGroup);
} else {
const compositeData = objectData["components"];
objects2[objectData.id] = getBuild(compositeData, objects2, modelData, textureData, objectData, buildComposite);
}
}
function buildObjects(data3mf2) {
const modelsData = data3mf2.model;
const modelRels = data3mf2.modelRels;
const objects2 = {};
const modelsKeys = Object.keys(modelsData);
const textureData = {};
if (modelRels) {
for (let i = 0, l = modelRels.length; i < l; i++) {
const modelRel = modelRels[i];
const textureKey = modelRel.target.substring(1);
if (data3mf2.texture[textureKey]) {
textureData[modelRel.target] = data3mf2.texture[textureKey];
}
}
}
for (let i = 0; i < modelsKeys.length; i++) {
const modelsKey = modelsKeys[i];
const modelData = modelsData[modelsKey];
const objectIds = Object.keys(modelData["resources"]["object"]);
for (let j = 0; j < objectIds.length; j++) {
const objectId = objectIds[j];
buildObject(objectId, objects2, modelData, textureData);
}
}
return objects2;
}
function fetch3DModelPart(rels) {
for (let i = 0; i < rels.length; i++) {
const rel = rels[i];
const extension = rel.target.split(".").pop();
if (extension.toLowerCase() === "model")
return rel;
}
}
function build(objects2, data3mf2) {
const group = new THREE.Group();
const relationship = fetch3DModelPart(data3mf2["rels"]);
const buildData = data3mf2.model[relationship["target"].substring(1)]["build"];
for (let i = 0; i < buildData.length; i++) {
const buildItem = buildData[i];
const object3D = objects2[buildItem["objectId"]];
const transform = buildItem["transform"];
if (transform) {
object3D.applyMatrix4(transform);
}
group.add(object3D);
}
return group;
}
const data3mf = loadDocument(data);
const objects = buildObjects(data3mf);
return build(objects, data3mf);
}
addExtension(extension) {
this.availableExtensions.push(extension);
}
}
exports.ThreeMFLoader = ThreeMFLoader;
//# sourceMappingURL=3MFLoader.cjs.map
File diff suppressed because one or more lines are too long
+16
View File
@@ -0,0 +1,16 @@
import { Loader, LoadingManager, Group } from 'three'
export class ThreeMFLoader extends Loader {
constructor(manager?: LoadingManager)
availableExtensions: object[]
load(
url: string,
onLoad: (object: Group) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Group>
parse(data: ArrayBuffer): Group
addExtension(extension: object): void
}
+853
View File
@@ -0,0 +1,853 @@
import { Loader, FileLoader, TextureLoader, Group, Color, Matrix4, BufferGeometry, Float32BufferAttribute, Mesh, MeshPhongMaterial, BufferAttribute, MeshStandardMaterial, RepeatWrapping, ClampToEdgeWrapping, MirroredRepeatWrapping, LinearFilter, LinearMipmapLinearFilter, NearestFilter } from "three";
import { unzipSync } from "fflate";
import { decodeText } from "../_polyfill/LoaderUtils.js";
class ThreeMFLoader extends Loader {
constructor(manager) {
super(manager);
this.availableExtensions = [];
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader = new FileLoader(scope.manager);
loader.setPath(scope.path);
loader.setResponseType("arraybuffer");
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
function(buffer) {
try {
onLoad(scope.parse(buffer));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(data) {
const scope = this;
const textureLoader = new TextureLoader(this.manager);
function loadDocument(data2) {
let zip = null;
let file = null;
let relsName;
let modelRelsName;
const modelPartNames = [];
const texturesPartNames = [];
let modelRels;
const modelParts = {};
const printTicketParts = {};
const texturesParts = {};
const otherParts = {};
try {
zip = unzipSync(new Uint8Array(data2));
} catch (e) {
if (e instanceof ReferenceError) {
console.error("THREE.3MFLoader: fflate missing and file is compressed.");
return null;
}
}
for (file in zip) {
if (file.match(/\_rels\/.rels$/)) {
relsName = file;
} else if (file.match(/3D\/_rels\/.*\.model\.rels$/)) {
modelRelsName = file;
} else if (file.match(/^3D\/.*\.model$/)) {
modelPartNames.push(file);
} else if (file.match(/^3D\/Metadata\/.*\.xml$/))
;
else if (file.match(/^3D\/Textures?\/.*/)) {
texturesPartNames.push(file);
} else if (file.match(/^3D\/Other\/.*/))
;
}
const relsView = zip[relsName];
const relsFileText = decodeText(relsView);
const rels = parseRelsXml(relsFileText);
if (modelRelsName) {
const relsView2 = zip[modelRelsName];
const relsFileText2 = decodeText(relsView2);
modelRels = parseRelsXml(relsFileText2);
}
for (let i = 0; i < modelPartNames.length; i++) {
const modelPart = modelPartNames[i];
const view = zip[modelPart];
const fileText = decodeText(view);
const xmlData = new DOMParser().parseFromString(fileText, "application/xml");
if (xmlData.documentElement.nodeName.toLowerCase() !== "model") {
console.error("THREE.3MFLoader: Error loading 3MF - no 3MF document found: ", modelPart);
}
const modelNode = xmlData.querySelector("model");
const extensions = {};
for (let i2 = 0; i2 < modelNode.attributes.length; i2++) {
const attr = modelNode.attributes[i2];
if (attr.name.match(/^xmlns:(.+)$/)) {
extensions[attr.value] = RegExp.$1;
}
}
const modelData = parseModelNode(modelNode);
modelData["xml"] = modelNode;
if (0 < Object.keys(extensions).length) {
modelData["extensions"] = extensions;
}
modelParts[modelPart] = modelData;
}
for (let i = 0; i < texturesPartNames.length; i++) {
const texturesPartName = texturesPartNames[i];
texturesParts[texturesPartName] = zip[texturesPartName].buffer;
}
return {
rels,
modelRels,
model: modelParts,
printTicket: printTicketParts,
texture: texturesParts,
other: otherParts
};
}
function parseRelsXml(relsFileText) {
const relationships = [];
const relsXmlData = new DOMParser().parseFromString(relsFileText, "application/xml");
const relsNodes = relsXmlData.querySelectorAll("Relationship");
for (let i = 0; i < relsNodes.length; i++) {
const relsNode = relsNodes[i];
const relationship = {
target: relsNode.getAttribute("Target"),
//required
id: relsNode.getAttribute("Id"),
//required
type: relsNode.getAttribute("Type")
//required
};
relationships.push(relationship);
}
return relationships;
}
function parseMetadataNodes(metadataNodes) {
const metadataData = {};
for (let i = 0; i < metadataNodes.length; i++) {
const metadataNode = metadataNodes[i];
const name = metadataNode.getAttribute("name");
const validNames = [
"Title",
"Designer",
"Description",
"Copyright",
"LicenseTerms",
"Rating",
"CreationDate",
"ModificationDate"
];
if (0 <= validNames.indexOf(name)) {
metadataData[name] = metadataNode.textContent;
}
}
return metadataData;
}
function parseBasematerialsNode(basematerialsNode) {
const basematerialsData = {
id: basematerialsNode.getAttribute("id"),
// required
basematerials: []
};
const basematerialNodes = basematerialsNode.querySelectorAll("base");
for (let i = 0; i < basematerialNodes.length; i++) {
const basematerialNode = basematerialNodes[i];
const basematerialData = parseBasematerialNode(basematerialNode);
basematerialData.index = i;
basematerialsData.basematerials.push(basematerialData);
}
return basematerialsData;
}
function parseTexture2DNode(texture2DNode) {
const texture2dData = {
id: texture2DNode.getAttribute("id"),
// required
path: texture2DNode.getAttribute("path"),
// required
contenttype: texture2DNode.getAttribute("contenttype"),
// required
tilestyleu: texture2DNode.getAttribute("tilestyleu"),
tilestylev: texture2DNode.getAttribute("tilestylev"),
filter: texture2DNode.getAttribute("filter")
};
return texture2dData;
}
function parseTextures2DGroupNode(texture2DGroupNode) {
const texture2DGroupData = {
id: texture2DGroupNode.getAttribute("id"),
// required
texid: texture2DGroupNode.getAttribute("texid"),
// required
displaypropertiesid: texture2DGroupNode.getAttribute("displaypropertiesid")
};
const tex2coordNodes = texture2DGroupNode.querySelectorAll("tex2coord");
const uvs = [];
for (let i = 0; i < tex2coordNodes.length; i++) {
const tex2coordNode = tex2coordNodes[i];
const u = tex2coordNode.getAttribute("u");
const v = tex2coordNode.getAttribute("v");
uvs.push(parseFloat(u), parseFloat(v));
}
texture2DGroupData["uvs"] = new Float32Array(uvs);
return texture2DGroupData;
}
function parseColorGroupNode(colorGroupNode) {
const colorGroupData = {
id: colorGroupNode.getAttribute("id"),
// required
displaypropertiesid: colorGroupNode.getAttribute("displaypropertiesid")
};
const colorNodes = colorGroupNode.querySelectorAll("color");
const colors = [];
const colorObject = new Color();
for (let i = 0; i < colorNodes.length; i++) {
const colorNode = colorNodes[i];
const color = colorNode.getAttribute("color");
colorObject.setStyle(color.substring(0, 7));
colorObject.convertSRGBToLinear();
colors.push(colorObject.r, colorObject.g, colorObject.b);
}
colorGroupData["colors"] = new Float32Array(colors);
return colorGroupData;
}
function parseMetallicDisplaypropertiesNode(metallicDisplaypropetiesNode) {
const metallicDisplaypropertiesData = {
id: metallicDisplaypropetiesNode.getAttribute("id")
// required
};
const metallicNodes = metallicDisplaypropetiesNode.querySelectorAll("pbmetallic");
const metallicData = [];
for (let i = 0; i < metallicNodes.length; i++) {
const metallicNode = metallicNodes[i];
metallicData.push({
name: metallicNode.getAttribute("name"),
// required
metallicness: parseFloat(metallicNode.getAttribute("metallicness")),
// required
roughness: parseFloat(metallicNode.getAttribute("roughness"))
// required
});
}
metallicDisplaypropertiesData.data = metallicData;
return metallicDisplaypropertiesData;
}
function parseBasematerialNode(basematerialNode) {
const basematerialData = {};
basematerialData["name"] = basematerialNode.getAttribute("name");
basematerialData["displaycolor"] = basematerialNode.getAttribute("displaycolor");
basematerialData["displaypropertiesid"] = basematerialNode.getAttribute("displaypropertiesid");
return basematerialData;
}
function parseMeshNode(meshNode) {
const meshData = {};
const vertices = [];
const vertexNodes = meshNode.querySelectorAll("vertices vertex");
for (let i = 0; i < vertexNodes.length; i++) {
const vertexNode = vertexNodes[i];
const x = vertexNode.getAttribute("x");
const y = vertexNode.getAttribute("y");
const z = vertexNode.getAttribute("z");
vertices.push(parseFloat(x), parseFloat(y), parseFloat(z));
}
meshData["vertices"] = new Float32Array(vertices);
const triangleProperties = [];
const triangles = [];
const triangleNodes = meshNode.querySelectorAll("triangles triangle");
for (let i = 0; i < triangleNodes.length; i++) {
const triangleNode = triangleNodes[i];
const v1 = triangleNode.getAttribute("v1");
const v2 = triangleNode.getAttribute("v2");
const v3 = triangleNode.getAttribute("v3");
const p1 = triangleNode.getAttribute("p1");
const p2 = triangleNode.getAttribute("p2");
const p3 = triangleNode.getAttribute("p3");
const pid = triangleNode.getAttribute("pid");
const triangleProperty = {};
triangleProperty["v1"] = parseInt(v1, 10);
triangleProperty["v2"] = parseInt(v2, 10);
triangleProperty["v3"] = parseInt(v3, 10);
triangles.push(triangleProperty["v1"], triangleProperty["v2"], triangleProperty["v3"]);
if (p1) {
triangleProperty["p1"] = parseInt(p1, 10);
}
if (p2) {
triangleProperty["p2"] = parseInt(p2, 10);
}
if (p3) {
triangleProperty["p3"] = parseInt(p3, 10);
}
if (pid) {
triangleProperty["pid"] = pid;
}
if (0 < Object.keys(triangleProperty).length) {
triangleProperties.push(triangleProperty);
}
}
meshData["triangleProperties"] = triangleProperties;
meshData["triangles"] = new Uint32Array(triangles);
return meshData;
}
function parseComponentsNode(componentsNode) {
const components = [];
const componentNodes = componentsNode.querySelectorAll("component");
for (let i = 0; i < componentNodes.length; i++) {
const componentNode = componentNodes[i];
const componentData = parseComponentNode(componentNode);
components.push(componentData);
}
return components;
}
function parseComponentNode(componentNode) {
const componentData = {};
componentData["objectId"] = componentNode.getAttribute("objectid");
const transform = componentNode.getAttribute("transform");
if (transform) {
componentData["transform"] = parseTransform(transform);
}
return componentData;
}
function parseTransform(transform) {
const t = [];
transform.split(" ").forEach(function(s) {
t.push(parseFloat(s));
});
const matrix = new Matrix4();
matrix.set(t[0], t[3], t[6], t[9], t[1], t[4], t[7], t[10], t[2], t[5], t[8], t[11], 0, 0, 0, 1);
return matrix;
}
function parseObjectNode(objectNode) {
const objectData = {
type: objectNode.getAttribute("type")
};
const id = objectNode.getAttribute("id");
if (id) {
objectData["id"] = id;
}
const pid = objectNode.getAttribute("pid");
if (pid) {
objectData["pid"] = pid;
}
const pindex = objectNode.getAttribute("pindex");
if (pindex) {
objectData["pindex"] = pindex;
}
const thumbnail = objectNode.getAttribute("thumbnail");
if (thumbnail) {
objectData["thumbnail"] = thumbnail;
}
const partnumber = objectNode.getAttribute("partnumber");
if (partnumber) {
objectData["partnumber"] = partnumber;
}
const name = objectNode.getAttribute("name");
if (name) {
objectData["name"] = name;
}
const meshNode = objectNode.querySelector("mesh");
if (meshNode) {
objectData["mesh"] = parseMeshNode(meshNode);
}
const componentsNode = objectNode.querySelector("components");
if (componentsNode) {
objectData["components"] = parseComponentsNode(componentsNode);
}
return objectData;
}
function parseResourcesNode(resourcesNode) {
const resourcesData = {};
resourcesData["basematerials"] = {};
const basematerialsNodes = resourcesNode.querySelectorAll("basematerials");
for (let i = 0; i < basematerialsNodes.length; i++) {
const basematerialsNode = basematerialsNodes[i];
const basematerialsData = parseBasematerialsNode(basematerialsNode);
resourcesData["basematerials"][basematerialsData["id"]] = basematerialsData;
}
resourcesData["texture2d"] = {};
const textures2DNodes = resourcesNode.querySelectorAll("texture2d");
for (let i = 0; i < textures2DNodes.length; i++) {
const textures2DNode = textures2DNodes[i];
const texture2DData = parseTexture2DNode(textures2DNode);
resourcesData["texture2d"][texture2DData["id"]] = texture2DData;
}
resourcesData["colorgroup"] = {};
const colorGroupNodes = resourcesNode.querySelectorAll("colorgroup");
for (let i = 0; i < colorGroupNodes.length; i++) {
const colorGroupNode = colorGroupNodes[i];
const colorGroupData = parseColorGroupNode(colorGroupNode);
resourcesData["colorgroup"][colorGroupData["id"]] = colorGroupData;
}
resourcesData["pbmetallicdisplayproperties"] = {};
const pbmetallicdisplaypropertiesNodes = resourcesNode.querySelectorAll("pbmetallicdisplayproperties");
for (let i = 0; i < pbmetallicdisplaypropertiesNodes.length; i++) {
const pbmetallicdisplaypropertiesNode = pbmetallicdisplaypropertiesNodes[i];
const pbmetallicdisplaypropertiesData = parseMetallicDisplaypropertiesNode(pbmetallicdisplaypropertiesNode);
resourcesData["pbmetallicdisplayproperties"][pbmetallicdisplaypropertiesData["id"]] = pbmetallicdisplaypropertiesData;
}
resourcesData["texture2dgroup"] = {};
const textures2DGroupNodes = resourcesNode.querySelectorAll("texture2dgroup");
for (let i = 0; i < textures2DGroupNodes.length; i++) {
const textures2DGroupNode = textures2DGroupNodes[i];
const textures2DGroupData = parseTextures2DGroupNode(textures2DGroupNode);
resourcesData["texture2dgroup"][textures2DGroupData["id"]] = textures2DGroupData;
}
resourcesData["object"] = {};
const objectNodes = resourcesNode.querySelectorAll("object");
for (let i = 0; i < objectNodes.length; i++) {
const objectNode = objectNodes[i];
const objectData = parseObjectNode(objectNode);
resourcesData["object"][objectData["id"]] = objectData;
}
return resourcesData;
}
function parseBuildNode(buildNode) {
const buildData = [];
const itemNodes = buildNode.querySelectorAll("item");
for (let i = 0; i < itemNodes.length; i++) {
const itemNode = itemNodes[i];
const buildItem = {
objectId: itemNode.getAttribute("objectid")
};
const transform = itemNode.getAttribute("transform");
if (transform) {
buildItem["transform"] = parseTransform(transform);
}
buildData.push(buildItem);
}
return buildData;
}
function parseModelNode(modelNode) {
const modelData = { unit: modelNode.getAttribute("unit") || "millimeter" };
const metadataNodes = modelNode.querySelectorAll("metadata");
if (metadataNodes) {
modelData["metadata"] = parseMetadataNodes(metadataNodes);
}
const resourcesNode = modelNode.querySelector("resources");
if (resourcesNode) {
modelData["resources"] = parseResourcesNode(resourcesNode);
}
const buildNode = modelNode.querySelector("build");
if (buildNode) {
modelData["build"] = parseBuildNode(buildNode);
}
return modelData;
}
function buildTexture(texture2dgroup, objects2, modelData, textureData) {
const texid = texture2dgroup.texid;
const texture2ds = modelData.resources.texture2d;
const texture2d = texture2ds[texid];
if (texture2d) {
const data2 = textureData[texture2d.path];
const type = texture2d.contenttype;
const blob = new Blob([data2], { type });
const sourceURI = URL.createObjectURL(blob);
const texture = textureLoader.load(sourceURI, function() {
URL.revokeObjectURL(sourceURI);
});
if ("colorSpace" in texture)
texture.colorSpace = "srgb";
else
texture.encoding = 3001;
switch (texture2d.tilestyleu) {
case "wrap":
texture.wrapS = RepeatWrapping;
break;
case "mirror":
texture.wrapS = MirroredRepeatWrapping;
break;
case "none":
case "clamp":
texture.wrapS = ClampToEdgeWrapping;
break;
default:
texture.wrapS = RepeatWrapping;
}
switch (texture2d.tilestylev) {
case "wrap":
texture.wrapT = RepeatWrapping;
break;
case "mirror":
texture.wrapT = MirroredRepeatWrapping;
break;
case "none":
case "clamp":
texture.wrapT = ClampToEdgeWrapping;
break;
default:
texture.wrapT = RepeatWrapping;
}
switch (texture2d.filter) {
case "auto":
texture.magFilter = LinearFilter;
texture.minFilter = LinearMipmapLinearFilter;
break;
case "linear":
texture.magFilter = LinearFilter;
texture.minFilter = LinearFilter;
break;
case "nearest":
texture.magFilter = NearestFilter;
texture.minFilter = NearestFilter;
break;
default:
texture.magFilter = LinearFilter;
texture.minFilter = LinearMipmapLinearFilter;
}
return texture;
} else {
return null;
}
}
function buildBasematerialsMeshes(basematerials, triangleProperties, meshData, objects2, modelData, textureData, objectData) {
const objectPindex = objectData.pindex;
const materialMap = {};
for (let i = 0, l = triangleProperties.length; i < l; i++) {
const triangleProperty = triangleProperties[i];
const pindex = triangleProperty.p1 !== void 0 ? triangleProperty.p1 : objectPindex;
if (materialMap[pindex] === void 0)
materialMap[pindex] = [];
materialMap[pindex].push(triangleProperty);
}
const keys = Object.keys(materialMap);
const meshes = [];
for (let i = 0, l = keys.length; i < l; i++) {
const materialIndex = keys[i];
const trianglePropertiesProps = materialMap[materialIndex];
const basematerialData = basematerials.basematerials[materialIndex];
const material = getBuild(basematerialData, objects2, modelData, textureData, objectData, buildBasematerial);
const geometry = new BufferGeometry();
const positionData = [];
const vertices = meshData.vertices;
for (let j = 0, jl = trianglePropertiesProps.length; j < jl; j++) {
const triangleProperty = trianglePropertiesProps[j];
positionData.push(vertices[triangleProperty.v1 * 3 + 0]);
positionData.push(vertices[triangleProperty.v1 * 3 + 1]);
positionData.push(vertices[triangleProperty.v1 * 3 + 2]);
positionData.push(vertices[triangleProperty.v2 * 3 + 0]);
positionData.push(vertices[triangleProperty.v2 * 3 + 1]);
positionData.push(vertices[triangleProperty.v2 * 3 + 2]);
positionData.push(vertices[triangleProperty.v3 * 3 + 0]);
positionData.push(vertices[triangleProperty.v3 * 3 + 1]);
positionData.push(vertices[triangleProperty.v3 * 3 + 2]);
}
geometry.setAttribute("position", new Float32BufferAttribute(positionData, 3));
const mesh = new Mesh(geometry, material);
meshes.push(mesh);
}
return meshes;
}
function buildTexturedMesh(texture2dgroup, triangleProperties, meshData, objects2, modelData, textureData, objectData) {
const geometry = new BufferGeometry();
const positionData = [];
const uvData = [];
const vertices = meshData.vertices;
const uvs = texture2dgroup.uvs;
for (let i = 0, l = triangleProperties.length; i < l; i++) {
const triangleProperty = triangleProperties[i];
positionData.push(vertices[triangleProperty.v1 * 3 + 0]);
positionData.push(vertices[triangleProperty.v1 * 3 + 1]);
positionData.push(vertices[triangleProperty.v1 * 3 + 2]);
positionData.push(vertices[triangleProperty.v2 * 3 + 0]);
positionData.push(vertices[triangleProperty.v2 * 3 + 1]);
positionData.push(vertices[triangleProperty.v2 * 3 + 2]);
positionData.push(vertices[triangleProperty.v3 * 3 + 0]);
positionData.push(vertices[triangleProperty.v3 * 3 + 1]);
positionData.push(vertices[triangleProperty.v3 * 3 + 2]);
uvData.push(uvs[triangleProperty.p1 * 2 + 0]);
uvData.push(uvs[triangleProperty.p1 * 2 + 1]);
uvData.push(uvs[triangleProperty.p2 * 2 + 0]);
uvData.push(uvs[triangleProperty.p2 * 2 + 1]);
uvData.push(uvs[triangleProperty.p3 * 2 + 0]);
uvData.push(uvs[triangleProperty.p3 * 2 + 1]);
}
geometry.setAttribute("position", new Float32BufferAttribute(positionData, 3));
geometry.setAttribute("uv", new Float32BufferAttribute(uvData, 2));
const texture = getBuild(texture2dgroup, objects2, modelData, textureData, objectData, buildTexture);
const material = new MeshPhongMaterial({ map: texture, flatShading: true });
const mesh = new Mesh(geometry, material);
return mesh;
}
function buildVertexColorMesh(colorgroup, triangleProperties, meshData, objects2, modelData, objectData) {
const geometry = new BufferGeometry();
const positionData = [];
const colorData = [];
const vertices = meshData.vertices;
const colors = colorgroup.colors;
for (let i = 0, l = triangleProperties.length; i < l; i++) {
const triangleProperty = triangleProperties[i];
const v1 = triangleProperty.v1;
const v2 = triangleProperty.v2;
const v3 = triangleProperty.v3;
positionData.push(vertices[v1 * 3 + 0]);
positionData.push(vertices[v1 * 3 + 1]);
positionData.push(vertices[v1 * 3 + 2]);
positionData.push(vertices[v2 * 3 + 0]);
positionData.push(vertices[v2 * 3 + 1]);
positionData.push(vertices[v2 * 3 + 2]);
positionData.push(vertices[v3 * 3 + 0]);
positionData.push(vertices[v3 * 3 + 1]);
positionData.push(vertices[v3 * 3 + 2]);
const p1 = triangleProperty.p1 !== void 0 ? triangleProperty.p1 : objectData.pindex;
const p2 = triangleProperty.p2 !== void 0 ? triangleProperty.p2 : p1;
const p3 = triangleProperty.p3 !== void 0 ? triangleProperty.p3 : p1;
colorData.push(colors[p1 * 3 + 0]);
colorData.push(colors[p1 * 3 + 1]);
colorData.push(colors[p1 * 3 + 2]);
colorData.push(colors[p2 * 3 + 0]);
colorData.push(colors[p2 * 3 + 1]);
colorData.push(colors[p2 * 3 + 2]);
colorData.push(colors[p3 * 3 + 0]);
colorData.push(colors[p3 * 3 + 1]);
colorData.push(colors[p3 * 3 + 2]);
}
geometry.setAttribute("position", new Float32BufferAttribute(positionData, 3));
geometry.setAttribute("color", new Float32BufferAttribute(colorData, 3));
const material = new MeshPhongMaterial({ vertexColors: true, flatShading: true });
const mesh = new Mesh(geometry, material);
return mesh;
}
function buildDefaultMesh(meshData) {
const geometry = new BufferGeometry();
geometry.setIndex(new BufferAttribute(meshData["triangles"], 1));
geometry.setAttribute("position", new BufferAttribute(meshData["vertices"], 3));
const material = new MeshPhongMaterial({ color: 11184895, flatShading: true });
const mesh = new Mesh(geometry, material);
return mesh;
}
function buildMeshes(resourceMap, meshData, objects2, modelData, textureData, objectData) {
const keys = Object.keys(resourceMap);
const meshes = [];
for (let i = 0, il = keys.length; i < il; i++) {
const resourceId = keys[i];
const triangleProperties = resourceMap[resourceId];
const resourceType = getResourceType(resourceId, modelData);
switch (resourceType) {
case "material":
const basematerials = modelData.resources.basematerials[resourceId];
const newMeshes = buildBasematerialsMeshes(
basematerials,
triangleProperties,
meshData,
objects2,
modelData,
textureData,
objectData
);
for (let j = 0, jl = newMeshes.length; j < jl; j++) {
meshes.push(newMeshes[j]);
}
break;
case "texture":
const texture2dgroup = modelData.resources.texture2dgroup[resourceId];
meshes.push(
buildTexturedMesh(
texture2dgroup,
triangleProperties,
meshData,
objects2,
modelData,
textureData,
objectData
)
);
break;
case "vertexColors":
const colorgroup = modelData.resources.colorgroup[resourceId];
meshes.push(buildVertexColorMesh(colorgroup, triangleProperties, meshData, objects2, modelData, objectData));
break;
case "default":
meshes.push(buildDefaultMesh(meshData));
break;
default:
console.error("THREE.3MFLoader: Unsupported resource type.");
}
}
return meshes;
}
function getResourceType(pid, modelData) {
if (modelData.resources.texture2dgroup[pid] !== void 0) {
return "texture";
} else if (modelData.resources.basematerials[pid] !== void 0) {
return "material";
} else if (modelData.resources.colorgroup[pid] !== void 0) {
return "vertexColors";
} else if (pid === "default") {
return "default";
} else {
return void 0;
}
}
function analyzeObject(modelData, meshData, objectData) {
const resourceMap = {};
const triangleProperties = meshData["triangleProperties"];
const objectPid = objectData.pid;
for (let i = 0, l = triangleProperties.length; i < l; i++) {
const triangleProperty = triangleProperties[i];
let pid = triangleProperty.pid !== void 0 ? triangleProperty.pid : objectPid;
if (pid === void 0)
pid = "default";
if (resourceMap[pid] === void 0)
resourceMap[pid] = [];
resourceMap[pid].push(triangleProperty);
}
return resourceMap;
}
function buildGroup(meshData, objects2, modelData, textureData, objectData) {
const group = new Group();
const resourceMap = analyzeObject(modelData, meshData, objectData);
const meshes = buildMeshes(resourceMap, meshData, objects2, modelData, textureData, objectData);
for (let i = 0, l = meshes.length; i < l; i++) {
group.add(meshes[i]);
}
return group;
}
function applyExtensions(extensions, meshData, modelXml) {
if (!extensions) {
return;
}
const availableExtensions = [];
const keys = Object.keys(extensions);
for (let i = 0; i < keys.length; i++) {
const ns = keys[i];
for (let j = 0; j < scope.availableExtensions.length; j++) {
const extension = scope.availableExtensions[j];
if (extension.ns === ns) {
availableExtensions.push(extension);
}
}
}
for (let i = 0; i < availableExtensions.length; i++) {
const extension = availableExtensions[i];
extension.apply(modelXml, extensions[extension["ns"]], meshData);
}
}
function getBuild(data2, objects2, modelData, textureData, objectData, builder) {
if (data2.build !== void 0)
return data2.build;
data2.build = builder(data2, objects2, modelData, textureData, objectData);
return data2.build;
}
function buildBasematerial(materialData, objects2, modelData) {
let material;
const displaypropertiesid = materialData.displaypropertiesid;
const pbmetallicdisplayproperties = modelData.resources.pbmetallicdisplayproperties;
if (displaypropertiesid !== null && pbmetallicdisplayproperties[displaypropertiesid] !== void 0) {
const pbmetallicdisplayproperty = pbmetallicdisplayproperties[displaypropertiesid];
const metallicData = pbmetallicdisplayproperty.data[materialData.index];
material = new MeshStandardMaterial({
flatShading: true,
roughness: metallicData.roughness,
metalness: metallicData.metallicness
});
} else {
material = new MeshPhongMaterial({ flatShading: true });
}
material.name = materialData.name;
const displaycolor = materialData.displaycolor;
const color = displaycolor.substring(0, 7);
material.color.setStyle(color);
material.color.convertSRGBToLinear();
if (displaycolor.length === 9) {
material.opacity = parseInt(displaycolor.charAt(7) + displaycolor.charAt(8), 16) / 255;
}
return material;
}
function buildComposite(compositeData, objects2, modelData, textureData) {
const composite = new Group();
for (let j = 0; j < compositeData.length; j++) {
const component = compositeData[j];
let build2 = objects2[component.objectId];
if (build2 === void 0) {
buildObject(component.objectId, objects2, modelData, textureData);
build2 = objects2[component.objectId];
}
const object3D = build2.clone();
const transform = component.transform;
if (transform) {
object3D.applyMatrix4(transform);
}
composite.add(object3D);
}
return composite;
}
function buildObject(objectId, objects2, modelData, textureData) {
const objectData = modelData["resources"]["object"][objectId];
if (objectData["mesh"]) {
const meshData = objectData["mesh"];
const extensions = modelData["extensions"];
const modelXml = modelData["xml"];
applyExtensions(extensions, meshData, modelXml);
objects2[objectData.id] = getBuild(meshData, objects2, modelData, textureData, objectData, buildGroup);
} else {
const compositeData = objectData["components"];
objects2[objectData.id] = getBuild(compositeData, objects2, modelData, textureData, objectData, buildComposite);
}
}
function buildObjects(data3mf2) {
const modelsData = data3mf2.model;
const modelRels = data3mf2.modelRels;
const objects2 = {};
const modelsKeys = Object.keys(modelsData);
const textureData = {};
if (modelRels) {
for (let i = 0, l = modelRels.length; i < l; i++) {
const modelRel = modelRels[i];
const textureKey = modelRel.target.substring(1);
if (data3mf2.texture[textureKey]) {
textureData[modelRel.target] = data3mf2.texture[textureKey];
}
}
}
for (let i = 0; i < modelsKeys.length; i++) {
const modelsKey = modelsKeys[i];
const modelData = modelsData[modelsKey];
const objectIds = Object.keys(modelData["resources"]["object"]);
for (let j = 0; j < objectIds.length; j++) {
const objectId = objectIds[j];
buildObject(objectId, objects2, modelData, textureData);
}
}
return objects2;
}
function fetch3DModelPart(rels) {
for (let i = 0; i < rels.length; i++) {
const rel = rels[i];
const extension = rel.target.split(".").pop();
if (extension.toLowerCase() === "model")
return rel;
}
}
function build(objects2, data3mf2) {
const group = new Group();
const relationship = fetch3DModelPart(data3mf2["rels"]);
const buildData = data3mf2.model[relationship["target"].substring(1)]["build"];
for (let i = 0; i < buildData.length; i++) {
const buildItem = buildData[i];
const object3D = objects2[buildItem["objectId"]];
const transform = buildItem["transform"];
if (transform) {
object3D.applyMatrix4(transform);
}
group.add(object3D);
}
return group;
}
const data3mf = loadDocument(data);
const objects = buildObjects(data3mf);
return build(objects, data3mf);
}
addExtension(extension) {
this.availableExtensions.push(extension);
}
}
export {
ThreeMFLoader
};
//# sourceMappingURL=3MFLoader.js.map
File diff suppressed because one or more lines are too long
+286
View File
@@ -0,0 +1,286 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const fflate = require("fflate");
const LoaderUtils = require("../_polyfill/LoaderUtils.cjs");
class AMFLoader extends THREE.Loader {
constructor(manager) {
super(manager);
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader = new THREE.FileLoader(scope.manager);
loader.setPath(scope.path);
loader.setResponseType("arraybuffer");
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
function(text) {
try {
onLoad(scope.parse(text));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(data) {
function loadDocument(data2) {
let view = new DataView(data2);
const magic = String.fromCharCode(view.getUint8(0), view.getUint8(1));
if (magic === "PK") {
let zip = null;
let file = null;
console.log("THREE.AMFLoader: Loading Zip");
try {
zip = fflate.unzipSync(new Uint8Array(data2));
} catch (e) {
if (e instanceof ReferenceError) {
console.log("THREE.AMFLoader: fflate missing and file is compressed.");
return null;
}
}
for (file in zip) {
if (file.toLowerCase().substr(-4) === ".amf") {
break;
}
}
console.log("THREE.AMFLoader: Trying to load file asset: " + file);
view = new DataView(zip[file].buffer);
}
const fileText = LoaderUtils.decodeText(view);
const xmlData2 = new DOMParser().parseFromString(fileText, "application/xml");
if (xmlData2.documentElement.nodeName.toLowerCase() !== "amf") {
console.log("THREE.AMFLoader: Error loading AMF - no AMF document found.");
return null;
}
return xmlData2;
}
function loadDocumentScale(node) {
let scale = 1;
let unit = "millimeter";
if (node.documentElement.attributes.unit !== void 0) {
unit = node.documentElement.attributes.unit.value.toLowerCase();
}
const scaleUnits = {
millimeter: 1,
inch: 25.4,
feet: 304.8,
meter: 1e3,
micron: 1e-3
};
if (scaleUnits[unit] !== void 0) {
scale = scaleUnits[unit];
}
console.log("THREE.AMFLoader: Unit scale: " + scale);
return scale;
}
function loadMaterials(node) {
let matName = "AMF Material";
const matId = node.attributes.id.textContent;
let color = { r: 1, g: 1, b: 1, a: 1 };
let loadedMaterial = null;
for (let i2 = 0; i2 < node.childNodes.length; i2++) {
const matChildEl = node.childNodes[i2];
if (matChildEl.nodeName === "metadata" && matChildEl.attributes.type !== void 0) {
if (matChildEl.attributes.type.value === "name") {
matName = matChildEl.textContent;
}
} else if (matChildEl.nodeName === "color") {
color = loadColor(matChildEl);
}
}
loadedMaterial = new THREE.MeshPhongMaterial({
flatShading: true,
color: new THREE.Color(color.r, color.g, color.b),
name: matName
});
if (color.a !== 1) {
loadedMaterial.transparent = true;
loadedMaterial.opacity = color.a;
}
return { id: matId, material: loadedMaterial };
}
function loadColor(node) {
const color = { r: 1, g: 1, b: 1, a: 1 };
for (let i2 = 0; i2 < node.childNodes.length; i2++) {
const matColor = node.childNodes[i2];
if (matColor.nodeName === "r") {
color.r = matColor.textContent;
} else if (matColor.nodeName === "g") {
color.g = matColor.textContent;
} else if (matColor.nodeName === "b") {
color.b = matColor.textContent;
} else if (matColor.nodeName === "a") {
color.a = matColor.textContent;
}
}
return color;
}
function loadMeshVolume(node) {
const volume = { name: "", triangles: [], materialid: null };
let currVolumeNode = node.firstElementChild;
if (node.attributes.materialid !== void 0) {
volume.materialId = node.attributes.materialid.nodeValue;
}
while (currVolumeNode) {
if (currVolumeNode.nodeName === "metadata") {
if (currVolumeNode.attributes.type !== void 0) {
if (currVolumeNode.attributes.type.value === "name") {
volume.name = currVolumeNode.textContent;
}
}
} else if (currVolumeNode.nodeName === "triangle") {
const v1 = currVolumeNode.getElementsByTagName("v1")[0].textContent;
const v2 = currVolumeNode.getElementsByTagName("v2")[0].textContent;
const v3 = currVolumeNode.getElementsByTagName("v3")[0].textContent;
volume.triangles.push(v1, v2, v3);
}
currVolumeNode = currVolumeNode.nextElementSibling;
}
return volume;
}
function loadMeshVertices(node) {
const vertArray = [];
const normalArray = [];
let currVerticesNode = node.firstElementChild;
while (currVerticesNode) {
if (currVerticesNode.nodeName === "vertex") {
let vNode = currVerticesNode.firstElementChild;
while (vNode) {
if (vNode.nodeName === "coordinates") {
const x = vNode.getElementsByTagName("x")[0].textContent;
const y = vNode.getElementsByTagName("y")[0].textContent;
const z = vNode.getElementsByTagName("z")[0].textContent;
vertArray.push(x, y, z);
} else if (vNode.nodeName === "normal") {
const nx = vNode.getElementsByTagName("nx")[0].textContent;
const ny = vNode.getElementsByTagName("ny")[0].textContent;
const nz = vNode.getElementsByTagName("nz")[0].textContent;
normalArray.push(nx, ny, nz);
}
vNode = vNode.nextElementSibling;
}
}
currVerticesNode = currVerticesNode.nextElementSibling;
}
return { vertices: vertArray, normals: normalArray };
}
function loadObject(node) {
const objId = node.attributes.id.textContent;
const loadedObject = { name: "amfobject", meshes: [] };
let currColor = null;
let currObjNode = node.firstElementChild;
while (currObjNode) {
if (currObjNode.nodeName === "metadata") {
if (currObjNode.attributes.type !== void 0) {
if (currObjNode.attributes.type.value === "name") {
loadedObject.name = currObjNode.textContent;
}
}
} else if (currObjNode.nodeName === "color") {
currColor = loadColor(currObjNode);
} else if (currObjNode.nodeName === "mesh") {
let currMeshNode = currObjNode.firstElementChild;
const mesh = { vertices: [], normals: [], volumes: [], color: currColor };
while (currMeshNode) {
if (currMeshNode.nodeName === "vertices") {
const loadedVertices = loadMeshVertices(currMeshNode);
mesh.normals = mesh.normals.concat(loadedVertices.normals);
mesh.vertices = mesh.vertices.concat(loadedVertices.vertices);
} else if (currMeshNode.nodeName === "volume") {
mesh.volumes.push(loadMeshVolume(currMeshNode));
}
currMeshNode = currMeshNode.nextElementSibling;
}
loadedObject.meshes.push(mesh);
}
currObjNode = currObjNode.nextElementSibling;
}
return { id: objId, obj: loadedObject };
}
const xmlData = loadDocument(data);
let amfName = "";
let amfAuthor = "";
const amfScale = loadDocumentScale(xmlData);
const amfMaterials = {};
const amfObjects = {};
const childNodes = xmlData.documentElement.childNodes;
let i, j;
for (i = 0; i < childNodes.length; i++) {
const child = childNodes[i];
if (child.nodeName === "metadata") {
if (child.attributes.type !== void 0) {
if (child.attributes.type.value === "name") {
amfName = child.textContent;
} else if (child.attributes.type.value === "author") {
amfAuthor = child.textContent;
}
}
} else if (child.nodeName === "material") {
const loadedMaterial = loadMaterials(child);
amfMaterials[loadedMaterial.id] = loadedMaterial.material;
} else if (child.nodeName === "object") {
const loadedObject = loadObject(child);
amfObjects[loadedObject.id] = loadedObject.obj;
}
}
const sceneObject = new THREE.Group();
const defaultMaterial = new THREE.MeshPhongMaterial({ color: 11184895, flatShading: true });
sceneObject.name = amfName;
sceneObject.userData.author = amfAuthor;
sceneObject.userData.loader = "AMF";
for (const id in amfObjects) {
const part = amfObjects[id];
const meshes = part.meshes;
const newObject = new THREE.Group();
newObject.name = part.name || "";
for (i = 0; i < meshes.length; i++) {
let objDefaultMaterial = defaultMaterial;
const mesh = meshes[i];
const vertices = new THREE.Float32BufferAttribute(mesh.vertices, 3);
let normals = null;
if (mesh.normals.length) {
normals = new THREE.Float32BufferAttribute(mesh.normals, 3);
}
if (mesh.color) {
const color = mesh.color;
objDefaultMaterial = defaultMaterial.clone();
objDefaultMaterial.color = new THREE.Color(color.r, color.g, color.b);
if (color.a !== 1) {
objDefaultMaterial.transparent = true;
objDefaultMaterial.opacity = color.a;
}
}
const volumes = mesh.volumes;
for (j = 0; j < volumes.length; j++) {
const volume = volumes[j];
const newGeometry = new THREE.BufferGeometry();
let material = objDefaultMaterial;
newGeometry.setIndex(volume.triangles);
newGeometry.setAttribute("position", vertices.clone());
if (normals) {
newGeometry.setAttribute("normal", normals.clone());
}
if (amfMaterials[volume.materialId] !== void 0) {
material = amfMaterials[volume.materialId];
}
newGeometry.scale(amfScale, amfScale, amfScale);
newObject.add(new THREE.Mesh(newGeometry, material.clone()));
}
}
sceneObject.add(newObject);
}
return sceneObject;
}
}
exports.AMFLoader = AMFLoader;
//# sourceMappingURL=AMFLoader.cjs.map
File diff suppressed because one or more lines are too long
+14
View File
@@ -0,0 +1,14 @@
import { Loader, LoadingManager, Group } from 'three'
export class AMFLoader extends Loader {
constructor(manager?: LoadingManager)
load(
url: string,
onLoad: (object: Group) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Group>
parse(data: ArrayBuffer): Group
}
+286
View File
@@ -0,0 +1,286 @@
import { Loader, FileLoader, Group, MeshPhongMaterial, Float32BufferAttribute, Color, BufferGeometry, Mesh } from "three";
import { unzipSync } from "fflate";
import { decodeText } from "../_polyfill/LoaderUtils.js";
class AMFLoader extends Loader {
constructor(manager) {
super(manager);
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader = new FileLoader(scope.manager);
loader.setPath(scope.path);
loader.setResponseType("arraybuffer");
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
function(text) {
try {
onLoad(scope.parse(text));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(data) {
function loadDocument(data2) {
let view = new DataView(data2);
const magic = String.fromCharCode(view.getUint8(0), view.getUint8(1));
if (magic === "PK") {
let zip = null;
let file = null;
console.log("THREE.AMFLoader: Loading Zip");
try {
zip = unzipSync(new Uint8Array(data2));
} catch (e) {
if (e instanceof ReferenceError) {
console.log("THREE.AMFLoader: fflate missing and file is compressed.");
return null;
}
}
for (file in zip) {
if (file.toLowerCase().substr(-4) === ".amf") {
break;
}
}
console.log("THREE.AMFLoader: Trying to load file asset: " + file);
view = new DataView(zip[file].buffer);
}
const fileText = decodeText(view);
const xmlData2 = new DOMParser().parseFromString(fileText, "application/xml");
if (xmlData2.documentElement.nodeName.toLowerCase() !== "amf") {
console.log("THREE.AMFLoader: Error loading AMF - no AMF document found.");
return null;
}
return xmlData2;
}
function loadDocumentScale(node) {
let scale = 1;
let unit = "millimeter";
if (node.documentElement.attributes.unit !== void 0) {
unit = node.documentElement.attributes.unit.value.toLowerCase();
}
const scaleUnits = {
millimeter: 1,
inch: 25.4,
feet: 304.8,
meter: 1e3,
micron: 1e-3
};
if (scaleUnits[unit] !== void 0) {
scale = scaleUnits[unit];
}
console.log("THREE.AMFLoader: Unit scale: " + scale);
return scale;
}
function loadMaterials(node) {
let matName = "AMF Material";
const matId = node.attributes.id.textContent;
let color = { r: 1, g: 1, b: 1, a: 1 };
let loadedMaterial = null;
for (let i2 = 0; i2 < node.childNodes.length; i2++) {
const matChildEl = node.childNodes[i2];
if (matChildEl.nodeName === "metadata" && matChildEl.attributes.type !== void 0) {
if (matChildEl.attributes.type.value === "name") {
matName = matChildEl.textContent;
}
} else if (matChildEl.nodeName === "color") {
color = loadColor(matChildEl);
}
}
loadedMaterial = new MeshPhongMaterial({
flatShading: true,
color: new Color(color.r, color.g, color.b),
name: matName
});
if (color.a !== 1) {
loadedMaterial.transparent = true;
loadedMaterial.opacity = color.a;
}
return { id: matId, material: loadedMaterial };
}
function loadColor(node) {
const color = { r: 1, g: 1, b: 1, a: 1 };
for (let i2 = 0; i2 < node.childNodes.length; i2++) {
const matColor = node.childNodes[i2];
if (matColor.nodeName === "r") {
color.r = matColor.textContent;
} else if (matColor.nodeName === "g") {
color.g = matColor.textContent;
} else if (matColor.nodeName === "b") {
color.b = matColor.textContent;
} else if (matColor.nodeName === "a") {
color.a = matColor.textContent;
}
}
return color;
}
function loadMeshVolume(node) {
const volume = { name: "", triangles: [], materialid: null };
let currVolumeNode = node.firstElementChild;
if (node.attributes.materialid !== void 0) {
volume.materialId = node.attributes.materialid.nodeValue;
}
while (currVolumeNode) {
if (currVolumeNode.nodeName === "metadata") {
if (currVolumeNode.attributes.type !== void 0) {
if (currVolumeNode.attributes.type.value === "name") {
volume.name = currVolumeNode.textContent;
}
}
} else if (currVolumeNode.nodeName === "triangle") {
const v1 = currVolumeNode.getElementsByTagName("v1")[0].textContent;
const v2 = currVolumeNode.getElementsByTagName("v2")[0].textContent;
const v3 = currVolumeNode.getElementsByTagName("v3")[0].textContent;
volume.triangles.push(v1, v2, v3);
}
currVolumeNode = currVolumeNode.nextElementSibling;
}
return volume;
}
function loadMeshVertices(node) {
const vertArray = [];
const normalArray = [];
let currVerticesNode = node.firstElementChild;
while (currVerticesNode) {
if (currVerticesNode.nodeName === "vertex") {
let vNode = currVerticesNode.firstElementChild;
while (vNode) {
if (vNode.nodeName === "coordinates") {
const x = vNode.getElementsByTagName("x")[0].textContent;
const y = vNode.getElementsByTagName("y")[0].textContent;
const z = vNode.getElementsByTagName("z")[0].textContent;
vertArray.push(x, y, z);
} else if (vNode.nodeName === "normal") {
const nx = vNode.getElementsByTagName("nx")[0].textContent;
const ny = vNode.getElementsByTagName("ny")[0].textContent;
const nz = vNode.getElementsByTagName("nz")[0].textContent;
normalArray.push(nx, ny, nz);
}
vNode = vNode.nextElementSibling;
}
}
currVerticesNode = currVerticesNode.nextElementSibling;
}
return { vertices: vertArray, normals: normalArray };
}
function loadObject(node) {
const objId = node.attributes.id.textContent;
const loadedObject = { name: "amfobject", meshes: [] };
let currColor = null;
let currObjNode = node.firstElementChild;
while (currObjNode) {
if (currObjNode.nodeName === "metadata") {
if (currObjNode.attributes.type !== void 0) {
if (currObjNode.attributes.type.value === "name") {
loadedObject.name = currObjNode.textContent;
}
}
} else if (currObjNode.nodeName === "color") {
currColor = loadColor(currObjNode);
} else if (currObjNode.nodeName === "mesh") {
let currMeshNode = currObjNode.firstElementChild;
const mesh = { vertices: [], normals: [], volumes: [], color: currColor };
while (currMeshNode) {
if (currMeshNode.nodeName === "vertices") {
const loadedVertices = loadMeshVertices(currMeshNode);
mesh.normals = mesh.normals.concat(loadedVertices.normals);
mesh.vertices = mesh.vertices.concat(loadedVertices.vertices);
} else if (currMeshNode.nodeName === "volume") {
mesh.volumes.push(loadMeshVolume(currMeshNode));
}
currMeshNode = currMeshNode.nextElementSibling;
}
loadedObject.meshes.push(mesh);
}
currObjNode = currObjNode.nextElementSibling;
}
return { id: objId, obj: loadedObject };
}
const xmlData = loadDocument(data);
let amfName = "";
let amfAuthor = "";
const amfScale = loadDocumentScale(xmlData);
const amfMaterials = {};
const amfObjects = {};
const childNodes = xmlData.documentElement.childNodes;
let i, j;
for (i = 0; i < childNodes.length; i++) {
const child = childNodes[i];
if (child.nodeName === "metadata") {
if (child.attributes.type !== void 0) {
if (child.attributes.type.value === "name") {
amfName = child.textContent;
} else if (child.attributes.type.value === "author") {
amfAuthor = child.textContent;
}
}
} else if (child.nodeName === "material") {
const loadedMaterial = loadMaterials(child);
amfMaterials[loadedMaterial.id] = loadedMaterial.material;
} else if (child.nodeName === "object") {
const loadedObject = loadObject(child);
amfObjects[loadedObject.id] = loadedObject.obj;
}
}
const sceneObject = new Group();
const defaultMaterial = new MeshPhongMaterial({ color: 11184895, flatShading: true });
sceneObject.name = amfName;
sceneObject.userData.author = amfAuthor;
sceneObject.userData.loader = "AMF";
for (const id in amfObjects) {
const part = amfObjects[id];
const meshes = part.meshes;
const newObject = new Group();
newObject.name = part.name || "";
for (i = 0; i < meshes.length; i++) {
let objDefaultMaterial = defaultMaterial;
const mesh = meshes[i];
const vertices = new Float32BufferAttribute(mesh.vertices, 3);
let normals = null;
if (mesh.normals.length) {
normals = new Float32BufferAttribute(mesh.normals, 3);
}
if (mesh.color) {
const color = mesh.color;
objDefaultMaterial = defaultMaterial.clone();
objDefaultMaterial.color = new Color(color.r, color.g, color.b);
if (color.a !== 1) {
objDefaultMaterial.transparent = true;
objDefaultMaterial.opacity = color.a;
}
}
const volumes = mesh.volumes;
for (j = 0; j < volumes.length; j++) {
const volume = volumes[j];
const newGeometry = new BufferGeometry();
let material = objDefaultMaterial;
newGeometry.setIndex(volume.triangles);
newGeometry.setAttribute("position", vertices.clone());
if (normals) {
newGeometry.setAttribute("normal", normals.clone());
}
if (amfMaterials[volume.materialId] !== void 0) {
material = amfMaterials[volume.materialId];
}
newGeometry.scale(amfScale, amfScale, amfScale);
newObject.add(new Mesh(newGeometry, material.clone()));
}
}
sceneObject.add(newObject);
}
return sceneObject;
}
}
export {
AMFLoader
};
//# sourceMappingURL=AMFLoader.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+19
View File
@@ -0,0 +1,19 @@
import { Loader, Object3D, LoadingManager } from 'three'
export interface Assimp {
animation: any
object: Object3D
}
export class AssimpLoader extends Loader {
constructor(manager?: LoadingManager)
load(
url: string,
onLoad: (result: Assimp) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Assimp>
parse(buffer: ArrayBuffer, path: string): Assimp
}
+1435
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+208
View File
@@ -0,0 +1,208 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
class BVHLoader extends THREE.Loader {
constructor(manager) {
super(manager);
this.animateBonePositions = true;
this.animateBoneRotations = true;
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader = new THREE.FileLoader(scope.manager);
loader.setPath(scope.path);
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
function(text) {
try {
onLoad(scope.parse(text));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(text) {
function readBvh(lines2) {
if (nextLine(lines2) !== "HIERARCHY") {
console.error("THREE.BVHLoader: HIERARCHY expected.");
}
const list = [];
const root = readNode(lines2, nextLine(lines2), list);
if (nextLine(lines2) !== "MOTION") {
console.error("THREE.BVHLoader: MOTION expected.");
}
let tokens = nextLine(lines2).split(/[\s]+/);
const numFrames = parseInt(tokens[1]);
if (isNaN(numFrames)) {
console.error("THREE.BVHLoader: Failed to read number of frames.");
}
tokens = nextLine(lines2).split(/[\s]+/);
const frameTime = parseFloat(tokens[2]);
if (isNaN(frameTime)) {
console.error("THREE.BVHLoader: Failed to read frame time.");
}
for (let i = 0; i < numFrames; i++) {
tokens = nextLine(lines2).split(/[\s]+/);
readFrameData(tokens, i * frameTime, root);
}
return list;
}
function readFrameData(data, frameTime, bone) {
if (bone.type === "ENDSITE")
return;
const keyframe = {
time: frameTime,
position: new THREE.Vector3(),
rotation: new THREE.Quaternion()
};
bone.frames.push(keyframe);
const quat = new THREE.Quaternion();
const vx = new THREE.Vector3(1, 0, 0);
const vy = new THREE.Vector3(0, 1, 0);
const vz = new THREE.Vector3(0, 0, 1);
for (let i = 0; i < bone.channels.length; i++) {
switch (bone.channels[i]) {
case "Xposition":
keyframe.position.x = parseFloat(data.shift().trim());
break;
case "Yposition":
keyframe.position.y = parseFloat(data.shift().trim());
break;
case "Zposition":
keyframe.position.z = parseFloat(data.shift().trim());
break;
case "Xrotation":
quat.setFromAxisAngle(vx, parseFloat(data.shift().trim()) * Math.PI / 180);
keyframe.rotation.multiply(quat);
break;
case "Yrotation":
quat.setFromAxisAngle(vy, parseFloat(data.shift().trim()) * Math.PI / 180);
keyframe.rotation.multiply(quat);
break;
case "Zrotation":
quat.setFromAxisAngle(vz, parseFloat(data.shift().trim()) * Math.PI / 180);
keyframe.rotation.multiply(quat);
break;
default:
console.warn("THREE.BVHLoader: Invalid channel type.");
}
}
for (let i = 0; i < bone.children.length; i++) {
readFrameData(data, frameTime, bone.children[i]);
}
}
function readNode(lines2, firstline, list) {
const node = { name: "", type: "", frames: [] };
list.push(node);
let tokens = firstline.split(/[\s]+/);
if (tokens[0].toUpperCase() === "END" && tokens[1].toUpperCase() === "SITE") {
node.type = "ENDSITE";
node.name = "ENDSITE";
} else {
node.name = tokens[1];
node.type = tokens[0].toUpperCase();
}
if (nextLine(lines2) !== "{") {
console.error("THREE.BVHLoader: Expected opening { after type & name");
}
tokens = nextLine(lines2).split(/[\s]+/);
if (tokens[0] !== "OFFSET") {
console.error("THREE.BVHLoader: Expected OFFSET but got: " + tokens[0]);
}
if (tokens.length !== 4) {
console.error("THREE.BVHLoader: Invalid number of values for OFFSET.");
}
const offset = new THREE.Vector3(parseFloat(tokens[1]), parseFloat(tokens[2]), parseFloat(tokens[3]));
if (isNaN(offset.x) || isNaN(offset.y) || isNaN(offset.z)) {
console.error("THREE.BVHLoader: Invalid values of OFFSET.");
}
node.offset = offset;
if (node.type !== "ENDSITE") {
tokens = nextLine(lines2).split(/[\s]+/);
if (tokens[0] !== "CHANNELS") {
console.error("THREE.BVHLoader: Expected CHANNELS definition.");
}
const numChannels = parseInt(tokens[1]);
node.channels = tokens.splice(2, numChannels);
node.children = [];
}
while (true) {
const line = nextLine(lines2);
if (line === "}") {
return node;
} else {
node.children.push(readNode(lines2, line, list));
}
}
}
function toTHREEBone(source, list) {
const bone = new THREE.Bone();
list.push(bone);
bone.position.add(source.offset);
bone.name = source.name;
if (source.type !== "ENDSITE") {
for (let i = 0; i < source.children.length; i++) {
bone.add(toTHREEBone(source.children[i], list));
}
}
return bone;
}
function toTHREEAnimation(bones2) {
const tracks = [];
for (let i = 0; i < bones2.length; i++) {
const bone = bones2[i];
if (bone.type === "ENDSITE")
continue;
const times = [];
const positions = [];
const rotations = [];
for (let j = 0; j < bone.frames.length; j++) {
const frame = bone.frames[j];
times.push(frame.time);
positions.push(frame.position.x + bone.offset.x);
positions.push(frame.position.y + bone.offset.y);
positions.push(frame.position.z + bone.offset.z);
rotations.push(frame.rotation.x);
rotations.push(frame.rotation.y);
rotations.push(frame.rotation.z);
rotations.push(frame.rotation.w);
}
if (scope.animateBonePositions) {
tracks.push(new THREE.VectorKeyframeTrack(".bones[" + bone.name + "].position", times, positions));
}
if (scope.animateBoneRotations) {
tracks.push(new THREE.QuaternionKeyframeTrack(".bones[" + bone.name + "].quaternion", times, rotations));
}
}
return new THREE.AnimationClip("animation", -1, tracks);
}
function nextLine(lines2) {
let line;
while ((line = lines2.shift().trim()).length === 0) {
}
return line;
}
const scope = this;
const lines = text.split(/[\r\n]+/g);
const bones = readBvh(lines);
const threeBones = [];
toTHREEBone(bones[0], threeBones);
const threeClip = toTHREEAnimation(bones);
return {
skeleton: new THREE.Skeleton(threeBones),
clip: threeClip
};
}
}
exports.BVHLoader = BVHLoader;
//# sourceMappingURL=BVHLoader.cjs.map
File diff suppressed because one or more lines are too long
+21
View File
@@ -0,0 +1,21 @@
import { Loader, AnimationClip, Skeleton, LoadingManager } from 'three'
export interface BVH {
clip: AnimationClip
skeleton: Skeleton
}
export class BVHLoader extends Loader {
constructor(manager?: LoadingManager)
animateBonePositions: boolean
animateBoneRotations: boolean
load(
url: string,
onLoad: (bvh: BVH) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<BVH>
parse(text: string): BVH
}
+208
View File
@@ -0,0 +1,208 @@
import { Loader, FileLoader, Skeleton, Vector3, Quaternion, Bone, VectorKeyframeTrack, QuaternionKeyframeTrack, AnimationClip } from "three";
class BVHLoader extends Loader {
constructor(manager) {
super(manager);
this.animateBonePositions = true;
this.animateBoneRotations = true;
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader = new FileLoader(scope.manager);
loader.setPath(scope.path);
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
function(text) {
try {
onLoad(scope.parse(text));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(text) {
function readBvh(lines2) {
if (nextLine(lines2) !== "HIERARCHY") {
console.error("THREE.BVHLoader: HIERARCHY expected.");
}
const list = [];
const root = readNode(lines2, nextLine(lines2), list);
if (nextLine(lines2) !== "MOTION") {
console.error("THREE.BVHLoader: MOTION expected.");
}
let tokens = nextLine(lines2).split(/[\s]+/);
const numFrames = parseInt(tokens[1]);
if (isNaN(numFrames)) {
console.error("THREE.BVHLoader: Failed to read number of frames.");
}
tokens = nextLine(lines2).split(/[\s]+/);
const frameTime = parseFloat(tokens[2]);
if (isNaN(frameTime)) {
console.error("THREE.BVHLoader: Failed to read frame time.");
}
for (let i = 0; i < numFrames; i++) {
tokens = nextLine(lines2).split(/[\s]+/);
readFrameData(tokens, i * frameTime, root);
}
return list;
}
function readFrameData(data, frameTime, bone) {
if (bone.type === "ENDSITE")
return;
const keyframe = {
time: frameTime,
position: new Vector3(),
rotation: new Quaternion()
};
bone.frames.push(keyframe);
const quat = new Quaternion();
const vx = new Vector3(1, 0, 0);
const vy = new Vector3(0, 1, 0);
const vz = new Vector3(0, 0, 1);
for (let i = 0; i < bone.channels.length; i++) {
switch (bone.channels[i]) {
case "Xposition":
keyframe.position.x = parseFloat(data.shift().trim());
break;
case "Yposition":
keyframe.position.y = parseFloat(data.shift().trim());
break;
case "Zposition":
keyframe.position.z = parseFloat(data.shift().trim());
break;
case "Xrotation":
quat.setFromAxisAngle(vx, parseFloat(data.shift().trim()) * Math.PI / 180);
keyframe.rotation.multiply(quat);
break;
case "Yrotation":
quat.setFromAxisAngle(vy, parseFloat(data.shift().trim()) * Math.PI / 180);
keyframe.rotation.multiply(quat);
break;
case "Zrotation":
quat.setFromAxisAngle(vz, parseFloat(data.shift().trim()) * Math.PI / 180);
keyframe.rotation.multiply(quat);
break;
default:
console.warn("THREE.BVHLoader: Invalid channel type.");
}
}
for (let i = 0; i < bone.children.length; i++) {
readFrameData(data, frameTime, bone.children[i]);
}
}
function readNode(lines2, firstline, list) {
const node = { name: "", type: "", frames: [] };
list.push(node);
let tokens = firstline.split(/[\s]+/);
if (tokens[0].toUpperCase() === "END" && tokens[1].toUpperCase() === "SITE") {
node.type = "ENDSITE";
node.name = "ENDSITE";
} else {
node.name = tokens[1];
node.type = tokens[0].toUpperCase();
}
if (nextLine(lines2) !== "{") {
console.error("THREE.BVHLoader: Expected opening { after type & name");
}
tokens = nextLine(lines2).split(/[\s]+/);
if (tokens[0] !== "OFFSET") {
console.error("THREE.BVHLoader: Expected OFFSET but got: " + tokens[0]);
}
if (tokens.length !== 4) {
console.error("THREE.BVHLoader: Invalid number of values for OFFSET.");
}
const offset = new Vector3(parseFloat(tokens[1]), parseFloat(tokens[2]), parseFloat(tokens[3]));
if (isNaN(offset.x) || isNaN(offset.y) || isNaN(offset.z)) {
console.error("THREE.BVHLoader: Invalid values of OFFSET.");
}
node.offset = offset;
if (node.type !== "ENDSITE") {
tokens = nextLine(lines2).split(/[\s]+/);
if (tokens[0] !== "CHANNELS") {
console.error("THREE.BVHLoader: Expected CHANNELS definition.");
}
const numChannels = parseInt(tokens[1]);
node.channels = tokens.splice(2, numChannels);
node.children = [];
}
while (true) {
const line = nextLine(lines2);
if (line === "}") {
return node;
} else {
node.children.push(readNode(lines2, line, list));
}
}
}
function toTHREEBone(source, list) {
const bone = new Bone();
list.push(bone);
bone.position.add(source.offset);
bone.name = source.name;
if (source.type !== "ENDSITE") {
for (let i = 0; i < source.children.length; i++) {
bone.add(toTHREEBone(source.children[i], list));
}
}
return bone;
}
function toTHREEAnimation(bones2) {
const tracks = [];
for (let i = 0; i < bones2.length; i++) {
const bone = bones2[i];
if (bone.type === "ENDSITE")
continue;
const times = [];
const positions = [];
const rotations = [];
for (let j = 0; j < bone.frames.length; j++) {
const frame = bone.frames[j];
times.push(frame.time);
positions.push(frame.position.x + bone.offset.x);
positions.push(frame.position.y + bone.offset.y);
positions.push(frame.position.z + bone.offset.z);
rotations.push(frame.rotation.x);
rotations.push(frame.rotation.y);
rotations.push(frame.rotation.z);
rotations.push(frame.rotation.w);
}
if (scope.animateBonePositions) {
tracks.push(new VectorKeyframeTrack(".bones[" + bone.name + "].position", times, positions));
}
if (scope.animateBoneRotations) {
tracks.push(new QuaternionKeyframeTrack(".bones[" + bone.name + "].quaternion", times, rotations));
}
}
return new AnimationClip("animation", -1, tracks);
}
function nextLine(lines2) {
let line;
while ((line = lines2.shift().trim()).length === 0) {
}
return line;
}
const scope = this;
const lines = text.split(/[\r\n]+/g);
const bones = readBvh(lines);
const threeBones = [];
toTHREEBone(bones[0], threeBones);
const threeClip = toTHREEAnimation(bones);
return {
skeleton: new Skeleton(threeBones),
clip: threeClip
};
}
}
export {
BVHLoader
};
//# sourceMappingURL=BVHLoader.js.map
File diff suppressed because one or more lines are too long
+496
View File
@@ -0,0 +1,496 @@
"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 _taskCache = /* @__PURE__ */ new WeakMap();
const BasisTextureLoader = /* @__PURE__ */ (() => {
const _BasisTextureLoader = class extends THREE.Loader {
constructor(manager) {
super(manager);
this.transcoderPath = "";
this.transcoderBinary = null;
this.transcoderPending = null;
this.workerLimit = 4;
this.workerPool = [];
this.workerNextTaskID = 1;
this.workerSourceURL = "";
this.workerConfig = null;
}
setTranscoderPath(path) {
this.transcoderPath = path;
return this;
}
setWorkerLimit(workerLimit) {
this.workerLimit = workerLimit;
return this;
}
detectSupport(renderer) {
this.workerConfig = {
astcSupported: renderer.extensions.has("WEBGL_compressed_texture_astc"),
etc1Supported: renderer.extensions.has("WEBGL_compressed_texture_etc1"),
etc2Supported: renderer.extensions.has("WEBGL_compressed_texture_etc"),
dxtSupported: renderer.extensions.has("WEBGL_compressed_texture_s3tc"),
bptcSupported: renderer.extensions.has("EXT_texture_compression_bptc"),
pvrtcSupported: renderer.extensions.has("WEBGL_compressed_texture_pvrtc") || renderer.extensions.has("WEBKIT_WEBGL_compressed_texture_pvrtc")
};
return this;
}
load(url, onLoad, onProgress, onError) {
const loader = new THREE.FileLoader(this.manager);
loader.setResponseType("arraybuffer");
loader.setWithCredentials(this.withCredentials);
const texture = new THREE.CompressedTexture();
loader.load(
url,
(buffer) => {
if (_taskCache.has(buffer)) {
const cachedTask = _taskCache.get(buffer);
return cachedTask.promise.then(onLoad).catch(onError);
}
this._createTexture([buffer]).then(function(_texture) {
texture.copy(_texture);
texture.needsUpdate = true;
if (onLoad)
onLoad(texture);
}).catch(onError);
},
onProgress,
onError
);
return texture;
}
/** Low-level transcoding API, exposed for use by KTX2Loader. */
parseInternalAsync(options) {
const { levels } = options;
const buffers = /* @__PURE__ */ new Set();
for (let i = 0; i < levels.length; i++) {
buffers.add(levels[i].data.buffer);
}
return this._createTexture(Array.from(buffers), { ...options, lowLevel: true });
}
/**
* @param {ArrayBuffer[]} buffers
* @param {object?} config
* @return {Promise<CompressedTexture>}
*/
_createTexture(buffers, config = {}) {
let worker;
let taskID;
const taskConfig = config;
let taskCost = 0;
for (let i = 0; i < buffers.length; i++) {
taskCost += buffers[i].byteLength;
}
const texturePending = this._allocateWorker(taskCost).then((_worker) => {
worker = _worker;
taskID = this.workerNextTaskID++;
return new Promise((resolve, reject) => {
worker._callbacks[taskID] = { resolve, reject };
worker.postMessage({ type: "transcode", id: taskID, buffers, taskConfig }, buffers);
});
}).then((message) => {
const { mipmaps, width, height, format } = message;
const texture = new THREE.CompressedTexture(mipmaps, width, height, format, THREE.UnsignedByteType);
texture.minFilter = mipmaps.length === 1 ? THREE.LinearFilter : THREE.LinearMipmapLinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.generateMipmaps = false;
texture.needsUpdate = true;
return texture;
});
texturePending.catch(() => true).then(() => {
if (worker && taskID) {
worker._taskLoad -= taskCost;
delete worker._callbacks[taskID];
}
});
_taskCache.set(buffers[0], { promise: texturePending });
return texturePending;
}
_initTranscoder() {
if (!this.transcoderPending) {
const jsLoader = new THREE.FileLoader(this.manager);
jsLoader.setPath(this.transcoderPath);
jsLoader.setWithCredentials(this.withCredentials);
const jsContent = new Promise((resolve, reject) => {
jsLoader.load("basis_transcoder.js", resolve, void 0, reject);
});
const binaryLoader = new THREE.FileLoader(this.manager);
binaryLoader.setPath(this.transcoderPath);
binaryLoader.setResponseType("arraybuffer");
binaryLoader.setWithCredentials(this.withCredentials);
const binaryContent = new Promise((resolve, reject) => {
binaryLoader.load("basis_transcoder.wasm", resolve, void 0, reject);
});
this.transcoderPending = Promise.all([jsContent, binaryContent]).then(([jsContent2, binaryContent2]) => {
const fn = _BasisTextureLoader.BasisWorker.toString();
const body = [
"/* constants */",
"let _EngineFormat = " + JSON.stringify(_BasisTextureLoader.EngineFormat),
"let _TranscoderFormat = " + JSON.stringify(_BasisTextureLoader.TranscoderFormat),
"let _BasisFormat = " + JSON.stringify(_BasisTextureLoader.BasisFormat),
"/* basis_transcoder.js */",
jsContent2,
"/* worker */",
fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"))
].join("\n");
this.workerSourceURL = URL.createObjectURL(new Blob([body]));
this.transcoderBinary = binaryContent2;
});
}
return this.transcoderPending;
}
_allocateWorker(taskCost) {
return this._initTranscoder().then(() => {
if (this.workerPool.length < this.workerLimit) {
const worker2 = new Worker(this.workerSourceURL);
worker2._callbacks = {};
worker2._taskLoad = 0;
worker2.postMessage({
type: "init",
config: this.workerConfig,
transcoderBinary: this.transcoderBinary
});
worker2.onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "transcode":
worker2._callbacks[message.id].resolve(message);
break;
case "error":
worker2._callbacks[message.id].reject(message);
break;
default:
console.error('THREE.BasisTextureLoader: Unexpected message, "' + message.type + '"');
}
};
this.workerPool.push(worker2);
} else {
this.workerPool.sort(function(a, b) {
return a._taskLoad > b._taskLoad ? -1 : 1;
});
}
const worker = this.workerPool[this.workerPool.length - 1];
worker._taskLoad += taskCost;
return worker;
});
}
dispose() {
for (let i = 0; i < this.workerPool.length; i++) {
this.workerPool[i].terminate();
}
this.workerPool.length = 0;
return this;
}
};
let BasisTextureLoader2 = _BasisTextureLoader;
/* CONSTANTS */
__publicField(BasisTextureLoader2, "BasisFormat", {
ETC1S: 0,
UASTC_4x4: 1
});
__publicField(BasisTextureLoader2, "TranscoderFormat", {
ETC1: 0,
ETC2: 1,
BC1: 2,
BC3: 3,
BC4: 4,
BC5: 5,
BC7_M6_OPAQUE_ONLY: 6,
BC7_M5: 7,
PVRTC1_4_RGB: 8,
PVRTC1_4_RGBA: 9,
ASTC_4x4: 10,
ATC_RGB: 11,
ATC_RGBA_INTERPOLATED_ALPHA: 12,
RGBA32: 13,
RGB565: 14,
BGR565: 15,
RGBA4444: 16
});
__publicField(BasisTextureLoader2, "EngineFormat", {
RGBAFormat: THREE.RGBAFormat,
RGBA_ASTC_4x4_Format: THREE.RGBA_ASTC_4x4_Format,
RGBA_BPTC_Format: THREE.RGBA_BPTC_Format,
RGBA_ETC2_EAC_Format: THREE.RGBA_ETC2_EAC_Format,
RGBA_PVRTC_4BPPV1_Format: THREE.RGBA_PVRTC_4BPPV1_Format,
RGBA_S3TC_DXT5_Format: THREE.RGBA_S3TC_DXT5_Format,
RGB_ETC1_Format: THREE.RGB_ETC1_Format,
RGB_ETC2_Format: THREE.RGB_ETC2_Format,
RGB_PVRTC_4BPPV1_Format: THREE.RGB_PVRTC_4BPPV1_Format,
RGB_S3TC_DXT1_Format: THREE.RGB_S3TC_DXT1_Format
});
/* WEB WORKER */
__publicField(BasisTextureLoader2, "BasisWorker", function() {
let config;
let transcoderPending;
let BasisModule;
const EngineFormat = _EngineFormat;
const TranscoderFormat = _TranscoderFormat;
const BasisFormat = _BasisFormat;
onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "init":
config = message.config;
init(message.transcoderBinary);
break;
case "transcode":
transcoderPending.then(() => {
try {
const { width, height, hasAlpha, mipmaps, format } = message.taskConfig.lowLevel ? transcodeLowLevel(message.taskConfig) : transcode(message.buffers[0]);
const buffers = [];
for (let i = 0; i < mipmaps.length; ++i) {
buffers.push(mipmaps[i].data.buffer);
}
self.postMessage(
{ type: "transcode", id: message.id, width, height, hasAlpha, mipmaps, format },
buffers
);
} catch (error) {
console.error(error);
self.postMessage({ type: "error", id: message.id, error: error.message });
}
});
break;
}
};
function init(wasmBinary) {
transcoderPending = new Promise((resolve) => {
BasisModule = { wasmBinary, onRuntimeInitialized: resolve };
BASIS(BasisModule);
}).then(() => {
BasisModule.initializeBasis();
});
}
function transcodeLowLevel(taskConfig) {
const { basisFormat, width, height, hasAlpha } = taskConfig;
const { transcoderFormat, engineFormat } = getTranscoderFormat(basisFormat, width, height, hasAlpha);
const blockByteLength = BasisModule.getBytesPerBlockOrPixel(transcoderFormat);
assert(BasisModule.isFormatSupported(transcoderFormat), "THREE.BasisTextureLoader: Unsupported format.");
const mipmaps = [];
if (basisFormat === BasisFormat.ETC1S) {
const transcoder = new BasisModule.LowLevelETC1SImageTranscoder();
const { endpointCount, endpointsData, selectorCount, selectorsData, tablesData } = taskConfig.globalData;
try {
let ok;
ok = transcoder.decodePalettes(endpointCount, endpointsData, selectorCount, selectorsData);
assert(ok, "THREE.BasisTextureLoader: decodePalettes() failed.");
ok = transcoder.decodeTables(tablesData);
assert(ok, "THREE.BasisTextureLoader: decodeTables() failed.");
for (let i = 0; i < taskConfig.levels.length; i++) {
const level = taskConfig.levels[i];
const imageDesc = taskConfig.globalData.imageDescs[i];
const dstByteLength = getTranscodedImageByteLength(transcoderFormat, level.width, level.height);
const dst = new Uint8Array(dstByteLength);
ok = transcoder.transcodeImage(
transcoderFormat,
dst,
dstByteLength / blockByteLength,
level.data,
getWidthInBlocks(transcoderFormat, level.width),
getHeightInBlocks(transcoderFormat, level.height),
level.width,
level.height,
level.index,
imageDesc.rgbSliceByteOffset,
imageDesc.rgbSliceByteLength,
imageDesc.alphaSliceByteOffset,
imageDesc.alphaSliceByteLength,
imageDesc.imageFlags,
hasAlpha,
false,
0,
0
);
assert(ok, "THREE.BasisTextureLoader: transcodeImage() failed for level " + level.index + ".");
mipmaps.push({ data: dst, width: level.width, height: level.height });
}
} finally {
transcoder.delete();
}
} else {
for (let i = 0; i < taskConfig.levels.length; i++) {
const level = taskConfig.levels[i];
const dstByteLength = getTranscodedImageByteLength(transcoderFormat, level.width, level.height);
const dst = new Uint8Array(dstByteLength);
const ok = BasisModule.transcodeUASTCImage(
transcoderFormat,
dst,
dstByteLength / blockByteLength,
level.data,
getWidthInBlocks(transcoderFormat, level.width),
getHeightInBlocks(transcoderFormat, level.height),
level.width,
level.height,
level.index,
0,
level.data.byteLength,
0,
hasAlpha,
false,
0,
0,
-1,
-1
);
assert(ok, "THREE.BasisTextureLoader: transcodeUASTCImage() failed for level " + level.index + ".");
mipmaps.push({ data: dst, width: level.width, height: level.height });
}
}
return { width, height, hasAlpha, mipmaps, format: engineFormat };
}
function transcode(buffer) {
const basisFile = new BasisModule.BasisFile(new Uint8Array(buffer));
const basisFormat = basisFile.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
const width = basisFile.getImageWidth(0, 0);
const height = basisFile.getImageHeight(0, 0);
const levels = basisFile.getNumLevels(0);
const hasAlpha = basisFile.getHasAlpha();
function cleanup() {
basisFile.close();
basisFile.delete();
}
const { transcoderFormat, engineFormat } = getTranscoderFormat(basisFormat, width, height, hasAlpha);
if (!width || !height || !levels) {
cleanup();
throw new Error("THREE.BasisTextureLoader: Invalid texture");
}
if (!basisFile.startTranscoding()) {
cleanup();
throw new Error("THREE.BasisTextureLoader: .startTranscoding failed");
}
const mipmaps = [];
for (let mip = 0; mip < levels; mip++) {
const mipWidth = basisFile.getImageWidth(0, mip);
const mipHeight = basisFile.getImageHeight(0, mip);
const dst = new Uint8Array(basisFile.getImageTranscodedSizeInBytes(0, mip, transcoderFormat));
const status = basisFile.transcodeImage(dst, 0, mip, transcoderFormat, 0, hasAlpha);
if (!status) {
cleanup();
throw new Error("THREE.BasisTextureLoader: .transcodeImage failed.");
}
mipmaps.push({ data: dst, width: mipWidth, height: mipHeight });
}
cleanup();
return { width, height, hasAlpha, mipmaps, format: engineFormat };
}
const FORMAT_OPTIONS = [
{
if: "astcSupported",
basisFormat: [BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4],
engineFormat: [EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format],
priorityETC1S: Infinity,
priorityUASTC: 1,
needsPowerOfTwo: false
},
{
if: "bptcSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5],
engineFormat: [EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format],
priorityETC1S: 3,
priorityUASTC: 2,
needsPowerOfTwo: false
},
{
if: "dxtSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.BC1, TranscoderFormat.BC3],
engineFormat: [EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format],
priorityETC1S: 4,
priorityUASTC: 5,
needsPowerOfTwo: false
},
{
if: "etc2Supported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ETC1, TranscoderFormat.ETC2],
engineFormat: [EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format],
priorityETC1S: 1,
priorityUASTC: 3,
needsPowerOfTwo: false
},
{
if: "etc1Supported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ETC1, TranscoderFormat.ETC1],
engineFormat: [EngineFormat.RGB_ETC1_Format, EngineFormat.RGB_ETC1_Format],
priorityETC1S: 2,
priorityUASTC: 4,
needsPowerOfTwo: false
},
{
if: "pvrtcSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA],
engineFormat: [EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format],
priorityETC1S: 5,
priorityUASTC: 6,
needsPowerOfTwo: true
}
];
const ETC1S_OPTIONS = FORMAT_OPTIONS.sort(function(a, b) {
return a.priorityETC1S - b.priorityETC1S;
});
const UASTC_OPTIONS = FORMAT_OPTIONS.sort(function(a, b) {
return a.priorityUASTC - b.priorityUASTC;
});
function getTranscoderFormat(basisFormat, width, height, hasAlpha) {
let transcoderFormat;
let engineFormat;
const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS;
for (let i = 0; i < options.length; i++) {
const opt = options[i];
if (!config[opt.if])
continue;
if (!opt.basisFormat.includes(basisFormat))
continue;
if (opt.needsPowerOfTwo && !(isPowerOfTwo(width) && isPowerOfTwo(height)))
continue;
transcoderFormat = opt.transcoderFormat[hasAlpha ? 1 : 0];
engineFormat = opt.engineFormat[hasAlpha ? 1 : 0];
return { transcoderFormat, engineFormat };
}
console.warn("THREE.BasisTextureLoader: No suitable compressed texture format found. Decoding to RGBA32.");
transcoderFormat = TranscoderFormat.RGBA32;
engineFormat = EngineFormat.RGBAFormat;
return { transcoderFormat, engineFormat };
}
function assert(ok, message) {
if (!ok)
throw new Error(message);
}
function getWidthInBlocks(transcoderFormat, width) {
return Math.ceil(width / BasisModule.getFormatBlockWidth(transcoderFormat));
}
function getHeightInBlocks(transcoderFormat, height) {
return Math.ceil(height / BasisModule.getFormatBlockHeight(transcoderFormat));
}
function getTranscodedImageByteLength(transcoderFormat, width, height) {
const blockByteLength = BasisModule.getBytesPerBlockOrPixel(transcoderFormat);
if (BasisModule.formatIsUncompressed(transcoderFormat)) {
return width * height * blockByteLength;
}
if (transcoderFormat === TranscoderFormat.PVRTC1_4_RGB || transcoderFormat === TranscoderFormat.PVRTC1_4_RGBA) {
const paddedWidth = width + 3 & ~3;
const paddedHeight = height + 3 & ~3;
return (Math.max(8, paddedWidth) * Math.max(8, paddedHeight) * 4 + 7) / 8;
}
return getWidthInBlocks(transcoderFormat, width) * getHeightInBlocks(transcoderFormat, height) * blockByteLength;
}
function isPowerOfTwo(value) {
if (value <= 2)
return true;
return (value & value - 1) === 0 && value !== 0;
}
});
return BasisTextureLoader2;
})();
exports.BasisTextureLoader = BasisTextureLoader;
//# sourceMappingURL=BasisTextureLoader.cjs.map
File diff suppressed because one or more lines are too long
+32
View File
@@ -0,0 +1,32 @@
import { Loader, CompressedTexture, LoadingManager, WebGLRenderer } from 'three'
export class BasisTextureLoader extends Loader {
constructor(manager?: LoadingManager)
transcoderBinary: ArrayBuffer | null
transcoderPath: string
transcoderPending: Promise<void> | null
workerConfig: {
format: number
astcSupported: boolean
etcSupported: boolean
dxtSupported: boolean
pvrtcSupported: boolean
}
workerLimit: number
workerNextTaskID: number
workerPool: object[]
workerSourceURL: string
detectSupport(renderer: WebGLRenderer): this
load(
url: string,
onLoad: (texture: CompressedTexture) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<CompressedTexture>
setTranscoderPath(path: string): this
setWorkerLimit(workerLimit: number): this
dispose(): void
}
+496
View File
@@ -0,0 +1,496 @@
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;
};
import { Loader, RGBAFormat, RGBA_ASTC_4x4_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, FileLoader, CompressedTexture, UnsignedByteType, LinearFilter, LinearMipmapLinearFilter } from "three";
const _taskCache = /* @__PURE__ */ new WeakMap();
const BasisTextureLoader = /* @__PURE__ */ (() => {
const _BasisTextureLoader = class extends Loader {
constructor(manager) {
super(manager);
this.transcoderPath = "";
this.transcoderBinary = null;
this.transcoderPending = null;
this.workerLimit = 4;
this.workerPool = [];
this.workerNextTaskID = 1;
this.workerSourceURL = "";
this.workerConfig = null;
}
setTranscoderPath(path) {
this.transcoderPath = path;
return this;
}
setWorkerLimit(workerLimit) {
this.workerLimit = workerLimit;
return this;
}
detectSupport(renderer) {
this.workerConfig = {
astcSupported: renderer.extensions.has("WEBGL_compressed_texture_astc"),
etc1Supported: renderer.extensions.has("WEBGL_compressed_texture_etc1"),
etc2Supported: renderer.extensions.has("WEBGL_compressed_texture_etc"),
dxtSupported: renderer.extensions.has("WEBGL_compressed_texture_s3tc"),
bptcSupported: renderer.extensions.has("EXT_texture_compression_bptc"),
pvrtcSupported: renderer.extensions.has("WEBGL_compressed_texture_pvrtc") || renderer.extensions.has("WEBKIT_WEBGL_compressed_texture_pvrtc")
};
return this;
}
load(url, onLoad, onProgress, onError) {
const loader = new FileLoader(this.manager);
loader.setResponseType("arraybuffer");
loader.setWithCredentials(this.withCredentials);
const texture = new CompressedTexture();
loader.load(
url,
(buffer) => {
if (_taskCache.has(buffer)) {
const cachedTask = _taskCache.get(buffer);
return cachedTask.promise.then(onLoad).catch(onError);
}
this._createTexture([buffer]).then(function(_texture) {
texture.copy(_texture);
texture.needsUpdate = true;
if (onLoad)
onLoad(texture);
}).catch(onError);
},
onProgress,
onError
);
return texture;
}
/** Low-level transcoding API, exposed for use by KTX2Loader. */
parseInternalAsync(options) {
const { levels } = options;
const buffers = /* @__PURE__ */ new Set();
for (let i = 0; i < levels.length; i++) {
buffers.add(levels[i].data.buffer);
}
return this._createTexture(Array.from(buffers), { ...options, lowLevel: true });
}
/**
* @param {ArrayBuffer[]} buffers
* @param {object?} config
* @return {Promise<CompressedTexture>}
*/
_createTexture(buffers, config = {}) {
let worker;
let taskID;
const taskConfig = config;
let taskCost = 0;
for (let i = 0; i < buffers.length; i++) {
taskCost += buffers[i].byteLength;
}
const texturePending = this._allocateWorker(taskCost).then((_worker) => {
worker = _worker;
taskID = this.workerNextTaskID++;
return new Promise((resolve, reject) => {
worker._callbacks[taskID] = { resolve, reject };
worker.postMessage({ type: "transcode", id: taskID, buffers, taskConfig }, buffers);
});
}).then((message) => {
const { mipmaps, width, height, format } = message;
const texture = new CompressedTexture(mipmaps, width, height, format, UnsignedByteType);
texture.minFilter = mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter;
texture.magFilter = LinearFilter;
texture.generateMipmaps = false;
texture.needsUpdate = true;
return texture;
});
texturePending.catch(() => true).then(() => {
if (worker && taskID) {
worker._taskLoad -= taskCost;
delete worker._callbacks[taskID];
}
});
_taskCache.set(buffers[0], { promise: texturePending });
return texturePending;
}
_initTranscoder() {
if (!this.transcoderPending) {
const jsLoader = new FileLoader(this.manager);
jsLoader.setPath(this.transcoderPath);
jsLoader.setWithCredentials(this.withCredentials);
const jsContent = new Promise((resolve, reject) => {
jsLoader.load("basis_transcoder.js", resolve, void 0, reject);
});
const binaryLoader = new FileLoader(this.manager);
binaryLoader.setPath(this.transcoderPath);
binaryLoader.setResponseType("arraybuffer");
binaryLoader.setWithCredentials(this.withCredentials);
const binaryContent = new Promise((resolve, reject) => {
binaryLoader.load("basis_transcoder.wasm", resolve, void 0, reject);
});
this.transcoderPending = Promise.all([jsContent, binaryContent]).then(([jsContent2, binaryContent2]) => {
const fn = _BasisTextureLoader.BasisWorker.toString();
const body = [
"/* constants */",
"let _EngineFormat = " + JSON.stringify(_BasisTextureLoader.EngineFormat),
"let _TranscoderFormat = " + JSON.stringify(_BasisTextureLoader.TranscoderFormat),
"let _BasisFormat = " + JSON.stringify(_BasisTextureLoader.BasisFormat),
"/* basis_transcoder.js */",
jsContent2,
"/* worker */",
fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"))
].join("\n");
this.workerSourceURL = URL.createObjectURL(new Blob([body]));
this.transcoderBinary = binaryContent2;
});
}
return this.transcoderPending;
}
_allocateWorker(taskCost) {
return this._initTranscoder().then(() => {
if (this.workerPool.length < this.workerLimit) {
const worker2 = new Worker(this.workerSourceURL);
worker2._callbacks = {};
worker2._taskLoad = 0;
worker2.postMessage({
type: "init",
config: this.workerConfig,
transcoderBinary: this.transcoderBinary
});
worker2.onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "transcode":
worker2._callbacks[message.id].resolve(message);
break;
case "error":
worker2._callbacks[message.id].reject(message);
break;
default:
console.error('THREE.BasisTextureLoader: Unexpected message, "' + message.type + '"');
}
};
this.workerPool.push(worker2);
} else {
this.workerPool.sort(function(a, b) {
return a._taskLoad > b._taskLoad ? -1 : 1;
});
}
const worker = this.workerPool[this.workerPool.length - 1];
worker._taskLoad += taskCost;
return worker;
});
}
dispose() {
for (let i = 0; i < this.workerPool.length; i++) {
this.workerPool[i].terminate();
}
this.workerPool.length = 0;
return this;
}
};
let BasisTextureLoader2 = _BasisTextureLoader;
/* CONSTANTS */
__publicField(BasisTextureLoader2, "BasisFormat", {
ETC1S: 0,
UASTC_4x4: 1
});
__publicField(BasisTextureLoader2, "TranscoderFormat", {
ETC1: 0,
ETC2: 1,
BC1: 2,
BC3: 3,
BC4: 4,
BC5: 5,
BC7_M6_OPAQUE_ONLY: 6,
BC7_M5: 7,
PVRTC1_4_RGB: 8,
PVRTC1_4_RGBA: 9,
ASTC_4x4: 10,
ATC_RGB: 11,
ATC_RGBA_INTERPOLATED_ALPHA: 12,
RGBA32: 13,
RGB565: 14,
BGR565: 15,
RGBA4444: 16
});
__publicField(BasisTextureLoader2, "EngineFormat", {
RGBAFormat,
RGBA_ASTC_4x4_Format,
RGBA_BPTC_Format,
RGBA_ETC2_EAC_Format,
RGBA_PVRTC_4BPPV1_Format,
RGBA_S3TC_DXT5_Format,
RGB_ETC1_Format,
RGB_ETC2_Format,
RGB_PVRTC_4BPPV1_Format,
RGB_S3TC_DXT1_Format
});
/* WEB WORKER */
__publicField(BasisTextureLoader2, "BasisWorker", function() {
let config;
let transcoderPending;
let BasisModule;
const EngineFormat = _EngineFormat;
const TranscoderFormat = _TranscoderFormat;
const BasisFormat = _BasisFormat;
onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "init":
config = message.config;
init(message.transcoderBinary);
break;
case "transcode":
transcoderPending.then(() => {
try {
const { width, height, hasAlpha, mipmaps, format } = message.taskConfig.lowLevel ? transcodeLowLevel(message.taskConfig) : transcode(message.buffers[0]);
const buffers = [];
for (let i = 0; i < mipmaps.length; ++i) {
buffers.push(mipmaps[i].data.buffer);
}
self.postMessage(
{ type: "transcode", id: message.id, width, height, hasAlpha, mipmaps, format },
buffers
);
} catch (error) {
console.error(error);
self.postMessage({ type: "error", id: message.id, error: error.message });
}
});
break;
}
};
function init(wasmBinary) {
transcoderPending = new Promise((resolve) => {
BasisModule = { wasmBinary, onRuntimeInitialized: resolve };
BASIS(BasisModule);
}).then(() => {
BasisModule.initializeBasis();
});
}
function transcodeLowLevel(taskConfig) {
const { basisFormat, width, height, hasAlpha } = taskConfig;
const { transcoderFormat, engineFormat } = getTranscoderFormat(basisFormat, width, height, hasAlpha);
const blockByteLength = BasisModule.getBytesPerBlockOrPixel(transcoderFormat);
assert(BasisModule.isFormatSupported(transcoderFormat), "THREE.BasisTextureLoader: Unsupported format.");
const mipmaps = [];
if (basisFormat === BasisFormat.ETC1S) {
const transcoder = new BasisModule.LowLevelETC1SImageTranscoder();
const { endpointCount, endpointsData, selectorCount, selectorsData, tablesData } = taskConfig.globalData;
try {
let ok;
ok = transcoder.decodePalettes(endpointCount, endpointsData, selectorCount, selectorsData);
assert(ok, "THREE.BasisTextureLoader: decodePalettes() failed.");
ok = transcoder.decodeTables(tablesData);
assert(ok, "THREE.BasisTextureLoader: decodeTables() failed.");
for (let i = 0; i < taskConfig.levels.length; i++) {
const level = taskConfig.levels[i];
const imageDesc = taskConfig.globalData.imageDescs[i];
const dstByteLength = getTranscodedImageByteLength(transcoderFormat, level.width, level.height);
const dst = new Uint8Array(dstByteLength);
ok = transcoder.transcodeImage(
transcoderFormat,
dst,
dstByteLength / blockByteLength,
level.data,
getWidthInBlocks(transcoderFormat, level.width),
getHeightInBlocks(transcoderFormat, level.height),
level.width,
level.height,
level.index,
imageDesc.rgbSliceByteOffset,
imageDesc.rgbSliceByteLength,
imageDesc.alphaSliceByteOffset,
imageDesc.alphaSliceByteLength,
imageDesc.imageFlags,
hasAlpha,
false,
0,
0
);
assert(ok, "THREE.BasisTextureLoader: transcodeImage() failed for level " + level.index + ".");
mipmaps.push({ data: dst, width: level.width, height: level.height });
}
} finally {
transcoder.delete();
}
} else {
for (let i = 0; i < taskConfig.levels.length; i++) {
const level = taskConfig.levels[i];
const dstByteLength = getTranscodedImageByteLength(transcoderFormat, level.width, level.height);
const dst = new Uint8Array(dstByteLength);
const ok = BasisModule.transcodeUASTCImage(
transcoderFormat,
dst,
dstByteLength / blockByteLength,
level.data,
getWidthInBlocks(transcoderFormat, level.width),
getHeightInBlocks(transcoderFormat, level.height),
level.width,
level.height,
level.index,
0,
level.data.byteLength,
0,
hasAlpha,
false,
0,
0,
-1,
-1
);
assert(ok, "THREE.BasisTextureLoader: transcodeUASTCImage() failed for level " + level.index + ".");
mipmaps.push({ data: dst, width: level.width, height: level.height });
}
}
return { width, height, hasAlpha, mipmaps, format: engineFormat };
}
function transcode(buffer) {
const basisFile = new BasisModule.BasisFile(new Uint8Array(buffer));
const basisFormat = basisFile.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
const width = basisFile.getImageWidth(0, 0);
const height = basisFile.getImageHeight(0, 0);
const levels = basisFile.getNumLevels(0);
const hasAlpha = basisFile.getHasAlpha();
function cleanup() {
basisFile.close();
basisFile.delete();
}
const { transcoderFormat, engineFormat } = getTranscoderFormat(basisFormat, width, height, hasAlpha);
if (!width || !height || !levels) {
cleanup();
throw new Error("THREE.BasisTextureLoader: Invalid texture");
}
if (!basisFile.startTranscoding()) {
cleanup();
throw new Error("THREE.BasisTextureLoader: .startTranscoding failed");
}
const mipmaps = [];
for (let mip = 0; mip < levels; mip++) {
const mipWidth = basisFile.getImageWidth(0, mip);
const mipHeight = basisFile.getImageHeight(0, mip);
const dst = new Uint8Array(basisFile.getImageTranscodedSizeInBytes(0, mip, transcoderFormat));
const status = basisFile.transcodeImage(dst, 0, mip, transcoderFormat, 0, hasAlpha);
if (!status) {
cleanup();
throw new Error("THREE.BasisTextureLoader: .transcodeImage failed.");
}
mipmaps.push({ data: dst, width: mipWidth, height: mipHeight });
}
cleanup();
return { width, height, hasAlpha, mipmaps, format: engineFormat };
}
const FORMAT_OPTIONS = [
{
if: "astcSupported",
basisFormat: [BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4],
engineFormat: [EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format],
priorityETC1S: Infinity,
priorityUASTC: 1,
needsPowerOfTwo: false
},
{
if: "bptcSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5],
engineFormat: [EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format],
priorityETC1S: 3,
priorityUASTC: 2,
needsPowerOfTwo: false
},
{
if: "dxtSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.BC1, TranscoderFormat.BC3],
engineFormat: [EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format],
priorityETC1S: 4,
priorityUASTC: 5,
needsPowerOfTwo: false
},
{
if: "etc2Supported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ETC1, TranscoderFormat.ETC2],
engineFormat: [EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format],
priorityETC1S: 1,
priorityUASTC: 3,
needsPowerOfTwo: false
},
{
if: "etc1Supported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ETC1, TranscoderFormat.ETC1],
engineFormat: [EngineFormat.RGB_ETC1_Format, EngineFormat.RGB_ETC1_Format],
priorityETC1S: 2,
priorityUASTC: 4,
needsPowerOfTwo: false
},
{
if: "pvrtcSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA],
engineFormat: [EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format],
priorityETC1S: 5,
priorityUASTC: 6,
needsPowerOfTwo: true
}
];
const ETC1S_OPTIONS = FORMAT_OPTIONS.sort(function(a, b) {
return a.priorityETC1S - b.priorityETC1S;
});
const UASTC_OPTIONS = FORMAT_OPTIONS.sort(function(a, b) {
return a.priorityUASTC - b.priorityUASTC;
});
function getTranscoderFormat(basisFormat, width, height, hasAlpha) {
let transcoderFormat;
let engineFormat;
const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS;
for (let i = 0; i < options.length; i++) {
const opt = options[i];
if (!config[opt.if])
continue;
if (!opt.basisFormat.includes(basisFormat))
continue;
if (opt.needsPowerOfTwo && !(isPowerOfTwo(width) && isPowerOfTwo(height)))
continue;
transcoderFormat = opt.transcoderFormat[hasAlpha ? 1 : 0];
engineFormat = opt.engineFormat[hasAlpha ? 1 : 0];
return { transcoderFormat, engineFormat };
}
console.warn("THREE.BasisTextureLoader: No suitable compressed texture format found. Decoding to RGBA32.");
transcoderFormat = TranscoderFormat.RGBA32;
engineFormat = EngineFormat.RGBAFormat;
return { transcoderFormat, engineFormat };
}
function assert(ok, message) {
if (!ok)
throw new Error(message);
}
function getWidthInBlocks(transcoderFormat, width) {
return Math.ceil(width / BasisModule.getFormatBlockWidth(transcoderFormat));
}
function getHeightInBlocks(transcoderFormat, height) {
return Math.ceil(height / BasisModule.getFormatBlockHeight(transcoderFormat));
}
function getTranscodedImageByteLength(transcoderFormat, width, height) {
const blockByteLength = BasisModule.getBytesPerBlockOrPixel(transcoderFormat);
if (BasisModule.formatIsUncompressed(transcoderFormat)) {
return width * height * blockByteLength;
}
if (transcoderFormat === TranscoderFormat.PVRTC1_4_RGB || transcoderFormat === TranscoderFormat.PVRTC1_4_RGBA) {
const paddedWidth = width + 3 & ~3;
const paddedHeight = height + 3 & ~3;
return (Math.max(8, paddedWidth) * Math.max(8, paddedHeight) * 4 + 7) / 8;
}
return getWidthInBlocks(transcoderFormat, width) * getHeightInBlocks(transcoderFormat, height) * blockByteLength;
}
function isPowerOfTwo(value) {
if (value <= 2)
return true;
return (value & value - 1) === 0 && value !== 0;
}
});
return BasisTextureLoader2;
})();
export {
BasisTextureLoader
};
//# sourceMappingURL=BasisTextureLoader.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+20
View File
@@ -0,0 +1,20 @@
import { Loader, LoadingManager, Scene } from 'three'
export interface Collada {
kinematics: object
library: object
scene: Scene
}
export class ColladaLoader extends Loader {
constructor(manager?: LoadingManager)
load(
url: string,
onLoad: (collada: Collada) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Collada>
parse(text: string, path: string): Collada
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+149
View File
@@ -0,0 +1,149 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
class DDSLoader extends THREE.CompressedTextureLoader {
constructor(manager) {
super(manager);
}
parse(buffer, loadMipmaps) {
const dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 };
const DDS_MAGIC = 542327876;
const DDSD_MIPMAPCOUNT = 131072;
const DDSCAPS2_CUBEMAP = 512;
const DDSCAPS2_CUBEMAP_POSITIVEX = 1024;
const DDSCAPS2_CUBEMAP_NEGATIVEX = 2048;
const DDSCAPS2_CUBEMAP_POSITIVEY = 4096;
const DDSCAPS2_CUBEMAP_NEGATIVEY = 8192;
const DDSCAPS2_CUBEMAP_POSITIVEZ = 16384;
const DDSCAPS2_CUBEMAP_NEGATIVEZ = 32768;
const DDPF_FOURCC = 4;
function fourCCToInt32(value) {
return value.charCodeAt(0) + (value.charCodeAt(1) << 8) + (value.charCodeAt(2) << 16) + (value.charCodeAt(3) << 24);
}
function int32ToFourCC(value) {
return String.fromCharCode(value & 255, value >> 8 & 255, value >> 16 & 255, value >> 24 & 255);
}
function loadARGBMip(buffer2, dataOffset2, width, height) {
const dataLength = width * height * 4;
const srcBuffer = new Uint8Array(buffer2, dataOffset2, dataLength);
const byteArray = new Uint8Array(dataLength);
let dst = 0;
let src = 0;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const b = srcBuffer[src];
src++;
const g = srcBuffer[src];
src++;
const r = srcBuffer[src];
src++;
const a = srcBuffer[src];
src++;
byteArray[dst] = r;
dst++;
byteArray[dst] = g;
dst++;
byteArray[dst] = b;
dst++;
byteArray[dst] = a;
dst++;
}
}
return byteArray;
}
const FOURCC_DXT1 = fourCCToInt32("DXT1");
const FOURCC_DXT3 = fourCCToInt32("DXT3");
const FOURCC_DXT5 = fourCCToInt32("DXT5");
const FOURCC_ETC1 = fourCCToInt32("ETC1");
const headerLengthInt = 31;
const off_magic = 0;
const off_size = 1;
const off_flags = 2;
const off_height = 3;
const off_width = 4;
const off_mipmapCount = 7;
const off_pfFlags = 20;
const off_pfFourCC = 21;
const off_RGBBitCount = 22;
const off_RBitMask = 23;
const off_GBitMask = 24;
const off_BBitMask = 25;
const off_ABitMask = 26;
const off_caps2 = 28;
const header = new Int32Array(buffer, 0, headerLengthInt);
if (header[off_magic] !== DDS_MAGIC) {
console.error("THREE.DDSLoader.parse: Invalid magic number in DDS header.");
return dds;
}
if (!header[off_pfFlags] & DDPF_FOURCC) {
console.error("THREE.DDSLoader.parse: Unsupported format, must contain a FourCC code.");
return dds;
}
let blockBytes;
const fourCC = header[off_pfFourCC];
let isRGBAUncompressed = false;
switch (fourCC) {
case FOURCC_DXT1:
blockBytes = 8;
dds.format = THREE.RGB_S3TC_DXT1_Format;
break;
case FOURCC_DXT3:
blockBytes = 16;
dds.format = THREE.RGBA_S3TC_DXT3_Format;
break;
case FOURCC_DXT5:
blockBytes = 16;
dds.format = THREE.RGBA_S3TC_DXT5_Format;
break;
case FOURCC_ETC1:
blockBytes = 8;
dds.format = THREE.RGB_ETC1_Format;
break;
default:
if (header[off_RGBBitCount] === 32 && header[off_RBitMask] & 16711680 && header[off_GBitMask] & 65280 && header[off_BBitMask] & 255 && header[off_ABitMask] & 4278190080) {
isRGBAUncompressed = true;
blockBytes = 64;
dds.format = THREE.RGBAFormat;
} else {
console.error("THREE.DDSLoader.parse: Unsupported FourCC code ", int32ToFourCC(fourCC));
return dds;
}
}
dds.mipmapCount = 1;
if (header[off_flags] & DDSD_MIPMAPCOUNT && loadMipmaps !== false) {
dds.mipmapCount = Math.max(1, header[off_mipmapCount]);
}
const caps2 = header[off_caps2];
dds.isCubemap = caps2 & DDSCAPS2_CUBEMAP ? true : false;
if (dds.isCubemap && (!(caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) || !(caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) || !(caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) || !(caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) || !(caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) || !(caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ))) {
console.error("THREE.DDSLoader.parse: Incomplete cubemap faces");
return dds;
}
dds.width = header[off_width];
dds.height = header[off_height];
let dataOffset = header[off_size] + 4;
const faces = dds.isCubemap ? 6 : 1;
for (let face = 0; face < faces; face++) {
let width = dds.width;
let height = dds.height;
for (let i = 0; i < dds.mipmapCount; i++) {
let byteArray, dataLength;
if (isRGBAUncompressed) {
byteArray = loadARGBMip(buffer, dataOffset, width, height);
dataLength = byteArray.length;
} else {
dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes;
byteArray = new Uint8Array(buffer, dataOffset, dataLength);
}
const mipmap = { data: byteArray, width, height };
dds.mipmaps.push(mipmap);
dataOffset += dataLength;
width = Math.max(width >> 1, 1);
height = Math.max(height >> 1, 1);
}
}
return dds;
}
}
exports.DDSLoader = DDSLoader;
//# sourceMappingURL=DDSLoader.cjs.map
File diff suppressed because one or more lines are too long
+16
View File
@@ -0,0 +1,16 @@
import { LoadingManager, CompressedTextureLoader, PixelFormat, CompressedPixelFormat } from 'three'
export interface DDS {
mipmaps: object[]
width: number
height: number
format: PixelFormat | CompressedPixelFormat
mipmapCount: number
isCubemap: boolean
}
export class DDSLoader extends CompressedTextureLoader {
constructor(manager?: LoadingManager)
parse(buffer: ArrayBuffer, loadMipmaps: boolean): DDS
}
+149
View File
@@ -0,0 +1,149 @@
import { CompressedTextureLoader, RGBAFormat, RGB_ETC1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGB_S3TC_DXT1_Format } from "three";
class DDSLoader extends CompressedTextureLoader {
constructor(manager) {
super(manager);
}
parse(buffer, loadMipmaps) {
const dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 };
const DDS_MAGIC = 542327876;
const DDSD_MIPMAPCOUNT = 131072;
const DDSCAPS2_CUBEMAP = 512;
const DDSCAPS2_CUBEMAP_POSITIVEX = 1024;
const DDSCAPS2_CUBEMAP_NEGATIVEX = 2048;
const DDSCAPS2_CUBEMAP_POSITIVEY = 4096;
const DDSCAPS2_CUBEMAP_NEGATIVEY = 8192;
const DDSCAPS2_CUBEMAP_POSITIVEZ = 16384;
const DDSCAPS2_CUBEMAP_NEGATIVEZ = 32768;
const DDPF_FOURCC = 4;
function fourCCToInt32(value) {
return value.charCodeAt(0) + (value.charCodeAt(1) << 8) + (value.charCodeAt(2) << 16) + (value.charCodeAt(3) << 24);
}
function int32ToFourCC(value) {
return String.fromCharCode(value & 255, value >> 8 & 255, value >> 16 & 255, value >> 24 & 255);
}
function loadARGBMip(buffer2, dataOffset2, width, height) {
const dataLength = width * height * 4;
const srcBuffer = new Uint8Array(buffer2, dataOffset2, dataLength);
const byteArray = new Uint8Array(dataLength);
let dst = 0;
let src = 0;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const b = srcBuffer[src];
src++;
const g = srcBuffer[src];
src++;
const r = srcBuffer[src];
src++;
const a = srcBuffer[src];
src++;
byteArray[dst] = r;
dst++;
byteArray[dst] = g;
dst++;
byteArray[dst] = b;
dst++;
byteArray[dst] = a;
dst++;
}
}
return byteArray;
}
const FOURCC_DXT1 = fourCCToInt32("DXT1");
const FOURCC_DXT3 = fourCCToInt32("DXT3");
const FOURCC_DXT5 = fourCCToInt32("DXT5");
const FOURCC_ETC1 = fourCCToInt32("ETC1");
const headerLengthInt = 31;
const off_magic = 0;
const off_size = 1;
const off_flags = 2;
const off_height = 3;
const off_width = 4;
const off_mipmapCount = 7;
const off_pfFlags = 20;
const off_pfFourCC = 21;
const off_RGBBitCount = 22;
const off_RBitMask = 23;
const off_GBitMask = 24;
const off_BBitMask = 25;
const off_ABitMask = 26;
const off_caps2 = 28;
const header = new Int32Array(buffer, 0, headerLengthInt);
if (header[off_magic] !== DDS_MAGIC) {
console.error("THREE.DDSLoader.parse: Invalid magic number in DDS header.");
return dds;
}
if (!header[off_pfFlags] & DDPF_FOURCC) {
console.error("THREE.DDSLoader.parse: Unsupported format, must contain a FourCC code.");
return dds;
}
let blockBytes;
const fourCC = header[off_pfFourCC];
let isRGBAUncompressed = false;
switch (fourCC) {
case FOURCC_DXT1:
blockBytes = 8;
dds.format = RGB_S3TC_DXT1_Format;
break;
case FOURCC_DXT3:
blockBytes = 16;
dds.format = RGBA_S3TC_DXT3_Format;
break;
case FOURCC_DXT5:
blockBytes = 16;
dds.format = RGBA_S3TC_DXT5_Format;
break;
case FOURCC_ETC1:
blockBytes = 8;
dds.format = RGB_ETC1_Format;
break;
default:
if (header[off_RGBBitCount] === 32 && header[off_RBitMask] & 16711680 && header[off_GBitMask] & 65280 && header[off_BBitMask] & 255 && header[off_ABitMask] & 4278190080) {
isRGBAUncompressed = true;
blockBytes = 64;
dds.format = RGBAFormat;
} else {
console.error("THREE.DDSLoader.parse: Unsupported FourCC code ", int32ToFourCC(fourCC));
return dds;
}
}
dds.mipmapCount = 1;
if (header[off_flags] & DDSD_MIPMAPCOUNT && loadMipmaps !== false) {
dds.mipmapCount = Math.max(1, header[off_mipmapCount]);
}
const caps2 = header[off_caps2];
dds.isCubemap = caps2 & DDSCAPS2_CUBEMAP ? true : false;
if (dds.isCubemap && (!(caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) || !(caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) || !(caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) || !(caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) || !(caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) || !(caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ))) {
console.error("THREE.DDSLoader.parse: Incomplete cubemap faces");
return dds;
}
dds.width = header[off_width];
dds.height = header[off_height];
let dataOffset = header[off_size] + 4;
const faces = dds.isCubemap ? 6 : 1;
for (let face = 0; face < faces; face++) {
let width = dds.width;
let height = dds.height;
for (let i = 0; i < dds.mipmapCount; i++) {
let byteArray, dataLength;
if (isRGBAUncompressed) {
byteArray = loadARGBMip(buffer, dataOffset, width, height);
dataLength = byteArray.length;
} else {
dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes;
byteArray = new Uint8Array(buffer, dataOffset, dataLength);
}
const mipmap = { data: byteArray, width, height };
dds.mipmaps.push(mipmap);
dataOffset += dataLength;
width = Math.max(width >> 1, 1);
height = Math.max(height >> 1, 1);
}
}
return dds;
}
}
export {
DDSLoader
};
//# sourceMappingURL=DDSLoader.js.map
File diff suppressed because one or more lines are too long
+342
View File
@@ -0,0 +1,342 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const _taskCache = /* @__PURE__ */ new WeakMap();
class DRACOLoader extends THREE.Loader {
constructor(manager) {
super(manager);
this.decoderPath = "";
this.decoderConfig = {};
this.decoderBinary = null;
this.decoderPending = null;
this.workerLimit = 4;
this.workerPool = [];
this.workerNextTaskID = 1;
this.workerSourceURL = "";
this.defaultAttributeIDs = {
position: "POSITION",
normal: "NORMAL",
color: "COLOR",
uv: "TEX_COORD"
};
this.defaultAttributeTypes = {
position: "Float32Array",
normal: "Float32Array",
color: "Float32Array",
uv: "Float32Array"
};
}
setDecoderPath(path) {
this.decoderPath = path;
return this;
}
setDecoderConfig(config) {
this.decoderConfig = config;
return this;
}
setWorkerLimit(workerLimit) {
this.workerLimit = workerLimit;
return this;
}
load(url, onLoad, onProgress, onError) {
const loader = new THREE.FileLoader(this.manager);
loader.setPath(this.path);
loader.setResponseType("arraybuffer");
loader.setRequestHeader(this.requestHeader);
loader.setWithCredentials(this.withCredentials);
loader.load(
url,
(buffer) => {
const taskConfig = {
attributeIDs: this.defaultAttributeIDs,
attributeTypes: this.defaultAttributeTypes,
useUniqueIDs: false
};
this.decodeGeometry(buffer, taskConfig).then(onLoad).catch(onError);
},
onProgress,
onError
);
}
/** @deprecated Kept for backward-compatibility with previous DRACOLoader versions. */
decodeDracoFile(buffer, callback, attributeIDs, attributeTypes) {
const taskConfig = {
attributeIDs: attributeIDs || this.defaultAttributeIDs,
attributeTypes: attributeTypes || this.defaultAttributeTypes,
useUniqueIDs: !!attributeIDs
};
this.decodeGeometry(buffer, taskConfig).then(callback);
}
decodeGeometry(buffer, taskConfig) {
for (const attribute in taskConfig.attributeTypes) {
const type = taskConfig.attributeTypes[attribute];
if (type.BYTES_PER_ELEMENT !== void 0) {
taskConfig.attributeTypes[attribute] = type.name;
}
}
const taskKey = JSON.stringify(taskConfig);
if (_taskCache.has(buffer)) {
const cachedTask = _taskCache.get(buffer);
if (cachedTask.key === taskKey) {
return cachedTask.promise;
} else if (buffer.byteLength === 0) {
throw new Error(
"THREE.DRACOLoader: Unable to re-decode a buffer with different settings. Buffer has already been transferred."
);
}
}
let worker;
const taskID = this.workerNextTaskID++;
const taskCost = buffer.byteLength;
const geometryPending = this._getWorker(taskID, taskCost).then((_worker) => {
worker = _worker;
return new Promise((resolve, reject) => {
worker._callbacks[taskID] = { resolve, reject };
worker.postMessage({ type: "decode", id: taskID, taskConfig, buffer }, [buffer]);
});
}).then((message) => this._createGeometry(message.geometry));
geometryPending.catch(() => true).then(() => {
if (worker && taskID) {
this._releaseTask(worker, taskID);
}
});
_taskCache.set(buffer, {
key: taskKey,
promise: geometryPending
});
return geometryPending;
}
_createGeometry(geometryData) {
const geometry = new THREE.BufferGeometry();
if (geometryData.index) {
geometry.setIndex(new THREE.BufferAttribute(geometryData.index.array, 1));
}
for (let i = 0; i < geometryData.attributes.length; i++) {
const attribute = geometryData.attributes[i];
const name = attribute.name;
const array = attribute.array;
const itemSize = attribute.itemSize;
geometry.setAttribute(name, new THREE.BufferAttribute(array, itemSize));
}
return geometry;
}
_loadLibrary(url, responseType) {
const loader = new THREE.FileLoader(this.manager);
loader.setPath(this.decoderPath);
loader.setResponseType(responseType);
loader.setWithCredentials(this.withCredentials);
return new Promise((resolve, reject) => {
loader.load(url, resolve, void 0, reject);
});
}
preload() {
this._initDecoder();
return this;
}
_initDecoder() {
if (this.decoderPending)
return this.decoderPending;
const useJS = typeof WebAssembly !== "object" || this.decoderConfig.type === "js";
const librariesPending = [];
if (useJS) {
librariesPending.push(this._loadLibrary("draco_decoder.js", "text"));
} else {
librariesPending.push(this._loadLibrary("draco_wasm_wrapper.js", "text"));
librariesPending.push(this._loadLibrary("draco_decoder.wasm", "arraybuffer"));
}
this.decoderPending = Promise.all(librariesPending).then((libraries) => {
const jsContent = libraries[0];
if (!useJS) {
this.decoderConfig.wasmBinary = libraries[1];
}
const fn = DRACOWorker.toString();
const body = [
"/* draco decoder */",
jsContent,
"",
"/* worker */",
fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"))
].join("\n");
this.workerSourceURL = URL.createObjectURL(new Blob([body]));
});
return this.decoderPending;
}
_getWorker(taskID, taskCost) {
return this._initDecoder().then(() => {
if (this.workerPool.length < this.workerLimit) {
const worker2 = new Worker(this.workerSourceURL);
worker2._callbacks = {};
worker2._taskCosts = {};
worker2._taskLoad = 0;
worker2.postMessage({ type: "init", decoderConfig: this.decoderConfig });
worker2.onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "decode":
worker2._callbacks[message.id].resolve(message);
break;
case "error":
worker2._callbacks[message.id].reject(message);
break;
default:
console.error('THREE.DRACOLoader: Unexpected message, "' + message.type + '"');
}
};
this.workerPool.push(worker2);
} else {
this.workerPool.sort(function(a, b) {
return a._taskLoad > b._taskLoad ? -1 : 1;
});
}
const worker = this.workerPool[this.workerPool.length - 1];
worker._taskCosts[taskID] = taskCost;
worker._taskLoad += taskCost;
return worker;
});
}
_releaseTask(worker, taskID) {
worker._taskLoad -= worker._taskCosts[taskID];
delete worker._callbacks[taskID];
delete worker._taskCosts[taskID];
}
debug() {
console.log(
"Task load: ",
this.workerPool.map((worker) => worker._taskLoad)
);
}
dispose() {
for (let i = 0; i < this.workerPool.length; ++i) {
this.workerPool[i].terminate();
}
this.workerPool.length = 0;
return this;
}
}
function DRACOWorker() {
let decoderConfig;
let decoderPending;
onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "init":
decoderConfig = message.decoderConfig;
decoderPending = new Promise(function(resolve) {
decoderConfig.onModuleLoaded = function(draco) {
resolve({ draco });
};
DracoDecoderModule(decoderConfig);
});
break;
case "decode":
const buffer = message.buffer;
const taskConfig = message.taskConfig;
decoderPending.then((module2) => {
const draco = module2.draco;
const decoder = new draco.Decoder();
const decoderBuffer = new draco.DecoderBuffer();
decoderBuffer.Init(new Int8Array(buffer), buffer.byteLength);
try {
const geometry = decodeGeometry(draco, decoder, decoderBuffer, taskConfig);
const buffers = geometry.attributes.map((attr) => attr.array.buffer);
if (geometry.index)
buffers.push(geometry.index.array.buffer);
self.postMessage({ type: "decode", id: message.id, geometry }, buffers);
} catch (error) {
console.error(error);
self.postMessage({ type: "error", id: message.id, error: error.message });
} finally {
draco.destroy(decoderBuffer);
draco.destroy(decoder);
}
});
break;
}
};
function decodeGeometry(draco, decoder, decoderBuffer, taskConfig) {
const attributeIDs = taskConfig.attributeIDs;
const attributeTypes = taskConfig.attributeTypes;
let dracoGeometry;
let decodingStatus;
const geometryType = decoder.GetEncodedGeometryType(decoderBuffer);
if (geometryType === draco.TRIANGULAR_MESH) {
dracoGeometry = new draco.Mesh();
decodingStatus = decoder.DecodeBufferToMesh(decoderBuffer, dracoGeometry);
} else if (geometryType === draco.POINT_CLOUD) {
dracoGeometry = new draco.PointCloud();
decodingStatus = decoder.DecodeBufferToPointCloud(decoderBuffer, dracoGeometry);
} else {
throw new Error("THREE.DRACOLoader: Unexpected geometry type.");
}
if (!decodingStatus.ok() || dracoGeometry.ptr === 0) {
throw new Error("THREE.DRACOLoader: Decoding failed: " + decodingStatus.error_msg());
}
const geometry = { index: null, attributes: [] };
for (const attributeName in attributeIDs) {
const attributeType = self[attributeTypes[attributeName]];
let attribute;
let attributeID;
if (taskConfig.useUniqueIDs) {
attributeID = attributeIDs[attributeName];
attribute = decoder.GetAttributeByUniqueId(dracoGeometry, attributeID);
} else {
attributeID = decoder.GetAttributeId(dracoGeometry, draco[attributeIDs[attributeName]]);
if (attributeID === -1)
continue;
attribute = decoder.GetAttribute(dracoGeometry, attributeID);
}
geometry.attributes.push(decodeAttribute(draco, decoder, dracoGeometry, attributeName, attributeType, attribute));
}
if (geometryType === draco.TRIANGULAR_MESH) {
geometry.index = decodeIndex(draco, decoder, dracoGeometry);
}
draco.destroy(dracoGeometry);
return geometry;
}
function decodeIndex(draco, decoder, dracoGeometry) {
const numFaces = dracoGeometry.num_faces();
const numIndices = numFaces * 3;
const byteLength = numIndices * 4;
const ptr = draco._malloc(byteLength);
decoder.GetTrianglesUInt32Array(dracoGeometry, byteLength, ptr);
const index = new Uint32Array(draco.HEAPF32.buffer, ptr, numIndices).slice();
draco._free(ptr);
return { array: index, itemSize: 1 };
}
function decodeAttribute(draco, decoder, dracoGeometry, attributeName, attributeType, attribute) {
const numComponents = attribute.num_components();
const numPoints = dracoGeometry.num_points();
const numValues = numPoints * numComponents;
const byteLength = numValues * attributeType.BYTES_PER_ELEMENT;
const dataType = getDracoDataType(draco, attributeType);
const ptr = draco._malloc(byteLength);
decoder.GetAttributeDataArrayForAllPoints(dracoGeometry, attribute, dataType, byteLength, ptr);
const array = new attributeType(draco.HEAPF32.buffer, ptr, numValues).slice();
draco._free(ptr);
return {
name: attributeName,
array,
itemSize: numComponents
};
}
function getDracoDataType(draco, attributeType) {
switch (attributeType) {
case Float32Array:
return draco.DT_FLOAT32;
case Int8Array:
return draco.DT_INT8;
case Int16Array:
return draco.DT_INT16;
case Int32Array:
return draco.DT_INT32;
case Uint8Array:
return draco.DT_UINT8;
case Uint16Array:
return draco.DT_UINT16;
case Uint32Array:
return draco.DT_UINT32;
}
}
}
exports.DRACOLoader = DRACOLoader;
//# sourceMappingURL=DRACOLoader.cjs.map
File diff suppressed because one or more lines are too long
+18
View File
@@ -0,0 +1,18 @@
import { Loader, LoadingManager, BufferGeometry } from 'three'
export class DRACOLoader extends Loader {
constructor(manager?: LoadingManager)
load(
url: string,
onLoad: (geometry: BufferGeometry) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<BufferGeometry>
setDecoderPath(path: string): DRACOLoader
setDecoderConfig(config: object): DRACOLoader
setWorkerLimit(workerLimit: number): DRACOLoader
preload(): DRACOLoader
dispose(): DRACOLoader
}
+342
View File
@@ -0,0 +1,342 @@
import { Loader, FileLoader, BufferGeometry, BufferAttribute } from "three";
const _taskCache = /* @__PURE__ */ new WeakMap();
class DRACOLoader extends Loader {
constructor(manager) {
super(manager);
this.decoderPath = "";
this.decoderConfig = {};
this.decoderBinary = null;
this.decoderPending = null;
this.workerLimit = 4;
this.workerPool = [];
this.workerNextTaskID = 1;
this.workerSourceURL = "";
this.defaultAttributeIDs = {
position: "POSITION",
normal: "NORMAL",
color: "COLOR",
uv: "TEX_COORD"
};
this.defaultAttributeTypes = {
position: "Float32Array",
normal: "Float32Array",
color: "Float32Array",
uv: "Float32Array"
};
}
setDecoderPath(path) {
this.decoderPath = path;
return this;
}
setDecoderConfig(config) {
this.decoderConfig = config;
return this;
}
setWorkerLimit(workerLimit) {
this.workerLimit = workerLimit;
return this;
}
load(url, onLoad, onProgress, onError) {
const loader = new FileLoader(this.manager);
loader.setPath(this.path);
loader.setResponseType("arraybuffer");
loader.setRequestHeader(this.requestHeader);
loader.setWithCredentials(this.withCredentials);
loader.load(
url,
(buffer) => {
const taskConfig = {
attributeIDs: this.defaultAttributeIDs,
attributeTypes: this.defaultAttributeTypes,
useUniqueIDs: false
};
this.decodeGeometry(buffer, taskConfig).then(onLoad).catch(onError);
},
onProgress,
onError
);
}
/** @deprecated Kept for backward-compatibility with previous DRACOLoader versions. */
decodeDracoFile(buffer, callback, attributeIDs, attributeTypes) {
const taskConfig = {
attributeIDs: attributeIDs || this.defaultAttributeIDs,
attributeTypes: attributeTypes || this.defaultAttributeTypes,
useUniqueIDs: !!attributeIDs
};
this.decodeGeometry(buffer, taskConfig).then(callback);
}
decodeGeometry(buffer, taskConfig) {
for (const attribute in taskConfig.attributeTypes) {
const type = taskConfig.attributeTypes[attribute];
if (type.BYTES_PER_ELEMENT !== void 0) {
taskConfig.attributeTypes[attribute] = type.name;
}
}
const taskKey = JSON.stringify(taskConfig);
if (_taskCache.has(buffer)) {
const cachedTask = _taskCache.get(buffer);
if (cachedTask.key === taskKey) {
return cachedTask.promise;
} else if (buffer.byteLength === 0) {
throw new Error(
"THREE.DRACOLoader: Unable to re-decode a buffer with different settings. Buffer has already been transferred."
);
}
}
let worker;
const taskID = this.workerNextTaskID++;
const taskCost = buffer.byteLength;
const geometryPending = this._getWorker(taskID, taskCost).then((_worker) => {
worker = _worker;
return new Promise((resolve, reject) => {
worker._callbacks[taskID] = { resolve, reject };
worker.postMessage({ type: "decode", id: taskID, taskConfig, buffer }, [buffer]);
});
}).then((message) => this._createGeometry(message.geometry));
geometryPending.catch(() => true).then(() => {
if (worker && taskID) {
this._releaseTask(worker, taskID);
}
});
_taskCache.set(buffer, {
key: taskKey,
promise: geometryPending
});
return geometryPending;
}
_createGeometry(geometryData) {
const geometry = new BufferGeometry();
if (geometryData.index) {
geometry.setIndex(new BufferAttribute(geometryData.index.array, 1));
}
for (let i = 0; i < geometryData.attributes.length; i++) {
const attribute = geometryData.attributes[i];
const name = attribute.name;
const array = attribute.array;
const itemSize = attribute.itemSize;
geometry.setAttribute(name, new BufferAttribute(array, itemSize));
}
return geometry;
}
_loadLibrary(url, responseType) {
const loader = new FileLoader(this.manager);
loader.setPath(this.decoderPath);
loader.setResponseType(responseType);
loader.setWithCredentials(this.withCredentials);
return new Promise((resolve, reject) => {
loader.load(url, resolve, void 0, reject);
});
}
preload() {
this._initDecoder();
return this;
}
_initDecoder() {
if (this.decoderPending)
return this.decoderPending;
const useJS = typeof WebAssembly !== "object" || this.decoderConfig.type === "js";
const librariesPending = [];
if (useJS) {
librariesPending.push(this._loadLibrary("draco_decoder.js", "text"));
} else {
librariesPending.push(this._loadLibrary("draco_wasm_wrapper.js", "text"));
librariesPending.push(this._loadLibrary("draco_decoder.wasm", "arraybuffer"));
}
this.decoderPending = Promise.all(librariesPending).then((libraries) => {
const jsContent = libraries[0];
if (!useJS) {
this.decoderConfig.wasmBinary = libraries[1];
}
const fn = DRACOWorker.toString();
const body = [
"/* draco decoder */",
jsContent,
"",
"/* worker */",
fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"))
].join("\n");
this.workerSourceURL = URL.createObjectURL(new Blob([body]));
});
return this.decoderPending;
}
_getWorker(taskID, taskCost) {
return this._initDecoder().then(() => {
if (this.workerPool.length < this.workerLimit) {
const worker2 = new Worker(this.workerSourceURL);
worker2._callbacks = {};
worker2._taskCosts = {};
worker2._taskLoad = 0;
worker2.postMessage({ type: "init", decoderConfig: this.decoderConfig });
worker2.onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "decode":
worker2._callbacks[message.id].resolve(message);
break;
case "error":
worker2._callbacks[message.id].reject(message);
break;
default:
console.error('THREE.DRACOLoader: Unexpected message, "' + message.type + '"');
}
};
this.workerPool.push(worker2);
} else {
this.workerPool.sort(function(a, b) {
return a._taskLoad > b._taskLoad ? -1 : 1;
});
}
const worker = this.workerPool[this.workerPool.length - 1];
worker._taskCosts[taskID] = taskCost;
worker._taskLoad += taskCost;
return worker;
});
}
_releaseTask(worker, taskID) {
worker._taskLoad -= worker._taskCosts[taskID];
delete worker._callbacks[taskID];
delete worker._taskCosts[taskID];
}
debug() {
console.log(
"Task load: ",
this.workerPool.map((worker) => worker._taskLoad)
);
}
dispose() {
for (let i = 0; i < this.workerPool.length; ++i) {
this.workerPool[i].terminate();
}
this.workerPool.length = 0;
return this;
}
}
function DRACOWorker() {
let decoderConfig;
let decoderPending;
onmessage = function(e) {
const message = e.data;
switch (message.type) {
case "init":
decoderConfig = message.decoderConfig;
decoderPending = new Promise(function(resolve) {
decoderConfig.onModuleLoaded = function(draco) {
resolve({ draco });
};
DracoDecoderModule(decoderConfig);
});
break;
case "decode":
const buffer = message.buffer;
const taskConfig = message.taskConfig;
decoderPending.then((module) => {
const draco = module.draco;
const decoder = new draco.Decoder();
const decoderBuffer = new draco.DecoderBuffer();
decoderBuffer.Init(new Int8Array(buffer), buffer.byteLength);
try {
const geometry = decodeGeometry(draco, decoder, decoderBuffer, taskConfig);
const buffers = geometry.attributes.map((attr) => attr.array.buffer);
if (geometry.index)
buffers.push(geometry.index.array.buffer);
self.postMessage({ type: "decode", id: message.id, geometry }, buffers);
} catch (error) {
console.error(error);
self.postMessage({ type: "error", id: message.id, error: error.message });
} finally {
draco.destroy(decoderBuffer);
draco.destroy(decoder);
}
});
break;
}
};
function decodeGeometry(draco, decoder, decoderBuffer, taskConfig) {
const attributeIDs = taskConfig.attributeIDs;
const attributeTypes = taskConfig.attributeTypes;
let dracoGeometry;
let decodingStatus;
const geometryType = decoder.GetEncodedGeometryType(decoderBuffer);
if (geometryType === draco.TRIANGULAR_MESH) {
dracoGeometry = new draco.Mesh();
decodingStatus = decoder.DecodeBufferToMesh(decoderBuffer, dracoGeometry);
} else if (geometryType === draco.POINT_CLOUD) {
dracoGeometry = new draco.PointCloud();
decodingStatus = decoder.DecodeBufferToPointCloud(decoderBuffer, dracoGeometry);
} else {
throw new Error("THREE.DRACOLoader: Unexpected geometry type.");
}
if (!decodingStatus.ok() || dracoGeometry.ptr === 0) {
throw new Error("THREE.DRACOLoader: Decoding failed: " + decodingStatus.error_msg());
}
const geometry = { index: null, attributes: [] };
for (const attributeName in attributeIDs) {
const attributeType = self[attributeTypes[attributeName]];
let attribute;
let attributeID;
if (taskConfig.useUniqueIDs) {
attributeID = attributeIDs[attributeName];
attribute = decoder.GetAttributeByUniqueId(dracoGeometry, attributeID);
} else {
attributeID = decoder.GetAttributeId(dracoGeometry, draco[attributeIDs[attributeName]]);
if (attributeID === -1)
continue;
attribute = decoder.GetAttribute(dracoGeometry, attributeID);
}
geometry.attributes.push(decodeAttribute(draco, decoder, dracoGeometry, attributeName, attributeType, attribute));
}
if (geometryType === draco.TRIANGULAR_MESH) {
geometry.index = decodeIndex(draco, decoder, dracoGeometry);
}
draco.destroy(dracoGeometry);
return geometry;
}
function decodeIndex(draco, decoder, dracoGeometry) {
const numFaces = dracoGeometry.num_faces();
const numIndices = numFaces * 3;
const byteLength = numIndices * 4;
const ptr = draco._malloc(byteLength);
decoder.GetTrianglesUInt32Array(dracoGeometry, byteLength, ptr);
const index = new Uint32Array(draco.HEAPF32.buffer, ptr, numIndices).slice();
draco._free(ptr);
return { array: index, itemSize: 1 };
}
function decodeAttribute(draco, decoder, dracoGeometry, attributeName, attributeType, attribute) {
const numComponents = attribute.num_components();
const numPoints = dracoGeometry.num_points();
const numValues = numPoints * numComponents;
const byteLength = numValues * attributeType.BYTES_PER_ELEMENT;
const dataType = getDracoDataType(draco, attributeType);
const ptr = draco._malloc(byteLength);
decoder.GetAttributeDataArrayForAllPoints(dracoGeometry, attribute, dataType, byteLength, ptr);
const array = new attributeType(draco.HEAPF32.buffer, ptr, numValues).slice();
draco._free(ptr);
return {
name: attributeName,
array,
itemSize: numComponents
};
}
function getDracoDataType(draco, attributeType) {
switch (attributeType) {
case Float32Array:
return draco.DT_FLOAT32;
case Int8Array:
return draco.DT_INT8;
case Int16Array:
return draco.DT_INT16;
case Int32Array:
return draco.DT_INT32;
case Uint8Array:
return draco.DT_UINT8;
case Uint16Array:
return draco.DT_UINT16;
case Uint32Array:
return draco.DT_UINT32;
}
}
}
export {
DRACOLoader
};
//# sourceMappingURL=DRACOLoader.js.map
File diff suppressed because one or more lines are too long
+1358
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+18
View File
@@ -0,0 +1,18 @@
import { LoadingManager, DataTextureLoader, TextureDataType, PixelFormat } from 'three'
export interface EXR {
header: object
width: number
height: number
data: Float32Array
format: PixelFormat
type: TextureDataType
}
export class EXRLoader extends DataTextureLoader {
constructor(manager?: LoadingManager)
type: TextureDataType
parse(buffer: ArrayBuffer): EXR
setDataType(type: TextureDataType): this
}
+1358
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+2457
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+14
View File
@@ -0,0 +1,14 @@
import { Loader, Group, LoadingManager } from 'three'
export class FBXLoader extends Loader {
constructor(manager?: LoadingManager)
load(
url: string,
onLoad: (object: Group) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Group>
parse(FBXBuffer: ArrayBuffer | string, path: string): Group
}
+2457
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+124
View File
@@ -0,0 +1,124 @@
"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");
class FontLoader extends THREE.Loader {
constructor(manager) {
super(manager);
}
load(url, onLoad, onProgress, onError) {
const loader = new THREE.FileLoader(this.manager);
loader.setPath(this.path);
loader.setRequestHeader(this.requestHeader);
loader.setWithCredentials(this.withCredentials);
loader.load(
url,
(response) => {
if (typeof response !== "string")
throw new Error("unsupported data type");
const json = JSON.parse(response);
const font = this.parse(json);
if (onLoad)
onLoad(font);
},
onProgress,
onError
);
}
loadAsync(url, onProgress) {
return super.loadAsync(url, onProgress);
}
parse(json) {
return new Font(json);
}
}
class Font {
constructor(data) {
__publicField(this, "data");
__publicField(this, "isFont", true);
__publicField(this, "type", "Font");
this.data = data;
}
generateShapes(text, size = 100, _options) {
const shapes = [];
const options = { letterSpacing: 0, lineHeight: 1, ..._options };
const paths = createPaths(text, size, this.data, options);
for (let p = 0, pl = paths.length; p < pl; p++) {
Array.prototype.push.apply(shapes, paths[p].toShapes(false));
}
return shapes;
}
}
function createPaths(text, size, data, options) {
const chars = Array.from(text);
const scale = size / data.resolution;
const line_height = (data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness) * scale;
const paths = [];
let offsetX = 0, offsetY = 0;
for (let i = 0; i < chars.length; i++) {
const char = chars[i];
if (char === "\n") {
offsetX = 0;
offsetY -= line_height * options.lineHeight;
} else {
const ret = createPath(char, scale, offsetX, offsetY, data);
if (ret) {
offsetX += ret.offsetX + options.letterSpacing;
paths.push(ret.path);
}
}
}
return paths;
}
function createPath(char, scale, offsetX, offsetY, data) {
const glyph = data.glyphs[char] || data.glyphs["?"];
if (!glyph) {
console.error('THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + ".");
return;
}
const path = new THREE.ShapePath();
let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
if (glyph.o) {
const outline = glyph._cachedOutline || (glyph._cachedOutline = glyph.o.split(" "));
for (let i = 0, l = outline.length; i < l; ) {
const action = outline[i++];
switch (action) {
case "m":
x = parseInt(outline[i++]) * scale + offsetX;
y = parseInt(outline[i++]) * scale + offsetY;
path.moveTo(x, y);
break;
case "l":
x = parseInt(outline[i++]) * scale + offsetX;
y = parseInt(outline[i++]) * scale + offsetY;
path.lineTo(x, y);
break;
case "q":
cpx = parseInt(outline[i++]) * scale + offsetX;
cpy = parseInt(outline[i++]) * scale + offsetY;
cpx1 = parseInt(outline[i++]) * scale + offsetX;
cpy1 = parseInt(outline[i++]) * scale + offsetY;
path.quadraticCurveTo(cpx1, cpy1, cpx, cpy);
break;
case "b":
cpx = parseInt(outline[i++]) * scale + offsetX;
cpy = parseInt(outline[i++]) * scale + offsetY;
cpx1 = parseInt(outline[i++]) * scale + offsetX;
cpy1 = parseInt(outline[i++]) * scale + offsetY;
cpx2 = parseInt(outline[i++]) * scale + offsetX;
cpy2 = parseInt(outline[i++]) * scale + offsetY;
path.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, cpx, cpy);
break;
}
}
}
return { offsetX: glyph.ha * scale, path };
}
exports.Font = Font;
exports.FontLoader = FontLoader;
//# sourceMappingURL=FontLoader.cjs.map
File diff suppressed because one or more lines are too long
+37
View File
@@ -0,0 +1,37 @@
import { Loader } from 'three';
import type { LoadingManager, Shape } from 'three';
type Options = {
lineHeight: number;
letterSpacing: number;
};
export declare class FontLoader extends Loader {
constructor(manager?: LoadingManager);
load(url: string, onLoad?: (responseFont: Font) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Font>;
parse(json: FontData): Font;
}
type Glyph = {
_cachedOutline: string[];
ha: number;
o: string;
};
type FontData = {
boundingBox: {
yMax: number;
yMin: number;
};
familyName: string;
glyphs: {
[k: string]: Glyph;
};
resolution: number;
underlineThickness: number;
};
export declare class Font {
data: FontData;
isFont: boolean;
type: string;
constructor(data: FontData);
generateShapes(text: string, size?: number, _options?: Partial<Options>): Shape[];
}
export {};
+124
View File
@@ -0,0 +1,124 @@
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;
};
import { Loader, FileLoader, ShapePath } from "three";
class FontLoader extends Loader {
constructor(manager) {
super(manager);
}
load(url, onLoad, onProgress, onError) {
const loader = new FileLoader(this.manager);
loader.setPath(this.path);
loader.setRequestHeader(this.requestHeader);
loader.setWithCredentials(this.withCredentials);
loader.load(
url,
(response) => {
if (typeof response !== "string")
throw new Error("unsupported data type");
const json = JSON.parse(response);
const font = this.parse(json);
if (onLoad)
onLoad(font);
},
onProgress,
onError
);
}
loadAsync(url, onProgress) {
return super.loadAsync(url, onProgress);
}
parse(json) {
return new Font(json);
}
}
class Font {
constructor(data) {
__publicField(this, "data");
__publicField(this, "isFont", true);
__publicField(this, "type", "Font");
this.data = data;
}
generateShapes(text, size = 100, _options) {
const shapes = [];
const options = { letterSpacing: 0, lineHeight: 1, ..._options };
const paths = createPaths(text, size, this.data, options);
for (let p = 0, pl = paths.length; p < pl; p++) {
Array.prototype.push.apply(shapes, paths[p].toShapes(false));
}
return shapes;
}
}
function createPaths(text, size, data, options) {
const chars = Array.from(text);
const scale = size / data.resolution;
const line_height = (data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness) * scale;
const paths = [];
let offsetX = 0, offsetY = 0;
for (let i = 0; i < chars.length; i++) {
const char = chars[i];
if (char === "\n") {
offsetX = 0;
offsetY -= line_height * options.lineHeight;
} else {
const ret = createPath(char, scale, offsetX, offsetY, data);
if (ret) {
offsetX += ret.offsetX + options.letterSpacing;
paths.push(ret.path);
}
}
}
return paths;
}
function createPath(char, scale, offsetX, offsetY, data) {
const glyph = data.glyphs[char] || data.glyphs["?"];
if (!glyph) {
console.error('THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + ".");
return;
}
const path = new ShapePath();
let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
if (glyph.o) {
const outline = glyph._cachedOutline || (glyph._cachedOutline = glyph.o.split(" "));
for (let i = 0, l = outline.length; i < l; ) {
const action = outline[i++];
switch (action) {
case "m":
x = parseInt(outline[i++]) * scale + offsetX;
y = parseInt(outline[i++]) * scale + offsetY;
path.moveTo(x, y);
break;
case "l":
x = parseInt(outline[i++]) * scale + offsetX;
y = parseInt(outline[i++]) * scale + offsetY;
path.lineTo(x, y);
break;
case "q":
cpx = parseInt(outline[i++]) * scale + offsetX;
cpy = parseInt(outline[i++]) * scale + offsetY;
cpx1 = parseInt(outline[i++]) * scale + offsetX;
cpy1 = parseInt(outline[i++]) * scale + offsetY;
path.quadraticCurveTo(cpx1, cpy1, cpx, cpy);
break;
case "b":
cpx = parseInt(outline[i++]) * scale + offsetX;
cpy = parseInt(outline[i++]) * scale + offsetY;
cpx1 = parseInt(outline[i++]) * scale + offsetX;
cpy1 = parseInt(outline[i++]) * scale + offsetY;
cpx2 = parseInt(outline[i++]) * scale + offsetX;
cpy2 = parseInt(outline[i++]) * scale + offsetY;
path.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, cpx, cpy);
break;
}
}
}
return { offsetX: glyph.ha * scale, path };
}
export {
Font,
FontLoader
};
//# sourceMappingURL=FontLoader.js.map
File diff suppressed because one or more lines are too long
+143
View File
@@ -0,0 +1,143 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
class GCodeLoader extends THREE.Loader {
constructor(manager) {
super(manager);
this.splitLayer = false;
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader = new THREE.FileLoader(scope.manager);
loader.setPath(scope.path);
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
function(text) {
try {
onLoad(scope.parse(text));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(data) {
let state = { x: 0, y: 0, z: 0, e: 0, f: 0, extruding: false, relative: false };
let layers = [];
let currentLayer = void 0;
const pathMaterial = new THREE.LineBasicMaterial({ color: 16711680 });
pathMaterial.name = "path";
const extrudingMaterial = new THREE.LineBasicMaterial({ color: 65280 });
extrudingMaterial.name = "extruded";
function newLayer(line) {
currentLayer = { vertex: [], pathVertex: [], z: line.z };
layers.push(currentLayer);
}
function addSegment(p1, p2) {
if (currentLayer === void 0) {
newLayer(p1);
}
if (state.extruding) {
currentLayer.vertex.push(p1.x, p1.y, p1.z);
currentLayer.vertex.push(p2.x, p2.y, p2.z);
} else {
currentLayer.pathVertex.push(p1.x, p1.y, p1.z);
currentLayer.pathVertex.push(p2.x, p2.y, p2.z);
}
}
function delta(v1, v2) {
return state.relative ? v2 : v2 - v1;
}
function absolute(v1, v2) {
return state.relative ? v1 + v2 : v2;
}
let lines = data.replace(/;.+/g, "").split("\n");
for (let i = 0; i < lines.length; i++) {
let tokens = lines[i].split(" ");
let cmd = tokens[0].toUpperCase();
let args = {};
tokens.splice(1).forEach(function(token) {
if (token[0] !== void 0) {
let key = token[0].toLowerCase();
let value = parseFloat(token.substring(1));
args[key] = value;
}
});
if (cmd === "G0" || cmd === "G1") {
let line = {
x: args.x !== void 0 ? absolute(state.x, args.x) : state.x,
y: args.y !== void 0 ? absolute(state.y, args.y) : state.y,
z: args.z !== void 0 ? absolute(state.z, args.z) : state.z,
e: args.e !== void 0 ? absolute(state.e, args.e) : state.e,
f: args.f !== void 0 ? absolute(state.f, args.f) : state.f
};
if (delta(state.e, line.e) > 0) {
line.extruding = delta(state.e, line.e) > 0;
if (currentLayer == void 0 || line.z != currentLayer.z) {
newLayer(line);
}
}
addSegment(state, line);
state = line;
} else if (cmd === "G2" || cmd === "G3")
;
else if (cmd === "G90") {
state.relative = false;
} else if (cmd === "G91") {
state.relative = true;
} else if (cmd === "G92") {
let line = state;
line.x = args.x !== void 0 ? args.x : line.x;
line.y = args.y !== void 0 ? args.y : line.y;
line.z = args.z !== void 0 ? args.z : line.z;
line.e = args.e !== void 0 ? args.e : line.e;
state = line;
} else
;
}
function addObject(vertex, extruding, i) {
let geometry = new THREE.BufferGeometry();
geometry.setAttribute("position", new THREE.Float32BufferAttribute(vertex, 3));
let segments = new THREE.LineSegments(geometry, extruding ? extrudingMaterial : pathMaterial);
segments.name = "layer" + i;
object.add(segments);
}
const object = new THREE.Group();
object.name = "gcode";
if (this.splitLayer) {
for (let i = 0; i < layers.length; i++) {
let layer = layers[i];
addObject(layer.vertex, true, i);
addObject(layer.pathVertex, false, i);
}
} else {
const vertex = [], pathVertex = [];
for (let i = 0; i < layers.length; i++) {
let layer = layers[i];
let layerVertex = layer.vertex;
let layerPathVertex = layer.pathVertex;
for (let j = 0; j < layerVertex.length; j++) {
vertex.push(layerVertex[j]);
}
for (let j = 0; j < layerPathVertex.length; j++) {
pathVertex.push(layerPathVertex[j]);
}
}
addObject(vertex, true, layers.length);
addObject(pathVertex, false, layers.length);
}
object.quaternion.setFromEuler(new THREE.Euler(-Math.PI / 2, 0, 0));
return object;
}
}
exports.GCodeLoader = GCodeLoader;
//# sourceMappingURL=GCodeLoader.cjs.map
File diff suppressed because one or more lines are too long
+15
View File
@@ -0,0 +1,15 @@
import { Loader, Group, LoadingManager } from 'three'
export class GCodeLoader extends Loader {
constructor(manager?: LoadingManager)
splitLayer: boolean
load(
url: string,
onLoad: (object: Group) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Group>
parse(data: string): Group
}
+143
View File
@@ -0,0 +1,143 @@
import { Loader, FileLoader, LineBasicMaterial, Group, Euler, BufferGeometry, Float32BufferAttribute, LineSegments } from "three";
class GCodeLoader extends Loader {
constructor(manager) {
super(manager);
this.splitLayer = false;
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader = new FileLoader(scope.manager);
loader.setPath(scope.path);
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
function(text) {
try {
onLoad(scope.parse(text));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(data) {
let state = { x: 0, y: 0, z: 0, e: 0, f: 0, extruding: false, relative: false };
let layers = [];
let currentLayer = void 0;
const pathMaterial = new LineBasicMaterial({ color: 16711680 });
pathMaterial.name = "path";
const extrudingMaterial = new LineBasicMaterial({ color: 65280 });
extrudingMaterial.name = "extruded";
function newLayer(line) {
currentLayer = { vertex: [], pathVertex: [], z: line.z };
layers.push(currentLayer);
}
function addSegment(p1, p2) {
if (currentLayer === void 0) {
newLayer(p1);
}
if (state.extruding) {
currentLayer.vertex.push(p1.x, p1.y, p1.z);
currentLayer.vertex.push(p2.x, p2.y, p2.z);
} else {
currentLayer.pathVertex.push(p1.x, p1.y, p1.z);
currentLayer.pathVertex.push(p2.x, p2.y, p2.z);
}
}
function delta(v1, v2) {
return state.relative ? v2 : v2 - v1;
}
function absolute(v1, v2) {
return state.relative ? v1 + v2 : v2;
}
let lines = data.replace(/;.+/g, "").split("\n");
for (let i = 0; i < lines.length; i++) {
let tokens = lines[i].split(" ");
let cmd = tokens[0].toUpperCase();
let args = {};
tokens.splice(1).forEach(function(token) {
if (token[0] !== void 0) {
let key = token[0].toLowerCase();
let value = parseFloat(token.substring(1));
args[key] = value;
}
});
if (cmd === "G0" || cmd === "G1") {
let line = {
x: args.x !== void 0 ? absolute(state.x, args.x) : state.x,
y: args.y !== void 0 ? absolute(state.y, args.y) : state.y,
z: args.z !== void 0 ? absolute(state.z, args.z) : state.z,
e: args.e !== void 0 ? absolute(state.e, args.e) : state.e,
f: args.f !== void 0 ? absolute(state.f, args.f) : state.f
};
if (delta(state.e, line.e) > 0) {
line.extruding = delta(state.e, line.e) > 0;
if (currentLayer == void 0 || line.z != currentLayer.z) {
newLayer(line);
}
}
addSegment(state, line);
state = line;
} else if (cmd === "G2" || cmd === "G3")
;
else if (cmd === "G90") {
state.relative = false;
} else if (cmd === "G91") {
state.relative = true;
} else if (cmd === "G92") {
let line = state;
line.x = args.x !== void 0 ? args.x : line.x;
line.y = args.y !== void 0 ? args.y : line.y;
line.z = args.z !== void 0 ? args.z : line.z;
line.e = args.e !== void 0 ? args.e : line.e;
state = line;
} else
;
}
function addObject(vertex, extruding, i) {
let geometry = new BufferGeometry();
geometry.setAttribute("position", new Float32BufferAttribute(vertex, 3));
let segments = new LineSegments(geometry, extruding ? extrudingMaterial : pathMaterial);
segments.name = "layer" + i;
object.add(segments);
}
const object = new Group();
object.name = "gcode";
if (this.splitLayer) {
for (let i = 0; i < layers.length; i++) {
let layer = layers[i];
addObject(layer.vertex, true, i);
addObject(layer.pathVertex, false, i);
}
} else {
const vertex = [], pathVertex = [];
for (let i = 0; i < layers.length; i++) {
let layer = layers[i];
let layerVertex = layer.vertex;
let layerPathVertex = layer.pathVertex;
for (let j = 0; j < layerVertex.length; j++) {
vertex.push(layerVertex[j]);
}
for (let j = 0; j < layerPathVertex.length; j++) {
pathVertex.push(layerPathVertex[j]);
}
}
addObject(vertex, true, layers.length);
addObject(pathVertex, false, layers.length);
}
object.quaternion.setFromEuler(new Euler(-Math.PI / 2, 0, 0));
return object;
}
}
export {
GCodeLoader
};
//# sourceMappingURL=GCodeLoader.js.map
File diff suppressed because one or more lines are too long
+2625
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+155
View File
@@ -0,0 +1,155 @@
import {
AnimationClip,
BufferAttribute,
BufferGeometry,
Camera,
Group,
InterleavedBufferAttribute,
LoadingManager,
Mesh,
MeshStandardMaterial,
Object3D,
Material,
SkinnedMesh,
Texture,
TextureLoader,
FileLoader,
ImageBitmapLoader,
Skeleton,
Loader,
} from 'three'
import { DRACOLoader } from './DRACOLoader'
import { KTX2Loader } from './KTX2Loader'
export interface GLTF {
animations: AnimationClip[]
scene: Group
scenes: Group[]
cameras: Camera[]
asset: {
copyright?: string | undefined
generator?: string | undefined
version?: string | undefined
minVersion?: string | undefined
extensions?: any
extras?: any
}
parser: GLTFParser
userData: any
}
export class GLTFLoader extends Loader {
constructor(manager?: LoadingManager)
dracoLoader: DRACOLoader | null
load(
url: string,
onLoad: (gltf: GLTF) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<GLTF>
setDRACOLoader(dracoLoader: DRACOLoader): GLTFLoader
register(callback: (parser: GLTFParser) => GLTFLoaderPlugin): GLTFLoader
unregister(callback: (parser: GLTFParser) => GLTFLoaderPlugin): GLTFLoader
setKTX2Loader(ktx2Loader: KTX2Loader): GLTFLoader
setMeshoptDecoder(meshoptDecoder: /* MeshoptDecoder */ any): GLTFLoader
parse(
data: ArrayBuffer | string,
path: string,
onLoad: (gltf: GLTF) => void,
onError?: (event: ErrorEvent) => void,
): void
parseAsync(data: ArrayBuffer | string, path: string): Promise<GLTF>
}
export type GLTFReferenceType = 'materials' | 'nodes' | 'textures' | 'meshes'
export interface GLTFReference {
materials?: number
nodes?: number
textures?: number
meshes?: number
}
export class GLTFParser {
json: any
options: {
path: string
manager: LoadingManager
ktx2Loader: KTX2Loader
meshoptDecoder: /* MeshoptDecoder */ any
crossOrigin: string
requestHeader: { [header: string]: string }
}
fileLoader: FileLoader
textureLoader: TextureLoader | ImageBitmapLoader
plugins: { [name: string]: GLTFLoaderPlugin }
extensions: { [name: string]: any }
associations: Map<Object3D | Material | Texture, GLTFReference>
setExtensions(extensions: { [name: string]: any }): void
setPlugins(plugins: { [name: string]: GLTFLoaderPlugin }): void
parse(onLoad: (gltf: GLTF) => void, onError?: (event: ErrorEvent) => void): void
getDependency: (type: string, index: number) => Promise<any>
getDependencies: (type: string) => Promise<any[]>
loadBuffer: (bufferIndex: number) => Promise<ArrayBuffer>
loadBufferView: (bufferViewIndex: number) => Promise<ArrayBuffer>
loadAccessor: (accessorIndex: number) => Promise<BufferAttribute | InterleavedBufferAttribute>
loadTexture: (textureIndex: number) => Promise<Texture>
loadTextureImage: (textureIndex: number, sourceIndex: number, loader: Loader) => Promise<Texture>
loadImageSource: (sourceIndex: number, loader: Loader) => Promise<Texture>
assignTexture: (
materialParams: { [key: string]: any },
mapName: string,
mapDef: {
index: number
texCoord?: number | undefined
extensions?: any
},
) => Promise<void>
assignFinalMaterial: (object: Mesh) => void
getMaterialType: () => typeof MeshStandardMaterial
loadMaterial: (materialIndex: number) => Promise<Material>
createUniqueName: (originalName: string) => string
createNodeMesh: (nodeIndex: number) => Promise<Group | Mesh | SkinnedMesh>
loadGeometries: (
/**
* GLTF.Primitive[]
* See: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/schema/mesh.primitive.schema.json
*/
primitives: Array<{ [key: string]: any }>,
) => Promise<BufferGeometry[]>
loadMesh: (meshIndex: number) => Promise<Group | Mesh | SkinnedMesh>
loadCamera: (cameraIndex: number) => Promise<Camera>
loadSkin: (skinIndex: number) => Promise<Skeleton>
loadAnimation: (animationIndex: number) => Promise<AnimationClip>
loadNode: (nodeIndex: number) => Promise<Object3D>
loadScene: () => Promise<Group>
}
export interface GLTFLoaderPlugin {
beforeRoot?: (() => Promise<void> | null) | undefined
afterRoot?: ((result: GLTF) => Promise<void> | null) | undefined
loadNode?: ((nodeIndex: number) => Promise<Object3D> | null) | undefined
loadMesh?: ((meshIndex: number) => Promise<Group | Mesh | SkinnedMesh> | null) | undefined
loadBufferView?: ((bufferViewIndex: number) => Promise<ArrayBuffer> | null) | undefined
loadMaterial?: ((materialIndex: number) => Promise<Material> | null) | undefined
loadTexture?: ((textureIndex: number) => Promise<Texture> | null) | undefined
getMaterialType?: ((materialIndex: number) => typeof Material | null) | undefined
extendMaterialParams?:
| ((materialIndex: number, materialParams: { [key: string]: any }) => Promise<any> | null)
| undefined
createNodeMesh?: ((nodeIndex: number) => Promise<Group | Mesh | SkinnedMesh> | null) | undefined
createNodeAttachment?: ((nodeIndex: number) => Promise<Object3D> | null) | undefined
}
+2625
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+81
View File
@@ -0,0 +1,81 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const RGBELoader = require("./RGBELoader.cjs");
class HDRCubeTextureLoader extends THREE.Loader {
constructor(manager) {
super(manager);
this.hdrLoader = new RGBELoader.RGBELoader();
this.type = THREE.HalfFloatType;
}
load(urls, onLoad, onProgress, onError) {
if (typeof urls === "string") {
urls = [urls];
} else if (!Array.isArray(urls)) {
console.warn("THREE.HDRCubeTextureLoader signature has changed. Use .setDataType() instead.");
this.setDataType(urls);
urls = onLoad;
onLoad = onProgress;
onProgress = onError;
onError = arguments[4];
}
const texture = new THREE.CubeTexture();
texture.type = this.type;
switch (texture.type) {
case THREE.FloatType:
case THREE.HalfFloatType:
if ("colorSpace" in texture)
texture.colorSpace = "srgb-linear";
else
texture.encoding = 3e3;
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.generateMipmaps = false;
break;
}
const scope = this;
let loaded = 0;
function loadHDRData(i, onLoad2, onProgress2, onError2) {
new THREE.FileLoader(scope.manager).setPath(scope.path).setResponseType("arraybuffer").setWithCredentials(scope.withCredentials).load(
urls[i],
function(buffer) {
loaded++;
const texData = scope.hdrLoader.parse(buffer);
if (!texData)
return;
if (texData.data !== void 0) {
const dataTexture = new THREE.DataTexture(texData.data, texData.width, texData.height);
dataTexture.type = texture.type;
if ("colorSpace" in dataTexture)
dataTexture.colorSpace = texture.SRGBColorSpace;
else
dataTexture.encoding = texture.encoding;
dataTexture.format = texture.format;
dataTexture.minFilter = texture.minFilter;
dataTexture.magFilter = texture.magFilter;
dataTexture.generateMipmaps = texture.generateMipmaps;
texture.images[i] = dataTexture;
}
if (loaded === 6) {
texture.needsUpdate = true;
if (onLoad2)
onLoad2(texture);
}
},
onProgress2,
onError2
);
}
for (let i = 0; i < urls.length; i++) {
loadHDRData(i, onLoad, onProgress, onError);
}
return texture;
}
setDataType(value) {
this.type = value;
this.hdrLoader.setDataType(value);
return this;
}
}
exports.HDRCubeTextureLoader = HDRCubeTextureLoader;
//# sourceMappingURL=HDRCubeTextureLoader.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"HDRCubeTextureLoader.cjs","sources":["../../src/loaders/HDRCubeTextureLoader.js"],"sourcesContent":["import { CubeTexture, DataTexture, FileLoader, FloatType, HalfFloatType, LinearFilter, Loader } from 'three'\nimport { RGBELoader } from '../loaders/RGBELoader.js'\n\nclass HDRCubeTextureLoader extends Loader {\n constructor(manager) {\n super(manager)\n\n this.hdrLoader = new RGBELoader()\n this.type = HalfFloatType\n }\n\n load(urls, onLoad, onProgress, onError) {\n if (typeof urls === 'string') {\n urls = [urls]\n } else if (!Array.isArray(urls)) {\n console.warn('THREE.HDRCubeTextureLoader signature has changed. Use .setDataType() instead.')\n\n this.setDataType(urls)\n\n urls = onLoad\n onLoad = onProgress\n onProgress = onError\n onError = arguments[4]\n }\n\n const texture = new CubeTexture()\n\n texture.type = this.type\n\n switch (texture.type) {\n case FloatType:\n case HalfFloatType:\n if ('colorSpace' in texture) texture.colorSpace = 'srgb-linear'\n else texture.encoding = 3000 // LinearEncoding\n texture.minFilter = LinearFilter\n texture.magFilter = LinearFilter\n texture.generateMipmaps = false\n break\n }\n\n const scope = this\n\n let loaded = 0\n\n function loadHDRData(i, onLoad, onProgress, onError) {\n new FileLoader(scope.manager)\n .setPath(scope.path)\n .setResponseType('arraybuffer')\n .setWithCredentials(scope.withCredentials)\n .load(\n urls[i],\n function (buffer) {\n loaded++\n\n const texData = scope.hdrLoader.parse(buffer)\n\n if (!texData) return\n\n if (texData.data !== undefined) {\n const dataTexture = new DataTexture(texData.data, texData.width, texData.height)\n\n dataTexture.type = texture.type\n if ('colorSpace' in dataTexture) dataTexture.colorSpace = texture.SRGBColorSpace\n else dataTexture.encoding = texture.encoding\n dataTexture.format = texture.format\n dataTexture.minFilter = texture.minFilter\n dataTexture.magFilter = texture.magFilter\n dataTexture.generateMipmaps = texture.generateMipmaps\n\n texture.images[i] = dataTexture\n }\n\n if (loaded === 6) {\n texture.needsUpdate = true\n if (onLoad) onLoad(texture)\n }\n },\n onProgress,\n onError,\n )\n }\n\n for (let i = 0; i < urls.length; i++) {\n loadHDRData(i, onLoad, onProgress, onError)\n }\n\n return texture\n }\n\n setDataType(value) {\n this.type = value\n this.hdrLoader.setDataType(value)\n\n return this\n }\n}\n\nexport { HDRCubeTextureLoader }\n"],"names":["Loader","RGBELoader","HalfFloatType","CubeTexture","FloatType","LinearFilter","onLoad","onProgress","onError","FileLoader","DataTexture"],"mappings":";;;;AAGA,MAAM,6BAA6BA,MAAAA,OAAO;AAAA,EACxC,YAAY,SAAS;AACnB,UAAM,OAAO;AAEb,SAAK,YAAY,IAAIC,sBAAY;AACjC,SAAK,OAAOC,MAAa;AAAA,EAC1B;AAAA,EAED,KAAK,MAAM,QAAQ,YAAY,SAAS;AACtC,QAAI,OAAO,SAAS,UAAU;AAC5B,aAAO,CAAC,IAAI;AAAA,IACb,WAAU,CAAC,MAAM,QAAQ,IAAI,GAAG;AAC/B,cAAQ,KAAK,+EAA+E;AAE5F,WAAK,YAAY,IAAI;AAErB,aAAO;AACP,eAAS;AACT,mBAAa;AACb,gBAAU,UAAU,CAAC;AAAA,IACtB;AAED,UAAM,UAAU,IAAIC,kBAAa;AAEjC,YAAQ,OAAO,KAAK;AAEpB,YAAQ,QAAQ,MAAI;AAAA,MAClB,KAAKC;MACL,KAAKF,MAAa;AAChB,YAAI,gBAAgB;AAAS,kBAAQ,aAAa;AAAA;AAC7C,kBAAQ,WAAW;AACxB,gBAAQ,YAAYG,MAAY;AAChC,gBAAQ,YAAYA,MAAY;AAChC,gBAAQ,kBAAkB;AAC1B;AAAA,IACH;AAED,UAAM,QAAQ;AAEd,QAAI,SAAS;AAEb,aAAS,YAAY,GAAGC,SAAQC,aAAYC,UAAS;AACnD,UAAIC,MAAU,WAAC,MAAM,OAAO,EACzB,QAAQ,MAAM,IAAI,EAClB,gBAAgB,aAAa,EAC7B,mBAAmB,MAAM,eAAe,EACxC;AAAA,QACC,KAAK,CAAC;AAAA,QACN,SAAU,QAAQ;AAChB;AAEA,gBAAM,UAAU,MAAM,UAAU,MAAM,MAAM;AAE5C,cAAI,CAAC;AAAS;AAEd,cAAI,QAAQ,SAAS,QAAW;AAC9B,kBAAM,cAAc,IAAIC,MAAAA,YAAY,QAAQ,MAAM,QAAQ,OAAO,QAAQ,MAAM;AAE/E,wBAAY,OAAO,QAAQ;AAC3B,gBAAI,gBAAgB;AAAa,0BAAY,aAAa,QAAQ;AAAA;AAC7D,0BAAY,WAAW,QAAQ;AACpC,wBAAY,SAAS,QAAQ;AAC7B,wBAAY,YAAY,QAAQ;AAChC,wBAAY,YAAY,QAAQ;AAChC,wBAAY,kBAAkB,QAAQ;AAEtC,oBAAQ,OAAO,CAAC,IAAI;AAAA,UACrB;AAED,cAAI,WAAW,GAAG;AAChB,oBAAQ,cAAc;AACtB,gBAAIJ;AAAQ,cAAAA,QAAO,OAAO;AAAA,UAC3B;AAAA,QACF;AAAA,QACDC;AAAA,QACAC;AAAA,MACD;AAAA,IACJ;AAED,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,kBAAY,GAAG,QAAQ,YAAY,OAAO;AAAA,IAC3C;AAED,WAAO;AAAA,EACR;AAAA,EAED,YAAY,OAAO;AACjB,SAAK,OAAO;AACZ,SAAK,UAAU,YAAY,KAAK;AAEhC,WAAO;AAAA,EACR;AACH;;"}
+18
View File
@@ -0,0 +1,18 @@
import { Loader, CubeTexture, LoadingManager, TextureDataType } from 'three'
import { RGBELoader } from './RGBELoader'
export class HDRCubeTextureLoader extends Loader {
constructor(manager?: LoadingManager)
hdrLoader: RGBELoader
type: TextureDataType
load(
urls: string | string[],
onLoad: (texture: CubeTexture) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): CubeTexture
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<CubeTexture>
setDataType(type: TextureDataType): this
}
+81
View File
@@ -0,0 +1,81 @@
import { Loader, HalfFloatType, CubeTexture, LinearFilter, FloatType, FileLoader, DataTexture } from "three";
import { RGBELoader } from "./RGBELoader.js";
class HDRCubeTextureLoader extends Loader {
constructor(manager) {
super(manager);
this.hdrLoader = new RGBELoader();
this.type = HalfFloatType;
}
load(urls, onLoad, onProgress, onError) {
if (typeof urls === "string") {
urls = [urls];
} else if (!Array.isArray(urls)) {
console.warn("THREE.HDRCubeTextureLoader signature has changed. Use .setDataType() instead.");
this.setDataType(urls);
urls = onLoad;
onLoad = onProgress;
onProgress = onError;
onError = arguments[4];
}
const texture = new CubeTexture();
texture.type = this.type;
switch (texture.type) {
case FloatType:
case HalfFloatType:
if ("colorSpace" in texture)
texture.colorSpace = "srgb-linear";
else
texture.encoding = 3e3;
texture.minFilter = LinearFilter;
texture.magFilter = LinearFilter;
texture.generateMipmaps = false;
break;
}
const scope = this;
let loaded = 0;
function loadHDRData(i, onLoad2, onProgress2, onError2) {
new FileLoader(scope.manager).setPath(scope.path).setResponseType("arraybuffer").setWithCredentials(scope.withCredentials).load(
urls[i],
function(buffer) {
loaded++;
const texData = scope.hdrLoader.parse(buffer);
if (!texData)
return;
if (texData.data !== void 0) {
const dataTexture = new DataTexture(texData.data, texData.width, texData.height);
dataTexture.type = texture.type;
if ("colorSpace" in dataTexture)
dataTexture.colorSpace = texture.SRGBColorSpace;
else
dataTexture.encoding = texture.encoding;
dataTexture.format = texture.format;
dataTexture.minFilter = texture.minFilter;
dataTexture.magFilter = texture.magFilter;
dataTexture.generateMipmaps = texture.generateMipmaps;
texture.images[i] = dataTexture;
}
if (loaded === 6) {
texture.needsUpdate = true;
if (onLoad2)
onLoad2(texture);
}
},
onProgress2,
onError2
);
}
for (let i = 0; i < urls.length; i++) {
loadHDRData(i, onLoad, onProgress, onError);
}
return texture;
}
setDataType(value) {
this.type = value;
this.hdrLoader.setDataType(value);
return this;
}
}
export {
HDRCubeTextureLoader
};
//# sourceMappingURL=HDRCubeTextureLoader.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"HDRCubeTextureLoader.js","sources":["../../src/loaders/HDRCubeTextureLoader.js"],"sourcesContent":["import { CubeTexture, DataTexture, FileLoader, FloatType, HalfFloatType, LinearFilter, Loader } from 'three'\nimport { RGBELoader } from '../loaders/RGBELoader.js'\n\nclass HDRCubeTextureLoader extends Loader {\n constructor(manager) {\n super(manager)\n\n this.hdrLoader = new RGBELoader()\n this.type = HalfFloatType\n }\n\n load(urls, onLoad, onProgress, onError) {\n if (typeof urls === 'string') {\n urls = [urls]\n } else if (!Array.isArray(urls)) {\n console.warn('THREE.HDRCubeTextureLoader signature has changed. Use .setDataType() instead.')\n\n this.setDataType(urls)\n\n urls = onLoad\n onLoad = onProgress\n onProgress = onError\n onError = arguments[4]\n }\n\n const texture = new CubeTexture()\n\n texture.type = this.type\n\n switch (texture.type) {\n case FloatType:\n case HalfFloatType:\n if ('colorSpace' in texture) texture.colorSpace = 'srgb-linear'\n else texture.encoding = 3000 // LinearEncoding\n texture.minFilter = LinearFilter\n texture.magFilter = LinearFilter\n texture.generateMipmaps = false\n break\n }\n\n const scope = this\n\n let loaded = 0\n\n function loadHDRData(i, onLoad, onProgress, onError) {\n new FileLoader(scope.manager)\n .setPath(scope.path)\n .setResponseType('arraybuffer')\n .setWithCredentials(scope.withCredentials)\n .load(\n urls[i],\n function (buffer) {\n loaded++\n\n const texData = scope.hdrLoader.parse(buffer)\n\n if (!texData) return\n\n if (texData.data !== undefined) {\n const dataTexture = new DataTexture(texData.data, texData.width, texData.height)\n\n dataTexture.type = texture.type\n if ('colorSpace' in dataTexture) dataTexture.colorSpace = texture.SRGBColorSpace\n else dataTexture.encoding = texture.encoding\n dataTexture.format = texture.format\n dataTexture.minFilter = texture.minFilter\n dataTexture.magFilter = texture.magFilter\n dataTexture.generateMipmaps = texture.generateMipmaps\n\n texture.images[i] = dataTexture\n }\n\n if (loaded === 6) {\n texture.needsUpdate = true\n if (onLoad) onLoad(texture)\n }\n },\n onProgress,\n onError,\n )\n }\n\n for (let i = 0; i < urls.length; i++) {\n loadHDRData(i, onLoad, onProgress, onError)\n }\n\n return texture\n }\n\n setDataType(value) {\n this.type = value\n this.hdrLoader.setDataType(value)\n\n return this\n }\n}\n\nexport { HDRCubeTextureLoader }\n"],"names":["onLoad","onProgress","onError"],"mappings":";;AAGA,MAAM,6BAA6B,OAAO;AAAA,EACxC,YAAY,SAAS;AACnB,UAAM,OAAO;AAEb,SAAK,YAAY,IAAI,WAAY;AACjC,SAAK,OAAO;AAAA,EACb;AAAA,EAED,KAAK,MAAM,QAAQ,YAAY,SAAS;AACtC,QAAI,OAAO,SAAS,UAAU;AAC5B,aAAO,CAAC,IAAI;AAAA,IACb,WAAU,CAAC,MAAM,QAAQ,IAAI,GAAG;AAC/B,cAAQ,KAAK,+EAA+E;AAE5F,WAAK,YAAY,IAAI;AAErB,aAAO;AACP,eAAS;AACT,mBAAa;AACb,gBAAU,UAAU,CAAC;AAAA,IACtB;AAED,UAAM,UAAU,IAAI,YAAa;AAEjC,YAAQ,OAAO,KAAK;AAEpB,YAAQ,QAAQ,MAAI;AAAA,MAClB,KAAK;AAAA,MACL,KAAK;AACH,YAAI,gBAAgB;AAAS,kBAAQ,aAAa;AAAA;AAC7C,kBAAQ,WAAW;AACxB,gBAAQ,YAAY;AACpB,gBAAQ,YAAY;AACpB,gBAAQ,kBAAkB;AAC1B;AAAA,IACH;AAED,UAAM,QAAQ;AAEd,QAAI,SAAS;AAEb,aAAS,YAAY,GAAGA,SAAQC,aAAYC,UAAS;AACnD,UAAI,WAAW,MAAM,OAAO,EACzB,QAAQ,MAAM,IAAI,EAClB,gBAAgB,aAAa,EAC7B,mBAAmB,MAAM,eAAe,EACxC;AAAA,QACC,KAAK,CAAC;AAAA,QACN,SAAU,QAAQ;AAChB;AAEA,gBAAM,UAAU,MAAM,UAAU,MAAM,MAAM;AAE5C,cAAI,CAAC;AAAS;AAEd,cAAI,QAAQ,SAAS,QAAW;AAC9B,kBAAM,cAAc,IAAI,YAAY,QAAQ,MAAM,QAAQ,OAAO,QAAQ,MAAM;AAE/E,wBAAY,OAAO,QAAQ;AAC3B,gBAAI,gBAAgB;AAAa,0BAAY,aAAa,QAAQ;AAAA;AAC7D,0BAAY,WAAW,QAAQ;AACpC,wBAAY,SAAS,QAAQ;AAC7B,wBAAY,YAAY,QAAQ;AAChC,wBAAY,YAAY,QAAQ;AAChC,wBAAY,kBAAkB,QAAQ;AAEtC,oBAAQ,OAAO,CAAC,IAAI;AAAA,UACrB;AAED,cAAI,WAAW,GAAG;AAChB,oBAAQ,cAAc;AACtB,gBAAIF;AAAQ,cAAAA,QAAO,OAAO;AAAA,UAC3B;AAAA,QACF;AAAA,QACDC;AAAA,QACAC;AAAA,MACD;AAAA,IACJ;AAED,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,kBAAY,GAAG,QAAQ,YAAY,OAAO;AAAA,IAC3C;AAED,WAAO;AAAA,EACR;AAAA,EAED,YAAY,OAAO;AACjB,SAAK,OAAO;AACZ,SAAK,UAAU,YAAY,KAAK;AAEhC,WAAO;AAAA,EACR;AACH;"}
+76
View File
@@ -0,0 +1,76 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const ColladaLoader = require("./ColladaLoader.cjs");
const fflate$1 = require("fflate");
class KMZLoader extends THREE.Loader {
constructor(manager) {
super(manager);
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader = new THREE.FileLoader(scope.manager);
loader.setPath(scope.path);
loader.setResponseType("arraybuffer");
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
function(text) {
try {
onLoad(scope.parse(text));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(data) {
function findFile(url) {
for (const path in zip) {
if (path.substr(-url.length) === url) {
return zip[path];
}
}
}
const manager = new THREE.LoadingManager();
manager.setURLModifier(function(url) {
const image = findFile(url);
if (image) {
console.log("Loading", url);
const blob = new Blob([image.buffer], { type: "application/octet-stream" });
return URL.createObjectURL(blob);
}
return url;
});
const zip = fflate$1.unzipSync(new Uint8Array(data));
if (zip["doc.kml"]) {
const xml = new DOMParser().parseFromString(fflate.strFromU8(zip["doc.kml"]), "application/xml");
const model = xml.querySelector("Placemark Model Link href");
if (model) {
const loader = new ColladaLoader.ColladaLoader(manager);
return loader.parse(fflate.strFromU8(zip[model.textContent]));
}
} else {
console.warn("KMZLoader: Missing doc.kml file.");
for (const path in zip) {
const extension = path.split(".").pop().toLowerCase();
if (extension === "dae") {
const loader = new ColladaLoader.ColladaLoader(manager);
return loader.parse(fflate.strFromU8(zip[path]));
}
}
}
console.error("KMZLoader: Couldn't find .dae file.");
return { scene: new THREE.Group() };
}
}
exports.KMZLoader = KMZLoader;
//# sourceMappingURL=KMZLoader.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"KMZLoader.cjs","sources":["../../src/loaders/KMZLoader.js"],"sourcesContent":["import { FileLoader, Group, Loader, LoadingManager } from 'three'\nimport { ColladaLoader } from '../loaders/ColladaLoader'\nimport { unzipSync } from 'fflate'\n\nclass KMZLoader extends Loader {\n constructor(manager) {\n super(manager)\n }\n\n load(url, onLoad, onProgress, onError) {\n const scope = this\n\n const loader = new FileLoader(scope.manager)\n loader.setPath(scope.path)\n loader.setResponseType('arraybuffer')\n loader.setRequestHeader(scope.requestHeader)\n loader.setWithCredentials(scope.withCredentials)\n loader.load(\n url,\n function (text) {\n try {\n onLoad(scope.parse(text))\n } catch (e) {\n if (onError) {\n onError(e)\n } else {\n console.error(e)\n }\n\n scope.manager.itemError(url)\n }\n },\n onProgress,\n onError,\n )\n }\n\n parse(data) {\n function findFile(url) {\n for (const path in zip) {\n if (path.substr(-url.length) === url) {\n return zip[path]\n }\n }\n }\n\n const manager = new LoadingManager()\n manager.setURLModifier(function (url) {\n const image = findFile(url)\n\n if (image) {\n console.log('Loading', url)\n\n const blob = new Blob([image.buffer], { type: 'application/octet-stream' })\n return URL.createObjectURL(blob)\n }\n\n return url\n })\n\n //\n\n const zip = unzipSync(new Uint8Array(data))\n\n if (zip['doc.kml']) {\n const xml = new DOMParser().parseFromString(fflate.strFromU8(zip['doc.kml']), 'application/xml')\n const model = xml.querySelector('Placemark Model Link href')\n\n if (model) {\n const loader = new ColladaLoader(manager)\n return loader.parse(fflate.strFromU8(zip[model.textContent]))\n }\n } else {\n console.warn('KMZLoader: Missing doc.kml file.')\n\n for (const path in zip) {\n const extension = path.split('.').pop().toLowerCase()\n\n if (extension === 'dae') {\n const loader = new ColladaLoader(manager)\n return loader.parse(fflate.strFromU8(zip[path]))\n }\n }\n }\n\n console.error(\"KMZLoader: Couldn't find .dae file.\")\n return { scene: new Group() }\n }\n}\n\nexport { KMZLoader }\n"],"names":["Loader","FileLoader","LoadingManager","unzipSync","ColladaLoader","Group"],"mappings":";;;;;AAIA,MAAM,kBAAkBA,MAAAA,OAAO;AAAA,EAC7B,YAAY,SAAS;AACnB,UAAM,OAAO;AAAA,EACd;AAAA,EAED,KAAK,KAAK,QAAQ,YAAY,SAAS;AACrC,UAAM,QAAQ;AAEd,UAAM,SAAS,IAAIC,iBAAW,MAAM,OAAO;AAC3C,WAAO,QAAQ,MAAM,IAAI;AACzB,WAAO,gBAAgB,aAAa;AACpC,WAAO,iBAAiB,MAAM,aAAa;AAC3C,WAAO,mBAAmB,MAAM,eAAe;AAC/C,WAAO;AAAA,MACL;AAAA,MACA,SAAU,MAAM;AACd,YAAI;AACF,iBAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QACzB,SAAQ,GAAP;AACA,cAAI,SAAS;AACX,oBAAQ,CAAC;AAAA,UACrB,OAAiB;AACL,oBAAQ,MAAM,CAAC;AAAA,UAChB;AAED,gBAAM,QAAQ,UAAU,GAAG;AAAA,QAC5B;AAAA,MACF;AAAA,MACD;AAAA,MACA;AAAA,IACD;AAAA,EACF;AAAA,EAED,MAAM,MAAM;AACV,aAAS,SAAS,KAAK;AACrB,iBAAW,QAAQ,KAAK;AACtB,YAAI,KAAK,OAAO,CAAC,IAAI,MAAM,MAAM,KAAK;AACpC,iBAAO,IAAI,IAAI;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAED,UAAM,UAAU,IAAIC,qBAAgB;AACpC,YAAQ,eAAe,SAAU,KAAK;AACpC,YAAM,QAAQ,SAAS,GAAG;AAE1B,UAAI,OAAO;AACT,gBAAQ,IAAI,WAAW,GAAG;AAE1B,cAAM,OAAO,IAAI,KAAK,CAAC,MAAM,MAAM,GAAG,EAAE,MAAM,4BAA4B;AAC1E,eAAO,IAAI,gBAAgB,IAAI;AAAA,MAChC;AAED,aAAO;AAAA,IACb,CAAK;AAID,UAAM,MAAMC,SAAS,UAAC,IAAI,WAAW,IAAI,CAAC;AAE1C,QAAI,IAAI,SAAS,GAAG;AAClB,YAAM,MAAM,IAAI,UAAW,EAAC,gBAAgB,OAAO,UAAU,IAAI,SAAS,CAAC,GAAG,iBAAiB;AAC/F,YAAM,QAAQ,IAAI,cAAc,2BAA2B;AAE3D,UAAI,OAAO;AACT,cAAM,SAAS,IAAIC,cAAa,cAAC,OAAO;AACxC,eAAO,OAAO,MAAM,OAAO,UAAU,IAAI,MAAM,WAAW,CAAC,CAAC;AAAA,MAC7D;AAAA,IACP,OAAW;AACL,cAAQ,KAAK,kCAAkC;AAE/C,iBAAW,QAAQ,KAAK;AACtB,cAAM,YAAY,KAAK,MAAM,GAAG,EAAE,IAAK,EAAC,YAAa;AAErD,YAAI,cAAc,OAAO;AACvB,gBAAM,SAAS,IAAIA,cAAa,cAAC,OAAO;AACxC,iBAAO,OAAO,MAAM,OAAO,UAAU,IAAI,IAAI,CAAC,CAAC;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AAED,YAAQ,MAAM,qCAAqC;AACnD,WAAO,EAAE,OAAO,IAAIC,MAAAA,QAAS;AAAA,EAC9B;AACH;;"}
+16
View File
@@ -0,0 +1,16 @@
import { Loader, LoadingManager } from 'three'
import { Collada } from './ColladaLoader'
export class KMZLoader extends Loader {
constructor(manager?: LoadingManager)
load(
url: string,
onLoad: (kmz: Collada) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Collada>
parse(data: ArrayBuffer): Collada
}
+76
View File
@@ -0,0 +1,76 @@
import { Loader, FileLoader, LoadingManager, Group } from "three";
import { ColladaLoader } from "./ColladaLoader.js";
import { unzipSync } from "fflate";
class KMZLoader extends Loader {
constructor(manager) {
super(manager);
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader = new FileLoader(scope.manager);
loader.setPath(scope.path);
loader.setResponseType("arraybuffer");
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
function(text) {
try {
onLoad(scope.parse(text));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(data) {
function findFile(url) {
for (const path in zip) {
if (path.substr(-url.length) === url) {
return zip[path];
}
}
}
const manager = new LoadingManager();
manager.setURLModifier(function(url) {
const image = findFile(url);
if (image) {
console.log("Loading", url);
const blob = new Blob([image.buffer], { type: "application/octet-stream" });
return URL.createObjectURL(blob);
}
return url;
});
const zip = unzipSync(new Uint8Array(data));
if (zip["doc.kml"]) {
const xml = new DOMParser().parseFromString(fflate.strFromU8(zip["doc.kml"]), "application/xml");
const model = xml.querySelector("Placemark Model Link href");
if (model) {
const loader = new ColladaLoader(manager);
return loader.parse(fflate.strFromU8(zip[model.textContent]));
}
} else {
console.warn("KMZLoader: Missing doc.kml file.");
for (const path in zip) {
const extension = path.split(".").pop().toLowerCase();
if (extension === "dae") {
const loader = new ColladaLoader(manager);
return loader.parse(fflate.strFromU8(zip[path]));
}
}
}
console.error("KMZLoader: Couldn't find .dae file.");
return { scene: new Group() };
}
}
export {
KMZLoader
};
//# sourceMappingURL=KMZLoader.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"KMZLoader.js","sources":["../../src/loaders/KMZLoader.js"],"sourcesContent":["import { FileLoader, Group, Loader, LoadingManager } from 'three'\nimport { ColladaLoader } from '../loaders/ColladaLoader'\nimport { unzipSync } from 'fflate'\n\nclass KMZLoader extends Loader {\n constructor(manager) {\n super(manager)\n }\n\n load(url, onLoad, onProgress, onError) {\n const scope = this\n\n const loader = new FileLoader(scope.manager)\n loader.setPath(scope.path)\n loader.setResponseType('arraybuffer')\n loader.setRequestHeader(scope.requestHeader)\n loader.setWithCredentials(scope.withCredentials)\n loader.load(\n url,\n function (text) {\n try {\n onLoad(scope.parse(text))\n } catch (e) {\n if (onError) {\n onError(e)\n } else {\n console.error(e)\n }\n\n scope.manager.itemError(url)\n }\n },\n onProgress,\n onError,\n )\n }\n\n parse(data) {\n function findFile(url) {\n for (const path in zip) {\n if (path.substr(-url.length) === url) {\n return zip[path]\n }\n }\n }\n\n const manager = new LoadingManager()\n manager.setURLModifier(function (url) {\n const image = findFile(url)\n\n if (image) {\n console.log('Loading', url)\n\n const blob = new Blob([image.buffer], { type: 'application/octet-stream' })\n return URL.createObjectURL(blob)\n }\n\n return url\n })\n\n //\n\n const zip = unzipSync(new Uint8Array(data))\n\n if (zip['doc.kml']) {\n const xml = new DOMParser().parseFromString(fflate.strFromU8(zip['doc.kml']), 'application/xml')\n const model = xml.querySelector('Placemark Model Link href')\n\n if (model) {\n const loader = new ColladaLoader(manager)\n return loader.parse(fflate.strFromU8(zip[model.textContent]))\n }\n } else {\n console.warn('KMZLoader: Missing doc.kml file.')\n\n for (const path in zip) {\n const extension = path.split('.').pop().toLowerCase()\n\n if (extension === 'dae') {\n const loader = new ColladaLoader(manager)\n return loader.parse(fflate.strFromU8(zip[path]))\n }\n }\n }\n\n console.error(\"KMZLoader: Couldn't find .dae file.\")\n return { scene: new Group() }\n }\n}\n\nexport { KMZLoader }\n"],"names":[],"mappings":";;;AAIA,MAAM,kBAAkB,OAAO;AAAA,EAC7B,YAAY,SAAS;AACnB,UAAM,OAAO;AAAA,EACd;AAAA,EAED,KAAK,KAAK,QAAQ,YAAY,SAAS;AACrC,UAAM,QAAQ;AAEd,UAAM,SAAS,IAAI,WAAW,MAAM,OAAO;AAC3C,WAAO,QAAQ,MAAM,IAAI;AACzB,WAAO,gBAAgB,aAAa;AACpC,WAAO,iBAAiB,MAAM,aAAa;AAC3C,WAAO,mBAAmB,MAAM,eAAe;AAC/C,WAAO;AAAA,MACL;AAAA,MACA,SAAU,MAAM;AACd,YAAI;AACF,iBAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QACzB,SAAQ,GAAP;AACA,cAAI,SAAS;AACX,oBAAQ,CAAC;AAAA,UACrB,OAAiB;AACL,oBAAQ,MAAM,CAAC;AAAA,UAChB;AAED,gBAAM,QAAQ,UAAU,GAAG;AAAA,QAC5B;AAAA,MACF;AAAA,MACD;AAAA,MACA;AAAA,IACD;AAAA,EACF;AAAA,EAED,MAAM,MAAM;AACV,aAAS,SAAS,KAAK;AACrB,iBAAW,QAAQ,KAAK;AACtB,YAAI,KAAK,OAAO,CAAC,IAAI,MAAM,MAAM,KAAK;AACpC,iBAAO,IAAI,IAAI;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAED,UAAM,UAAU,IAAI,eAAgB;AACpC,YAAQ,eAAe,SAAU,KAAK;AACpC,YAAM,QAAQ,SAAS,GAAG;AAE1B,UAAI,OAAO;AACT,gBAAQ,IAAI,WAAW,GAAG;AAE1B,cAAM,OAAO,IAAI,KAAK,CAAC,MAAM,MAAM,GAAG,EAAE,MAAM,4BAA4B;AAC1E,eAAO,IAAI,gBAAgB,IAAI;AAAA,MAChC;AAED,aAAO;AAAA,IACb,CAAK;AAID,UAAM,MAAM,UAAU,IAAI,WAAW,IAAI,CAAC;AAE1C,QAAI,IAAI,SAAS,GAAG;AAClB,YAAM,MAAM,IAAI,UAAW,EAAC,gBAAgB,OAAO,UAAU,IAAI,SAAS,CAAC,GAAG,iBAAiB;AAC/F,YAAM,QAAQ,IAAI,cAAc,2BAA2B;AAE3D,UAAI,OAAO;AACT,cAAM,SAAS,IAAI,cAAc,OAAO;AACxC,eAAO,OAAO,MAAM,OAAO,UAAU,IAAI,MAAM,WAAW,CAAC,CAAC;AAAA,MAC7D;AAAA,IACP,OAAW;AACL,cAAQ,KAAK,kCAAkC;AAE/C,iBAAW,QAAQ,KAAK;AACtB,cAAM,YAAY,KAAK,MAAM,GAAG,EAAE,IAAK,EAAC,YAAa;AAErD,YAAI,cAAc,OAAO;AACvB,gBAAM,SAAS,IAAI,cAAc,OAAO;AACxC,iBAAO,OAAO,MAAM,OAAO,UAAU,IAAI,IAAI,CAAC,CAAC;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AAED,YAAQ,MAAM,qCAAqC;AACnD,WAAO,EAAE,OAAO,IAAI,QAAS;AAAA,EAC9B;AACH;"}
+544
View File
@@ -0,0 +1,544 @@
"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 WorkerPool = require("../utils/WorkerPool.cjs");
const ktxParse = require("../libs/ktx-parse.cjs");
const zstddec = require("../libs/zstddec.cjs");
const CompressedCubeTexture = require("../_polyfill/CompressedCubeTexture.cjs");
const CompressedArrayTexture = require("../_polyfill/CompressedArrayTexture.cjs");
const Data3DTexture = require("../_polyfill/Data3DTexture.cjs");
const LinearEncoding = 3e3;
const sRGBEncoding = 3001;
const NoColorSpace = "";
const DisplayP3ColorSpace = "display-p3";
const LinearDisplayP3ColorSpace = "display-p3-linear";
const LinearSRGBColorSpace = "srgb-linear";
const SRGBColorSpace = "srgb";
const _taskCache = /* @__PURE__ */ new WeakMap();
let _activeLoaders = 0;
let _zstd;
const KTX2Loader = /* @__PURE__ */ (() => {
const _KTX2Loader = class extends THREE.Loader {
constructor(manager) {
super(manager);
this.transcoderPath = "";
this.transcoderBinary = null;
this.transcoderPending = null;
this.workerPool = new WorkerPool.WorkerPool();
this.workerSourceURL = "";
this.workerConfig = null;
if (typeof MSC_TRANSCODER !== "undefined") {
console.warn(
'THREE.KTX2Loader: Please update to latest "basis_transcoder". "msc_basis_transcoder" is no longer supported in three.js r125+.'
);
}
}
setTranscoderPath(path) {
this.transcoderPath = path;
return this;
}
setWorkerLimit(num) {
this.workerPool.setWorkerLimit(num);
return this;
}
detectSupport(renderer) {
this.workerConfig = {
astcSupported: renderer.extensions.has("WEBGL_compressed_texture_astc"),
etc1Supported: renderer.extensions.has("WEBGL_compressed_texture_etc1"),
etc2Supported: renderer.extensions.has("WEBGL_compressed_texture_etc"),
dxtSupported: renderer.extensions.has("WEBGL_compressed_texture_s3tc"),
bptcSupported: renderer.extensions.has("EXT_texture_compression_bptc"),
pvrtcSupported: renderer.extensions.has("WEBGL_compressed_texture_pvrtc") || renderer.extensions.has("WEBKIT_WEBGL_compressed_texture_pvrtc")
};
if (renderer.capabilities.isWebGL2) {
this.workerConfig.etc1Supported = false;
}
return this;
}
init() {
if (!this.transcoderPending) {
const jsLoader = new THREE.FileLoader(this.manager);
jsLoader.setPath(this.transcoderPath);
jsLoader.setWithCredentials(this.withCredentials);
const jsContent = jsLoader.loadAsync("basis_transcoder.js");
const binaryLoader = new THREE.FileLoader(this.manager);
binaryLoader.setPath(this.transcoderPath);
binaryLoader.setResponseType("arraybuffer");
binaryLoader.setWithCredentials(this.withCredentials);
const binaryContent = binaryLoader.loadAsync("basis_transcoder.wasm");
this.transcoderPending = Promise.all([jsContent, binaryContent]).then(([jsContent2, binaryContent2]) => {
const fn = _KTX2Loader.BasisWorker.toString();
const body = [
"/* constants */",
"let _EngineFormat = " + JSON.stringify(_KTX2Loader.EngineFormat),
"let _TranscoderFormat = " + JSON.stringify(_KTX2Loader.TranscoderFormat),
"let _BasisFormat = " + JSON.stringify(_KTX2Loader.BasisFormat),
"/* basis_transcoder.js */",
jsContent2,
"/* worker */",
fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"))
].join("\n");
this.workerSourceURL = URL.createObjectURL(new Blob([body]));
this.transcoderBinary = binaryContent2;
this.workerPool.setWorkerCreator(() => {
const worker = new Worker(this.workerSourceURL);
const transcoderBinary = this.transcoderBinary.slice(0);
worker.postMessage({ type: "init", config: this.workerConfig, transcoderBinary }, [transcoderBinary]);
return worker;
});
});
if (_activeLoaders > 0) {
console.warn(
"THREE.KTX2Loader: Multiple active KTX2 loaders may cause performance issues. Use a single KTX2Loader instance, or call .dispose() on old instances."
);
}
_activeLoaders++;
}
return this.transcoderPending;
}
load(url, onLoad, onProgress, onError) {
if (this.workerConfig === null) {
throw new Error("THREE.KTX2Loader: Missing initialization with `.detectSupport( renderer )`.");
}
const loader = new THREE.FileLoader(this.manager);
loader.setResponseType("arraybuffer");
loader.setWithCredentials(this.withCredentials);
loader.load(
url,
(buffer) => {
if (_taskCache.has(buffer)) {
const cachedTask = _taskCache.get(buffer);
return cachedTask.promise.then(onLoad).catch(onError);
}
this._createTexture(buffer).then((texture) => onLoad ? onLoad(texture) : null).catch(onError);
},
onProgress,
onError
);
}
_createTextureFrom(transcodeResult, container) {
const { faces, width, height, format, type, error, dfdFlags } = transcodeResult;
if (type === "error")
return Promise.reject(error);
let texture;
if (container.faceCount === 6) {
texture = new CompressedCubeTexture.CompressedCubeTexture(faces, format, THREE.UnsignedByteType);
} else {
const mipmaps = faces[0].mipmaps;
texture = container.layerCount > 1 ? new CompressedArrayTexture.CompressedArrayTexture(mipmaps, width, height, container.layerCount, format, THREE.UnsignedByteType) : new THREE.CompressedTexture(mipmaps, width, height, format, THREE.UnsignedByteType);
}
texture.minFilter = faces[0].mipmaps.length === 1 ? THREE.LinearFilter : THREE.LinearMipmapLinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.generateMipmaps = false;
texture.needsUpdate = true;
const colorSpace = parseColorSpace(container);
if ("colorSpace" in texture)
texture.colorSpace = colorSpace;
else
texture.encoding = colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding;
texture.premultiplyAlpha = !!(dfdFlags & ktxParse.KHR_DF_FLAG_ALPHA_PREMULTIPLIED);
return texture;
}
/**
* @param {ArrayBuffer} buffer
* @param {object?} config
* @return {Promise<CompressedTexture|CompressedArrayTexture|DataTexture|Data3DTexture>}
*/
async _createTexture(buffer, config = {}) {
const container = ktxParse.read(new Uint8Array(buffer));
if (container.vkFormat !== ktxParse.VK_FORMAT_UNDEFINED) {
return createRawTexture(container);
}
const taskConfig = config;
const texturePending = this.init().then(() => {
return this.workerPool.postMessage({ type: "transcode", buffer, taskConfig }, [buffer]);
}).then((e) => this._createTextureFrom(e.data, container));
_taskCache.set(buffer, { promise: texturePending });
return texturePending;
}
dispose() {
this.workerPool.dispose();
if (this.workerSourceURL)
URL.revokeObjectURL(this.workerSourceURL);
_activeLoaders--;
return this;
}
};
let KTX2Loader2 = _KTX2Loader;
/* CONSTANTS */
__publicField(KTX2Loader2, "BasisFormat", {
ETC1S: 0,
UASTC_4x4: 1
});
__publicField(KTX2Loader2, "TranscoderFormat", {
ETC1: 0,
ETC2: 1,
BC1: 2,
BC3: 3,
BC4: 4,
BC5: 5,
BC7_M6_OPAQUE_ONLY: 6,
BC7_M5: 7,
PVRTC1_4_RGB: 8,
PVRTC1_4_RGBA: 9,
ASTC_4x4: 10,
ATC_RGB: 11,
ATC_RGBA_INTERPOLATED_ALPHA: 12,
RGBA32: 13,
RGB565: 14,
BGR565: 15,
RGBA4444: 16
});
__publicField(KTX2Loader2, "EngineFormat", {
RGBAFormat: THREE.RGBAFormat,
RGBA_ASTC_4x4_Format: THREE.RGBA_ASTC_4x4_Format,
RGBA_BPTC_Format: THREE.RGBA_BPTC_Format,
RGBA_ETC2_EAC_Format: THREE.RGBA_ETC2_EAC_Format,
RGBA_PVRTC_4BPPV1_Format: THREE.RGBA_PVRTC_4BPPV1_Format,
RGBA_S3TC_DXT5_Format: THREE.RGBA_S3TC_DXT5_Format,
RGB_ETC1_Format: THREE.RGB_ETC1_Format,
RGB_ETC2_Format: THREE.RGB_ETC2_Format,
RGB_PVRTC_4BPPV1_Format: THREE.RGB_PVRTC_4BPPV1_Format,
RGB_S3TC_DXT1_Format: THREE.RGB_S3TC_DXT1_Format
});
/* WEB WORKER */
__publicField(KTX2Loader2, "BasisWorker", function() {
let config;
let transcoderPending;
let BasisModule;
const EngineFormat = _EngineFormat;
const TranscoderFormat = _TranscoderFormat;
const BasisFormat = _BasisFormat;
self.addEventListener("message", function(e) {
const message = e.data;
switch (message.type) {
case "init":
config = message.config;
init(message.transcoderBinary);
break;
case "transcode":
transcoderPending.then(() => {
try {
const { faces, buffers, width, height, hasAlpha, format, dfdFlags } = transcode(message.buffer);
self.postMessage(
{ type: "transcode", id: message.id, faces, width, height, hasAlpha, format, dfdFlags },
buffers
);
} catch (error) {
console.error(error);
self.postMessage({ type: "error", id: message.id, error: error.message });
}
});
break;
}
});
function init(wasmBinary) {
transcoderPending = new Promise((resolve) => {
BasisModule = { wasmBinary, onRuntimeInitialized: resolve };
BASIS(BasisModule);
}).then(() => {
BasisModule.initializeBasis();
if (BasisModule.KTX2File === void 0) {
console.warn("THREE.KTX2Loader: Please update Basis Universal transcoder.");
}
});
}
function transcode(buffer) {
const ktx2File = new BasisModule.KTX2File(new Uint8Array(buffer));
function cleanup() {
ktx2File.close();
ktx2File.delete();
}
if (!ktx2File.isValid()) {
cleanup();
throw new Error("THREE.KTX2Loader: Invalid or unsupported .ktx2 file");
}
const basisFormat = ktx2File.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
const width = ktx2File.getWidth();
const height = ktx2File.getHeight();
const layerCount = ktx2File.getLayers() || 1;
const levelCount = ktx2File.getLevels();
const faceCount = ktx2File.getFaces();
const hasAlpha = ktx2File.getHasAlpha();
const dfdFlags = ktx2File.getDFDFlags();
const { transcoderFormat, engineFormat } = getTranscoderFormat(basisFormat, width, height, hasAlpha);
if (!width || !height || !levelCount) {
cleanup();
throw new Error("THREE.KTX2Loader: Invalid texture");
}
if (!ktx2File.startTranscoding()) {
cleanup();
throw new Error("THREE.KTX2Loader: .startTranscoding failed");
}
const faces = [];
const buffers = [];
for (let face = 0; face < faceCount; face++) {
const mipmaps = [];
for (let mip = 0; mip < levelCount; mip++) {
const layerMips = [];
let mipWidth, mipHeight;
for (let layer = 0; layer < layerCount; layer++) {
const levelInfo = ktx2File.getImageLevelInfo(mip, layer, face);
if (face === 0 && mip === 0 && layer === 0 && (levelInfo.origWidth % 4 !== 0 || levelInfo.origHeight % 4 !== 0)) {
console.warn("THREE.KTX2Loader: ETC1S and UASTC textures should use multiple-of-four dimensions.");
}
if (levelCount > 1) {
mipWidth = levelInfo.origWidth;
mipHeight = levelInfo.origHeight;
} else {
mipWidth = levelInfo.width;
mipHeight = levelInfo.height;
}
const dst = new Uint8Array(ktx2File.getImageTranscodedSizeInBytes(mip, layer, 0, transcoderFormat));
const status = ktx2File.transcodeImage(dst, mip, layer, face, transcoderFormat, 0, -1, -1);
if (!status) {
cleanup();
throw new Error("THREE.KTX2Loader: .transcodeImage failed.");
}
layerMips.push(dst);
}
const mipData = concat(layerMips);
mipmaps.push({ data: mipData, width: mipWidth, height: mipHeight });
buffers.push(mipData.buffer);
}
faces.push({ mipmaps, width, height, format: engineFormat });
}
cleanup();
return { faces, buffers, width, height, hasAlpha, format: engineFormat, dfdFlags };
}
const FORMAT_OPTIONS = [
{
if: "astcSupported",
basisFormat: [BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4],
engineFormat: [EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format],
priorityETC1S: Infinity,
priorityUASTC: 1,
needsPowerOfTwo: false
},
{
if: "bptcSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5],
engineFormat: [EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format],
priorityETC1S: 3,
priorityUASTC: 2,
needsPowerOfTwo: false
},
{
if: "dxtSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.BC1, TranscoderFormat.BC3],
engineFormat: [EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format],
priorityETC1S: 4,
priorityUASTC: 5,
needsPowerOfTwo: false
},
{
if: "etc2Supported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ETC1, TranscoderFormat.ETC2],
engineFormat: [EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format],
priorityETC1S: 1,
priorityUASTC: 3,
needsPowerOfTwo: false
},
{
if: "etc1Supported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ETC1],
engineFormat: [EngineFormat.RGB_ETC1_Format],
priorityETC1S: 2,
priorityUASTC: 4,
needsPowerOfTwo: false
},
{
if: "pvrtcSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA],
engineFormat: [EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format],
priorityETC1S: 5,
priorityUASTC: 6,
needsPowerOfTwo: true
}
];
const ETC1S_OPTIONS = FORMAT_OPTIONS.sort(function(a, b) {
return a.priorityETC1S - b.priorityETC1S;
});
const UASTC_OPTIONS = FORMAT_OPTIONS.sort(function(a, b) {
return a.priorityUASTC - b.priorityUASTC;
});
function getTranscoderFormat(basisFormat, width, height, hasAlpha) {
let transcoderFormat;
let engineFormat;
const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS;
for (let i = 0; i < options.length; i++) {
const opt = options[i];
if (!config[opt.if])
continue;
if (!opt.basisFormat.includes(basisFormat))
continue;
if (hasAlpha && opt.transcoderFormat.length < 2)
continue;
if (opt.needsPowerOfTwo && !(isPowerOfTwo(width) && isPowerOfTwo(height)))
continue;
transcoderFormat = opt.transcoderFormat[hasAlpha ? 1 : 0];
engineFormat = opt.engineFormat[hasAlpha ? 1 : 0];
return { transcoderFormat, engineFormat };
}
console.warn("THREE.KTX2Loader: No suitable compressed texture format found. Decoding to RGBA32.");
transcoderFormat = TranscoderFormat.RGBA32;
engineFormat = EngineFormat.RGBAFormat;
return { transcoderFormat, engineFormat };
}
function isPowerOfTwo(value) {
if (value <= 2)
return true;
return (value & value - 1) === 0 && value !== 0;
}
function concat(arrays) {
if (arrays.length === 1)
return arrays[0];
let totalByteLength = 0;
for (let i = 0; i < arrays.length; i++) {
const array = arrays[i];
totalByteLength += array.byteLength;
}
const result = new Uint8Array(totalByteLength);
let byteOffset = 0;
for (let i = 0; i < arrays.length; i++) {
const array = arrays[i];
result.set(array, byteOffset);
byteOffset += array.byteLength;
}
return result;
}
});
return KTX2Loader2;
})();
const UNCOMPRESSED_FORMATS = /* @__PURE__ */ new Set([THREE.RGBAFormat, THREE.RGFormat, THREE.RedFormat]);
const FORMAT_MAP = {
[ktxParse.VK_FORMAT_R32G32B32A32_SFLOAT]: THREE.RGBAFormat,
[ktxParse.VK_FORMAT_R16G16B16A16_SFLOAT]: THREE.RGBAFormat,
[ktxParse.VK_FORMAT_R8G8B8A8_UNORM]: THREE.RGBAFormat,
[ktxParse.VK_FORMAT_R8G8B8A8_SRGB]: THREE.RGBAFormat,
[ktxParse.VK_FORMAT_R32G32_SFLOAT]: THREE.RGFormat,
[ktxParse.VK_FORMAT_R16G16_SFLOAT]: THREE.RGFormat,
[ktxParse.VK_FORMAT_R8G8_UNORM]: THREE.RGFormat,
[ktxParse.VK_FORMAT_R8G8_SRGB]: THREE.RGFormat,
[ktxParse.VK_FORMAT_R32_SFLOAT]: THREE.RedFormat,
[ktxParse.VK_FORMAT_R16_SFLOAT]: THREE.RedFormat,
[ktxParse.VK_FORMAT_R8_SRGB]: THREE.RedFormat,
[ktxParse.VK_FORMAT_R8_UNORM]: THREE.RedFormat,
[ktxParse.VK_FORMAT_ASTC_6x6_SRGB_BLOCK]: THREE.RGBA_ASTC_6x6_Format,
[ktxParse.VK_FORMAT_ASTC_6x6_UNORM_BLOCK]: THREE.RGBA_ASTC_6x6_Format
};
const TYPE_MAP = {
[ktxParse.VK_FORMAT_R32G32B32A32_SFLOAT]: THREE.FloatType,
[ktxParse.VK_FORMAT_R16G16B16A16_SFLOAT]: THREE.HalfFloatType,
[ktxParse.VK_FORMAT_R8G8B8A8_UNORM]: THREE.UnsignedByteType,
[ktxParse.VK_FORMAT_R8G8B8A8_SRGB]: THREE.UnsignedByteType,
[ktxParse.VK_FORMAT_R32G32_SFLOAT]: THREE.FloatType,
[ktxParse.VK_FORMAT_R16G16_SFLOAT]: THREE.HalfFloatType,
[ktxParse.VK_FORMAT_R8G8_UNORM]: THREE.UnsignedByteType,
[ktxParse.VK_FORMAT_R8G8_SRGB]: THREE.UnsignedByteType,
[ktxParse.VK_FORMAT_R32_SFLOAT]: THREE.FloatType,
[ktxParse.VK_FORMAT_R16_SFLOAT]: THREE.HalfFloatType,
[ktxParse.VK_FORMAT_R8_SRGB]: THREE.UnsignedByteType,
[ktxParse.VK_FORMAT_R8_UNORM]: THREE.UnsignedByteType,
[ktxParse.VK_FORMAT_ASTC_6x6_SRGB_BLOCK]: THREE.UnsignedByteType,
[ktxParse.VK_FORMAT_ASTC_6x6_UNORM_BLOCK]: THREE.UnsignedByteType
};
async function createRawTexture(container) {
const { vkFormat } = container;
if (FORMAT_MAP[vkFormat] === void 0) {
throw new Error("THREE.KTX2Loader: Unsupported vkFormat.");
}
let zstd;
if (container.supercompressionScheme === ktxParse.KHR_SUPERCOMPRESSION_ZSTD) {
if (!_zstd) {
_zstd = new Promise(async (resolve) => {
const zstd2 = new zstddec.ZSTDDecoder();
await zstd2.init();
resolve(zstd2);
});
}
zstd = await _zstd;
}
const mipmaps = [];
for (let levelIndex = 0; levelIndex < container.levels.length; levelIndex++) {
const levelWidth = Math.max(1, container.pixelWidth >> levelIndex);
const levelHeight = Math.max(1, container.pixelHeight >> levelIndex);
const levelDepth = container.pixelDepth ? Math.max(1, container.pixelDepth >> levelIndex) : 0;
const level = container.levels[levelIndex];
let levelData;
if (container.supercompressionScheme === ktxParse.KHR_SUPERCOMPRESSION_NONE) {
levelData = level.levelData;
} else if (container.supercompressionScheme === ktxParse.KHR_SUPERCOMPRESSION_ZSTD) {
levelData = zstd.decode(level.levelData, level.uncompressedByteLength);
} else {
throw new Error("THREE.KTX2Loader: Unsupported supercompressionScheme.");
}
let data;
if (TYPE_MAP[vkFormat] === THREE.FloatType) {
data = new Float32Array(
levelData.buffer,
levelData.byteOffset,
levelData.byteLength / Float32Array.BYTES_PER_ELEMENT
);
} else if (TYPE_MAP[vkFormat] === THREE.HalfFloatType) {
data = new Uint16Array(
levelData.buffer,
levelData.byteOffset,
levelData.byteLength / Uint16Array.BYTES_PER_ELEMENT
);
} else {
data = levelData;
}
mipmaps.push({
data,
width: levelWidth,
height: levelHeight,
depth: levelDepth
});
}
let texture;
if (UNCOMPRESSED_FORMATS.has(FORMAT_MAP[vkFormat])) {
texture = container.pixelDepth === 0 ? new THREE.DataTexture(mipmaps[0].data, container.pixelWidth, container.pixelHeight) : new Data3DTexture.Data3DTexture(mipmaps[0].data, container.pixelWidth, container.pixelHeight, container.pixelDepth);
} else {
if (container.pixelDepth > 0)
throw new Error("THREE.KTX2Loader: Unsupported pixelDepth.");
texture = new THREE.CompressedTexture(mipmaps, container.pixelWidth, container.pixelHeight);
}
texture.mipmaps = mipmaps;
texture.type = TYPE_MAP[vkFormat];
texture.format = FORMAT_MAP[vkFormat];
texture.needsUpdate = true;
const colorSpace = parseColorSpace(container);
if ("colorSpace" in texture)
texture.colorSpace = colorSpace;
else
texture.encoding = colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding;
return Promise.resolve(texture);
}
function parseColorSpace(container) {
const dfd = container.dataFormatDescriptor[0];
if (dfd.colorPrimaries === ktxParse.KHR_DF_PRIMARIES_BT709) {
return dfd.transferFunction === ktxParse.KHR_DF_TRANSFER_SRGB ? SRGBColorSpace : LinearSRGBColorSpace;
} else if (dfd.colorPrimaries === ktxParse.KHR_DF_PRIMARIES_DISPLAYP3) {
return dfd.transferFunction === ktxParse.KHR_DF_TRANSFER_SRGB ? DisplayP3ColorSpace : LinearDisplayP3ColorSpace;
} else if (dfd.colorPrimaries === ktxParse.KHR_DF_PRIMARIES_UNSPECIFIED) {
return NoColorSpace;
} else {
console.warn(`THREE.KTX2Loader: Unsupported color primaries, "${dfd.colorPrimaries}"`);
return NoColorSpace;
}
}
exports.KTX2Loader = KTX2Loader;
//# sourceMappingURL=KTX2Loader.cjs.map
File diff suppressed because one or more lines are too long
+10
View File
@@ -0,0 +1,10 @@
import { LoadingManager, CompressedTextureLoader, CompressedTexture, WebGLRenderer } from 'three'
export class KTX2Loader extends CompressedTextureLoader {
constructor(manager?: LoadingManager)
setTranscoderPath(path: string): KTX2Loader
setWorkerLimit(limit: number): KTX2Loader
detectSupport(renderer: WebGLRenderer): KTX2Loader
dispose(): KTX2Loader
}
+544
View File
@@ -0,0 +1,544 @@
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;
};
import { Loader, RGBAFormat, RGBA_ASTC_4x4_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, FileLoader, UnsignedByteType, CompressedTexture, LinearFilter, LinearMipmapLinearFilter, FloatType, HalfFloatType, DataTexture, RGFormat, RedFormat, RGBA_ASTC_6x6_Format } from "three";
import { WorkerPool } from "../utils/WorkerPool.js";
import { KHR_DF_FLAG_ALPHA_PREMULTIPLIED, read, VK_FORMAT_UNDEFINED, KHR_SUPERCOMPRESSION_ZSTD, KHR_SUPERCOMPRESSION_NONE, KHR_DF_PRIMARIES_BT709, KHR_DF_TRANSFER_SRGB, KHR_DF_PRIMARIES_DISPLAYP3, KHR_DF_PRIMARIES_UNSPECIFIED, VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R16G16_SFLOAT, VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8_SRGB, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R16_SFLOAT, VK_FORMAT_R8_SRGB, VK_FORMAT_R8_UNORM, VK_FORMAT_ASTC_6x6_SRGB_BLOCK, VK_FORMAT_ASTC_6x6_UNORM_BLOCK } from "../libs/ktx-parse.js";
import { ZSTDDecoder } from "../libs/zstddec.js";
import { CompressedCubeTexture } from "../_polyfill/CompressedCubeTexture.js";
import { CompressedArrayTexture } from "../_polyfill/CompressedArrayTexture.js";
import { Data3DTexture } from "../_polyfill/Data3DTexture.js";
const LinearEncoding = 3e3;
const sRGBEncoding = 3001;
const NoColorSpace = "";
const DisplayP3ColorSpace = "display-p3";
const LinearDisplayP3ColorSpace = "display-p3-linear";
const LinearSRGBColorSpace = "srgb-linear";
const SRGBColorSpace = "srgb";
const _taskCache = /* @__PURE__ */ new WeakMap();
let _activeLoaders = 0;
let _zstd;
const KTX2Loader = /* @__PURE__ */ (() => {
const _KTX2Loader = class extends Loader {
constructor(manager) {
super(manager);
this.transcoderPath = "";
this.transcoderBinary = null;
this.transcoderPending = null;
this.workerPool = new WorkerPool();
this.workerSourceURL = "";
this.workerConfig = null;
if (typeof MSC_TRANSCODER !== "undefined") {
console.warn(
'THREE.KTX2Loader: Please update to latest "basis_transcoder". "msc_basis_transcoder" is no longer supported in three.js r125+.'
);
}
}
setTranscoderPath(path) {
this.transcoderPath = path;
return this;
}
setWorkerLimit(num) {
this.workerPool.setWorkerLimit(num);
return this;
}
detectSupport(renderer) {
this.workerConfig = {
astcSupported: renderer.extensions.has("WEBGL_compressed_texture_astc"),
etc1Supported: renderer.extensions.has("WEBGL_compressed_texture_etc1"),
etc2Supported: renderer.extensions.has("WEBGL_compressed_texture_etc"),
dxtSupported: renderer.extensions.has("WEBGL_compressed_texture_s3tc"),
bptcSupported: renderer.extensions.has("EXT_texture_compression_bptc"),
pvrtcSupported: renderer.extensions.has("WEBGL_compressed_texture_pvrtc") || renderer.extensions.has("WEBKIT_WEBGL_compressed_texture_pvrtc")
};
if (renderer.capabilities.isWebGL2) {
this.workerConfig.etc1Supported = false;
}
return this;
}
init() {
if (!this.transcoderPending) {
const jsLoader = new FileLoader(this.manager);
jsLoader.setPath(this.transcoderPath);
jsLoader.setWithCredentials(this.withCredentials);
const jsContent = jsLoader.loadAsync("basis_transcoder.js");
const binaryLoader = new FileLoader(this.manager);
binaryLoader.setPath(this.transcoderPath);
binaryLoader.setResponseType("arraybuffer");
binaryLoader.setWithCredentials(this.withCredentials);
const binaryContent = binaryLoader.loadAsync("basis_transcoder.wasm");
this.transcoderPending = Promise.all([jsContent, binaryContent]).then(([jsContent2, binaryContent2]) => {
const fn = _KTX2Loader.BasisWorker.toString();
const body = [
"/* constants */",
"let _EngineFormat = " + JSON.stringify(_KTX2Loader.EngineFormat),
"let _TranscoderFormat = " + JSON.stringify(_KTX2Loader.TranscoderFormat),
"let _BasisFormat = " + JSON.stringify(_KTX2Loader.BasisFormat),
"/* basis_transcoder.js */",
jsContent2,
"/* worker */",
fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"))
].join("\n");
this.workerSourceURL = URL.createObjectURL(new Blob([body]));
this.transcoderBinary = binaryContent2;
this.workerPool.setWorkerCreator(() => {
const worker = new Worker(this.workerSourceURL);
const transcoderBinary = this.transcoderBinary.slice(0);
worker.postMessage({ type: "init", config: this.workerConfig, transcoderBinary }, [transcoderBinary]);
return worker;
});
});
if (_activeLoaders > 0) {
console.warn(
"THREE.KTX2Loader: Multiple active KTX2 loaders may cause performance issues. Use a single KTX2Loader instance, or call .dispose() on old instances."
);
}
_activeLoaders++;
}
return this.transcoderPending;
}
load(url, onLoad, onProgress, onError) {
if (this.workerConfig === null) {
throw new Error("THREE.KTX2Loader: Missing initialization with `.detectSupport( renderer )`.");
}
const loader = new FileLoader(this.manager);
loader.setResponseType("arraybuffer");
loader.setWithCredentials(this.withCredentials);
loader.load(
url,
(buffer) => {
if (_taskCache.has(buffer)) {
const cachedTask = _taskCache.get(buffer);
return cachedTask.promise.then(onLoad).catch(onError);
}
this._createTexture(buffer).then((texture) => onLoad ? onLoad(texture) : null).catch(onError);
},
onProgress,
onError
);
}
_createTextureFrom(transcodeResult, container) {
const { faces, width, height, format, type, error, dfdFlags } = transcodeResult;
if (type === "error")
return Promise.reject(error);
let texture;
if (container.faceCount === 6) {
texture = new CompressedCubeTexture(faces, format, UnsignedByteType);
} else {
const mipmaps = faces[0].mipmaps;
texture = container.layerCount > 1 ? new CompressedArrayTexture(mipmaps, width, height, container.layerCount, format, UnsignedByteType) : new CompressedTexture(mipmaps, width, height, format, UnsignedByteType);
}
texture.minFilter = faces[0].mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter;
texture.magFilter = LinearFilter;
texture.generateMipmaps = false;
texture.needsUpdate = true;
const colorSpace = parseColorSpace(container);
if ("colorSpace" in texture)
texture.colorSpace = colorSpace;
else
texture.encoding = colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding;
texture.premultiplyAlpha = !!(dfdFlags & KHR_DF_FLAG_ALPHA_PREMULTIPLIED);
return texture;
}
/**
* @param {ArrayBuffer} buffer
* @param {object?} config
* @return {Promise<CompressedTexture|CompressedArrayTexture|DataTexture|Data3DTexture>}
*/
async _createTexture(buffer, config = {}) {
const container = read(new Uint8Array(buffer));
if (container.vkFormat !== VK_FORMAT_UNDEFINED) {
return createRawTexture(container);
}
const taskConfig = config;
const texturePending = this.init().then(() => {
return this.workerPool.postMessage({ type: "transcode", buffer, taskConfig }, [buffer]);
}).then((e) => this._createTextureFrom(e.data, container));
_taskCache.set(buffer, { promise: texturePending });
return texturePending;
}
dispose() {
this.workerPool.dispose();
if (this.workerSourceURL)
URL.revokeObjectURL(this.workerSourceURL);
_activeLoaders--;
return this;
}
};
let KTX2Loader2 = _KTX2Loader;
/* CONSTANTS */
__publicField(KTX2Loader2, "BasisFormat", {
ETC1S: 0,
UASTC_4x4: 1
});
__publicField(KTX2Loader2, "TranscoderFormat", {
ETC1: 0,
ETC2: 1,
BC1: 2,
BC3: 3,
BC4: 4,
BC5: 5,
BC7_M6_OPAQUE_ONLY: 6,
BC7_M5: 7,
PVRTC1_4_RGB: 8,
PVRTC1_4_RGBA: 9,
ASTC_4x4: 10,
ATC_RGB: 11,
ATC_RGBA_INTERPOLATED_ALPHA: 12,
RGBA32: 13,
RGB565: 14,
BGR565: 15,
RGBA4444: 16
});
__publicField(KTX2Loader2, "EngineFormat", {
RGBAFormat,
RGBA_ASTC_4x4_Format,
RGBA_BPTC_Format,
RGBA_ETC2_EAC_Format,
RGBA_PVRTC_4BPPV1_Format,
RGBA_S3TC_DXT5_Format,
RGB_ETC1_Format,
RGB_ETC2_Format,
RGB_PVRTC_4BPPV1_Format,
RGB_S3TC_DXT1_Format
});
/* WEB WORKER */
__publicField(KTX2Loader2, "BasisWorker", function() {
let config;
let transcoderPending;
let BasisModule;
const EngineFormat = _EngineFormat;
const TranscoderFormat = _TranscoderFormat;
const BasisFormat = _BasisFormat;
self.addEventListener("message", function(e) {
const message = e.data;
switch (message.type) {
case "init":
config = message.config;
init(message.transcoderBinary);
break;
case "transcode":
transcoderPending.then(() => {
try {
const { faces, buffers, width, height, hasAlpha, format, dfdFlags } = transcode(message.buffer);
self.postMessage(
{ type: "transcode", id: message.id, faces, width, height, hasAlpha, format, dfdFlags },
buffers
);
} catch (error) {
console.error(error);
self.postMessage({ type: "error", id: message.id, error: error.message });
}
});
break;
}
});
function init(wasmBinary) {
transcoderPending = new Promise((resolve) => {
BasisModule = { wasmBinary, onRuntimeInitialized: resolve };
BASIS(BasisModule);
}).then(() => {
BasisModule.initializeBasis();
if (BasisModule.KTX2File === void 0) {
console.warn("THREE.KTX2Loader: Please update Basis Universal transcoder.");
}
});
}
function transcode(buffer) {
const ktx2File = new BasisModule.KTX2File(new Uint8Array(buffer));
function cleanup() {
ktx2File.close();
ktx2File.delete();
}
if (!ktx2File.isValid()) {
cleanup();
throw new Error("THREE.KTX2Loader: Invalid or unsupported .ktx2 file");
}
const basisFormat = ktx2File.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
const width = ktx2File.getWidth();
const height = ktx2File.getHeight();
const layerCount = ktx2File.getLayers() || 1;
const levelCount = ktx2File.getLevels();
const faceCount = ktx2File.getFaces();
const hasAlpha = ktx2File.getHasAlpha();
const dfdFlags = ktx2File.getDFDFlags();
const { transcoderFormat, engineFormat } = getTranscoderFormat(basisFormat, width, height, hasAlpha);
if (!width || !height || !levelCount) {
cleanup();
throw new Error("THREE.KTX2Loader: Invalid texture");
}
if (!ktx2File.startTranscoding()) {
cleanup();
throw new Error("THREE.KTX2Loader: .startTranscoding failed");
}
const faces = [];
const buffers = [];
for (let face = 0; face < faceCount; face++) {
const mipmaps = [];
for (let mip = 0; mip < levelCount; mip++) {
const layerMips = [];
let mipWidth, mipHeight;
for (let layer = 0; layer < layerCount; layer++) {
const levelInfo = ktx2File.getImageLevelInfo(mip, layer, face);
if (face === 0 && mip === 0 && layer === 0 && (levelInfo.origWidth % 4 !== 0 || levelInfo.origHeight % 4 !== 0)) {
console.warn("THREE.KTX2Loader: ETC1S and UASTC textures should use multiple-of-four dimensions.");
}
if (levelCount > 1) {
mipWidth = levelInfo.origWidth;
mipHeight = levelInfo.origHeight;
} else {
mipWidth = levelInfo.width;
mipHeight = levelInfo.height;
}
const dst = new Uint8Array(ktx2File.getImageTranscodedSizeInBytes(mip, layer, 0, transcoderFormat));
const status = ktx2File.transcodeImage(dst, mip, layer, face, transcoderFormat, 0, -1, -1);
if (!status) {
cleanup();
throw new Error("THREE.KTX2Loader: .transcodeImage failed.");
}
layerMips.push(dst);
}
const mipData = concat(layerMips);
mipmaps.push({ data: mipData, width: mipWidth, height: mipHeight });
buffers.push(mipData.buffer);
}
faces.push({ mipmaps, width, height, format: engineFormat });
}
cleanup();
return { faces, buffers, width, height, hasAlpha, format: engineFormat, dfdFlags };
}
const FORMAT_OPTIONS = [
{
if: "astcSupported",
basisFormat: [BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4],
engineFormat: [EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format],
priorityETC1S: Infinity,
priorityUASTC: 1,
needsPowerOfTwo: false
},
{
if: "bptcSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5],
engineFormat: [EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format],
priorityETC1S: 3,
priorityUASTC: 2,
needsPowerOfTwo: false
},
{
if: "dxtSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.BC1, TranscoderFormat.BC3],
engineFormat: [EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format],
priorityETC1S: 4,
priorityUASTC: 5,
needsPowerOfTwo: false
},
{
if: "etc2Supported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ETC1, TranscoderFormat.ETC2],
engineFormat: [EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format],
priorityETC1S: 1,
priorityUASTC: 3,
needsPowerOfTwo: false
},
{
if: "etc1Supported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.ETC1],
engineFormat: [EngineFormat.RGB_ETC1_Format],
priorityETC1S: 2,
priorityUASTC: 4,
needsPowerOfTwo: false
},
{
if: "pvrtcSupported",
basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
transcoderFormat: [TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA],
engineFormat: [EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format],
priorityETC1S: 5,
priorityUASTC: 6,
needsPowerOfTwo: true
}
];
const ETC1S_OPTIONS = FORMAT_OPTIONS.sort(function(a, b) {
return a.priorityETC1S - b.priorityETC1S;
});
const UASTC_OPTIONS = FORMAT_OPTIONS.sort(function(a, b) {
return a.priorityUASTC - b.priorityUASTC;
});
function getTranscoderFormat(basisFormat, width, height, hasAlpha) {
let transcoderFormat;
let engineFormat;
const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS;
for (let i = 0; i < options.length; i++) {
const opt = options[i];
if (!config[opt.if])
continue;
if (!opt.basisFormat.includes(basisFormat))
continue;
if (hasAlpha && opt.transcoderFormat.length < 2)
continue;
if (opt.needsPowerOfTwo && !(isPowerOfTwo(width) && isPowerOfTwo(height)))
continue;
transcoderFormat = opt.transcoderFormat[hasAlpha ? 1 : 0];
engineFormat = opt.engineFormat[hasAlpha ? 1 : 0];
return { transcoderFormat, engineFormat };
}
console.warn("THREE.KTX2Loader: No suitable compressed texture format found. Decoding to RGBA32.");
transcoderFormat = TranscoderFormat.RGBA32;
engineFormat = EngineFormat.RGBAFormat;
return { transcoderFormat, engineFormat };
}
function isPowerOfTwo(value) {
if (value <= 2)
return true;
return (value & value - 1) === 0 && value !== 0;
}
function concat(arrays) {
if (arrays.length === 1)
return arrays[0];
let totalByteLength = 0;
for (let i = 0; i < arrays.length; i++) {
const array = arrays[i];
totalByteLength += array.byteLength;
}
const result = new Uint8Array(totalByteLength);
let byteOffset = 0;
for (let i = 0; i < arrays.length; i++) {
const array = arrays[i];
result.set(array, byteOffset);
byteOffset += array.byteLength;
}
return result;
}
});
return KTX2Loader2;
})();
const UNCOMPRESSED_FORMATS = /* @__PURE__ */ new Set([RGBAFormat, RGFormat, RedFormat]);
const FORMAT_MAP = {
[VK_FORMAT_R32G32B32A32_SFLOAT]: RGBAFormat,
[VK_FORMAT_R16G16B16A16_SFLOAT]: RGBAFormat,
[VK_FORMAT_R8G8B8A8_UNORM]: RGBAFormat,
[VK_FORMAT_R8G8B8A8_SRGB]: RGBAFormat,
[VK_FORMAT_R32G32_SFLOAT]: RGFormat,
[VK_FORMAT_R16G16_SFLOAT]: RGFormat,
[VK_FORMAT_R8G8_UNORM]: RGFormat,
[VK_FORMAT_R8G8_SRGB]: RGFormat,
[VK_FORMAT_R32_SFLOAT]: RedFormat,
[VK_FORMAT_R16_SFLOAT]: RedFormat,
[VK_FORMAT_R8_SRGB]: RedFormat,
[VK_FORMAT_R8_UNORM]: RedFormat,
[VK_FORMAT_ASTC_6x6_SRGB_BLOCK]: RGBA_ASTC_6x6_Format,
[VK_FORMAT_ASTC_6x6_UNORM_BLOCK]: RGBA_ASTC_6x6_Format
};
const TYPE_MAP = {
[VK_FORMAT_R32G32B32A32_SFLOAT]: FloatType,
[VK_FORMAT_R16G16B16A16_SFLOAT]: HalfFloatType,
[VK_FORMAT_R8G8B8A8_UNORM]: UnsignedByteType,
[VK_FORMAT_R8G8B8A8_SRGB]: UnsignedByteType,
[VK_FORMAT_R32G32_SFLOAT]: FloatType,
[VK_FORMAT_R16G16_SFLOAT]: HalfFloatType,
[VK_FORMAT_R8G8_UNORM]: UnsignedByteType,
[VK_FORMAT_R8G8_SRGB]: UnsignedByteType,
[VK_FORMAT_R32_SFLOAT]: FloatType,
[VK_FORMAT_R16_SFLOAT]: HalfFloatType,
[VK_FORMAT_R8_SRGB]: UnsignedByteType,
[VK_FORMAT_R8_UNORM]: UnsignedByteType,
[VK_FORMAT_ASTC_6x6_SRGB_BLOCK]: UnsignedByteType,
[VK_FORMAT_ASTC_6x6_UNORM_BLOCK]: UnsignedByteType
};
async function createRawTexture(container) {
const { vkFormat } = container;
if (FORMAT_MAP[vkFormat] === void 0) {
throw new Error("THREE.KTX2Loader: Unsupported vkFormat.");
}
let zstd;
if (container.supercompressionScheme === KHR_SUPERCOMPRESSION_ZSTD) {
if (!_zstd) {
_zstd = new Promise(async (resolve) => {
const zstd2 = new ZSTDDecoder();
await zstd2.init();
resolve(zstd2);
});
}
zstd = await _zstd;
}
const mipmaps = [];
for (let levelIndex = 0; levelIndex < container.levels.length; levelIndex++) {
const levelWidth = Math.max(1, container.pixelWidth >> levelIndex);
const levelHeight = Math.max(1, container.pixelHeight >> levelIndex);
const levelDepth = container.pixelDepth ? Math.max(1, container.pixelDepth >> levelIndex) : 0;
const level = container.levels[levelIndex];
let levelData;
if (container.supercompressionScheme === KHR_SUPERCOMPRESSION_NONE) {
levelData = level.levelData;
} else if (container.supercompressionScheme === KHR_SUPERCOMPRESSION_ZSTD) {
levelData = zstd.decode(level.levelData, level.uncompressedByteLength);
} else {
throw new Error("THREE.KTX2Loader: Unsupported supercompressionScheme.");
}
let data;
if (TYPE_MAP[vkFormat] === FloatType) {
data = new Float32Array(
levelData.buffer,
levelData.byteOffset,
levelData.byteLength / Float32Array.BYTES_PER_ELEMENT
);
} else if (TYPE_MAP[vkFormat] === HalfFloatType) {
data = new Uint16Array(
levelData.buffer,
levelData.byteOffset,
levelData.byteLength / Uint16Array.BYTES_PER_ELEMENT
);
} else {
data = levelData;
}
mipmaps.push({
data,
width: levelWidth,
height: levelHeight,
depth: levelDepth
});
}
let texture;
if (UNCOMPRESSED_FORMATS.has(FORMAT_MAP[vkFormat])) {
texture = container.pixelDepth === 0 ? new DataTexture(mipmaps[0].data, container.pixelWidth, container.pixelHeight) : new Data3DTexture(mipmaps[0].data, container.pixelWidth, container.pixelHeight, container.pixelDepth);
} else {
if (container.pixelDepth > 0)
throw new Error("THREE.KTX2Loader: Unsupported pixelDepth.");
texture = new CompressedTexture(mipmaps, container.pixelWidth, container.pixelHeight);
}
texture.mipmaps = mipmaps;
texture.type = TYPE_MAP[vkFormat];
texture.format = FORMAT_MAP[vkFormat];
texture.needsUpdate = true;
const colorSpace = parseColorSpace(container);
if ("colorSpace" in texture)
texture.colorSpace = colorSpace;
else
texture.encoding = colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding;
return Promise.resolve(texture);
}
function parseColorSpace(container) {
const dfd = container.dataFormatDescriptor[0];
if (dfd.colorPrimaries === KHR_DF_PRIMARIES_BT709) {
return dfd.transferFunction === KHR_DF_TRANSFER_SRGB ? SRGBColorSpace : LinearSRGBColorSpace;
} else if (dfd.colorPrimaries === KHR_DF_PRIMARIES_DISPLAYP3) {
return dfd.transferFunction === KHR_DF_TRANSFER_SRGB ? DisplayP3ColorSpace : LinearDisplayP3ColorSpace;
} else if (dfd.colorPrimaries === KHR_DF_PRIMARIES_UNSPECIFIED) {
return NoColorSpace;
} else {
console.warn(`THREE.KTX2Loader: Unsupported color primaries, "${dfd.colorPrimaries}"`);
return NoColorSpace;
}
}
export {
KTX2Loader
};
//# sourceMappingURL=KTX2Loader.js.map
File diff suppressed because one or more lines are too long
+94
View File
@@ -0,0 +1,94 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
class KTXLoader extends THREE.CompressedTextureLoader {
constructor(manager) {
super(manager);
}
parse(buffer, loadMipmaps) {
const ktx = new KhronosTextureContainer(buffer, 1);
return {
mipmaps: ktx.mipmaps(loadMipmaps),
width: ktx.pixelWidth,
height: ktx.pixelHeight,
format: ktx.glInternalFormat,
isCubemap: ktx.numberOfFaces === 6,
mipmapCount: ktx.numberOfMipmapLevels
};
}
}
const HEADER_LEN = 12 + 13 * 4;
const COMPRESSED_2D = 0;
class KhronosTextureContainer {
/**
* @param {ArrayBuffer} arrayBuffer- contents of the KTX container file
* @param {number} facesExpected- should be either 1 or 6, based whether a cube texture or or
* @param {boolean} threeDExpected- provision for indicating that data should be a 3D texture, not implemented
* @param {boolean} textureArrayExpected- provision for indicating that data should be a texture array, not implemented
*/
constructor(arrayBuffer, facesExpected) {
this.arrayBuffer = arrayBuffer;
const identifier = new Uint8Array(this.arrayBuffer, 0, 12);
if (identifier[0] !== 171 || identifier[1] !== 75 || identifier[2] !== 84 || identifier[3] !== 88 || identifier[4] !== 32 || identifier[5] !== 49 || identifier[6] !== 49 || identifier[7] !== 187 || identifier[8] !== 13 || identifier[9] !== 10 || identifier[10] !== 26 || identifier[11] !== 10) {
console.error("texture missing KTX identifier");
return;
}
const dataSize = Uint32Array.BYTES_PER_ELEMENT;
const headerDataView = new DataView(this.arrayBuffer, 12, 13 * dataSize);
const endianness = headerDataView.getUint32(0, true);
const littleEndian = endianness === 67305985;
this.glType = headerDataView.getUint32(1 * dataSize, littleEndian);
this.glTypeSize = headerDataView.getUint32(2 * dataSize, littleEndian);
this.glFormat = headerDataView.getUint32(3 * dataSize, littleEndian);
this.glInternalFormat = headerDataView.getUint32(4 * dataSize, littleEndian);
this.glBaseInternalFormat = headerDataView.getUint32(5 * dataSize, littleEndian);
this.pixelWidth = headerDataView.getUint32(6 * dataSize, littleEndian);
this.pixelHeight = headerDataView.getUint32(7 * dataSize, littleEndian);
this.pixelDepth = headerDataView.getUint32(8 * dataSize, littleEndian);
this.numberOfArrayElements = headerDataView.getUint32(9 * dataSize, littleEndian);
this.numberOfFaces = headerDataView.getUint32(10 * dataSize, littleEndian);
this.numberOfMipmapLevels = headerDataView.getUint32(11 * dataSize, littleEndian);
this.bytesOfKeyValueData = headerDataView.getUint32(12 * dataSize, littleEndian);
if (this.glType !== 0) {
console.warn("only compressed formats currently supported");
return;
} else {
this.numberOfMipmapLevels = Math.max(1, this.numberOfMipmapLevels);
}
if (this.pixelHeight === 0 || this.pixelDepth !== 0) {
console.warn("only 2D textures currently supported");
return;
}
if (this.numberOfArrayElements !== 0) {
console.warn("texture arrays not currently supported");
return;
}
if (this.numberOfFaces !== facesExpected) {
console.warn("number of faces expected" + facesExpected + ", but found " + this.numberOfFaces);
return;
}
this.loadType = COMPRESSED_2D;
}
mipmaps(loadMipmaps) {
const mipmaps = [];
let dataOffset = HEADER_LEN + this.bytesOfKeyValueData;
let width = this.pixelWidth;
let height = this.pixelHeight;
const mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1;
for (let level = 0; level < mipmapCount; level++) {
const imageSize = new Int32Array(this.arrayBuffer, dataOffset, 1)[0];
dataOffset += 4;
for (let face = 0; face < this.numberOfFaces; face++) {
const byteArray = new Uint8Array(this.arrayBuffer, dataOffset, imageSize);
mipmaps.push({ data: byteArray, width, height });
dataOffset += imageSize;
dataOffset += 3 - (imageSize + 3) % 4;
}
width = Math.max(1, width * 0.5);
height = Math.max(1, height * 0.5);
}
return mipmaps;
}
}
exports.KTXLoader = KTXLoader;
//# sourceMappingURL=KTXLoader.cjs.map
File diff suppressed because one or more lines are too long
+16
View File
@@ -0,0 +1,16 @@
import { LoadingManager, CompressedTextureLoader, PixelFormat, CompressedPixelFormat } from 'three'
export interface KTX {
mipmaps: object[]
width: number
height: number
format: PixelFormat | CompressedPixelFormat
mipmapCount: number
isCubemap: boolean
}
export class KTXLoader extends CompressedTextureLoader {
constructor(manager?: LoadingManager)
parse(buffer: ArrayBuffer, loadMipmaps: boolean): KTX
}
+94
View File
@@ -0,0 +1,94 @@
import { CompressedTextureLoader } from "three";
class KTXLoader extends CompressedTextureLoader {
constructor(manager) {
super(manager);
}
parse(buffer, loadMipmaps) {
const ktx = new KhronosTextureContainer(buffer, 1);
return {
mipmaps: ktx.mipmaps(loadMipmaps),
width: ktx.pixelWidth,
height: ktx.pixelHeight,
format: ktx.glInternalFormat,
isCubemap: ktx.numberOfFaces === 6,
mipmapCount: ktx.numberOfMipmapLevels
};
}
}
const HEADER_LEN = 12 + 13 * 4;
const COMPRESSED_2D = 0;
class KhronosTextureContainer {
/**
* @param {ArrayBuffer} arrayBuffer- contents of the KTX container file
* @param {number} facesExpected- should be either 1 or 6, based whether a cube texture or or
* @param {boolean} threeDExpected- provision for indicating that data should be a 3D texture, not implemented
* @param {boolean} textureArrayExpected- provision for indicating that data should be a texture array, not implemented
*/
constructor(arrayBuffer, facesExpected) {
this.arrayBuffer = arrayBuffer;
const identifier = new Uint8Array(this.arrayBuffer, 0, 12);
if (identifier[0] !== 171 || identifier[1] !== 75 || identifier[2] !== 84 || identifier[3] !== 88 || identifier[4] !== 32 || identifier[5] !== 49 || identifier[6] !== 49 || identifier[7] !== 187 || identifier[8] !== 13 || identifier[9] !== 10 || identifier[10] !== 26 || identifier[11] !== 10) {
console.error("texture missing KTX identifier");
return;
}
const dataSize = Uint32Array.BYTES_PER_ELEMENT;
const headerDataView = new DataView(this.arrayBuffer, 12, 13 * dataSize);
const endianness = headerDataView.getUint32(0, true);
const littleEndian = endianness === 67305985;
this.glType = headerDataView.getUint32(1 * dataSize, littleEndian);
this.glTypeSize = headerDataView.getUint32(2 * dataSize, littleEndian);
this.glFormat = headerDataView.getUint32(3 * dataSize, littleEndian);
this.glInternalFormat = headerDataView.getUint32(4 * dataSize, littleEndian);
this.glBaseInternalFormat = headerDataView.getUint32(5 * dataSize, littleEndian);
this.pixelWidth = headerDataView.getUint32(6 * dataSize, littleEndian);
this.pixelHeight = headerDataView.getUint32(7 * dataSize, littleEndian);
this.pixelDepth = headerDataView.getUint32(8 * dataSize, littleEndian);
this.numberOfArrayElements = headerDataView.getUint32(9 * dataSize, littleEndian);
this.numberOfFaces = headerDataView.getUint32(10 * dataSize, littleEndian);
this.numberOfMipmapLevels = headerDataView.getUint32(11 * dataSize, littleEndian);
this.bytesOfKeyValueData = headerDataView.getUint32(12 * dataSize, littleEndian);
if (this.glType !== 0) {
console.warn("only compressed formats currently supported");
return;
} else {
this.numberOfMipmapLevels = Math.max(1, this.numberOfMipmapLevels);
}
if (this.pixelHeight === 0 || this.pixelDepth !== 0) {
console.warn("only 2D textures currently supported");
return;
}
if (this.numberOfArrayElements !== 0) {
console.warn("texture arrays not currently supported");
return;
}
if (this.numberOfFaces !== facesExpected) {
console.warn("number of faces expected" + facesExpected + ", but found " + this.numberOfFaces);
return;
}
this.loadType = COMPRESSED_2D;
}
mipmaps(loadMipmaps) {
const mipmaps = [];
let dataOffset = HEADER_LEN + this.bytesOfKeyValueData;
let width = this.pixelWidth;
let height = this.pixelHeight;
const mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1;
for (let level = 0; level < mipmapCount; level++) {
const imageSize = new Int32Array(this.arrayBuffer, dataOffset, 1)[0];
dataOffset += 4;
for (let face = 0; face < this.numberOfFaces; face++) {
const byteArray = new Uint8Array(this.arrayBuffer, dataOffset, imageSize);
mipmaps.push({ data: byteArray, width, height });
dataOffset += imageSize;
dataOffset += 3 - (imageSize + 3) % 4;
}
width = Math.max(1, width * 0.5);
height = Math.max(1, height * 0.5);
}
return mipmaps;
}
}
export {
KTXLoader
};
//# sourceMappingURL=KTXLoader.js.map
File diff suppressed because one or more lines are too long
+1420
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+26
View File
@@ -0,0 +1,26 @@
import { Loader, LoadingManager, Group, Material } from 'three'
export class LDrawLoader extends Loader {
materials: Material[]
materialsLibrary: Record<string, Material>
fileMap: Record<string, string>
smoothNormals: boolean
constructor(manager?: LoadingManager)
load(
url: string,
onLoad: (data: Group) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: ErrorEvent) => void,
): void
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<Group>
preloadMaterials(url: string): Promise<void>
setFileMap(fileMap: Record<string, string>): void
setMaterials(materials: Material[]): void
parse(text: string, path: string, onLoad: (data: Group) => void): void
addMaterial(material: Material): void
getMaterial(colourCode: string): Material | null
}
+1420
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+104
View File
@@ -0,0 +1,104 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const Data3DTexture = require("../_polyfill/Data3DTexture.cjs");
class LUT3dlLoader extends THREE.Loader {
load(url, onLoad, onProgress, onError) {
const loader = new THREE.FileLoader(this.manager);
loader.setPath(this.path);
loader.setResponseType("text");
loader.load(
url,
(text) => {
try {
onLoad(this.parse(text));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
this.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(str) {
str = str.replace(/^#.*?(\n|\r)/gm, "").replace(/^\s*?(\n|\r)/gm, "").trim();
const lines = str.split(/[\n\r]+/g);
const gridLines = lines[0].trim().split(/\s+/g).map((e) => parseFloat(e));
const gridStep = gridLines[1] - gridLines[0];
const size = gridLines.length;
for (let i = 1, l = gridLines.length; i < l; i++) {
if (gridStep !== gridLines[i] - gridLines[i - 1]) {
throw new Error("LUT3dlLoader: Inconsistent grid size not supported.");
}
}
const dataArray = new Array(size * size * size * 4);
let index = 0;
let maxOutputValue = 0;
for (let i = 1, l = lines.length; i < l; i++) {
const line = lines[i].trim();
const split = line.split(/\s/g);
const r = parseFloat(split[0]);
const g = parseFloat(split[1]);
const b = parseFloat(split[2]);
maxOutputValue = Math.max(maxOutputValue, r, g, b);
const bLayer = index % size;
const gLayer = Math.floor(index / size) % size;
const rLayer = Math.floor(index / (size * size)) % size;
const pixelIndex = bLayer * size * size + gLayer * size + rLayer;
dataArray[4 * pixelIndex + 0] = r;
dataArray[4 * pixelIndex + 1] = g;
dataArray[4 * pixelIndex + 2] = b;
dataArray[4 * pixelIndex + 3] = 1;
index += 1;
}
const bits = Math.ceil(Math.log2(maxOutputValue));
const maxBitValue = Math.pow(2, bits);
for (let i = 0, l = dataArray.length; i < l; i += 4) {
const r = dataArray[i + 0];
const g = dataArray[i + 1];
const b = dataArray[i + 2];
dataArray[i + 0] = 255 * r / maxBitValue;
dataArray[i + 1] = 255 * g / maxBitValue;
dataArray[i + 2] = 255 * b / maxBitValue;
}
const data = new Uint8Array(dataArray);
const texture = new THREE.DataTexture();
texture.image.data = data;
texture.image.width = size;
texture.image.height = size * size;
texture.format = THREE.RGBAFormat;
texture.type = THREE.UnsignedByteType;
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearFilter;
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.wrapT = THREE.ClampToEdgeWrapping;
texture.generateMipmaps = false;
texture.needsUpdate = true;
const texture3D = new Data3DTexture.Data3DTexture();
texture3D.image.data = data;
texture3D.image.width = size;
texture3D.image.height = size;
texture3D.image.depth = size;
texture3D.format = THREE.RGBAFormat;
texture3D.type = THREE.UnsignedByteType;
texture3D.magFilter = THREE.LinearFilter;
texture3D.minFilter = THREE.LinearFilter;
texture3D.wrapS = THREE.ClampToEdgeWrapping;
texture3D.wrapT = THREE.ClampToEdgeWrapping;
texture3D.wrapR = THREE.ClampToEdgeWrapping;
texture3D.generateMipmaps = false;
texture3D.needsUpdate = true;
return {
size,
texture,
texture3D
};
}
}
exports.LUT3dlLoader = LUT3dlLoader;
//# sourceMappingURL=LUT3dlLoader.cjs.map
File diff suppressed because one or more lines are too long
+20
View File
@@ -0,0 +1,20 @@
import { Loader, LoadingManager, DataTexture, Texture } from 'three'
export interface LUT3dlResult {
size: number
texture: DataTexture
texture3D: Texture // Data3DTexture
}
export class LUT3dlLoader extends Loader {
constructor(manager?: LoadingManager)
load(
url: string,
onLoad: (result: LUT3dlResult) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (event: Error) => void,
): any
loadAsync(url: string, onProgress?: (event: ProgressEvent) => void): Promise<LUT3dlResult>
parse(data: string): LUT3dlResult
}
+104
View File
@@ -0,0 +1,104 @@
import { Loader, FileLoader, DataTexture, RGBAFormat, UnsignedByteType, LinearFilter, ClampToEdgeWrapping } from "three";
import { Data3DTexture } from "../_polyfill/Data3DTexture.js";
class LUT3dlLoader extends Loader {
load(url, onLoad, onProgress, onError) {
const loader = new FileLoader(this.manager);
loader.setPath(this.path);
loader.setResponseType("text");
loader.load(
url,
(text) => {
try {
onLoad(this.parse(text));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
this.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(str) {
str = str.replace(/^#.*?(\n|\r)/gm, "").replace(/^\s*?(\n|\r)/gm, "").trim();
const lines = str.split(/[\n\r]+/g);
const gridLines = lines[0].trim().split(/\s+/g).map((e) => parseFloat(e));
const gridStep = gridLines[1] - gridLines[0];
const size = gridLines.length;
for (let i = 1, l = gridLines.length; i < l; i++) {
if (gridStep !== gridLines[i] - gridLines[i - 1]) {
throw new Error("LUT3dlLoader: Inconsistent grid size not supported.");
}
}
const dataArray = new Array(size * size * size * 4);
let index = 0;
let maxOutputValue = 0;
for (let i = 1, l = lines.length; i < l; i++) {
const line = lines[i].trim();
const split = line.split(/\s/g);
const r = parseFloat(split[0]);
const g = parseFloat(split[1]);
const b = parseFloat(split[2]);
maxOutputValue = Math.max(maxOutputValue, r, g, b);
const bLayer = index % size;
const gLayer = Math.floor(index / size) % size;
const rLayer = Math.floor(index / (size * size)) % size;
const pixelIndex = bLayer * size * size + gLayer * size + rLayer;
dataArray[4 * pixelIndex + 0] = r;
dataArray[4 * pixelIndex + 1] = g;
dataArray[4 * pixelIndex + 2] = b;
dataArray[4 * pixelIndex + 3] = 1;
index += 1;
}
const bits = Math.ceil(Math.log2(maxOutputValue));
const maxBitValue = Math.pow(2, bits);
for (let i = 0, l = dataArray.length; i < l; i += 4) {
const r = dataArray[i + 0];
const g = dataArray[i + 1];
const b = dataArray[i + 2];
dataArray[i + 0] = 255 * r / maxBitValue;
dataArray[i + 1] = 255 * g / maxBitValue;
dataArray[i + 2] = 255 * b / maxBitValue;
}
const data = new Uint8Array(dataArray);
const texture = new DataTexture();
texture.image.data = data;
texture.image.width = size;
texture.image.height = size * size;
texture.format = RGBAFormat;
texture.type = UnsignedByteType;
texture.magFilter = LinearFilter;
texture.minFilter = LinearFilter;
texture.wrapS = ClampToEdgeWrapping;
texture.wrapT = ClampToEdgeWrapping;
texture.generateMipmaps = false;
texture.needsUpdate = true;
const texture3D = new Data3DTexture();
texture3D.image.data = data;
texture3D.image.width = size;
texture3D.image.height = size;
texture3D.image.depth = size;
texture3D.format = RGBAFormat;
texture3D.type = UnsignedByteType;
texture3D.magFilter = LinearFilter;
texture3D.minFilter = LinearFilter;
texture3D.wrapS = ClampToEdgeWrapping;
texture3D.wrapT = ClampToEdgeWrapping;
texture3D.wrapR = ClampToEdgeWrapping;
texture3D.generateMipmaps = false;
texture3D.needsUpdate = true;
return {
size,
texture,
texture3D
};
}
}
export {
LUT3dlLoader
};
//# sourceMappingURL=LUT3dlLoader.js.map
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More