You've already forked Nitro_Render_V3
mirror of
https://github.com/duckietm/Nitro_Render_V3.git
synced 2026-06-20 07:26:18 +00:00
Move to Renderer V2
This commit is contained in:
@@ -0,0 +1,287 @@
|
||||
import { IAvatarImage } from '@nitrots/api';
|
||||
import { Vector3d } from '@nitrots/utils';
|
||||
import { Matrix4x4 } from '@nitrots/utils/src/Matrix4x4';
|
||||
import { AvatarCanvas } from '../structure';
|
||||
import { AvatarSet } from './AvatarSet';
|
||||
import { GeometryBodyPart } from './GeometryBodyPart';
|
||||
|
||||
export class AvatarModelGeometry
|
||||
{
|
||||
private _camera: Vector3d;
|
||||
private _avatarSet: AvatarSet;
|
||||
private _geometryTypes: Map<string, Map<string, GeometryBodyPart>>;
|
||||
private _itemIdToBodyPartMap: Map<string, Map<string, GeometryBodyPart>>;
|
||||
private _transformation: Matrix4x4;
|
||||
private _canvases: Map<string, Map<string, AvatarCanvas>>;
|
||||
|
||||
constructor(k: any)
|
||||
{
|
||||
this._camera = new Vector3d(0, 0, 10);
|
||||
this._avatarSet = new AvatarSet(k.avatarSets[0]);
|
||||
this._geometryTypes = new Map();
|
||||
this._itemIdToBodyPartMap = new Map();
|
||||
this._transformation = new Matrix4x4();
|
||||
this._canvases = new Map();
|
||||
|
||||
const camera = k.camera;
|
||||
|
||||
if(camera)
|
||||
{
|
||||
this._camera.x = parseFloat(camera.x);
|
||||
this._camera.y = parseFloat(camera.y);
|
||||
this._camera.z = parseFloat(camera.z);
|
||||
}
|
||||
|
||||
if(k.canvases && (k.canvases.length > 0))
|
||||
{
|
||||
for(const canvas of k.canvases)
|
||||
{
|
||||
if(!canvas) continue;
|
||||
|
||||
const scale = canvas.scale;
|
||||
const geometries = new Map();
|
||||
|
||||
if(canvas.geometries && (canvas.geometries.length > 0))
|
||||
{
|
||||
for(const geometry of canvas.geometries)
|
||||
{
|
||||
if(!geometry) continue;
|
||||
|
||||
const avatarCanvas = new AvatarCanvas(geometry, scale);
|
||||
|
||||
geometries.set(avatarCanvas.id, avatarCanvas);
|
||||
}
|
||||
}
|
||||
|
||||
this._canvases.set(scale, geometries);
|
||||
}
|
||||
}
|
||||
|
||||
if(k.types && (k.types.length > 0))
|
||||
{
|
||||
for(const type of k.types)
|
||||
{
|
||||
if(!type) continue;
|
||||
|
||||
const bodyParts: Map<string, GeometryBodyPart> = new Map();
|
||||
const itemIds: Map<string, GeometryBodyPart> = new Map();
|
||||
|
||||
if(type.bodyParts && (type.bodyParts.length > 0))
|
||||
{
|
||||
for(const bodyPart of type.bodyParts)
|
||||
{
|
||||
if(!bodyPart) continue;
|
||||
|
||||
const geometryBodyPart = new GeometryBodyPart(bodyPart);
|
||||
|
||||
bodyParts.set(geometryBodyPart.id, geometryBodyPart);
|
||||
|
||||
for(const part of geometryBodyPart.getPartIds(null))
|
||||
{
|
||||
itemIds.set(part, geometryBodyPart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._geometryTypes.set(type.id, bodyParts);
|
||||
this._itemIdToBodyPartMap.set(type.id, itemIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public removeDynamicItems(k: IAvatarImage): void
|
||||
{
|
||||
for(const geometry of this._geometryTypes.values())
|
||||
{
|
||||
if(!geometry) continue;
|
||||
|
||||
for(const part of geometry.values())
|
||||
{
|
||||
if(!part) continue;
|
||||
|
||||
part.removeDynamicParts(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getBodyPartIdsInAvatarSet(k: string): string[]
|
||||
{
|
||||
const avatarSet = this._avatarSet.findAvatarSet(k);
|
||||
|
||||
if(!avatarSet) return [];
|
||||
|
||||
return avatarSet.getBodyParts();
|
||||
}
|
||||
|
||||
public isMainAvatarSet(k: string): boolean
|
||||
{
|
||||
const avatarSet = this._avatarSet.findAvatarSet(k);
|
||||
|
||||
if(!avatarSet) return false;
|
||||
|
||||
return avatarSet.isMain;
|
||||
}
|
||||
|
||||
public getCanvas(k: string, _arg_2: string): AvatarCanvas
|
||||
{
|
||||
const canvas = this._canvases.get(k);
|
||||
|
||||
if(!canvas) return null;
|
||||
|
||||
return (canvas.get(_arg_2) || null);
|
||||
}
|
||||
|
||||
private typeExists(k: string): boolean
|
||||
{
|
||||
const existing = this._geometryTypes.get(k);
|
||||
|
||||
if(existing) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private hasBodyPart(k: string, _arg_2: string): boolean
|
||||
{
|
||||
if(this.typeExists(k))
|
||||
{
|
||||
const existing = this._geometryTypes.get(k);
|
||||
|
||||
if(existing && existing.get(_arg_2)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private getBodyPartIDs(k: string): string[]
|
||||
{
|
||||
const parts = this.getBodyPartsOfType(k);
|
||||
|
||||
const types = [];
|
||||
|
||||
if(parts)
|
||||
{
|
||||
for(const part of parts.values())
|
||||
{
|
||||
if(!part) continue;
|
||||
|
||||
types.push(part.id);
|
||||
}
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
private getBodyPartsOfType(k: string): Map<string, GeometryBodyPart>
|
||||
{
|
||||
if(this.typeExists(k)) return this._geometryTypes.get(k);
|
||||
|
||||
return new Map();
|
||||
}
|
||||
|
||||
public getBodyPart(k: string, _arg_2: string): GeometryBodyPart
|
||||
{
|
||||
return (this.getBodyPartsOfType(k).get(_arg_2) || null);
|
||||
}
|
||||
|
||||
public getBodyPartOfItem(k: string, _arg_2: string, _arg_3: IAvatarImage): GeometryBodyPart
|
||||
{
|
||||
const itemIds = this._itemIdToBodyPartMap.get(k);
|
||||
|
||||
if(itemIds)
|
||||
{
|
||||
const part = itemIds.get(_arg_2);
|
||||
|
||||
if(part) return part;
|
||||
|
||||
const parts = this.getBodyPartsOfType(k);
|
||||
|
||||
if(parts)
|
||||
{
|
||||
for(const part of parts.values())
|
||||
{
|
||||
if(!part) continue;
|
||||
|
||||
if(part.hasPart(_arg_2, _arg_3)) return part;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private getBodyPartsInAvatarSet(k: Map<string, GeometryBodyPart>, _arg_2: string): GeometryBodyPart[]
|
||||
{
|
||||
const parts = this.getBodyPartIdsInAvatarSet(_arg_2);
|
||||
const geometryParts = [];
|
||||
|
||||
for(const part of parts)
|
||||
{
|
||||
if(!part) continue;
|
||||
|
||||
const bodyPart = k.get(part);
|
||||
|
||||
if(bodyPart)
|
||||
{
|
||||
geometryParts.push(bodyPart);
|
||||
}
|
||||
}
|
||||
|
||||
return geometryParts;
|
||||
}
|
||||
|
||||
public getBodyPartsAtAngle(k: string, _arg_2: number, _arg_3: string): string[]
|
||||
{
|
||||
if(!_arg_3) return [];
|
||||
|
||||
const geometryParts = this.getBodyPartsOfType(_arg_3);
|
||||
const parts = this.getBodyPartsInAvatarSet(geometryParts, k);
|
||||
const sets: [number, GeometryBodyPart][] = [];
|
||||
const ids: string[] = [];
|
||||
|
||||
this._transformation = Matrix4x4.getYRotationMatrix(_arg_2);
|
||||
|
||||
for(const part of parts.values())
|
||||
{
|
||||
if(!part) continue;
|
||||
|
||||
part.applyTransform(this._transformation);
|
||||
|
||||
sets.push([part.getDistance(this._camera), part]);
|
||||
}
|
||||
|
||||
sets.sort((a, b) =>
|
||||
{
|
||||
const partA = a[0];
|
||||
const partB = b[0];
|
||||
|
||||
if(partA < partB) return -1;
|
||||
|
||||
if(partA > partB) return 1;
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
for(const set of sets)
|
||||
{
|
||||
if(!set) continue;
|
||||
|
||||
ids.push(set[1].id);
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
public getParts(k: string, _arg_2: string, _arg_3: number, _arg_4: any[], _arg_5: IAvatarImage): string[]
|
||||
{
|
||||
if(this.hasBodyPart(k, _arg_2))
|
||||
{
|
||||
const part = this.getBodyPartsOfType(k).get(_arg_2);
|
||||
|
||||
this._transformation = Matrix4x4.getYRotationMatrix(_arg_3);
|
||||
|
||||
return part.getParts(this._transformation, this._camera, _arg_4, _arg_5);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
export class AvatarSet
|
||||
{
|
||||
private _id: string;
|
||||
private _isMain: boolean;
|
||||
private _avatarSets: Map<string, AvatarSet>;
|
||||
private _bodyParts: string[];
|
||||
private _allBodyParts: string[];
|
||||
|
||||
constructor(k: any)
|
||||
{
|
||||
this._id = k.id;
|
||||
this._isMain = k.main || false;
|
||||
this._avatarSets = new Map();
|
||||
this._bodyParts = [];
|
||||
this._allBodyParts = [];
|
||||
|
||||
if(k.avatarSets && (k.avatarSets.length > 0))
|
||||
{
|
||||
for(const avatarSet of k.avatarSets)
|
||||
{
|
||||
if(!avatarSet) continue;
|
||||
|
||||
const set = new AvatarSet(avatarSet);
|
||||
|
||||
this._avatarSets.set(set.id, set);
|
||||
}
|
||||
}
|
||||
|
||||
if(k.bodyParts && (k.bodyParts.length > 0))
|
||||
{
|
||||
for(const bodyPart of k.bodyParts)
|
||||
{
|
||||
if(!bodyPart) continue;
|
||||
|
||||
this._bodyParts.push(bodyPart.id);
|
||||
}
|
||||
}
|
||||
|
||||
let bodyParts = this._bodyParts.concat();
|
||||
|
||||
for(const avatarSet of this._avatarSets.values())
|
||||
{
|
||||
if(!avatarSet) continue;
|
||||
|
||||
bodyParts = bodyParts.concat(avatarSet.getBodyParts());
|
||||
}
|
||||
|
||||
this._allBodyParts = bodyParts;
|
||||
}
|
||||
|
||||
public findAvatarSet(k: string): AvatarSet
|
||||
{
|
||||
if(k === this._id) return this;
|
||||
|
||||
for(const avatarSet of this._avatarSets.values())
|
||||
{
|
||||
if(!avatarSet) continue;
|
||||
|
||||
if(!avatarSet.findAvatarSet(k)) continue;
|
||||
|
||||
return avatarSet;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public getBodyParts(): string[]
|
||||
{
|
||||
return this._allBodyParts.concat();
|
||||
}
|
||||
|
||||
public get id(): string
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get isMain(): boolean
|
||||
{
|
||||
if(this._isMain) return true;
|
||||
|
||||
for(const avatarSet of this._avatarSets.values())
|
||||
{
|
||||
if(!avatarSet) continue;
|
||||
|
||||
if(!avatarSet.isMain) continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
import { IAvatarImage } from '@nitrots/api';
|
||||
import { Matrix4x4, Node3D, Vector3d } from '@nitrots/utils';
|
||||
import { GeometryItem } from './GeometryItem';
|
||||
|
||||
export class GeometryBodyPart extends Node3D
|
||||
{
|
||||
private _id: string;
|
||||
private _radius: number;
|
||||
private _parts: Map<string, GeometryItem>;
|
||||
private _dynamicParts: Map<IAvatarImage, { [index: string]: GeometryItem }>;
|
||||
|
||||
constructor(k: any)
|
||||
{
|
||||
super(parseFloat(k.x), parseFloat(k.y), parseFloat(k.z));
|
||||
|
||||
this._id = k.id;
|
||||
this._radius = parseFloat(k.radius);
|
||||
this._parts = new Map();
|
||||
this._dynamicParts = new Map();
|
||||
|
||||
if(k.items && (k.items.length > 0))
|
||||
{
|
||||
for(const item of k.items)
|
||||
{
|
||||
if(!item) continue;
|
||||
|
||||
const geometryItem = new GeometryItem(item);
|
||||
|
||||
this._parts.set(geometryItem.id, geometryItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getDynamicParts(k: IAvatarImage): GeometryItem[]
|
||||
{
|
||||
const existing = this._dynamicParts.get(k);
|
||||
const parts: GeometryItem[] = [];
|
||||
|
||||
if(existing)
|
||||
{
|
||||
for(const index in existing)
|
||||
{
|
||||
const item = existing[index];
|
||||
|
||||
if(!item) continue;
|
||||
|
||||
parts.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
public getPartIds(k: IAvatarImage): string[]
|
||||
{
|
||||
const ids: string[] = [];
|
||||
|
||||
for(const part of this._parts.values())
|
||||
{
|
||||
if(!part) continue;
|
||||
|
||||
ids.push(part.id);
|
||||
}
|
||||
|
||||
if(k)
|
||||
{
|
||||
const existing = this._dynamicParts.get(k);
|
||||
|
||||
if(existing)
|
||||
{
|
||||
for(const index in existing)
|
||||
{
|
||||
const part = existing[index];
|
||||
|
||||
if(!part) continue;
|
||||
|
||||
ids.push(part.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
public removeDynamicParts(k: IAvatarImage): boolean
|
||||
{
|
||||
this._dynamicParts.delete(k);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public addPart(k: any, _arg_2: IAvatarImage): boolean
|
||||
{
|
||||
if(this.hasPart(k.id, _arg_2)) return false;
|
||||
|
||||
let existing = this._dynamicParts.get(_arg_2);
|
||||
|
||||
if(!existing)
|
||||
{
|
||||
existing = {};
|
||||
|
||||
this._dynamicParts.set(_arg_2, existing);
|
||||
}
|
||||
|
||||
existing[k.id] = new GeometryItem(k, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public hasPart(k: string, _arg_2: IAvatarImage): boolean
|
||||
{
|
||||
let existingPart = (this._parts.get(k) || null);
|
||||
|
||||
if(!existingPart && (this._dynamicParts.get(_arg_2) !== undefined))
|
||||
{
|
||||
existingPart = (this._dynamicParts.get(_arg_2)[k] || null);
|
||||
}
|
||||
|
||||
return (existingPart !== null);
|
||||
}
|
||||
|
||||
public getParts(k: Matrix4x4, _arg_2: Vector3d, _arg_3: any[], _arg_4: IAvatarImage): string[]
|
||||
{
|
||||
const parts: [number, GeometryItem][] = [];
|
||||
|
||||
for(const part of this._parts.values())
|
||||
{
|
||||
if(!part) continue;
|
||||
|
||||
part.applyTransform(k);
|
||||
|
||||
parts.push([part.getDistance(_arg_2), part]);
|
||||
}
|
||||
|
||||
const existingDynamic = this._dynamicParts.get(_arg_4);
|
||||
|
||||
if(existingDynamic)
|
||||
{
|
||||
for(const index in existingDynamic)
|
||||
{
|
||||
const part = existingDynamic[index];
|
||||
|
||||
if(!part) continue;
|
||||
|
||||
part.applyTransform(k);
|
||||
|
||||
parts.push([part.getDistance(_arg_2), part]);
|
||||
}
|
||||
}
|
||||
|
||||
parts.sort((a, b) =>
|
||||
{
|
||||
const partA = a[0];
|
||||
const partB = b[0];
|
||||
|
||||
if(partA < partB) return -1;
|
||||
|
||||
if(partA > partB) return 1;
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
const partIds: string[] = [];
|
||||
|
||||
for(const part of parts)
|
||||
{
|
||||
if(!part) continue;
|
||||
|
||||
partIds.push(part[1].id);
|
||||
}
|
||||
|
||||
return partIds;
|
||||
}
|
||||
|
||||
public getDistance(k: Vector3d): number
|
||||
{
|
||||
const _local_2 = Math.abs(((k.z - this.transformedLocation.z) - this._radius));
|
||||
const _local_3 = Math.abs(((k.z - this.transformedLocation.z) + this._radius));
|
||||
|
||||
return Math.min(_local_2, _local_3);
|
||||
}
|
||||
|
||||
public get id(): string
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get radius(): number
|
||||
{
|
||||
return this._radius;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Node3D, Vector3d } from '@nitrots/utils';
|
||||
|
||||
export class GeometryItem extends Node3D
|
||||
{
|
||||
private _id: string;
|
||||
private _radius: number;
|
||||
private _normal: Vector3d;
|
||||
private _isDoubleSided: boolean;
|
||||
private _isDynamic: boolean;
|
||||
|
||||
constructor(k: any, _arg_2: boolean = false)
|
||||
{
|
||||
super(parseFloat(k.x), parseFloat(k.y), parseFloat(k.z));
|
||||
|
||||
this._id = k.id;
|
||||
this._radius = parseFloat(k.radius);
|
||||
this._normal = new Vector3d(parseFloat(k.nx), parseFloat(k.ny), parseFloat(k.nz));
|
||||
this._isDoubleSided = k.double || false;
|
||||
this._isDynamic = _arg_2;
|
||||
}
|
||||
|
||||
public getDistance(k: Vector3d): number
|
||||
{
|
||||
const _local_2 = Math.abs(((k.z - this.transformedLocation.z) - this._radius));
|
||||
const _local_3 = Math.abs(((k.z - this.transformedLocation.z) + this._radius));
|
||||
|
||||
return Math.min(_local_2, _local_3);
|
||||
}
|
||||
|
||||
public get id(): string
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get normal(): Vector3d
|
||||
{
|
||||
return this._normal;
|
||||
}
|
||||
|
||||
public get isDoubleSided(): boolean
|
||||
{
|
||||
return this._isDoubleSided;
|
||||
}
|
||||
|
||||
public toString(): string
|
||||
{
|
||||
return ((((this._id + ': ') + this.location) + ' - ') + this.transformedLocation);
|
||||
}
|
||||
|
||||
public get isDynamic(): boolean
|
||||
{
|
||||
return this._isDynamic;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from './AvatarModelGeometry';
|
||||
export * from './AvatarSet';
|
||||
export * from './GeometryBodyPart';
|
||||
export * from './GeometryItem';
|
||||
Reference in New Issue
Block a user