Files
node-metaverse/lib/classes/TextureEntry.ts

363 lines
12 KiB
TypeScript
Raw Normal View History

import {TextureEntryFace} from './TextureEntryFace';
import {UUID} from './UUID';
import {Color4} from './Color4';
import {Utils} from './Utils';
export class TextureEntry
{
defaultTexture: TextureEntryFace | null;
faces: TextureEntryFace[] = [];
static readFaceBitfield(buf: Buffer, pos: number): {
result: boolean,
pos: number,
faceBits: number,
bitfieldSize: number
}
{
const result = {
result: false,
pos: pos,
faceBits: 0,
bitfieldSize: 0
};
if (result.pos >= buf.length)
{
return result;
}
let b = 0;
do
{
b = buf.readUInt8(result.pos);
result.faceBits = (result.faceBits << 7) | (b & 0x7F);
result.bitfieldSize += 7;
result.pos++;
}
while ((b & 0x80) !== 0);
result.result = (result.faceBits !== 0);
return result;
}
constructor(buf: Buffer)
{
if (buf.length < 16)
{
this.defaultTexture = null;
}
else
{
this.defaultTexture = new TextureEntryFace(null);
let pos = 0;
let i = pos;
// Texture
{
this.defaultTexture.textureID = new UUID(buf, i);
i += 16;
let done = false;
while (!done)
{
const result = TextureEntry.readFaceBitfield(buf, i);
done = !result.result;
i = result.pos;
if (!done)
{
const uuid = new UUID(buf, i);
i += 16;
for (let face = 0, bit = 1; face < result.bitfieldSize; face++, bit <<= 1)
{
if ((result.faceBits & bit) !== 0)
{
this.createFace(face);
this.faces[face].textureID = uuid;
}
}
}
}
}
// Colour
{
this.defaultTexture.rgba = new Color4(buf, i, true);
i += 4;
let done = false;
while (!done)
{
const result = TextureEntry.readFaceBitfield(buf, i);
done = !result.result;
i = result.pos;
if (!done)
{
const tmpColor = new Color4(buf, i, true);
i += 4;
for (let face = 0, bit = 1; face < result.bitfieldSize; face++, bit <<= 1)
{
if ((result.faceBits & bit) !== 0)
{
this.createFace(face);
this.faces[face].rgba = tmpColor;
}
}
}
}
}
// RepeatU
{
this.defaultTexture.repeatU = buf.readFloatLE(i);
i += 4;
let done = false;
while (!done)
{
const result = TextureEntry.readFaceBitfield(buf, i);
done = !result.result;
i = result.pos;
if (!done)
{
const tmpFloat = buf.readFloatLE(i);
i += 4;
for (let face = 0, bit = 1; face < result.bitfieldSize; face++, bit <<= 1)
{
if ((result.faceBits & bit) !== 0)
{
this.createFace(face);
this.faces[face].repeatU = tmpFloat;
}
}
}
}
}
// RepeatV
{
this.defaultTexture.repeatV = buf.readFloatLE(i);
i += 4;
let done = false;
while (!done)
{
const result = TextureEntry.readFaceBitfield(buf, i);
done = !result.result;
i = result.pos;
if (!done)
{
const tmpFloat = buf.readFloatLE(i);
i += 4;
for (let face = 0, bit = 1; face < result.bitfieldSize; face++, bit <<= 1)
{
if ((result.faceBits & bit) !== 0)
{
this.createFace(face);
this.faces[face].repeatV = tmpFloat;
}
}
}
}
}
// OffsetU
{
this.defaultTexture.offsetU = Utils.ReadOffsetFloat(buf, i);
i += 2;
let done = false;
while (!done)
{
const result = TextureEntry.readFaceBitfield(buf, i);
done = !result.result;
i = result.pos;
if (!done)
{
const tmpFloat = Utils.ReadOffsetFloat(buf, i);
i += 2;
for (let face = 0, bit = 1; face < result.bitfieldSize; face++, bit <<= 1)
{
if ((result.faceBits & bit) !== 0)
{
this.createFace(face);
this.faces[face].offsetU = tmpFloat;
}
}
}
}
}
// OffsetV
{
this.defaultTexture.offsetV = Utils.ReadOffsetFloat(buf, i);
i += 2;
let done = false;
while (!done)
{
const result = TextureEntry.readFaceBitfield(buf, i);
done = !result.result;
i = result.pos;
if (!done)
{
const tmpFloat = Utils.ReadOffsetFloat(buf, i);
i += 2;
for (let face = 0, bit = 1; face < result.bitfieldSize; face++, bit <<= 1)
{
if ((result.faceBits & bit) !== 0)
{
this.createFace(face);
this.faces[face].offsetV = tmpFloat;
}
}
}
}
}
// Rotation
{
this.defaultTexture.rotation = Utils.ReadRotationFloat(buf, i);
i += 2;
let done = false;
while (!done)
{
const result = TextureEntry.readFaceBitfield(buf, i);
done = !result.result;
i = result.pos;
if (!done)
{
const tmpFloat = Utils.ReadRotationFloat(buf, i);
i += 2;
for (let face = 0, bit = 1; face < result.bitfieldSize; face++, bit <<= 1)
{
if ((result.faceBits & bit) !== 0)
{
this.createFace(face);
this.faces[face].rotation = tmpFloat;
}
}
}
}
}
// Material
{
this.defaultTexture.materialb = buf[i++];
let done = false;
while (!done)
{
const result = TextureEntry.readFaceBitfield(buf, i);
done = !result.result;
i = result.pos;
if (!done)
{
const tmpByte = buf[i++];
for (let face = 0, bit = 1; face < result.bitfieldSize; face++, bit <<= 1)
{
if ((result.faceBits & bit) !== 0)
{
this.createFace(face);
this.faces[face].materialb = tmpByte;
}
}
}
}
}
// Media
{
this.defaultTexture.mediab = buf[i++];
let done = false;
while (i - pos < buf.length && !done)
{
const result = TextureEntry.readFaceBitfield(buf, i);
done = !result.result;
i = result.pos;
if (!done)
{
const tmpByte = buf[i++];
for (let face = 0, bit = 1; face < result.bitfieldSize; face++, bit <<= 1)
{
if ((result.faceBits & bit) !== 0)
{
this.createFace(face);
this.faces[face].mediab = tmpByte;
}
}
}
}
}
// Glow
{
this.defaultTexture.glow = Utils.ReadGlowFloat(buf, i++);
let done = false;
while (!done)
{
const result = TextureEntry.readFaceBitfield(buf, i);
done = !result.result;
i = result.pos;
if (!done)
{
const tmpFloat = Utils.ReadGlowFloat(buf, i++);
for (let face = 0, bit = 1; face < result.bitfieldSize; face++, bit <<= 1)
{
if ((result.faceBits & bit) !== 0)
{
this.createFace(face);
this.faces[face].glow = tmpFloat;
}
}
}
}
}
// MaterialID
{
const len = i - pos + 16;
if (i - pos + 16 <= buf.length)
{
this.defaultTexture.materialID = new UUID(buf, i);
i += 16;
let done = false;
while (i - pos + 16 <= buf.length && !done)
{
const result = TextureEntry.readFaceBitfield(buf, i);
done = !result.result;
i = result.pos;
if (!done)
{
const uuid = new UUID(buf, i);
i += 16;
for (let face = 0, bit = 1; face < result.bitfieldSize; face++, bit <<= 1)
{
if ((result.faceBits & bit) !== 0)
{
this.createFace(face);
this.faces[face].materialID = uuid;
}
}
}
}
}
}
}
}
private createFace(face: number)
{
if (face > 32)
{
console.error('Warning: Face number exceeds maximum number of faces: 32');
}
while (this.faces.length <= face)
{
this.faces.push(new TextureEntryFace(this.defaultTexture));
}
}
}