@runejs/filestore
Version:
Tools for managing the RuneJS filestore.
785 lines (784 loc) • 33 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModelStore = exports.ColorUtils = exports.VertexNormal = exports.RsModel = void 0;
const common_1 = require("@runejs/common");
const common_2 = require("@runejs/common");
class RsModel {
id;
vertexCount;
faceCount;
texturedFaceCount;
verticesX;
verticesY;
verticesZ;
faceIndicesA;
faceIndicesB;
faceIndicesC;
texturedFaceTypes;
texturedFaceIndicesA;
texturedFaceIndicesB;
texturedFaceIndicesC;
vertexSkins;
faceTypes;
texturedFaceTypeIndices;
faceTextures;
facePriorities;
facePriority;
faceAlphas;
faceSkins;
faceColors;
// rendering
faceTextureU;
faceTextureV;
// meta
faceColorsX;
faceColorsY;
faceColorsZ;
vertexNormals;
vertexNormalOffsets;
anInt3193;
constructor() {
this.texturedFaceCount = 0;
this.vertexCount = 0;
this.facePriority = 0;
}
computeTextureUVs() {
if (this.faceTextureU) {
return;
}
this.faceTextureU = new Array(this.faceCount);
this.faceTextureV = new Array(this.faceCount);
for (let i = 0; i < this.faceCount; i++) {
let texturedFaceTypeIndex;
if (this.texturedFaceTypeIndices == null) {
texturedFaceTypeIndex = -1;
}
else {
texturedFaceTypeIndex = this.texturedFaceTypeIndices[i];
}
let textureId;
if (this.faceTextures == null) {
textureId = -1;
}
else {
textureId = this.faceTextures[i] & 0xffff;
}
if (textureId !== -1) {
const u = new Array(3);
const v = new Array(3);
if (texturedFaceTypeIndex === -1) {
u[0] = 0.0;
v[0] = 1.0;
u[1] = 1.0;
v[1] = 1.0;
u[2] = 0.0;
v[2] = 0.0;
}
else {
texturedFaceTypeIndex &= 0xff;
let texturedFaceType = 0;
if (this.texturedFaceTypes != null) {
texturedFaceType =
this.texturedFaceTypes[texturedFaceTypeIndex];
}
if (texturedFaceType === 0) {
const faceIndexA = this.faceIndicesA[i];
const faceIndexB = this.faceIndicesB[i];
const faceIndexC = this.faceIndicesC[i];
const texturedFaceIndexA = this.texturedFaceIndicesA[texturedFaceTypeIndex];
const texturedFaceIndexB = this.texturedFaceIndicesB[texturedFaceTypeIndex];
const texturedFaceIndexC = this.texturedFaceIndicesC[texturedFaceTypeIndex];
const vertexX = this.verticesX[texturedFaceIndexA];
const vertexY = this.verticesY[texturedFaceIndexA];
const vertexZ = this.verticesZ[texturedFaceIndexA];
const f_882_ = this.verticesX[texturedFaceIndexB] - vertexX;
const f_883_ = this.verticesY[texturedFaceIndexB] - vertexY;
const f_884_ = this.verticesZ[texturedFaceIndexB] - vertexZ;
const f_885_ = this.verticesX[texturedFaceIndexC] - vertexX;
const f_886_ = this.verticesY[texturedFaceIndexC] - vertexY;
const f_887_ = this.verticesZ[texturedFaceIndexC] - vertexZ;
const f_888_ = this.verticesX[faceIndexA] - vertexX;
const f_889_ = this.verticesY[faceIndexA] - vertexY;
const f_890_ = this.verticesZ[faceIndexA] - vertexZ;
const f_891_ = this.verticesX[faceIndexB] - vertexX;
const f_892_ = this.verticesY[faceIndexB] - vertexY;
const f_893_ = this.verticesZ[faceIndexB] - vertexZ;
const f_894_ = this.verticesX[faceIndexC] - vertexX;
const f_895_ = this.verticesY[faceIndexC] - vertexY;
const f_896_ = this.verticesZ[faceIndexC] - vertexZ;
const f_897_ = f_883_ * f_887_ - f_884_ * f_886_;
const f_898_ = f_884_ * f_885_ - f_882_ * f_887_;
const f_899_ = f_882_ * f_886_ - f_883_ * f_885_;
let f_900_ = f_886_ * f_899_ - f_887_ * f_898_;
let f_901_ = f_887_ * f_897_ - f_885_ * f_899_;
let f_902_ = f_885_ * f_898_ - f_886_ * f_897_;
let f_903_ = 1.0 /
(f_900_ * f_882_ +
f_901_ * f_883_ +
f_902_ * f_884_);
u[0] =
(f_900_ * f_888_ +
f_901_ * f_889_ +
f_902_ * f_890_) *
f_903_;
u[1] =
(f_900_ * f_891_ +
f_901_ * f_892_ +
f_902_ * f_893_) *
f_903_;
u[2] =
(f_900_ * f_894_ +
f_901_ * f_895_ +
f_902_ * f_896_) *
f_903_;
f_900_ = f_883_ * f_899_ - f_884_ * f_898_;
f_901_ = f_884_ * f_897_ - f_882_ * f_899_;
f_902_ = f_882_ * f_898_ - f_883_ * f_897_;
f_903_ =
1.0 /
(f_900_ * f_885_ +
f_901_ * f_886_ +
f_902_ * f_887_);
v[0] =
(f_900_ * f_888_ +
f_901_ * f_889_ +
f_902_ * f_890_) *
f_903_;
v[1] =
(f_900_ * f_891_ +
f_901_ * f_892_ +
f_902_ * f_893_) *
f_903_;
v[2] =
(f_900_ * f_894_ +
f_901_ * f_895_ +
f_902_ * f_896_) *
f_903_;
}
}
this.faceTextureU[i] = u;
this.faceTextureV[i] = v;
}
}
}
applyLighting(ambient, contrast, arg2, arg3, arg4, applyShading) {
const i = ~~Math.sqrt(arg2 * arg2 + arg3 * arg3 + arg4 * arg4);
const i_50_ = (contrast * i) >> 8;
if (this.faceColorsX === null) {
this.faceColorsX = new Uint32Array(this.faceCount);
this.faceColorsY = new Uint32Array(this.faceCount);
this.faceColorsZ = new Uint32Array(this.faceCount);
}
if (this.vertexNormals === null) {
const initializeVertexNormals = [...Array(this.vertexCount)];
this.vertexNormals = initializeVertexNormals.map(() => new VertexNormal());
}
for (let i_52_ = 0; i_52_ < this.faceCount; i_52_++) {
const faceA = this.faceIndicesA[i_52_];
const faceB = this.faceIndicesB[i_52_];
const faceC = this.faceIndicesC[i_52_];
const i_56_ = this.verticesX[faceB] - this.verticesX[faceA];
const i_57_ = this.verticesY[faceB] - this.verticesY[faceA];
const i_58_ = this.verticesZ[faceB] - this.verticesZ[faceA];
const i_59_ = this.verticesX[faceC] - this.verticesX[faceA];
const i_60_ = this.verticesY[faceC] - this.verticesY[faceA];
const i_61_ = this.verticesZ[faceC] - this.verticesZ[faceA];
let i_62_ = i_57_ * i_61_ - i_60_ * i_58_;
let i_63_ = i_58_ * i_59_ - i_61_ * i_56_;
let i_64_;
for (i_64_ = i_56_ * i_60_ - i_59_ * i_57_; i_62_ > 8192 ||
i_63_ > 8192 ||
i_64_ > 8192 ||
i_62_ < -8192 ||
i_63_ < -8192 ||
i_64_ < -8192; i_64_ >>= 1) {
i_62_ >>= 1;
i_63_ >>= 1;
}
let i_65_ = ~~Math.sqrt(i_62_ * i_62_ + i_63_ * i_63_ + i_64_ * i_64_);
if (i_65_ <= 0) {
i_65_ = 1;
}
i_62_ = ~~((i_62_ * 256) / i_65_);
i_63_ = ~~((i_63_ * 256) / i_65_);
i_64_ = ~~((i_64_ * 256) / i_65_);
if (this.faceTypes == null || (this.faceTypes[i_52_] & 0x1) === 0) {
let class46 = this.vertexNormals[faceA];
class46.x += i_62_;
class46.y += i_63_;
class46.z += i_64_;
class46.magnitude++;
class46 = this.vertexNormals[faceB];
class46.x += i_62_;
class46.y += i_63_;
class46.z += i_64_;
class46.magnitude++;
class46 = this.vertexNormals[faceC];
class46.x += i_62_;
class46.y += i_63_;
class46.z += i_64_;
class46.magnitude++;
}
else {
const i_66_ = ambient +
(arg2 * i_62_ + arg3 * i_63_ + arg4 * i_64_) /
(i_50_ + i_50_ / 2);
this.faceColorsX[i_52_] = ColorUtils.method816(this.faceColors[i_52_], i_66_, this.faceTypes[i_52_]);
}
}
if (applyShading) {
this.applyShading(ambient, i_50_, arg2, arg3, arg4);
}
else {
this.vertexNormalOffsets = new Array(this.vertexCount);
for (let i_67_ = 0; i_67_ < this.vertexCount; i_67_++) {
const normal = this.vertexNormals[i_67_];
// biome-ignore lint/suspicious/noAssignInExpressions: Legacy
const normalOffset = (this.vertexNormalOffsets[i_67_] =
new VertexNormal());
normalOffset.x = normal.x;
normalOffset.y = normal.y;
normalOffset.z = normal.z;
normalOffset.magnitude = normal.magnitude;
}
this.anInt3193 = (ambient << 16) + (i_50_ & 0xffff);
}
}
applyShading(arg0, arg1, arg2, arg3, arg4) {
for (let i = 0; i < this.faceCount; i++) {
const faceA = this.faceIndicesA[i];
const faceB = this.faceIndicesB[i];
const faceC = this.faceIndicesC[i];
if (this.faceTypes == null) {
const faceColor = this.faceColors[i];
let normal = this.vertexNormals[faceA];
let i_76_ = ~~(arg0 +
(arg2 * normal.x + arg3 * normal.y + arg4 * normal.z) /
(arg1 * normal.magnitude));
this.faceColorsX[i] = ColorUtils.method816(faceColor, i_76_, 0);
normal = this.vertexNormals[faceB];
i_76_ = ~~(arg0 +
(arg2 * normal.x + arg3 * normal.y + arg4 * normal.z) /
(arg1 * normal.magnitude));
this.faceColorsY[i] = ColorUtils.method816(faceColor, i_76_, 0);
normal = this.vertexNormals[faceC];
i_76_ = ~~(arg0 +
(arg2 * normal.x + arg3 * normal.y + arg4 * normal.z) /
(arg1 * normal.magnitude));
this.faceColorsZ[i] = ColorUtils.method816(faceColor, i_76_, 0);
}
else if ((this.faceTypes[i] & 0x1) === 0) {
const faceColor = this.faceColors[i];
const faceType = this.faceTypes[i];
let normal = this.vertexNormals[faceA];
let i_79_ = ~~(arg0 +
(arg2 * normal.x + arg3 * normal.y + arg4 * normal.z) /
(arg1 * normal.magnitude));
this.faceColorsX[i] = ColorUtils.method816(faceColor, i_79_, faceType);
normal = this.vertexNormals[faceB];
i_79_ = ~~(arg0 +
(arg2 * normal.x + arg3 * normal.y + arg4 * normal.z) /
(arg1 * normal.magnitude));
this.faceColorsY[i] = ColorUtils.method816(faceColor, i_79_, faceType);
normal = this.vertexNormals[faceC];
i_79_ = ~~(arg0 +
(arg2 * normal.x + arg3 * normal.y + arg4 * normal.z) /
(arg1 * normal.magnitude));
this.faceColorsZ[i] = ColorUtils.method816(faceColor, i_79_, faceType);
}
}
}
}
exports.RsModel = RsModel;
class VertexNormal {
x;
y;
z;
magnitude;
constructor() {
this.x = 0;
this.y = 0;
this.z = 0;
this.magnitude = 0;
}
}
exports.VertexNormal = VertexNormal;
// biome-ignore lint/complexity/noStaticOnlyClass: Legacy
class ColorUtils {
static UNKNOWN_COLOR_TABLE = ColorUtils.initUnknownColorTable();
static HSB_TO_RGB = ColorUtils.initHsbToRgb(0.7, 0, 512);
static initUnknownColorTable() {
const table = new Uint32Array(128);
let i = 0;
let i_322_ = 248;
while (i < 9) {
table[i++] = 255;
}
while (i < 16) {
table[i++] = i_322_;
i_322_ -= 8;
}
while (i < 32) {
table[i++] = i_322_;
i_322_ -= 4;
}
while (i < 64) {
table[i++] = i_322_;
i_322_ -= 2;
}
while (i < 128) {
table[i++] = i_322_--;
}
return table;
}
// @TODO use @runejs/color when published
static initHsbToRgb(inputArg0, arg1, arg2) {
let arg0 = inputArg0;
const table = new Uint32Array(65536);
arg0 += Math.random() * 0.03 - 0.015;
let i = arg1 * 128;
for (let i_58_ = arg1; i_58_ < arg2; i_58_++) {
const d = (i_58_ >> 3) / 64.0 + 0.0078125;
const d_59_ = (i_58_ & 0x7) / 8.0 + 0.0625;
for (let i_60_ = 0; i_60_ < 128; i_60_++) {
const d_61_ = i_60_ / 128.0;
let red = d_61_;
let green = d_61_;
let blue = d_61_;
if (d_59_ !== 0.0) {
let d_65_;
if (d_61_ < 0.5) {
d_65_ = d_61_ * (1.0 + d_59_);
}
else {
d_65_ = d_61_ + d_59_ - d_61_ * d_59_;
}
const d_66_ = 2.0 * d_61_ - d_65_;
let d_67_ = d + 0.3333333333333333;
if (d_67_ > 1.0) {
d_67_--;
}
const d_68_ = d;
let d_69_ = d - 0.3333333333333333;
if (d_69_ < 0.0) {
d_69_++;
}
if (6.0 * d_67_ < 1.0) {
red = d_66_ + (d_65_ - d_66_) * 6.0 * d_67_;
}
else if (2.0 * d_67_ < 1.0) {
red = d_65_;
}
else if (3.0 * d_67_ < 2.0) {
red =
d_66_ +
(d_65_ - d_66_) *
(0.6666666666666666 - d_67_) *
6.0;
}
else {
red = d_66_;
}
if (6.0 * d_68_ < 1.0) {
green = d_66_ + (d_65_ - d_66_) * 6.0 * d_68_;
}
else if (2.0 * d_68_ < 1.0) {
green = d_65_;
}
else if (3.0 * d_68_ < 2.0) {
green =
d_66_ +
(d_65_ - d_66_) *
(0.6666666666666666 - d_68_) *
6.0;
}
else {
green = d_66_;
}
if (6.0 * d_69_ < 1.0) {
blue = d_66_ + (d_65_ - d_66_) * 6.0 * d_69_;
}
else if (2.0 * d_69_ < 1.0) {
blue = d_65_;
}
else if (3.0 * d_69_ < 2.0) {
blue =
d_66_ +
(d_65_ - d_66_) *
(0.6666666666666666 - d_69_) *
6.0;
}
else {
blue = d_66_;
}
}
const redUByte = red * 256.0;
const greenUByte = green * 256.0;
const blueUByte = blue * 256.0;
let rgb = (redUByte << 16) + (greenUByte << 8) + blueUByte;
rgb = ColorUtils.method707(rgb, arg0);
if (rgb === 0) {
rgb = 1;
}
table[i++] = rgb;
}
}
return table;
}
static hsbToRgb(hsb) {
return ColorUtils.HSB_TO_RGB[hsb];
}
static method707(rgb, arg1) {
let red = (rgb >> 16) / 256.0;
let green = ((rgb >> 8) & 0xff) / 256.0;
let blue = (rgb & 0xff) / 256.0;
red = red ** arg1;
green = green ** arg1;
blue = blue ** arg1;
const newRed = red * 256.0;
const newGreen = green * 256.0;
const newBlue = blue * 256.0;
return (newRed << 16) + (newGreen << 8) + newBlue;
}
static method816(faceColor, inputArg1, faceType) {
let arg1 = inputArg1;
if ((faceType & 0x2) === 2) {
if (arg1 < 0) {
arg1 = 0;
}
else if (arg1 > 127) {
arg1 = 127;
}
arg1 = ColorUtils.UNKNOWN_COLOR_TABLE[arg1];
return arg1;
}
arg1 = (arg1 * (faceColor & 0x7f)) >> 7;
if (arg1 < 2) {
arg1 = 2;
}
else if (arg1 > 126) {
arg1 = 126;
}
return (faceColor & 0xff80) + arg1;
}
static method709(arg0, inputArg1) {
let arg1 = inputArg1;
arg1 = ((127 - arg1) * (arg0 & 0x7f)) >> 7;
if (arg1 < 2) {
arg1 = 2;
}
else if (arg1 > 126) {
arg1 = 126;
}
return (arg0 & 0xff80) + arg1;
}
// custom shade function (i.e not from the client)
static shade(rgb, shadowRgb) {
let red = (rgb >> 16) / 256.0;
let green = ((rgb >> 8) & 0xff) / 256.0;
let blue = (rgb & 0xff) / 256.0;
const shadowRed = ((shadowRgb >> 16) & 0xff) / 255.0;
const shadowGreen = ((shadowRgb >> 8) & 0xff) / 255.0;
const shadowBlue = (shadowRgb & 0xff) / 255.0;
red *= 1 - shadowRed;
green *= 1 - shadowGreen;
blue *= 1 - shadowBlue;
const newRed = red * 256.0;
const newGreen = green * 256.0;
const newBlue = blue * 256.0;
return (newRed << 16) + (newGreen << 8) + newBlue;
}
}
exports.ColorUtils = ColorUtils;
/**
* Controls model file storage.
*/
class ModelStore {
fileStore;
modelFileIndex;
constructor(fileStore) {
this.fileStore = fileStore;
this.modelFileIndex = this.fileStore.getIndex('models');
}
getModel(id) {
const file = this.modelFileIndex.getFile(id) || null;
if (!file) {
common_1.logger.warn(`Model file ${id} not found`);
return null;
}
const rsModel = new RsModel();
rsModel.id = id;
const buffer = file.content;
buffer.readerIndex = 0;
let useFaceTypes = false;
let useFaceTextures = false;
const vertexDirectionOffsetBuffer = new common_2.ByteBuffer(buffer);
const xDataOffsetBuffer = new common_2.ByteBuffer(buffer);
const yDataOffsetBuffer = new common_2.ByteBuffer(buffer);
const zDataOffsetBuffer = new common_2.ByteBuffer(buffer);
const vertexSkinOffsetBuffer = new common_2.ByteBuffer(buffer);
vertexDirectionOffsetBuffer.readerIndex = buffer.length - 18;
rsModel.vertexCount = vertexDirectionOffsetBuffer.get('SHORT', 'UNSIGNED');
rsModel.faceCount = vertexDirectionOffsetBuffer.get('SHORT', 'UNSIGNED');
rsModel.texturedFaceCount = vertexDirectionOffsetBuffer.get('BYTE', 'UNSIGNED');
const hasFaceTypes = vertexDirectionOffsetBuffer.get('BYTE', 'UNSIGNED');
const modelPriority = vertexDirectionOffsetBuffer.get('BYTE', 'UNSIGNED');
const hasFaceAlphas = vertexDirectionOffsetBuffer.get('BYTE', 'UNSIGNED');
const hasFaceSkins = vertexDirectionOffsetBuffer.get('BYTE', 'UNSIGNED');
const hasVertexSkins = vertexDirectionOffsetBuffer.get('BYTE', 'UNSIGNED');
const verticesXSubOffset = vertexDirectionOffsetBuffer.get('SHORT', 'UNSIGNED');
const verticesYSubOffset = vertexDirectionOffsetBuffer.get('SHORT', 'UNSIGNED');
const verticesZSubOffset = vertexDirectionOffsetBuffer.get('SHORT', 'UNSIGNED');
const faceIndicesSubOffset = vertexDirectionOffsetBuffer.get('SHORT', 'UNSIGNED');
let offset = 0;
const vertexFlagsOffset = offset;
offset += rsModel.vertexCount;
const facesCompressTypeOffset = offset;
offset += rsModel.faceCount;
const facePrioritiesOffset = offset;
if (modelPriority === 255) {
offset += rsModel.faceCount;
}
const faceSkinsOffset = offset;
if (hasFaceSkins === 1) {
offset += rsModel.faceCount;
}
const faceTypesOffset = offset;
if (hasFaceTypes === 1) {
offset += rsModel.faceCount;
}
const vertexSkinsOffset = offset;
if (hasVertexSkins === 1) {
offset += rsModel.vertexCount;
}
const faceAlphasOffset = offset;
if (hasFaceAlphas === 1) {
offset += rsModel.faceCount;
}
const faceIndicesOffset = offset;
offset += faceIndicesSubOffset;
const faceColorsOffset = offset;
offset += rsModel.faceCount * 2;
const faceMappingsOffset = offset;
offset += rsModel.texturedFaceCount * 6;
const verticesXOffset = offset;
offset += verticesXSubOffset;
const verticesYOffset = offset;
offset += verticesYSubOffset;
const verticesZOffset = offset;
offset += verticesZSubOffset;
rsModel.verticesX = new Array(rsModel.vertexCount);
rsModel.verticesY = new Array(rsModel.vertexCount);
rsModel.verticesZ = new Array(rsModel.vertexCount);
rsModel.faceIndicesA = new Uint16Array(rsModel.faceCount);
rsModel.faceIndicesB = new Uint16Array(rsModel.faceCount);
rsModel.faceIndicesC = new Uint16Array(rsModel.faceCount);
if (rsModel.texturedFaceCount > 0) {
rsModel.texturedFaceTypes = new Uint8Array(rsModel.texturedFaceCount);
rsModel.texturedFaceIndicesA = new Uint16Array(rsModel.texturedFaceCount);
rsModel.texturedFaceIndicesB = new Uint16Array(rsModel.texturedFaceCount);
rsModel.texturedFaceIndicesC = new Uint16Array(rsModel.texturedFaceCount);
}
if (hasVertexSkins === 1) {
rsModel.vertexSkins = new Array(rsModel.texturedFaceCount);
}
if (hasFaceTypes === 1) {
rsModel.faceTypes = new Uint32Array(rsModel.faceCount);
rsModel.texturedFaceTypeIndices = new Int8Array(rsModel.faceCount);
rsModel.faceTextures = new Int8Array(rsModel.faceCount);
}
if (modelPriority === 255) {
rsModel.facePriorities = new Uint8Array(rsModel.faceCount);
}
else {
rsModel.facePriority = modelPriority & 128;
}
if (hasFaceAlphas === 1) {
rsModel.faceAlphas = new Uint8Array(rsModel.faceCount);
}
if (hasFaceSkins === 1) {
rsModel.faceSkins = new Array(rsModel.faceCount);
}
rsModel.faceColors = new Uint32Array(rsModel.faceCount);
vertexDirectionOffsetBuffer.readerIndex = vertexFlagsOffset;
xDataOffsetBuffer.readerIndex = verticesXOffset;
yDataOffsetBuffer.readerIndex = verticesYOffset;
zDataOffsetBuffer.readerIndex = verticesZOffset;
vertexSkinOffsetBuffer.readerIndex = vertexSkinsOffset;
let baseOffsetX = 0;
let baseOffsetY = 0;
let baseOffsetZ = 0;
for (let i = 0; i < rsModel.vertexCount; i++) {
const mask = vertexDirectionOffsetBuffer.get('BYTE', 'UNSIGNED');
let xOffset = 0;
if ((mask & 0x1) !== 0) {
try {
xOffset = xDataOffsetBuffer.get('SMART_SHORT', 'UNSIGNED');
}
catch {
common_1.logger.warn('Tried to read out of range xOffset for object', id);
}
}
let yOffset = 0;
if ((mask & 0x2) !== 0) {
try {
yOffset = yDataOffsetBuffer.get('SMART_SHORT', 'UNSIGNED');
}
catch {
common_1.logger.warn('Tried to read out of range yOffset for object', id);
}
}
let zOffset = 0;
if ((mask & 0x4) !== 0) {
try {
zOffset = zDataOffsetBuffer.get('SMART_SHORT', 'UNSIGNED');
}
catch {
common_1.logger.warn('Tried to read out of range zOffset for object', id);
}
}
rsModel.verticesX[i] = baseOffsetX + xOffset;
rsModel.verticesY[i] = baseOffsetY + yOffset;
rsModel.verticesZ[i] = baseOffsetZ + zOffset;
baseOffsetX = rsModel.verticesX[i];
baseOffsetY = rsModel.verticesY[i];
baseOffsetZ = rsModel.verticesZ[i];
if (hasVertexSkins === 1) {
rsModel.vertexSkins[i] = vertexSkinOffsetBuffer.get('BYTE', 'UNSIGNED');
}
}
vertexDirectionOffsetBuffer.readerIndex = faceColorsOffset;
xDataOffsetBuffer.readerIndex = faceTypesOffset;
yDataOffsetBuffer.readerIndex = facePrioritiesOffset;
zDataOffsetBuffer.readerIndex = faceAlphasOffset;
vertexSkinOffsetBuffer.readerIndex = faceSkinsOffset;
for (let i = 0; i < rsModel.faceCount; i++) {
rsModel.faceColors[i] = vertexDirectionOffsetBuffer.get('SHORT', 'UNSIGNED');
if (hasFaceTypes === 1) {
const mask = xDataOffsetBuffer.get('BYTE', 'UNSIGNED');
if ((mask & 0x1) === 1) {
rsModel.faceTypes[i] = 1;
useFaceTypes = true;
}
else {
rsModel.faceTypes[i] = 0;
}
if ((mask & 0x2) === 2) {
rsModel.texturedFaceTypeIndices[i] = mask >> 2;
rsModel.faceTextures[i] = rsModel.faceColors[i];
rsModel.faceColors[i] = 127;
if (rsModel.faceTextures[i] !== -1) {
useFaceTextures = true;
}
}
else {
rsModel.texturedFaceTypeIndices[i] = -1;
rsModel.faceTextures[i] = -1;
}
}
if (modelPriority === 255) {
rsModel.facePriorities[i] = yDataOffsetBuffer.get('BYTE', 'UNSIGNED');
}
if (hasFaceAlphas === 1) {
rsModel.faceAlphas[i] = zDataOffsetBuffer.get('BYTE', 'UNSIGNED');
}
if (hasFaceSkins === 1) {
rsModel.faceSkins[i] = vertexSkinOffsetBuffer.get('BYTE', 'UNSIGNED');
}
}
vertexDirectionOffsetBuffer.readerIndex = faceIndicesOffset;
xDataOffsetBuffer.readerIndex = facesCompressTypeOffset;
let lastA = 0;
let lastB = 0;
let lastC = 0;
let accumulator = 0;
let oldTrianglePointOffsetX;
for (let i = 0; i < rsModel.faceCount; i++) {
const type = xDataOffsetBuffer.get('BYTE', 'UNSIGNED');
switch (type) {
case 1:
lastA =
vertexDirectionOffsetBuffer.get('SMART_SHORT', 'UNSIGNED') + accumulator;
accumulator = lastA;
lastB =
vertexDirectionOffsetBuffer.get('SMART_SHORT', 'UNSIGNED') + accumulator;
accumulator = lastB;
lastC =
vertexDirectionOffsetBuffer.get('SMART_SHORT', 'UNSIGNED') + accumulator;
accumulator = lastC;
rsModel.faceIndicesA[i] = lastA;
rsModel.faceIndicesB[i] = lastB;
rsModel.faceIndicesC[i] = lastC;
break;
case 2:
lastB = lastC;
lastC =
vertexDirectionOffsetBuffer.get('SMART_SHORT', 'UNSIGNED') + accumulator;
accumulator = lastC;
rsModel.faceIndicesA[i] = lastA;
rsModel.faceIndicesB[i] = lastB;
rsModel.faceIndicesC[i] = lastC;
break;
case 3:
lastA = lastC;
lastC =
vertexDirectionOffsetBuffer.get('SMART_SHORT', 'UNSIGNED') + accumulator;
accumulator = lastC;
rsModel.faceIndicesA[i] = lastA;
rsModel.faceIndicesB[i] = lastB;
rsModel.faceIndicesC[i] = lastC;
break;
case 4:
oldTrianglePointOffsetX = lastA;
lastA = lastB;
lastB = oldTrianglePointOffsetX;
lastC =
vertexDirectionOffsetBuffer.get('SMART_SHORT', 'UNSIGNED') + accumulator;
accumulator = lastC;
rsModel.faceIndicesA[i] = lastA;
rsModel.faceIndicesB[i] = lastB;
rsModel.faceIndicesC[i] = lastC;
break;
}
}
vertexDirectionOffsetBuffer.readerIndex = faceMappingsOffset;
for (let i = 0; i < rsModel.texturedFaceCount; i++) {
rsModel.texturedFaceIndicesA[i] = vertexDirectionOffsetBuffer.get('SHORT', 'UNSIGNED');
rsModel.texturedFaceIndicesB[i] = vertexDirectionOffsetBuffer.get('SHORT', 'UNSIGNED');
rsModel.texturedFaceIndicesC[i] = vertexDirectionOffsetBuffer.get('SHORT', 'UNSIGNED');
}
if (rsModel.texturedFaceTypeIndices != null) {
let useTexturedFaceTypeIndices = false;
for (let face = 0; face < rsModel.faceCount; face++) {
const texturedFaceTypeIndex = rsModel.texturedFaceTypeIndices[face] & 0xff;
if (texturedFaceTypeIndex !== 255) {
if ((rsModel.texturedFaceIndicesA[texturedFaceTypeIndex] &
0xffff) ===
rsModel.faceIndicesA[face] &&
(rsModel.texturedFaceIndicesB[texturedFaceTypeIndex] &
0xffff) ===
rsModel.faceIndicesB[face] &&
(rsModel.texturedFaceIndicesC[texturedFaceTypeIndex] &
0xffff) ===
rsModel.faceIndicesC[face]) {
rsModel.texturedFaceTypeIndices[face] = -1;
}
else {
useTexturedFaceTypeIndices = true;
}
}
}
if (!useTexturedFaceTypeIndices) {
rsModel.texturedFaceTypeIndices = null;
}
}
if (!useFaceTextures) {
rsModel.faceTextures = null;
}
if (!useFaceTypes) {
rsModel.faceTypes = null;
}
return rsModel;
}
}
exports.ModelStore = ModelStore;