165 lines
5.2 KiB
JavaScript
165 lines
5.2 KiB
JavaScript
import { Loader, FileLoader, BufferGeometry, BufferAttribute } from "three";
|
|
let bigEndianPlatform = null;
|
|
function isBigEndianPlatform() {
|
|
if (bigEndianPlatform === null) {
|
|
const buffer = new ArrayBuffer(2), uint8Array = new Uint8Array(buffer), uint16Array = new Uint16Array(buffer);
|
|
uint8Array[0] = 170;
|
|
uint8Array[1] = 187;
|
|
bigEndianPlatform = uint16Array[0] === 43707;
|
|
}
|
|
return bigEndianPlatform;
|
|
}
|
|
const InvertedEncodingTypes = [
|
|
null,
|
|
Float32Array,
|
|
null,
|
|
Int8Array,
|
|
Int16Array,
|
|
null,
|
|
Int32Array,
|
|
Uint8Array,
|
|
Uint16Array,
|
|
null,
|
|
Uint32Array
|
|
];
|
|
const getMethods = {
|
|
Uint16Array: "getUint16",
|
|
Uint32Array: "getUint32",
|
|
Int16Array: "getInt16",
|
|
Int32Array: "getInt32",
|
|
Float32Array: "getFloat32",
|
|
Float64Array: "getFloat64"
|
|
};
|
|
function copyFromBuffer(sourceArrayBuffer, viewType, position, length, fromBigEndian) {
|
|
const bytesPerElement = viewType.BYTES_PER_ELEMENT;
|
|
let result;
|
|
if (fromBigEndian === isBigEndianPlatform() || bytesPerElement === 1) {
|
|
result = new viewType(sourceArrayBuffer, position, length);
|
|
} else {
|
|
const readView = new DataView(sourceArrayBuffer, position, length * bytesPerElement), getMethod = getMethods[viewType.name], littleEndian = !fromBigEndian;
|
|
result = new viewType(length);
|
|
for (let i = 0; i < length; i++) {
|
|
result[i] = readView[getMethod](i * bytesPerElement, littleEndian);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function decodePrwm(buffer) {
|
|
const array = new Uint8Array(buffer), version = array[0];
|
|
let flags = array[1];
|
|
const indexedGeometry = !!(flags >> 7 & 1), indicesType = flags >> 6 & 1, bigEndian = (flags >> 5 & 1) === 1, attributesNumber = flags & 31;
|
|
let valuesNumber = 0, indicesNumber = 0;
|
|
if (bigEndian) {
|
|
valuesNumber = (array[2] << 16) + (array[3] << 8) + array[4];
|
|
indicesNumber = (array[5] << 16) + (array[6] << 8) + array[7];
|
|
} else {
|
|
valuesNumber = array[2] + (array[3] << 8) + (array[4] << 16);
|
|
indicesNumber = array[5] + (array[6] << 8) + (array[7] << 16);
|
|
}
|
|
if (version === 0) {
|
|
throw new Error("PRWM decoder: Invalid format version: 0");
|
|
} else if (version !== 1) {
|
|
throw new Error("PRWM decoder: Unsupported format version: " + version);
|
|
}
|
|
if (!indexedGeometry) {
|
|
if (indicesType !== 0) {
|
|
throw new Error("PRWM decoder: Indices type must be set to 0 for non-indexed geometries");
|
|
} else if (indicesNumber !== 0) {
|
|
throw new Error("PRWM decoder: Number of indices must be set to 0 for non-indexed geometries");
|
|
}
|
|
}
|
|
let pos = 8;
|
|
const attributes = {};
|
|
for (let i = 0; i < attributesNumber; i++) {
|
|
let attributeName = "";
|
|
while (pos < array.length) {
|
|
const char = array[pos];
|
|
pos++;
|
|
if (char === 0) {
|
|
break;
|
|
} else {
|
|
attributeName += String.fromCharCode(char);
|
|
}
|
|
}
|
|
flags = array[pos];
|
|
const attributeType = flags >> 7 & 1;
|
|
const cardinality = (flags >> 4 & 3) + 1;
|
|
const encodingType = flags & 15;
|
|
const arrayType = InvertedEncodingTypes[encodingType];
|
|
pos++;
|
|
pos = Math.ceil(pos / 4) * 4;
|
|
const values = copyFromBuffer(buffer, arrayType, pos, cardinality * valuesNumber, bigEndian);
|
|
pos += arrayType.BYTES_PER_ELEMENT * cardinality * valuesNumber;
|
|
attributes[attributeName] = {
|
|
type: attributeType,
|
|
cardinality,
|
|
values
|
|
};
|
|
}
|
|
pos = Math.ceil(pos / 4) * 4;
|
|
let indices = null;
|
|
if (indexedGeometry) {
|
|
indices = copyFromBuffer(buffer, indicesType === 1 ? Uint32Array : Uint16Array, pos, indicesNumber, bigEndian);
|
|
}
|
|
return {
|
|
version,
|
|
attributes,
|
|
indices
|
|
};
|
|
}
|
|
const PRWMLoader = /* @__PURE__ */ (() => {
|
|
class PRWMLoader2 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);
|
|
url = url.replace(/\*/g, isBigEndianPlatform() ? "be" : "le");
|
|
loader.load(
|
|
url,
|
|
function(arrayBuffer) {
|
|
try {
|
|
onLoad(scope.parse(arrayBuffer));
|
|
} catch (e) {
|
|
if (onError) {
|
|
onError(e);
|
|
} else {
|
|
console.error(e);
|
|
}
|
|
scope.manager.itemError(url);
|
|
}
|
|
},
|
|
onProgress,
|
|
onError
|
|
);
|
|
}
|
|
parse(arrayBuffer) {
|
|
const data = decodePrwm(arrayBuffer), attributesKey = Object.keys(data.attributes), bufferGeometry = new BufferGeometry();
|
|
for (let i = 0; i < attributesKey.length; i++) {
|
|
const attribute = data.attributes[attributesKey[i]];
|
|
bufferGeometry.setAttribute(
|
|
attributesKey[i],
|
|
new BufferAttribute(attribute.values, attribute.cardinality, attribute.normalized)
|
|
);
|
|
}
|
|
if (data.indices !== null) {
|
|
bufferGeometry.setIndex(new BufferAttribute(data.indices, 1));
|
|
}
|
|
return bufferGeometry;
|
|
}
|
|
static isBigEndianPlatform() {
|
|
return isBigEndianPlatform();
|
|
}
|
|
}
|
|
return PRWMLoader2;
|
|
})();
|
|
export {
|
|
PRWMLoader
|
|
};
|
|
//# sourceMappingURL=PRWMLoader.js.map
|