Implement GLTF overrides

This commit is contained in:
Casper Warden
2023-11-10 23:57:26 +00:00
parent 3c69b8f05e
commit cb77865537
10 changed files with 1034 additions and 354 deletions

View File

@@ -55,6 +55,7 @@ import { Subject } from 'rxjs';
import { RezScriptMessage } from '../messages/RezScript';
import { PermissionMask } from '../../enums/PermissionMask';
import { AssetType } from '../../enums/AssetType';
import { LLGLTFMaterialOverride, LLGLTFTextureTransformOverride } from '../LLGLTFMaterialOverride';
import * as uuid from 'uuid';
@@ -380,6 +381,125 @@ export class GameObject implements IGameObjectData
const buf = Buffer.from(prop, 'base64');
go.TextureEntry = TextureEntry.from(buf);
}
if (go.TextureEntry && shape['GLTFMaterialOverrides'] && Array.isArray(shape['GLTFMaterialOverrides']) && shape['GLTFMaterialOverrides'].length > 0)
{
const te = go.TextureEntry;
te.gltfMaterialOverrides = new Map<number, LLGLTFMaterialOverride>();
const children = shape['GLTFMaterialOverrides'][0];
const childObj = children['GLTFMaterialOverride'];
if (childObj)
{
for (const entry of childObj)
{
const override = new LLGLTFMaterialOverride();
let textureEntry = 0;
if ((prop = Utils.getFromXMLJS(entry, 'TextureEntry')) !== undefined)
{
textureEntry = prop;
}
else
{
continue;
}
if ((prop = Utils.getFromXMLJS(entry, 'DoubleSided')) !== undefined)
{
override.doubleSided = prop;
}
if ((prop = Utils.getFromXMLJS(entry, 'AlphaCutoff')) !== undefined)
{
override.alphaCutoff = parseFloat(prop);
}
if ((prop = Utils.getFromXMLJS(entry, 'RoughnessFactor')) !== undefined)
{
override.roughnessFactor = parseFloat(prop);
}
if ((prop = Utils.getFromXMLJS(entry, 'MetallicFactor')) !== undefined)
{
override.metallicFactor = parseFloat(prop);
}
if ((prop = Utils.getFromXMLJS(entry, 'AlphaMode')) !== undefined)
{
override.alphaMode = prop;
}
if (entry['Textures'] && Array.isArray(entry['Textures']) && entry['Textures'].length > 0)
{
override.textures = [];
const childArr = entry['Textures'][0];
for (const tex of childArr['UUID'])
{
override.textures.push(tex);
}
}
if (entry['EmissiveColor'] && Array.isArray(entry['EmissiveColor']) && entry['EmissiveColor'].length > 0)
{
const childArr = entry['EmissiveColor'][0];
const red = parseFloat(childArr['R'][0]);
const green = parseFloat(childArr['G'][0]);
const blue = parseFloat(childArr['B'][0]);
override.emissiveColor = [
red,
green,
blue
];
}
if (entry['BaseColor'] && Array.isArray(entry['BaseColor']) && entry['BaseColor'].length > 0)
{
const childArr = entry['BaseColor'][0];
const red = parseFloat(childArr['R'][0]);
const green = parseFloat(childArr['G'][0]);
const blue = parseFloat(childArr['B'][0]);
const alpha = parseFloat(childArr['A'][0]);
override.baseColor = [
red,
green,
blue,
alpha
];
}
if (entry['TextureTransforms'] && Array.isArray(entry['TextureTransforms']) && entry['TextureTransforms'].length > 0)
{
const childArr = entry['TextureTransforms'][0];
override.textureTransforms = [];
for (const tex of childArr['Transform'])
{
const t: LLGLTFTextureTransformOverride = {
offset: [],
scale: [],
rotation: 0,
};
if ((prop = Utils.getFromXMLJS(tex, 'Rotation')) !== undefined)
{
t.rotation = parseFloat(prop);
}
if (tex['Offsets'] && Array.isArray(tex['Offsets']) && tex['Offsets'].length > 0)
{
const offsetArr = tex['Offsets'][0];
const xOffset = parseFloat(offsetArr['X'][0]);
const yOffset = parseFloat(offsetArr['Y'][0]);
t.offset = [
xOffset,
yOffset
];
}
if (tex['Scale'] && Array.isArray(tex['Scale']) && tex['Scale'].length > 0)
{
const offsetArr = tex['Scale'][0];
const xOffset = parseFloat(offsetArr['X'][0]);
const yOffset = parseFloat(offsetArr['Y'][0]);
t.scale = [
xOffset,
yOffset
];
}
override.textureTransforms.push(t);
}
}
te.gltfMaterialOverrides.set(textureEntry, override);
}
}
}
if ((prop = Utils.getFromXMLJS(shape, 'PathBegin')) !== undefined)
{
go.PathBegin = Utils.unpackBeginCut(prop);
@@ -1484,7 +1604,7 @@ export class GameObject implements IGameObjectData
private async getXML(xml: XMLNode, rootPrim: GameObject, linkNum: number, rootNode?: string): Promise<void>
{
if (this.resolvedAt === undefined || this.resolvedAt === 0 || this.resolvedInventory === false)
if ((this.resolvedAt === undefined || this.resolvedAt === 0 || !this.resolvedInventory) && this.region?.resolver)
{
await this.region.resolver.resolveObjects([this], true, false, false);
}
@@ -1502,7 +1622,10 @@ export class GameObject implements IGameObjectData
sceneObjectPart.ele('LocalId', this.ID);
sceneObjectPart.ele('Name', this.name);
sceneObjectPart.ele('Material', this.Material);
sceneObjectPart.ele('RegionHandle', this.region.regionHandle.toString());
if (this.region)
{
sceneObjectPart.ele('RegionHandle', this.region.regionHandle.toString());
}
Vector3.getXML(sceneObjectPart.ele('GroupPosition'), rootPrim.Position);
if (rootPrim === this)
{
@@ -1535,6 +1658,80 @@ export class GameObject implements IGameObjectData
if (this.TextureEntry)
{
shape.ele('TextureEntry', this.TextureEntry.toBase64());
if (this.TextureEntry.gltfMaterialOverrides)
{
const overrides = shape.ele('GLTFMaterialOverrides');
for (const te of this.TextureEntry.gltfMaterialOverrides.keys())
{
const entry = overrides.ele('GLTFMaterialOverride');
entry.ele('TextureEntry', te);
const override = this.TextureEntry.gltfMaterialOverrides.get(te);
if (override)
{
if (override.doubleSided !== undefined)
{
entry.ele('DoubleSided', override.doubleSided);
}
if (override.alphaCutoff !== undefined)
{
entry.ele('AlphaCutoff', override.alphaCutoff);
}
if (override.roughnessFactor !== undefined)
{
entry.ele('RoughnessFactor', override.roughnessFactor);
}
if (override.metallicFactor !== undefined)
{
entry.ele('MetallicFactor', override.metallicFactor);
}
if (override.alphaMode !== undefined)
{
entry.ele('AlphaMode', override.alphaMode);
}
if (override.textures !== undefined)
{
const texs = entry.ele('Textures');
for (const tex of override.textures)
{
texs.ele('UUID', tex);
}
}
if (override.emissiveColor !== undefined && override.emissiveColor.length === 3)
{
const emissive = entry.ele('EmissiveColor');
emissive.ele('R', override.emissiveColor[0]);
emissive.ele('G', override.emissiveColor[1]);
emissive.ele('B', override.emissiveColor[2]);
}
if (override.baseColor !== undefined && override.baseColor.length === 4)
{
const base = entry.ele('BaseColor');
base.ele('R', override.baseColor[0]);
base.ele('G', override.baseColor[1]);
base.ele('B', override.baseColor[2]);
base.ele('A', override.baseColor[3]);
}
if (override.textureTransforms && override.textureTransforms.length === 4)
{
const transforms = entry.ele('TextureTransforms');
for (const trans of override.textureTransforms)
{
const tfm = transforms.ele('Transform');
tfm.ele('Rotation', trans.rotation);
const offsets = tfm.ele('Offsets');
offsets.ele('X', trans.offset[0]);
offsets.ele('Y', trans.offset[1]);
const scale = tfm.ele('Scale');
scale.ele('X', trans.scale[0]);
scale.ele('Y', trans.scale[1]);
}
}
}
}
}
}
if (this.extraParams)
{