- Add grabObject, deGrabObject, dragGrabbedObject, touchObject to RegionCommands (closes #8)
- Properly decode object TextureEntry - Properly decode object ParticleSystem - Properly decode object ObjectData - Properly decode object TextColor - Properly decode Linden Tree species - Correct handling of ObjectUpdateCached (only request objects if we don't already have them) - Implement handling of ImprovedTerseObjectUpdate to complete support for R-Tree object searching - Object store interface: getObjectByUUID, getObjectByLocalID
This commit is contained in:
362
lib/classes/TextureEntry.ts
Normal file
362
lib/classes/TextureEntry.ts
Normal file
@@ -0,0 +1,362 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user