src/plugins/XKTLoaderPlugin/parsers/ParserV1.js
/*
Parser for .XKT Format V1
.XKT specifications: https://github.com/xeokit/xeokit-sdk/wiki/XKT-Format
DEPRECATED
*/
import {utils} from "../../../viewer/scene/utils.js";
import * as p from "./lib/pako.js";
import {math} from "../../../viewer/scene/math/math.js";
let pako = window.pako || p;
if (!pako.inflate) { // See https://github.com/nodeca/pako/issues/97
pako = pako.default;
}
const decompressColor = (function () {
const color2 = new Float32Array(3);
return function (color) {
color2[0] = color[0] / 255.0;
color2[1] = color[1] / 255.0;
color2[2] = color[2] / 255.0;
return color2;
};
})();
function extract(elements) {
return {
positions: elements[0],
normals: elements[1],
indices: elements[2],
edgeIndices: elements[3],
meshPositions: elements[4],
meshIndices: elements[5],
meshEdgesIndices: elements[6],
meshColors: elements[7],
entityIDs: elements[8],
entityMeshes: elements[9],
entityIsObjects: elements[10],
positionsDecodeMatrix: elements[11]
};
}
function inflate(deflatedData) {
return {
positions: new Uint16Array(pako.inflate(deflatedData.positions).buffer),
normals: new Int8Array(pako.inflate(deflatedData.normals).buffer),
indices: new Uint32Array(pako.inflate(deflatedData.indices).buffer),
edgeIndices: new Uint32Array(pako.inflate(deflatedData.edgeIndices).buffer),
meshPositions: new Uint32Array(pako.inflate(deflatedData.meshPositions).buffer),
meshIndices: new Uint32Array(pako.inflate(deflatedData.meshIndices).buffer),
meshEdgesIndices: new Uint32Array(pako.inflate(deflatedData.meshEdgesIndices).buffer),
meshColors: new Uint8Array(pako.inflate(deflatedData.meshColors).buffer),
entityIDs: pako.inflate(deflatedData.entityIDs, {to: 'string'}),
entityMeshes: new Uint32Array(pako.inflate(deflatedData.entityMeshes).buffer),
entityIsObjects: new Uint8Array(pako.inflate(deflatedData.entityIsObjects).buffer),
positionsDecodeMatrix: new Float32Array(pako.inflate(deflatedData.positionsDecodeMatrix).buffer)
};
}
function load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx) {
const modelPartId = manifestCtx.getNextId();
sceneModel.positionsCompression = "precompressed";
sceneModel.normalsCompression = "precompressed";
const positions = inflatedData.positions;
const normals = inflatedData.normals;
const indices = inflatedData.indices;
const edgeIndices = inflatedData.edgeIndices;
const meshPositions = inflatedData.meshPositions;
const meshIndices = inflatedData.meshIndices;
const meshEdgesIndices = inflatedData.meshEdgesIndices;
const meshColors = inflatedData.meshColors;
const entityIDs = JSON.parse(inflatedData.entityIDs);
const entityMeshes = inflatedData.entityMeshes;
const entityIsObjects = inflatedData.entityIsObjects;
const numMeshes = meshPositions.length;
const numEntities = entityMeshes.length;
for (let i = 0; i < numEntities; i++) {
const xktEntityId = entityIDs [i];
const entityId = options.globalizeObjectIds ? math.globalizeObjectId(sceneModel.id, xktEntityId) : xktEntityId;
const metaObject = viewer.metaScene.metaObjects[entityId];
const entityDefaults = {};
const meshDefaults = {};
if (metaObject) {
if (options.excludeTypesMap && metaObject.type && options.excludeTypesMap[metaObject.type]) {
continue;
}
if (options.includeTypesMap && metaObject.type && (!options.includeTypesMap[metaObject.type])) {
continue;
}
const props = options.objectDefaults ? options.objectDefaults[metaObject.type] || options.objectDefaults["DEFAULT"] : null;
if (props) {
if (props.visible === false) {
entityDefaults.visible = false;
}
if (props.pickable === false) {
entityDefaults.pickable = false;
}
if (props.colorize) {
meshDefaults.color = props.colorize;
}
if (props.opacity !== undefined && props.opacity !== null) {
meshDefaults.opacity = props.opacity;
}
}
} else {
if (options.excludeUnclassifiedObjects) {
continue;
}
}
const lastEntity = (i === numEntities - 1);
const meshIds = [];
for (let j = entityMeshes [i], jlen = lastEntity ? entityMeshes.length : entityMeshes [i + 1]; j < jlen; j++) {
const lastMesh = (j === (numMeshes - 1));
const meshId = entityId + ".mesh." + j;
const color = decompressColor(meshColors.subarray((j * 4), (j * 4) + 3));
const opacity = meshColors[(j * 4) + 3] / 255.0;
sceneModel.createMesh(utils.apply(meshDefaults, {
id: meshId,
primitive: "triangles",
positionsCompressed: positions.subarray(meshPositions [j], lastMesh ? positions.length : meshPositions [j + 1]),
normalsCompressed: normals.subarray(meshPositions [j], lastMesh ? positions.length : meshPositions [j + 1]),
indices: indices.subarray(meshIndices [j], lastMesh ? indices.length : meshIndices [j + 1]),
edgeIndices: edgeIndices.subarray(meshEdgesIndices [j], lastMesh ? edgeIndices.length : meshEdgesIndices [j + 1]),
positionsDecodeMatrix: inflatedData.positionsDecodeMatrix,
color: color,
opacity: opacity
}));
meshIds.push(meshId);
}
sceneModel.createEntity(utils.apply(entityDefaults, {
id: entityId,
isObject: (entityIsObjects [i] === 1),
meshIds: meshIds
}));
}
}
/** @private */
const ParserV1 = {
version: 1,
parse: function (viewer, options, elements, sceneModel, metaModel, manifestCtx) {
const deflatedData = extract(elements);
const inflatedData = inflate(deflatedData);
load(viewer, options, inflatedData, sceneModel, metaModel, manifestCtx);
}
};
export {ParserV1};