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
+744
View File
@@ -0,0 +1,744 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const LWO2Parser = require("./LWO2Parser.cjs");
const LWO3Parser = require("./LWO3Parser.cjs");
class IFFParser {
constructor() {
this.debugger = new Debugger();
}
parse(buffer) {
this.reader = new DataViewReader(buffer);
this.tree = {
materials: {},
layers: [],
tags: [],
textures: []
};
this.currentLayer = this.tree;
this.currentForm = this.tree;
this.parseTopForm();
if (this.tree.format === void 0)
return;
if (this.tree.format === "LWO2") {
this.parser = new LWO2Parser.LWO2Parser(this);
while (!this.reader.endOfFile())
this.parser.parseBlock();
} else if (this.tree.format === "LWO3") {
this.parser = new LWO3Parser.LWO3Parser(this);
while (!this.reader.endOfFile())
this.parser.parseBlock();
}
this.debugger.offset = this.reader.offset;
this.debugger.closeForms();
return this.tree;
}
parseTopForm() {
this.debugger.offset = this.reader.offset;
var topForm = this.reader.getIDTag();
if (topForm !== "FORM") {
console.warn("LWOLoader: Top-level FORM missing.");
return;
}
var length = this.reader.getUint32();
this.debugger.dataOffset = this.reader.offset;
this.debugger.length = length;
var type = this.reader.getIDTag();
if (type === "LWO2") {
this.tree.format = type;
} else if (type === "LWO3") {
this.tree.format = type;
}
this.debugger.node = 0;
this.debugger.nodeID = type;
this.debugger.log();
return;
}
///
// FORM PARSING METHODS
///
// Forms are organisational and can contain any number of sub chunks and sub forms
// FORM ::= 'FORM'[ID4], length[U4], type[ID4], ( chunk[CHUNK] | form[FORM] ) * }
parseForm(length) {
var type = this.reader.getIDTag();
switch (type) {
case "ISEQ":
case "ANIM":
case "STCC":
case "VPVL":
case "VPRM":
case "NROT":
case "WRPW":
case "WRPH":
case "FUNC":
case "FALL":
case "OPAC":
case "GRAD":
case "ENVS":
case "VMOP":
case "VMBG":
case "OMAX":
case "STEX":
case "CKBG":
case "CKEY":
case "VMLA":
case "VMLB":
this.debugger.skipped = true;
this.skipForm(length);
break;
case "META":
case "NNDS":
case "NODS":
case "NDTA":
case "ADAT":
case "AOVS":
case "BLOK":
case "IBGC":
case "IOPC":
case "IIMG":
case "TXTR":
this.debugger.length = 4;
this.debugger.skipped = true;
break;
case "IFAL":
case "ISCL":
case "IPOS":
case "IROT":
case "IBMP":
case "IUTD":
case "IVTD":
this.parseTextureNodeAttribute(type);
break;
case "ENVL":
this.parseEnvelope(length);
break;
case "CLIP":
if (this.tree.format === "LWO2") {
this.parseForm(length);
} else {
this.parseClip(length);
}
break;
case "STIL":
this.parseImage();
break;
case "XREF":
this.reader.skip(8);
this.currentForm.referenceTexture = {
index: this.reader.getUint32(),
refName: this.reader.getString()
// internal unique ref
};
break;
case "IMST":
this.parseImageStateForm(length);
break;
case "SURF":
this.parseSurfaceForm(length);
break;
case "VALU":
this.parseValueForm(length);
break;
case "NTAG":
this.parseSubNode(length);
break;
case "ATTR":
case "SATR":
this.setupForm("attributes", length);
break;
case "NCON":
this.parseConnections(length);
break;
case "SSHA":
this.parentForm = this.currentForm;
this.currentForm = this.currentSurface;
this.setupForm("surfaceShader", length);
break;
case "SSHD":
this.setupForm("surfaceShaderData", length);
break;
case "ENTR":
this.parseEntryForm(length);
break;
case "IMAP":
this.parseImageMap(length);
break;
case "TAMP":
this.parseXVAL("amplitude", length);
break;
case "TMAP":
this.setupForm("textureMap", length);
break;
case "CNTR":
this.parseXVAL3("center", length);
break;
case "SIZE":
this.parseXVAL3("scale", length);
break;
case "ROTA":
this.parseXVAL3("rotation", length);
break;
default:
this.parseUnknownForm(type, length);
}
this.debugger.node = 0;
this.debugger.nodeID = type;
this.debugger.log();
}
setupForm(type, length) {
if (!this.currentForm)
this.currentForm = this.currentNode;
this.currentFormEnd = this.reader.offset + length;
this.parentForm = this.currentForm;
if (!this.currentForm[type]) {
this.currentForm[type] = {};
this.currentForm = this.currentForm[type];
} else {
console.warn("LWOLoader: form already exists on parent: ", type, this.currentForm);
this.currentForm = this.currentForm[type];
}
}
skipForm(length) {
this.reader.skip(length - 4);
}
parseUnknownForm(type, length) {
console.warn("LWOLoader: unknown FORM encountered: " + type, length);
printBuffer(this.reader.dv.buffer, this.reader.offset, length - 4);
this.reader.skip(length - 4);
}
parseSurfaceForm(length) {
this.reader.skip(8);
var name = this.reader.getString();
var surface = {
attributes: {},
// LWO2 style non-node attributes will go here
connections: {},
name,
inputName: name,
nodes: {},
source: this.reader.getString()
};
this.tree.materials[name] = surface;
this.currentSurface = surface;
this.parentForm = this.tree.materials;
this.currentForm = surface;
this.currentFormEnd = this.reader.offset + length;
}
parseSurfaceLwo2(length) {
var name = this.reader.getString();
var surface = {
attributes: {},
// LWO2 style non-node attributes will go here
connections: {},
name,
nodes: {},
source: this.reader.getString()
};
this.tree.materials[name] = surface;
this.currentSurface = surface;
this.parentForm = this.tree.materials;
this.currentForm = surface;
this.currentFormEnd = this.reader.offset + length;
}
parseSubNode(length) {
this.reader.skip(8);
var name = this.reader.getString();
var node = {
name
};
this.currentForm = node;
this.currentNode = node;
this.currentFormEnd = this.reader.offset + length;
}
// collect attributes from all nodes at the top level of a surface
parseConnections(length) {
this.currentFormEnd = this.reader.offset + length;
this.parentForm = this.currentForm;
this.currentForm = this.currentSurface.connections;
}
// surface node attribute data, e.g. specular, roughness etc
parseEntryForm(length) {
this.reader.skip(8);
var name = this.reader.getString();
this.currentForm = this.currentNode.attributes;
this.setupForm(name, length);
}
// parse values from material - doesn't match up to other LWO3 data types
// sub form of entry form
parseValueForm() {
this.reader.skip(8);
var valueType = this.reader.getString();
if (valueType === "double") {
this.currentForm.value = this.reader.getUint64();
} else if (valueType === "int") {
this.currentForm.value = this.reader.getUint32();
} else if (valueType === "vparam") {
this.reader.skip(24);
this.currentForm.value = this.reader.getFloat64();
} else if (valueType === "vparam3") {
this.reader.skip(24);
this.currentForm.value = this.reader.getFloat64Array(3);
}
}
// holds various data about texture node image state
// Data other thanmipMapLevel unknown
parseImageStateForm() {
this.reader.skip(8);
this.currentForm.mipMapLevel = this.reader.getFloat32();
}
// LWO2 style image data node OR LWO3 textures defined at top level in editor (not as SURF node)
parseImageMap(length) {
this.currentFormEnd = this.reader.offset + length;
this.parentForm = this.currentForm;
if (!this.currentForm.maps)
this.currentForm.maps = [];
var map = {};
this.currentForm.maps.push(map);
this.currentForm = map;
this.reader.skip(10);
}
parseTextureNodeAttribute(type) {
this.reader.skip(28);
this.reader.skip(20);
switch (type) {
case "ISCL":
this.currentNode.scale = this.reader.getFloat32Array(3);
break;
case "IPOS":
this.currentNode.position = this.reader.getFloat32Array(3);
break;
case "IROT":
this.currentNode.rotation = this.reader.getFloat32Array(3);
break;
case "IFAL":
this.currentNode.falloff = this.reader.getFloat32Array(3);
break;
case "IBMP":
this.currentNode.amplitude = this.reader.getFloat32();
break;
case "IUTD":
this.currentNode.uTiles = this.reader.getFloat32();
break;
case "IVTD":
this.currentNode.vTiles = this.reader.getFloat32();
break;
}
this.reader.skip(2);
}
// ENVL forms are currently ignored
parseEnvelope(length) {
this.reader.skip(length - 4);
}
///
// CHUNK PARSING METHODS
///
// clips can either be defined inside a surface node, or at the top
// level and they have a different format in each case
parseClip(length) {
var tag = this.reader.getIDTag();
if (tag === "FORM") {
this.reader.skip(16);
this.currentNode.fileName = this.reader.getString();
return;
}
this.reader.setOffset(this.reader.offset - 4);
this.currentFormEnd = this.reader.offset + length;
this.parentForm = this.currentForm;
this.reader.skip(8);
var texture = {
index: this.reader.getUint32()
};
this.tree.textures.push(texture);
this.currentForm = texture;
}
parseClipLwo2(length) {
var texture = {
index: this.reader.getUint32(),
fileName: ""
};
while (true) {
var tag = this.reader.getIDTag();
var n_length = this.reader.getUint16();
if (tag === "STIL") {
texture.fileName = this.reader.getString();
break;
}
if (n_length >= length) {
break;
}
}
this.tree.textures.push(texture);
this.currentForm = texture;
}
parseImage() {
this.reader.skip(8);
this.currentForm.fileName = this.reader.getString();
}
parseXVAL(type, length) {
var endOffset = this.reader.offset + length - 4;
this.reader.skip(8);
this.currentForm[type] = this.reader.getFloat32();
this.reader.setOffset(endOffset);
}
parseXVAL3(type, length) {
var endOffset = this.reader.offset + length - 4;
this.reader.skip(8);
this.currentForm[type] = {
x: this.reader.getFloat32(),
y: this.reader.getFloat32(),
z: this.reader.getFloat32()
};
this.reader.setOffset(endOffset);
}
// Tags associated with an object
// OTAG { type[ID4], tag-string[S0] }
parseObjectTag() {
if (!this.tree.objectTags)
this.tree.objectTags = {};
this.tree.objectTags[this.reader.getIDTag()] = {
tagString: this.reader.getString()
};
}
// Signals the start of a new layer. All the data chunks which follow will be included in this layer until another layer chunk is encountered.
// LAYR: number[U2], flags[U2], pivot[VEC12], name[S0], parent[U2]
parseLayer(length) {
var layer = {
number: this.reader.getUint16(),
flags: this.reader.getUint16(),
// If the least significant bit of flags is set, the layer is hidden.
pivot: this.reader.getFloat32Array(3),
// Note: this seems to be superflous, as the geometry is translated when pivot is present
name: this.reader.getString()
};
this.tree.layers.push(layer);
this.currentLayer = layer;
var parsedLength = 16 + stringOffset(this.currentLayer.name);
this.currentLayer.parent = parsedLength < length ? this.reader.getUint16() : -1;
}
// VEC12 * ( F4 + F4 + F4 ) array of x,y,z vectors
// Converting from left to right handed coordinate system:
// x -> -x and switch material FrontSide -> BackSide
parsePoints(length) {
this.currentPoints = [];
for (var i = 0; i < length / 4; i += 3) {
this.currentPoints.push(this.reader.getFloat32(), this.reader.getFloat32(), -this.reader.getFloat32());
}
}
// parse VMAP or VMAD
// Associates a set of floating-point vectors with a set of points.
// VMAP: { type[ID4], dimension[U2], name[S0], ( vert[VX], value[F4] # dimension ) * }
// VMAD Associates a set of floating-point vectors with the vertices of specific polygons.
// Similar to VMAP UVs, but associates with polygon vertices rather than points
// to solve to problem of UV seams: VMAD chunks are paired with VMAPs of the same name,
// if they exist. The vector values in the VMAD will then replace those in the
// corresponding VMAP, but only for calculations involving the specified polygons.
// VMAD { type[ID4], dimension[U2], name[S0], ( vert[VX], poly[VX], value[F4] # dimension ) * }
parseVertexMapping(length, discontinuous) {
var finalOffset = this.reader.offset + length;
var channelName = this.reader.getString();
if (this.reader.offset === finalOffset) {
this.currentForm.UVChannel = channelName;
return;
}
this.reader.setOffset(this.reader.offset - stringOffset(channelName));
var type = this.reader.getIDTag();
this.reader.getUint16();
var name = this.reader.getString();
var remainingLength = length - 6 - stringOffset(name);
switch (type) {
case "TXUV":
this.parseUVMapping(name, finalOffset, discontinuous);
break;
case "MORF":
case "SPOT":
this.parseMorphTargets(name, finalOffset, type);
break;
case "APSL":
case "NORM":
case "WGHT":
case "MNVW":
case "PICK":
case "RGB ":
case "RGBA":
this.reader.skip(remainingLength);
break;
default:
console.warn("LWOLoader: unknown vertex map type: " + type);
this.reader.skip(remainingLength);
}
}
parseUVMapping(name, finalOffset, discontinuous) {
var uvIndices = [];
var polyIndices = [];
var uvs = [];
while (this.reader.offset < finalOffset) {
uvIndices.push(this.reader.getVariableLengthIndex());
if (discontinuous)
polyIndices.push(this.reader.getVariableLengthIndex());
uvs.push(this.reader.getFloat32(), this.reader.getFloat32());
}
if (discontinuous) {
if (!this.currentLayer.discontinuousUVs)
this.currentLayer.discontinuousUVs = {};
this.currentLayer.discontinuousUVs[name] = {
uvIndices,
polyIndices,
uvs
};
} else {
if (!this.currentLayer.uvs)
this.currentLayer.uvs = {};
this.currentLayer.uvs[name] = {
uvIndices,
uvs
};
}
}
parseMorphTargets(name, finalOffset, type) {
var indices = [];
var points = [];
type = type === "MORF" ? "relative" : "absolute";
while (this.reader.offset < finalOffset) {
indices.push(this.reader.getVariableLengthIndex());
points.push(this.reader.getFloat32(), this.reader.getFloat32(), -this.reader.getFloat32());
}
if (!this.currentLayer.morphTargets)
this.currentLayer.morphTargets = {};
this.currentLayer.morphTargets[name] = {
indices,
points,
type
};
}
// A list of polygons for the current layer.
// POLS { type[ID4], ( numvert+flags[U2], vert[VX] # numvert ) * }
parsePolygonList(length) {
var finalOffset = this.reader.offset + length;
var type = this.reader.getIDTag();
var indices = [];
var polygonDimensions = [];
while (this.reader.offset < finalOffset) {
var numverts = this.reader.getUint16();
numverts = numverts & 1023;
polygonDimensions.push(numverts);
for (var j = 0; j < numverts; j++)
indices.push(this.reader.getVariableLengthIndex());
}
var geometryData = {
type,
vertexIndices: indices,
polygonDimensions,
points: this.currentPoints
};
if (polygonDimensions[0] === 1)
geometryData.type = "points";
else if (polygonDimensions[0] === 2)
geometryData.type = "lines";
this.currentLayer.geometry = geometryData;
}
// Lists the tag strings that can be associated with polygons by the PTAG chunk.
// TAGS { tag-string[S0] * }
parseTagStrings(length) {
this.tree.tags = this.reader.getStringArray(length);
}
// Associates tags of a given type with polygons in the most recent POLS chunk.
// PTAG { type[ID4], ( poly[VX], tag[U2] ) * }
parsePolygonTagMapping(length) {
var finalOffset = this.reader.offset + length;
var type = this.reader.getIDTag();
if (type === "SURF")
this.parseMaterialIndices(finalOffset);
else {
this.reader.skip(length - 4);
}
}
parseMaterialIndices(finalOffset) {
this.currentLayer.geometry.materialIndices = [];
while (this.reader.offset < finalOffset) {
var polygonIndex = this.reader.getVariableLengthIndex();
var materialIndex = this.reader.getUint16();
this.currentLayer.geometry.materialIndices.push(polygonIndex, materialIndex);
}
}
parseUnknownCHUNK(blockID, length) {
console.warn("LWOLoader: unknown chunk type: " + blockID + " length: " + length);
var data = this.reader.getString(length);
this.currentForm[blockID] = data;
}
}
class DataViewReader {
constructor(buffer) {
this.dv = new DataView(buffer);
this.offset = 0;
this._textDecoder = new TextDecoder();
this._bytes = new Uint8Array(buffer);
}
size() {
return this.dv.buffer.byteLength;
}
setOffset(offset) {
if (offset > 0 && offset < this.dv.buffer.byteLength) {
this.offset = offset;
} else {
console.error("LWOLoader: invalid buffer offset");
}
}
endOfFile() {
if (this.offset >= this.size())
return true;
return false;
}
skip(length) {
this.offset += length;
}
getUint8() {
var value = this.dv.getUint8(this.offset);
this.offset += 1;
return value;
}
getUint16() {
var value = this.dv.getUint16(this.offset);
this.offset += 2;
return value;
}
getInt32() {
var value = this.dv.getInt32(this.offset, false);
this.offset += 4;
return value;
}
getUint32() {
var value = this.dv.getUint32(this.offset, false);
this.offset += 4;
return value;
}
getUint64() {
var low, high;
high = this.getUint32();
low = this.getUint32();
return high * 4294967296 + low;
}
getFloat32() {
var value = this.dv.getFloat32(this.offset, false);
this.offset += 4;
return value;
}
getFloat32Array(size) {
var a = [];
for (var i = 0; i < size; i++) {
a.push(this.getFloat32());
}
return a;
}
getFloat64() {
var value = this.dv.getFloat64(this.offset, this.littleEndian);
this.offset += 8;
return value;
}
getFloat64Array(size) {
var a = [];
for (var i = 0; i < size; i++) {
a.push(this.getFloat64());
}
return a;
}
// get variable-length index data type
// VX ::= index[U2] | (index + 0xFF000000)[U4]
// If the index value is less than 65,280 (0xFF00),then VX === U2
// otherwise VX === U4 with bits 24-31 set
// When reading an index, if the first byte encountered is 255 (0xFF), then
// the four-byte form is being used and the first byte should be discarded or masked out.
getVariableLengthIndex() {
var firstByte = this.getUint8();
if (firstByte === 255) {
return this.getUint8() * 65536 + this.getUint8() * 256 + this.getUint8();
}
return firstByte * 256 + this.getUint8();
}
// An ID tag is a sequence of 4 bytes containing 7-bit ASCII values
getIDTag() {
return this.getString(4);
}
getString(size) {
if (size === 0)
return;
const start = this.offset;
let result;
let length;
if (size) {
length = size;
result = this._textDecoder.decode(new Uint8Array(this.dv.buffer, start, size));
} else {
length = this._bytes.indexOf(0, start) - start;
result = this._textDecoder.decode(new Uint8Array(this.dv.buffer, start, length));
length++;
length += length % 2;
}
this.skip(length);
return result;
}
getStringArray(size) {
var a = this.getString(size);
a = a.split("\0");
return a.filter(Boolean);
}
}
class Debugger {
constructor() {
this.active = false;
this.depth = 0;
this.formList = [];
}
enable() {
this.active = true;
}
log() {
if (!this.active)
return;
var nodeType;
switch (this.node) {
case 0:
nodeType = "FORM";
break;
case 1:
nodeType = "CHK";
break;
case 2:
nodeType = "S-CHK";
break;
}
console.log(
"| ".repeat(this.depth) + nodeType,
this.nodeID,
`( ${this.offset} ) -> ( ${this.dataOffset + this.length} )`,
this.node == 0 ? " {" : "",
this.skipped ? "SKIPPED" : "",
this.node == 0 && this.skipped ? "}" : ""
);
if (this.node == 0 && !this.skipped) {
this.depth += 1;
this.formList.push(this.dataOffset + this.length);
}
this.skipped = false;
}
closeForms() {
if (!this.active)
return;
for (var i = this.formList.length - 1; i >= 0; i--) {
if (this.offset >= this.formList[i]) {
this.depth -= 1;
console.log("| ".repeat(this.depth) + "}");
this.formList.splice(-1, 1);
}
}
}
}
function isEven(num) {
return num % 2;
}
function stringOffset(string) {
return string.length + 1 + (isEven(string.length + 1) ? 1 : 0);
}
function printBuffer(buffer, from, to) {
console.log(new TextDecoder().decode(new Uint8Array(buffer, from, to)));
}
exports.IFFParser = IFFParser;
//# sourceMappingURL=IFFParser.cjs.map
File diff suppressed because one or more lines are too long
+744
View File
@@ -0,0 +1,744 @@
import { LWO2Parser } from "./LWO2Parser.js";
import { LWO3Parser } from "./LWO3Parser.js";
class IFFParser {
constructor() {
this.debugger = new Debugger();
}
parse(buffer) {
this.reader = new DataViewReader(buffer);
this.tree = {
materials: {},
layers: [],
tags: [],
textures: []
};
this.currentLayer = this.tree;
this.currentForm = this.tree;
this.parseTopForm();
if (this.tree.format === void 0)
return;
if (this.tree.format === "LWO2") {
this.parser = new LWO2Parser(this);
while (!this.reader.endOfFile())
this.parser.parseBlock();
} else if (this.tree.format === "LWO3") {
this.parser = new LWO3Parser(this);
while (!this.reader.endOfFile())
this.parser.parseBlock();
}
this.debugger.offset = this.reader.offset;
this.debugger.closeForms();
return this.tree;
}
parseTopForm() {
this.debugger.offset = this.reader.offset;
var topForm = this.reader.getIDTag();
if (topForm !== "FORM") {
console.warn("LWOLoader: Top-level FORM missing.");
return;
}
var length = this.reader.getUint32();
this.debugger.dataOffset = this.reader.offset;
this.debugger.length = length;
var type = this.reader.getIDTag();
if (type === "LWO2") {
this.tree.format = type;
} else if (type === "LWO3") {
this.tree.format = type;
}
this.debugger.node = 0;
this.debugger.nodeID = type;
this.debugger.log();
return;
}
///
// FORM PARSING METHODS
///
// Forms are organisational and can contain any number of sub chunks and sub forms
// FORM ::= 'FORM'[ID4], length[U4], type[ID4], ( chunk[CHUNK] | form[FORM] ) * }
parseForm(length) {
var type = this.reader.getIDTag();
switch (type) {
case "ISEQ":
case "ANIM":
case "STCC":
case "VPVL":
case "VPRM":
case "NROT":
case "WRPW":
case "WRPH":
case "FUNC":
case "FALL":
case "OPAC":
case "GRAD":
case "ENVS":
case "VMOP":
case "VMBG":
case "OMAX":
case "STEX":
case "CKBG":
case "CKEY":
case "VMLA":
case "VMLB":
this.debugger.skipped = true;
this.skipForm(length);
break;
case "META":
case "NNDS":
case "NODS":
case "NDTA":
case "ADAT":
case "AOVS":
case "BLOK":
case "IBGC":
case "IOPC":
case "IIMG":
case "TXTR":
this.debugger.length = 4;
this.debugger.skipped = true;
break;
case "IFAL":
case "ISCL":
case "IPOS":
case "IROT":
case "IBMP":
case "IUTD":
case "IVTD":
this.parseTextureNodeAttribute(type);
break;
case "ENVL":
this.parseEnvelope(length);
break;
case "CLIP":
if (this.tree.format === "LWO2") {
this.parseForm(length);
} else {
this.parseClip(length);
}
break;
case "STIL":
this.parseImage();
break;
case "XREF":
this.reader.skip(8);
this.currentForm.referenceTexture = {
index: this.reader.getUint32(),
refName: this.reader.getString()
// internal unique ref
};
break;
case "IMST":
this.parseImageStateForm(length);
break;
case "SURF":
this.parseSurfaceForm(length);
break;
case "VALU":
this.parseValueForm(length);
break;
case "NTAG":
this.parseSubNode(length);
break;
case "ATTR":
case "SATR":
this.setupForm("attributes", length);
break;
case "NCON":
this.parseConnections(length);
break;
case "SSHA":
this.parentForm = this.currentForm;
this.currentForm = this.currentSurface;
this.setupForm("surfaceShader", length);
break;
case "SSHD":
this.setupForm("surfaceShaderData", length);
break;
case "ENTR":
this.parseEntryForm(length);
break;
case "IMAP":
this.parseImageMap(length);
break;
case "TAMP":
this.parseXVAL("amplitude", length);
break;
case "TMAP":
this.setupForm("textureMap", length);
break;
case "CNTR":
this.parseXVAL3("center", length);
break;
case "SIZE":
this.parseXVAL3("scale", length);
break;
case "ROTA":
this.parseXVAL3("rotation", length);
break;
default:
this.parseUnknownForm(type, length);
}
this.debugger.node = 0;
this.debugger.nodeID = type;
this.debugger.log();
}
setupForm(type, length) {
if (!this.currentForm)
this.currentForm = this.currentNode;
this.currentFormEnd = this.reader.offset + length;
this.parentForm = this.currentForm;
if (!this.currentForm[type]) {
this.currentForm[type] = {};
this.currentForm = this.currentForm[type];
} else {
console.warn("LWOLoader: form already exists on parent: ", type, this.currentForm);
this.currentForm = this.currentForm[type];
}
}
skipForm(length) {
this.reader.skip(length - 4);
}
parseUnknownForm(type, length) {
console.warn("LWOLoader: unknown FORM encountered: " + type, length);
printBuffer(this.reader.dv.buffer, this.reader.offset, length - 4);
this.reader.skip(length - 4);
}
parseSurfaceForm(length) {
this.reader.skip(8);
var name = this.reader.getString();
var surface = {
attributes: {},
// LWO2 style non-node attributes will go here
connections: {},
name,
inputName: name,
nodes: {},
source: this.reader.getString()
};
this.tree.materials[name] = surface;
this.currentSurface = surface;
this.parentForm = this.tree.materials;
this.currentForm = surface;
this.currentFormEnd = this.reader.offset + length;
}
parseSurfaceLwo2(length) {
var name = this.reader.getString();
var surface = {
attributes: {},
// LWO2 style non-node attributes will go here
connections: {},
name,
nodes: {},
source: this.reader.getString()
};
this.tree.materials[name] = surface;
this.currentSurface = surface;
this.parentForm = this.tree.materials;
this.currentForm = surface;
this.currentFormEnd = this.reader.offset + length;
}
parseSubNode(length) {
this.reader.skip(8);
var name = this.reader.getString();
var node = {
name
};
this.currentForm = node;
this.currentNode = node;
this.currentFormEnd = this.reader.offset + length;
}
// collect attributes from all nodes at the top level of a surface
parseConnections(length) {
this.currentFormEnd = this.reader.offset + length;
this.parentForm = this.currentForm;
this.currentForm = this.currentSurface.connections;
}
// surface node attribute data, e.g. specular, roughness etc
parseEntryForm(length) {
this.reader.skip(8);
var name = this.reader.getString();
this.currentForm = this.currentNode.attributes;
this.setupForm(name, length);
}
// parse values from material - doesn't match up to other LWO3 data types
// sub form of entry form
parseValueForm() {
this.reader.skip(8);
var valueType = this.reader.getString();
if (valueType === "double") {
this.currentForm.value = this.reader.getUint64();
} else if (valueType === "int") {
this.currentForm.value = this.reader.getUint32();
} else if (valueType === "vparam") {
this.reader.skip(24);
this.currentForm.value = this.reader.getFloat64();
} else if (valueType === "vparam3") {
this.reader.skip(24);
this.currentForm.value = this.reader.getFloat64Array(3);
}
}
// holds various data about texture node image state
// Data other thanmipMapLevel unknown
parseImageStateForm() {
this.reader.skip(8);
this.currentForm.mipMapLevel = this.reader.getFloat32();
}
// LWO2 style image data node OR LWO3 textures defined at top level in editor (not as SURF node)
parseImageMap(length) {
this.currentFormEnd = this.reader.offset + length;
this.parentForm = this.currentForm;
if (!this.currentForm.maps)
this.currentForm.maps = [];
var map = {};
this.currentForm.maps.push(map);
this.currentForm = map;
this.reader.skip(10);
}
parseTextureNodeAttribute(type) {
this.reader.skip(28);
this.reader.skip(20);
switch (type) {
case "ISCL":
this.currentNode.scale = this.reader.getFloat32Array(3);
break;
case "IPOS":
this.currentNode.position = this.reader.getFloat32Array(3);
break;
case "IROT":
this.currentNode.rotation = this.reader.getFloat32Array(3);
break;
case "IFAL":
this.currentNode.falloff = this.reader.getFloat32Array(3);
break;
case "IBMP":
this.currentNode.amplitude = this.reader.getFloat32();
break;
case "IUTD":
this.currentNode.uTiles = this.reader.getFloat32();
break;
case "IVTD":
this.currentNode.vTiles = this.reader.getFloat32();
break;
}
this.reader.skip(2);
}
// ENVL forms are currently ignored
parseEnvelope(length) {
this.reader.skip(length - 4);
}
///
// CHUNK PARSING METHODS
///
// clips can either be defined inside a surface node, or at the top
// level and they have a different format in each case
parseClip(length) {
var tag = this.reader.getIDTag();
if (tag === "FORM") {
this.reader.skip(16);
this.currentNode.fileName = this.reader.getString();
return;
}
this.reader.setOffset(this.reader.offset - 4);
this.currentFormEnd = this.reader.offset + length;
this.parentForm = this.currentForm;
this.reader.skip(8);
var texture = {
index: this.reader.getUint32()
};
this.tree.textures.push(texture);
this.currentForm = texture;
}
parseClipLwo2(length) {
var texture = {
index: this.reader.getUint32(),
fileName: ""
};
while (true) {
var tag = this.reader.getIDTag();
var n_length = this.reader.getUint16();
if (tag === "STIL") {
texture.fileName = this.reader.getString();
break;
}
if (n_length >= length) {
break;
}
}
this.tree.textures.push(texture);
this.currentForm = texture;
}
parseImage() {
this.reader.skip(8);
this.currentForm.fileName = this.reader.getString();
}
parseXVAL(type, length) {
var endOffset = this.reader.offset + length - 4;
this.reader.skip(8);
this.currentForm[type] = this.reader.getFloat32();
this.reader.setOffset(endOffset);
}
parseXVAL3(type, length) {
var endOffset = this.reader.offset + length - 4;
this.reader.skip(8);
this.currentForm[type] = {
x: this.reader.getFloat32(),
y: this.reader.getFloat32(),
z: this.reader.getFloat32()
};
this.reader.setOffset(endOffset);
}
// Tags associated with an object
// OTAG { type[ID4], tag-string[S0] }
parseObjectTag() {
if (!this.tree.objectTags)
this.tree.objectTags = {};
this.tree.objectTags[this.reader.getIDTag()] = {
tagString: this.reader.getString()
};
}
// Signals the start of a new layer. All the data chunks which follow will be included in this layer until another layer chunk is encountered.
// LAYR: number[U2], flags[U2], pivot[VEC12], name[S0], parent[U2]
parseLayer(length) {
var layer = {
number: this.reader.getUint16(),
flags: this.reader.getUint16(),
// If the least significant bit of flags is set, the layer is hidden.
pivot: this.reader.getFloat32Array(3),
// Note: this seems to be superflous, as the geometry is translated when pivot is present
name: this.reader.getString()
};
this.tree.layers.push(layer);
this.currentLayer = layer;
var parsedLength = 16 + stringOffset(this.currentLayer.name);
this.currentLayer.parent = parsedLength < length ? this.reader.getUint16() : -1;
}
// VEC12 * ( F4 + F4 + F4 ) array of x,y,z vectors
// Converting from left to right handed coordinate system:
// x -> -x and switch material FrontSide -> BackSide
parsePoints(length) {
this.currentPoints = [];
for (var i = 0; i < length / 4; i += 3) {
this.currentPoints.push(this.reader.getFloat32(), this.reader.getFloat32(), -this.reader.getFloat32());
}
}
// parse VMAP or VMAD
// Associates a set of floating-point vectors with a set of points.
// VMAP: { type[ID4], dimension[U2], name[S0], ( vert[VX], value[F4] # dimension ) * }
// VMAD Associates a set of floating-point vectors with the vertices of specific polygons.
// Similar to VMAP UVs, but associates with polygon vertices rather than points
// to solve to problem of UV seams: VMAD chunks are paired with VMAPs of the same name,
// if they exist. The vector values in the VMAD will then replace those in the
// corresponding VMAP, but only for calculations involving the specified polygons.
// VMAD { type[ID4], dimension[U2], name[S0], ( vert[VX], poly[VX], value[F4] # dimension ) * }
parseVertexMapping(length, discontinuous) {
var finalOffset = this.reader.offset + length;
var channelName = this.reader.getString();
if (this.reader.offset === finalOffset) {
this.currentForm.UVChannel = channelName;
return;
}
this.reader.setOffset(this.reader.offset - stringOffset(channelName));
var type = this.reader.getIDTag();
this.reader.getUint16();
var name = this.reader.getString();
var remainingLength = length - 6 - stringOffset(name);
switch (type) {
case "TXUV":
this.parseUVMapping(name, finalOffset, discontinuous);
break;
case "MORF":
case "SPOT":
this.parseMorphTargets(name, finalOffset, type);
break;
case "APSL":
case "NORM":
case "WGHT":
case "MNVW":
case "PICK":
case "RGB ":
case "RGBA":
this.reader.skip(remainingLength);
break;
default:
console.warn("LWOLoader: unknown vertex map type: " + type);
this.reader.skip(remainingLength);
}
}
parseUVMapping(name, finalOffset, discontinuous) {
var uvIndices = [];
var polyIndices = [];
var uvs = [];
while (this.reader.offset < finalOffset) {
uvIndices.push(this.reader.getVariableLengthIndex());
if (discontinuous)
polyIndices.push(this.reader.getVariableLengthIndex());
uvs.push(this.reader.getFloat32(), this.reader.getFloat32());
}
if (discontinuous) {
if (!this.currentLayer.discontinuousUVs)
this.currentLayer.discontinuousUVs = {};
this.currentLayer.discontinuousUVs[name] = {
uvIndices,
polyIndices,
uvs
};
} else {
if (!this.currentLayer.uvs)
this.currentLayer.uvs = {};
this.currentLayer.uvs[name] = {
uvIndices,
uvs
};
}
}
parseMorphTargets(name, finalOffset, type) {
var indices = [];
var points = [];
type = type === "MORF" ? "relative" : "absolute";
while (this.reader.offset < finalOffset) {
indices.push(this.reader.getVariableLengthIndex());
points.push(this.reader.getFloat32(), this.reader.getFloat32(), -this.reader.getFloat32());
}
if (!this.currentLayer.morphTargets)
this.currentLayer.morphTargets = {};
this.currentLayer.morphTargets[name] = {
indices,
points,
type
};
}
// A list of polygons for the current layer.
// POLS { type[ID4], ( numvert+flags[U2], vert[VX] # numvert ) * }
parsePolygonList(length) {
var finalOffset = this.reader.offset + length;
var type = this.reader.getIDTag();
var indices = [];
var polygonDimensions = [];
while (this.reader.offset < finalOffset) {
var numverts = this.reader.getUint16();
numverts = numverts & 1023;
polygonDimensions.push(numverts);
for (var j = 0; j < numverts; j++)
indices.push(this.reader.getVariableLengthIndex());
}
var geometryData = {
type,
vertexIndices: indices,
polygonDimensions,
points: this.currentPoints
};
if (polygonDimensions[0] === 1)
geometryData.type = "points";
else if (polygonDimensions[0] === 2)
geometryData.type = "lines";
this.currentLayer.geometry = geometryData;
}
// Lists the tag strings that can be associated with polygons by the PTAG chunk.
// TAGS { tag-string[S0] * }
parseTagStrings(length) {
this.tree.tags = this.reader.getStringArray(length);
}
// Associates tags of a given type with polygons in the most recent POLS chunk.
// PTAG { type[ID4], ( poly[VX], tag[U2] ) * }
parsePolygonTagMapping(length) {
var finalOffset = this.reader.offset + length;
var type = this.reader.getIDTag();
if (type === "SURF")
this.parseMaterialIndices(finalOffset);
else {
this.reader.skip(length - 4);
}
}
parseMaterialIndices(finalOffset) {
this.currentLayer.geometry.materialIndices = [];
while (this.reader.offset < finalOffset) {
var polygonIndex = this.reader.getVariableLengthIndex();
var materialIndex = this.reader.getUint16();
this.currentLayer.geometry.materialIndices.push(polygonIndex, materialIndex);
}
}
parseUnknownCHUNK(blockID, length) {
console.warn("LWOLoader: unknown chunk type: " + blockID + " length: " + length);
var data = this.reader.getString(length);
this.currentForm[blockID] = data;
}
}
class DataViewReader {
constructor(buffer) {
this.dv = new DataView(buffer);
this.offset = 0;
this._textDecoder = new TextDecoder();
this._bytes = new Uint8Array(buffer);
}
size() {
return this.dv.buffer.byteLength;
}
setOffset(offset) {
if (offset > 0 && offset < this.dv.buffer.byteLength) {
this.offset = offset;
} else {
console.error("LWOLoader: invalid buffer offset");
}
}
endOfFile() {
if (this.offset >= this.size())
return true;
return false;
}
skip(length) {
this.offset += length;
}
getUint8() {
var value = this.dv.getUint8(this.offset);
this.offset += 1;
return value;
}
getUint16() {
var value = this.dv.getUint16(this.offset);
this.offset += 2;
return value;
}
getInt32() {
var value = this.dv.getInt32(this.offset, false);
this.offset += 4;
return value;
}
getUint32() {
var value = this.dv.getUint32(this.offset, false);
this.offset += 4;
return value;
}
getUint64() {
var low, high;
high = this.getUint32();
low = this.getUint32();
return high * 4294967296 + low;
}
getFloat32() {
var value = this.dv.getFloat32(this.offset, false);
this.offset += 4;
return value;
}
getFloat32Array(size) {
var a = [];
for (var i = 0; i < size; i++) {
a.push(this.getFloat32());
}
return a;
}
getFloat64() {
var value = this.dv.getFloat64(this.offset, this.littleEndian);
this.offset += 8;
return value;
}
getFloat64Array(size) {
var a = [];
for (var i = 0; i < size; i++) {
a.push(this.getFloat64());
}
return a;
}
// get variable-length index data type
// VX ::= index[U2] | (index + 0xFF000000)[U4]
// If the index value is less than 65,280 (0xFF00),then VX === U2
// otherwise VX === U4 with bits 24-31 set
// When reading an index, if the first byte encountered is 255 (0xFF), then
// the four-byte form is being used and the first byte should be discarded or masked out.
getVariableLengthIndex() {
var firstByte = this.getUint8();
if (firstByte === 255) {
return this.getUint8() * 65536 + this.getUint8() * 256 + this.getUint8();
}
return firstByte * 256 + this.getUint8();
}
// An ID tag is a sequence of 4 bytes containing 7-bit ASCII values
getIDTag() {
return this.getString(4);
}
getString(size) {
if (size === 0)
return;
const start = this.offset;
let result;
let length;
if (size) {
length = size;
result = this._textDecoder.decode(new Uint8Array(this.dv.buffer, start, size));
} else {
length = this._bytes.indexOf(0, start) - start;
result = this._textDecoder.decode(new Uint8Array(this.dv.buffer, start, length));
length++;
length += length % 2;
}
this.skip(length);
return result;
}
getStringArray(size) {
var a = this.getString(size);
a = a.split("\0");
return a.filter(Boolean);
}
}
class Debugger {
constructor() {
this.active = false;
this.depth = 0;
this.formList = [];
}
enable() {
this.active = true;
}
log() {
if (!this.active)
return;
var nodeType;
switch (this.node) {
case 0:
nodeType = "FORM";
break;
case 1:
nodeType = "CHK";
break;
case 2:
nodeType = "S-CHK";
break;
}
console.log(
"| ".repeat(this.depth) + nodeType,
this.nodeID,
`( ${this.offset} ) -> ( ${this.dataOffset + this.length} )`,
this.node == 0 ? " {" : "",
this.skipped ? "SKIPPED" : "",
this.node == 0 && this.skipped ? "}" : ""
);
if (this.node == 0 && !this.skipped) {
this.depth += 1;
this.formList.push(this.dataOffset + this.length);
}
this.skipped = false;
}
closeForms() {
if (!this.active)
return;
for (var i = this.formList.length - 1; i >= 0; i--) {
if (this.offset >= this.formList[i]) {
this.depth -= 1;
console.log("| ".repeat(this.depth) + "}");
this.formList.splice(-1, 1);
}
}
}
}
function isEven(num) {
return num % 2;
}
function stringOffset(string) {
return string.length + 1 + (isEven(string.length + 1) ? 1 : 0);
}
function printBuffer(buffer, from, to) {
console.log(new TextDecoder().decode(new Uint8Array(buffer, from, to)));
}
export {
IFFParser
};
//# sourceMappingURL=IFFParser.js.map
File diff suppressed because one or more lines are too long
+313
View File
@@ -0,0 +1,313 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
class LWO2Parser {
constructor(IFFParser) {
this.IFF = IFFParser;
}
parseBlock() {
this.IFF.debugger.offset = this.IFF.reader.offset;
this.IFF.debugger.closeForms();
const blockID = this.IFF.reader.getIDTag();
let length = this.IFF.reader.getUint32();
if (length > this.IFF.reader.dv.byteLength - this.IFF.reader.offset) {
this.IFF.reader.offset -= 4;
length = this.IFF.reader.getUint16();
}
this.IFF.debugger.dataOffset = this.IFF.reader.offset;
this.IFF.debugger.length = length;
switch (blockID) {
case "FORM":
this.IFF.parseForm(length);
break;
case "ICON":
case "VMPA":
case "BBOX":
case "NORM":
case "PRE ":
case "POST":
case "KEY ":
case "SPAN":
case "TIME":
case "CLRS":
case "CLRA":
case "FILT":
case "DITH":
case "CONT":
case "BRIT":
case "SATR":
case "HUE ":
case "GAMM":
case "NEGA":
case "IFLT":
case "PFLT":
case "PROJ":
case "AXIS":
case "AAST":
case "PIXB":
case "AUVO":
case "STCK":
case "PROC":
case "VALU":
case "FUNC":
case "PNAM":
case "INAM":
case "GRST":
case "GREN":
case "GRPT":
case "FKEY":
case "IKEY":
case "CSYS":
case "OPAQ":
case "CMAP":
case "NLOC":
case "NZOM":
case "NVER":
case "NSRV":
case "NVSK":
case "NCRD":
case "WRPW":
case "WRPH":
case "NMOD":
case "NSEL":
case "NPRW":
case "NPLA":
case "NODS":
case "VERS":
case "ENUM":
case "TAG ":
case "OPAC":
case "CGMD":
case "CGTY":
case "CGST":
case "CGEN":
case "CGTS":
case "CGTE":
case "OSMP":
case "OMDE":
case "OUTR":
case "FLAG":
case "TRNL":
case "GLOW":
case "GVAL":
case "SHRP":
case "RFOP":
case "RSAN":
case "TROP":
case "RBLR":
case "TBLR":
case "CLRH":
case "CLRF":
case "ADTR":
case "LINE":
case "ALPH":
case "VCOL":
case "ENAB":
this.IFF.debugger.skipped = true;
this.IFF.reader.skip(length);
break;
case "SURF":
this.IFF.parseSurfaceLwo2(length);
break;
case "CLIP":
this.IFF.parseClipLwo2(length);
break;
case "IPIX":
case "IMIP":
case "IMOD":
case "AMOD":
case "IINV":
case "INCR":
case "IAXS":
case "IFOT":
case "ITIM":
case "IWRL":
case "IUTI":
case "IINX":
case "IINY":
case "IINZ":
case "IREF":
if (length === 4)
this.IFF.currentNode[blockID] = this.IFF.reader.getInt32();
else
this.IFF.reader.skip(length);
break;
case "OTAG":
this.IFF.parseObjectTag();
break;
case "LAYR":
this.IFF.parseLayer(length);
break;
case "PNTS":
this.IFF.parsePoints(length);
break;
case "VMAP":
this.IFF.parseVertexMapping(length);
break;
case "AUVU":
case "AUVN":
this.IFF.reader.skip(length - 1);
this.IFF.reader.getVariableLengthIndex();
break;
case "POLS":
this.IFF.parsePolygonList(length);
break;
case "TAGS":
this.IFF.parseTagStrings(length);
break;
case "PTAG":
this.IFF.parsePolygonTagMapping(length);
break;
case "VMAD":
this.IFF.parseVertexMapping(length, true);
break;
case "DESC":
this.IFF.currentForm.description = this.IFF.reader.getString();
break;
case "TEXT":
case "CMNT":
case "NCOM":
this.IFF.currentForm.comment = this.IFF.reader.getString();
break;
case "NAME":
this.IFF.currentForm.channelName = this.IFF.reader.getString();
break;
case "WRAP":
this.IFF.currentForm.wrap = { w: this.IFF.reader.getUint16(), h: this.IFF.reader.getUint16() };
break;
case "IMAG":
const index = this.IFF.reader.getVariableLengthIndex();
this.IFF.currentForm.imageIndex = index;
break;
case "OREF":
this.IFF.currentForm.referenceObject = this.IFF.reader.getString();
break;
case "ROID":
this.IFF.currentForm.referenceObjectID = this.IFF.reader.getUint32();
break;
case "SSHN":
this.IFF.currentSurface.surfaceShaderName = this.IFF.reader.getString();
break;
case "AOVN":
this.IFF.currentSurface.surfaceCustomAOVName = this.IFF.reader.getString();
break;
case "NSTA":
this.IFF.currentForm.disabled = this.IFF.reader.getUint16();
break;
case "NRNM":
this.IFF.currentForm.realName = this.IFF.reader.getString();
break;
case "NNME":
this.IFF.currentForm.refName = this.IFF.reader.getString();
this.IFF.currentSurface.nodes[this.IFF.currentForm.refName] = this.IFF.currentForm;
break;
case "INME":
if (!this.IFF.currentForm.nodeName)
this.IFF.currentForm.nodeName = [];
this.IFF.currentForm.nodeName.push(this.IFF.reader.getString());
break;
case "IINN":
if (!this.IFF.currentForm.inputNodeName)
this.IFF.currentForm.inputNodeName = [];
this.IFF.currentForm.inputNodeName.push(this.IFF.reader.getString());
break;
case "IINM":
if (!this.IFF.currentForm.inputName)
this.IFF.currentForm.inputName = [];
this.IFF.currentForm.inputName.push(this.IFF.reader.getString());
break;
case "IONM":
if (!this.IFF.currentForm.inputOutputName)
this.IFF.currentForm.inputOutputName = [];
this.IFF.currentForm.inputOutputName.push(this.IFF.reader.getString());
break;
case "FNAM":
this.IFF.currentForm.fileName = this.IFF.reader.getString();
break;
case "CHAN":
if (length === 4)
this.IFF.currentForm.textureChannel = this.IFF.reader.getIDTag();
else
this.IFF.reader.skip(length);
break;
case "SMAN":
const maxSmoothingAngle = this.IFF.reader.getFloat32();
this.IFF.currentSurface.attributes.smooth = maxSmoothingAngle < 0 ? false : true;
break;
case "COLR":
this.IFF.currentSurface.attributes.Color = { value: this.IFF.reader.getFloat32Array(3) };
this.IFF.reader.skip(2);
break;
case "LUMI":
this.IFF.currentSurface.attributes.Luminosity = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "SPEC":
this.IFF.currentSurface.attributes.Specular = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "DIFF":
this.IFF.currentSurface.attributes.Diffuse = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "REFL":
this.IFF.currentSurface.attributes.Reflection = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "GLOS":
this.IFF.currentSurface.attributes.Glossiness = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "TRAN":
this.IFF.currentSurface.attributes.opacity = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "BUMP":
this.IFF.currentSurface.attributes.bumpStrength = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "SIDE":
this.IFF.currentSurface.attributes.side = this.IFF.reader.getUint16();
break;
case "RIMG":
this.IFF.currentSurface.attributes.reflectionMap = this.IFF.reader.getVariableLengthIndex();
break;
case "RIND":
this.IFF.currentSurface.attributes.refractiveIndex = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "TIMG":
this.IFF.currentSurface.attributes.refractionMap = this.IFF.reader.getVariableLengthIndex();
break;
case "IMAP":
this.IFF.reader.skip(2);
break;
case "TMAP":
this.IFF.debugger.skipped = true;
this.IFF.reader.skip(length);
break;
case "IUVI":
this.IFF.currentNode.UVChannel = this.IFF.reader.getString(length);
break;
case "IUTL":
this.IFF.currentNode.widthWrappingMode = this.IFF.reader.getUint32();
break;
case "IVTL":
this.IFF.currentNode.heightWrappingMode = this.IFF.reader.getUint32();
break;
case "BLOK":
break;
default:
this.IFF.parseUnknownCHUNK(blockID, length);
}
if (blockID != "FORM") {
this.IFF.debugger.node = 1;
this.IFF.debugger.nodeID = blockID;
this.IFF.debugger.log();
}
if (this.IFF.reader.offset >= this.IFF.currentFormEnd) {
this.IFF.currentForm = this.IFF.parentForm;
}
}
}
exports.LWO2Parser = LWO2Parser;
//# sourceMappingURL=LWO2Parser.cjs.map
File diff suppressed because one or more lines are too long
+313
View File
@@ -0,0 +1,313 @@
class LWO2Parser {
constructor(IFFParser) {
this.IFF = IFFParser;
}
parseBlock() {
this.IFF.debugger.offset = this.IFF.reader.offset;
this.IFF.debugger.closeForms();
const blockID = this.IFF.reader.getIDTag();
let length = this.IFF.reader.getUint32();
if (length > this.IFF.reader.dv.byteLength - this.IFF.reader.offset) {
this.IFF.reader.offset -= 4;
length = this.IFF.reader.getUint16();
}
this.IFF.debugger.dataOffset = this.IFF.reader.offset;
this.IFF.debugger.length = length;
switch (blockID) {
case "FORM":
this.IFF.parseForm(length);
break;
case "ICON":
case "VMPA":
case "BBOX":
case "NORM":
case "PRE ":
case "POST":
case "KEY ":
case "SPAN":
case "TIME":
case "CLRS":
case "CLRA":
case "FILT":
case "DITH":
case "CONT":
case "BRIT":
case "SATR":
case "HUE ":
case "GAMM":
case "NEGA":
case "IFLT":
case "PFLT":
case "PROJ":
case "AXIS":
case "AAST":
case "PIXB":
case "AUVO":
case "STCK":
case "PROC":
case "VALU":
case "FUNC":
case "PNAM":
case "INAM":
case "GRST":
case "GREN":
case "GRPT":
case "FKEY":
case "IKEY":
case "CSYS":
case "OPAQ":
case "CMAP":
case "NLOC":
case "NZOM":
case "NVER":
case "NSRV":
case "NVSK":
case "NCRD":
case "WRPW":
case "WRPH":
case "NMOD":
case "NSEL":
case "NPRW":
case "NPLA":
case "NODS":
case "VERS":
case "ENUM":
case "TAG ":
case "OPAC":
case "CGMD":
case "CGTY":
case "CGST":
case "CGEN":
case "CGTS":
case "CGTE":
case "OSMP":
case "OMDE":
case "OUTR":
case "FLAG":
case "TRNL":
case "GLOW":
case "GVAL":
case "SHRP":
case "RFOP":
case "RSAN":
case "TROP":
case "RBLR":
case "TBLR":
case "CLRH":
case "CLRF":
case "ADTR":
case "LINE":
case "ALPH":
case "VCOL":
case "ENAB":
this.IFF.debugger.skipped = true;
this.IFF.reader.skip(length);
break;
case "SURF":
this.IFF.parseSurfaceLwo2(length);
break;
case "CLIP":
this.IFF.parseClipLwo2(length);
break;
case "IPIX":
case "IMIP":
case "IMOD":
case "AMOD":
case "IINV":
case "INCR":
case "IAXS":
case "IFOT":
case "ITIM":
case "IWRL":
case "IUTI":
case "IINX":
case "IINY":
case "IINZ":
case "IREF":
if (length === 4)
this.IFF.currentNode[blockID] = this.IFF.reader.getInt32();
else
this.IFF.reader.skip(length);
break;
case "OTAG":
this.IFF.parseObjectTag();
break;
case "LAYR":
this.IFF.parseLayer(length);
break;
case "PNTS":
this.IFF.parsePoints(length);
break;
case "VMAP":
this.IFF.parseVertexMapping(length);
break;
case "AUVU":
case "AUVN":
this.IFF.reader.skip(length - 1);
this.IFF.reader.getVariableLengthIndex();
break;
case "POLS":
this.IFF.parsePolygonList(length);
break;
case "TAGS":
this.IFF.parseTagStrings(length);
break;
case "PTAG":
this.IFF.parsePolygonTagMapping(length);
break;
case "VMAD":
this.IFF.parseVertexMapping(length, true);
break;
case "DESC":
this.IFF.currentForm.description = this.IFF.reader.getString();
break;
case "TEXT":
case "CMNT":
case "NCOM":
this.IFF.currentForm.comment = this.IFF.reader.getString();
break;
case "NAME":
this.IFF.currentForm.channelName = this.IFF.reader.getString();
break;
case "WRAP":
this.IFF.currentForm.wrap = { w: this.IFF.reader.getUint16(), h: this.IFF.reader.getUint16() };
break;
case "IMAG":
const index = this.IFF.reader.getVariableLengthIndex();
this.IFF.currentForm.imageIndex = index;
break;
case "OREF":
this.IFF.currentForm.referenceObject = this.IFF.reader.getString();
break;
case "ROID":
this.IFF.currentForm.referenceObjectID = this.IFF.reader.getUint32();
break;
case "SSHN":
this.IFF.currentSurface.surfaceShaderName = this.IFF.reader.getString();
break;
case "AOVN":
this.IFF.currentSurface.surfaceCustomAOVName = this.IFF.reader.getString();
break;
case "NSTA":
this.IFF.currentForm.disabled = this.IFF.reader.getUint16();
break;
case "NRNM":
this.IFF.currentForm.realName = this.IFF.reader.getString();
break;
case "NNME":
this.IFF.currentForm.refName = this.IFF.reader.getString();
this.IFF.currentSurface.nodes[this.IFF.currentForm.refName] = this.IFF.currentForm;
break;
case "INME":
if (!this.IFF.currentForm.nodeName)
this.IFF.currentForm.nodeName = [];
this.IFF.currentForm.nodeName.push(this.IFF.reader.getString());
break;
case "IINN":
if (!this.IFF.currentForm.inputNodeName)
this.IFF.currentForm.inputNodeName = [];
this.IFF.currentForm.inputNodeName.push(this.IFF.reader.getString());
break;
case "IINM":
if (!this.IFF.currentForm.inputName)
this.IFF.currentForm.inputName = [];
this.IFF.currentForm.inputName.push(this.IFF.reader.getString());
break;
case "IONM":
if (!this.IFF.currentForm.inputOutputName)
this.IFF.currentForm.inputOutputName = [];
this.IFF.currentForm.inputOutputName.push(this.IFF.reader.getString());
break;
case "FNAM":
this.IFF.currentForm.fileName = this.IFF.reader.getString();
break;
case "CHAN":
if (length === 4)
this.IFF.currentForm.textureChannel = this.IFF.reader.getIDTag();
else
this.IFF.reader.skip(length);
break;
case "SMAN":
const maxSmoothingAngle = this.IFF.reader.getFloat32();
this.IFF.currentSurface.attributes.smooth = maxSmoothingAngle < 0 ? false : true;
break;
case "COLR":
this.IFF.currentSurface.attributes.Color = { value: this.IFF.reader.getFloat32Array(3) };
this.IFF.reader.skip(2);
break;
case "LUMI":
this.IFF.currentSurface.attributes.Luminosity = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "SPEC":
this.IFF.currentSurface.attributes.Specular = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "DIFF":
this.IFF.currentSurface.attributes.Diffuse = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "REFL":
this.IFF.currentSurface.attributes.Reflection = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "GLOS":
this.IFF.currentSurface.attributes.Glossiness = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "TRAN":
this.IFF.currentSurface.attributes.opacity = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "BUMP":
this.IFF.currentSurface.attributes.bumpStrength = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "SIDE":
this.IFF.currentSurface.attributes.side = this.IFF.reader.getUint16();
break;
case "RIMG":
this.IFF.currentSurface.attributes.reflectionMap = this.IFF.reader.getVariableLengthIndex();
break;
case "RIND":
this.IFF.currentSurface.attributes.refractiveIndex = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "TIMG":
this.IFF.currentSurface.attributes.refractionMap = this.IFF.reader.getVariableLengthIndex();
break;
case "IMAP":
this.IFF.reader.skip(2);
break;
case "TMAP":
this.IFF.debugger.skipped = true;
this.IFF.reader.skip(length);
break;
case "IUVI":
this.IFF.currentNode.UVChannel = this.IFF.reader.getString(length);
break;
case "IUTL":
this.IFF.currentNode.widthWrappingMode = this.IFF.reader.getUint32();
break;
case "IVTL":
this.IFF.currentNode.heightWrappingMode = this.IFF.reader.getUint32();
break;
case "BLOK":
break;
default:
this.IFF.parseUnknownCHUNK(blockID, length);
}
if (blockID != "FORM") {
this.IFF.debugger.node = 1;
this.IFF.debugger.nodeID = blockID;
this.IFF.debugger.log();
}
if (this.IFF.reader.offset >= this.IFF.currentFormEnd) {
this.IFF.currentForm = this.IFF.parentForm;
}
}
}
export {
LWO2Parser
};
//# sourceMappingURL=LWO2Parser.js.map
File diff suppressed because one or more lines are too long
+283
View File
@@ -0,0 +1,283 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
class LWO3Parser {
constructor(IFFParser) {
this.IFF = IFFParser;
}
parseBlock() {
this.IFF.debugger.offset = this.IFF.reader.offset;
this.IFF.debugger.closeForms();
const blockID = this.IFF.reader.getIDTag();
const length = this.IFF.reader.getUint32();
this.IFF.debugger.dataOffset = this.IFF.reader.offset;
this.IFF.debugger.length = length;
switch (blockID) {
case "FORM":
this.IFF.parseForm(length);
break;
case "ICON":
case "VMPA":
case "BBOX":
case "NORM":
case "PRE ":
case "POST":
case "KEY ":
case "SPAN":
case "TIME":
case "CLRS":
case "CLRA":
case "FILT":
case "DITH":
case "CONT":
case "BRIT":
case "SATR":
case "HUE ":
case "GAMM":
case "NEGA":
case "IFLT":
case "PFLT":
case "PROJ":
case "AXIS":
case "AAST":
case "PIXB":
case "STCK":
case "VALU":
case "PNAM":
case "INAM":
case "GRST":
case "GREN":
case "GRPT":
case "FKEY":
case "IKEY":
case "CSYS":
case "OPAQ":
case "CMAP":
case "NLOC":
case "NZOM":
case "NVER":
case "NSRV":
case "NCRD":
case "NMOD":
case "NSEL":
case "NPRW":
case "NPLA":
case "VERS":
case "ENUM":
case "TAG ":
case "CGMD":
case "CGTY":
case "CGST":
case "CGEN":
case "CGTS":
case "CGTE":
case "OSMP":
case "OMDE":
case "OUTR":
case "FLAG":
case "TRNL":
case "SHRP":
case "RFOP":
case "RSAN":
case "TROP":
case "RBLR":
case "TBLR":
case "CLRH":
case "CLRF":
case "ADTR":
case "GLOW":
case "LINE":
case "ALPH":
case "VCOL":
case "ENAB":
this.IFF.debugger.skipped = true;
this.IFF.reader.skip(length);
break;
case "IPIX":
case "IMIP":
case "IMOD":
case "AMOD":
case "IINV":
case "INCR":
case "IAXS":
case "IFOT":
case "ITIM":
case "IWRL":
case "IUTI":
case "IINX":
case "IINY":
case "IINZ":
case "IREF":
if (length === 4)
this.IFF.currentNode[blockID] = this.IFF.reader.getInt32();
else
this.IFF.reader.skip(length);
break;
case "OTAG":
this.IFF.parseObjectTag();
break;
case "LAYR":
this.IFF.parseLayer(length);
break;
case "PNTS":
this.IFF.parsePoints(length);
break;
case "VMAP":
this.IFF.parseVertexMapping(length);
break;
case "POLS":
this.IFF.parsePolygonList(length);
break;
case "TAGS":
this.IFF.parseTagStrings(length);
break;
case "PTAG":
this.IFF.parsePolygonTagMapping(length);
break;
case "VMAD":
this.IFF.parseVertexMapping(length, true);
break;
case "DESC":
this.IFF.currentForm.description = this.IFF.reader.getString();
break;
case "TEXT":
case "CMNT":
case "NCOM":
this.IFF.currentForm.comment = this.IFF.reader.getString();
break;
case "NAME":
this.IFF.currentForm.channelName = this.IFF.reader.getString();
break;
case "WRAP":
this.IFF.currentForm.wrap = { w: this.IFF.reader.getUint16(), h: this.IFF.reader.getUint16() };
break;
case "IMAG":
const index = this.IFF.reader.getVariableLengthIndex();
this.IFF.currentForm.imageIndex = index;
break;
case "OREF":
this.IFF.currentForm.referenceObject = this.IFF.reader.getString();
break;
case "ROID":
this.IFF.currentForm.referenceObjectID = this.IFF.reader.getUint32();
break;
case "SSHN":
this.IFF.currentSurface.surfaceShaderName = this.IFF.reader.getString();
break;
case "AOVN":
this.IFF.currentSurface.surfaceCustomAOVName = this.IFF.reader.getString();
break;
case "NSTA":
this.IFF.currentForm.disabled = this.IFF.reader.getUint16();
break;
case "NRNM":
this.IFF.currentForm.realName = this.IFF.reader.getString();
break;
case "NNME":
this.IFF.currentForm.refName = this.IFF.reader.getString();
this.IFF.currentSurface.nodes[this.IFF.currentForm.refName] = this.IFF.currentForm;
break;
case "INME":
if (!this.IFF.currentForm.nodeName)
this.IFF.currentForm.nodeName = [];
this.IFF.currentForm.nodeName.push(this.IFF.reader.getString());
break;
case "IINN":
if (!this.IFF.currentForm.inputNodeName)
this.IFF.currentForm.inputNodeName = [];
this.IFF.currentForm.inputNodeName.push(this.IFF.reader.getString());
break;
case "IINM":
if (!this.IFF.currentForm.inputName)
this.IFF.currentForm.inputName = [];
this.IFF.currentForm.inputName.push(this.IFF.reader.getString());
break;
case "IONM":
if (!this.IFF.currentForm.inputOutputName)
this.IFF.currentForm.inputOutputName = [];
this.IFF.currentForm.inputOutputName.push(this.IFF.reader.getString());
break;
case "FNAM":
this.IFF.currentForm.fileName = this.IFF.reader.getString();
break;
case "CHAN":
if (length === 4)
this.IFF.currentForm.textureChannel = this.IFF.reader.getIDTag();
else
this.IFF.reader.skip(length);
break;
case "SMAN":
const maxSmoothingAngle = this.IFF.reader.getFloat32();
this.IFF.currentSurface.attributes.smooth = maxSmoothingAngle < 0 ? false : true;
break;
case "COLR":
this.IFF.currentSurface.attributes.Color = { value: this.IFF.reader.getFloat32Array(3) };
this.IFF.reader.skip(2);
break;
case "LUMI":
this.IFF.currentSurface.attributes.Luminosity = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "SPEC":
this.IFF.currentSurface.attributes.Specular = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "DIFF":
this.IFF.currentSurface.attributes.Diffuse = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "REFL":
this.IFF.currentSurface.attributes.Reflection = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "GLOS":
this.IFF.currentSurface.attributes.Glossiness = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "TRAN":
this.IFF.currentSurface.attributes.opacity = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "BUMP":
this.IFF.currentSurface.attributes.bumpStrength = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "SIDE":
this.IFF.currentSurface.attributes.side = this.IFF.reader.getUint16();
break;
case "RIMG":
this.IFF.currentSurface.attributes.reflectionMap = this.IFF.reader.getVariableLengthIndex();
break;
case "RIND":
this.IFF.currentSurface.attributes.refractiveIndex = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "TIMG":
this.IFF.currentSurface.attributes.refractionMap = this.IFF.reader.getVariableLengthIndex();
break;
case "IMAP":
this.IFF.currentSurface.attributes.imageMapIndex = this.IFF.reader.getUint32();
break;
case "IUVI":
this.IFF.currentNode.UVChannel = this.IFF.reader.getString(length);
break;
case "IUTL":
this.IFF.currentNode.widthWrappingMode = this.IFF.reader.getUint32();
break;
case "IVTL":
this.IFF.currentNode.heightWrappingMode = this.IFF.reader.getUint32();
break;
default:
this.IFF.parseUnknownCHUNK(blockID, length);
}
if (blockID != "FORM") {
this.IFF.debugger.node = 1;
this.IFF.debugger.nodeID = blockID;
this.IFF.debugger.log();
}
if (this.IFF.reader.offset >= this.IFF.currentFormEnd) {
this.IFF.currentForm = this.IFF.parentForm;
}
}
}
exports.LWO3Parser = LWO3Parser;
//# sourceMappingURL=LWO3Parser.cjs.map
File diff suppressed because one or more lines are too long
+283
View File
@@ -0,0 +1,283 @@
class LWO3Parser {
constructor(IFFParser) {
this.IFF = IFFParser;
}
parseBlock() {
this.IFF.debugger.offset = this.IFF.reader.offset;
this.IFF.debugger.closeForms();
const blockID = this.IFF.reader.getIDTag();
const length = this.IFF.reader.getUint32();
this.IFF.debugger.dataOffset = this.IFF.reader.offset;
this.IFF.debugger.length = length;
switch (blockID) {
case "FORM":
this.IFF.parseForm(length);
break;
case "ICON":
case "VMPA":
case "BBOX":
case "NORM":
case "PRE ":
case "POST":
case "KEY ":
case "SPAN":
case "TIME":
case "CLRS":
case "CLRA":
case "FILT":
case "DITH":
case "CONT":
case "BRIT":
case "SATR":
case "HUE ":
case "GAMM":
case "NEGA":
case "IFLT":
case "PFLT":
case "PROJ":
case "AXIS":
case "AAST":
case "PIXB":
case "STCK":
case "VALU":
case "PNAM":
case "INAM":
case "GRST":
case "GREN":
case "GRPT":
case "FKEY":
case "IKEY":
case "CSYS":
case "OPAQ":
case "CMAP":
case "NLOC":
case "NZOM":
case "NVER":
case "NSRV":
case "NCRD":
case "NMOD":
case "NSEL":
case "NPRW":
case "NPLA":
case "VERS":
case "ENUM":
case "TAG ":
case "CGMD":
case "CGTY":
case "CGST":
case "CGEN":
case "CGTS":
case "CGTE":
case "OSMP":
case "OMDE":
case "OUTR":
case "FLAG":
case "TRNL":
case "SHRP":
case "RFOP":
case "RSAN":
case "TROP":
case "RBLR":
case "TBLR":
case "CLRH":
case "CLRF":
case "ADTR":
case "GLOW":
case "LINE":
case "ALPH":
case "VCOL":
case "ENAB":
this.IFF.debugger.skipped = true;
this.IFF.reader.skip(length);
break;
case "IPIX":
case "IMIP":
case "IMOD":
case "AMOD":
case "IINV":
case "INCR":
case "IAXS":
case "IFOT":
case "ITIM":
case "IWRL":
case "IUTI":
case "IINX":
case "IINY":
case "IINZ":
case "IREF":
if (length === 4)
this.IFF.currentNode[blockID] = this.IFF.reader.getInt32();
else
this.IFF.reader.skip(length);
break;
case "OTAG":
this.IFF.parseObjectTag();
break;
case "LAYR":
this.IFF.parseLayer(length);
break;
case "PNTS":
this.IFF.parsePoints(length);
break;
case "VMAP":
this.IFF.parseVertexMapping(length);
break;
case "POLS":
this.IFF.parsePolygonList(length);
break;
case "TAGS":
this.IFF.parseTagStrings(length);
break;
case "PTAG":
this.IFF.parsePolygonTagMapping(length);
break;
case "VMAD":
this.IFF.parseVertexMapping(length, true);
break;
case "DESC":
this.IFF.currentForm.description = this.IFF.reader.getString();
break;
case "TEXT":
case "CMNT":
case "NCOM":
this.IFF.currentForm.comment = this.IFF.reader.getString();
break;
case "NAME":
this.IFF.currentForm.channelName = this.IFF.reader.getString();
break;
case "WRAP":
this.IFF.currentForm.wrap = { w: this.IFF.reader.getUint16(), h: this.IFF.reader.getUint16() };
break;
case "IMAG":
const index = this.IFF.reader.getVariableLengthIndex();
this.IFF.currentForm.imageIndex = index;
break;
case "OREF":
this.IFF.currentForm.referenceObject = this.IFF.reader.getString();
break;
case "ROID":
this.IFF.currentForm.referenceObjectID = this.IFF.reader.getUint32();
break;
case "SSHN":
this.IFF.currentSurface.surfaceShaderName = this.IFF.reader.getString();
break;
case "AOVN":
this.IFF.currentSurface.surfaceCustomAOVName = this.IFF.reader.getString();
break;
case "NSTA":
this.IFF.currentForm.disabled = this.IFF.reader.getUint16();
break;
case "NRNM":
this.IFF.currentForm.realName = this.IFF.reader.getString();
break;
case "NNME":
this.IFF.currentForm.refName = this.IFF.reader.getString();
this.IFF.currentSurface.nodes[this.IFF.currentForm.refName] = this.IFF.currentForm;
break;
case "INME":
if (!this.IFF.currentForm.nodeName)
this.IFF.currentForm.nodeName = [];
this.IFF.currentForm.nodeName.push(this.IFF.reader.getString());
break;
case "IINN":
if (!this.IFF.currentForm.inputNodeName)
this.IFF.currentForm.inputNodeName = [];
this.IFF.currentForm.inputNodeName.push(this.IFF.reader.getString());
break;
case "IINM":
if (!this.IFF.currentForm.inputName)
this.IFF.currentForm.inputName = [];
this.IFF.currentForm.inputName.push(this.IFF.reader.getString());
break;
case "IONM":
if (!this.IFF.currentForm.inputOutputName)
this.IFF.currentForm.inputOutputName = [];
this.IFF.currentForm.inputOutputName.push(this.IFF.reader.getString());
break;
case "FNAM":
this.IFF.currentForm.fileName = this.IFF.reader.getString();
break;
case "CHAN":
if (length === 4)
this.IFF.currentForm.textureChannel = this.IFF.reader.getIDTag();
else
this.IFF.reader.skip(length);
break;
case "SMAN":
const maxSmoothingAngle = this.IFF.reader.getFloat32();
this.IFF.currentSurface.attributes.smooth = maxSmoothingAngle < 0 ? false : true;
break;
case "COLR":
this.IFF.currentSurface.attributes.Color = { value: this.IFF.reader.getFloat32Array(3) };
this.IFF.reader.skip(2);
break;
case "LUMI":
this.IFF.currentSurface.attributes.Luminosity = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "SPEC":
this.IFF.currentSurface.attributes.Specular = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "DIFF":
this.IFF.currentSurface.attributes.Diffuse = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "REFL":
this.IFF.currentSurface.attributes.Reflection = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "GLOS":
this.IFF.currentSurface.attributes.Glossiness = { value: this.IFF.reader.getFloat32() };
this.IFF.reader.skip(2);
break;
case "TRAN":
this.IFF.currentSurface.attributes.opacity = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "BUMP":
this.IFF.currentSurface.attributes.bumpStrength = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "SIDE":
this.IFF.currentSurface.attributes.side = this.IFF.reader.getUint16();
break;
case "RIMG":
this.IFF.currentSurface.attributes.reflectionMap = this.IFF.reader.getVariableLengthIndex();
break;
case "RIND":
this.IFF.currentSurface.attributes.refractiveIndex = this.IFF.reader.getFloat32();
this.IFF.reader.skip(2);
break;
case "TIMG":
this.IFF.currentSurface.attributes.refractionMap = this.IFF.reader.getVariableLengthIndex();
break;
case "IMAP":
this.IFF.currentSurface.attributes.imageMapIndex = this.IFF.reader.getUint32();
break;
case "IUVI":
this.IFF.currentNode.UVChannel = this.IFF.reader.getString(length);
break;
case "IUTL":
this.IFF.currentNode.widthWrappingMode = this.IFF.reader.getUint32();
break;
case "IVTL":
this.IFF.currentNode.heightWrappingMode = this.IFF.reader.getUint32();
break;
default:
this.IFF.parseUnknownCHUNK(blockID, length);
}
if (blockID != "FORM") {
this.IFF.debugger.node = 1;
this.IFF.debugger.nodeID = blockID;
this.IFF.debugger.log();
}
if (this.IFF.reader.offset >= this.IFF.currentFormEnd) {
this.IFF.currentForm = this.IFF.parentForm;
}
}
}
export {
LWO3Parser
};
//# sourceMappingURL=LWO3Parser.js.map
File diff suppressed because one or more lines are too long