@awayjs/renderer
Version:
Renderer for AwayJS
372 lines (301 loc) • 9.83 kB
text/typescript
import { AbstractMethodError, Box, Sphere, Matrix3D, Vector3D, AssetBase, Rectangle, Matrix } from '@awayjs/core';
import { AttributesBuffer, AttributesView, Float3Attributes, Short3Attributes } from '@awayjs/stage';
import { View, PickingCollision, ContainerNode } from '@awayjs/view';
import { ElementsEvent } from '../events/ElementsEvent';
import { IElements } from '../base/IElements';
import { IHullImpl } from '../utils/ConvexHullUtils';
import { IMaterial } from '../base/IMaterial';
export type THullImplId = IHullImpl & {offset: number, count: number};
/**
* @class away.base.TriangleElements
*/
export class ElementsBase extends AssetBase implements IElements {
public isDynamic: boolean = false;
private _indices: Short3Attributes;
private _customAttributesNames: Array<string> = new Array<string>();
private _customAttributes: Object = new Object();
protected _useCondensedIndices: boolean;
protected _condensedIndexLookUp: Array<number>;
protected _autoDeriveNormals: boolean = true;
protected _autoDeriveTangents: boolean = true;
protected _convexHull: THullImplId;
protected _boundsRequests: number = 0;
public _numElements: number = 0;
public _numVertices: number = 0;
public _concatenatedBuffer: AttributesBuffer;
private _invalidateIndices: ElementsEvent;
public _verticesDirty: Object = new Object();
public _invalidateVertices: Object = new Object();
/**
* Original Bounds for 9Slice
*/
public originalScale9Bounds: Rectangle;
/**
* Scale constraints! Not a Recangle. x - left side, width - right side, y - top, height - bottom
*/
public scale9Grid: Rectangle;
/**
* Right index bound for vertices for scalable regions
* Lenght MUST BE A 9
*/
public scale9Indices: number[];
/**
* Initial position buffer, store only XY values
*/
public initialScale9Positions: ArrayLike<number>;
public usages: number = 0;
public get concatenatedBuffer(): AttributesBuffer {
return this._concatenatedBuffer;
}
/**
* The raw index data that define the faces.
*/
public get indices(): Short3Attributes {
return this._indices;
}
/**
*
*/
public getCustomAtributesNames(): Array<string> {
return this._customAttributesNames;
}
/**
*
*/
public getCustomAtributes(name: string): AttributesView {
return this._customAttributes[name];
}
/**
* The total amount of triangles in the TriangleElements.
*/
public get numElements(): number {
return this._numElements;
}
public get numVertices(): number {
return this._numVertices;
}
public get condensedIndexLookUp(): Array<number> {
return this._condensedIndexLookUp;
}
/**
* True if the vertex normals should be derived from the geometry, false if the vertex normals are set
* explicitly.
*/
public get autoDeriveNormals(): boolean {
return this._autoDeriveNormals;
}
public set autoDeriveNormals(value: boolean) {
if (this._autoDeriveNormals == value)
return;
this._autoDeriveNormals = value;
}
/**
* True if the vertex tangents should be derived from the geometry, false if the vertex normals are set
* explicitly.
*/
public get autoDeriveTangents(): boolean {
return this._autoDeriveTangents;
}
public set autoDeriveTangents(value: boolean) {
if (this._autoDeriveTangents == value)
return;
this._autoDeriveTangents = value;
}
/**
* Offers the option of enabling GPU accelerated animation on skeletons larger than 32 joints
* by condensing the number of joint index values required per sprite. Only applicable to
* skeleton animations that utilise more than one sprite object. Defaults to false.
*/
public get useCondensedIndices(): boolean {
return this._useCondensedIndices;
}
public set useCondensedIndices(value: boolean) {
if (this._useCondensedIndices == value)
return;
this._useCondensedIndices = value;
}
/**
*
*/
constructor(concatenatedBuffer: AttributesBuffer = null) {
super();
this._concatenatedBuffer = concatenatedBuffer;
}
public copyTo(elements: ElementsBase): void {
if (this.indices)
elements.setIndices(this.indices.clone());
for (const name in this._customAttributes)
elements.setCustomAttributes(name, this.getCustomAtributes(name).clone());
}
/**
*
*/
public dispose(): void {
this.clear();
this._boundsRequests = 0;
if (this._convexHull) {
this._convexHull.dispose();
this._convexHull = null;
}
if (this._indices) {
this._indices.dispose();
this._indices = null;
}
for (const name in this._customAttributes) {
this._customAttributes[name].dispose();
delete this._customAttributes;
}
}
/**
* Updates the face indices of the TriangleElements.
*
* @param indices The face indices to upload.
*/
public setIndices(array: Array<number>, offset?: number);
public setIndices(uint16Array: Uint16Array, offset?: number);
public setIndices(short3Attributes: Short3Attributes, offset?: number);
public setIndices(values: any, offset: number = 0): void {
if (values instanceof Short3Attributes) {
if (this._indices)
this.clearIndices();
this._indices = <Short3Attributes> values;
} else if (values) {
if (!this._indices)
this._indices = new Short3Attributes();
this._indices.set(values, offset);
} else if (this._indices) {
this._indices.dispose();
this._indices = null;
this.clearIndices();
}
if (this._indices) {
this._numElements = this._indices.count;
this.invalidateIndices();
} else {
this._numElements = 0;
}
}
/**
* Updates custom attributes.
*/
public setCustomAttributes(name: string, array: Array<number>, offset?: number);
public setCustomAttributes(name: string, arrayBufferView: ArrayBufferView, offset?: number);
public setCustomAttributes(name: string, attributesView: AttributesView, offset?: number);
public setCustomAttributes(name: string, values: any, offset: number = 0): void {
if (values == this._customAttributes[name])
return;
if (values instanceof AttributesView) {
this.clearVertices(this._customAttributes[name]);
this._customAttributes[name] = values;
} else if (values) {
if (!this._customAttributes[name]) {
//default custom atrributes is Float3
this._customAttributes[name] = new Float3Attributes(this._concatenatedBuffer);
}
this._customAttributes[name].set(values, offset);
} else if (this._customAttributes[name]) {
this.clearVertices(this._customAttributes[name]);
this._customAttributesNames.splice(this._customAttributesNames.indexOf(name), 1);
delete this._customAttributes[name];
return;
}
this.invalidateVertices(this._customAttributes[name]);
this._verticesDirty[this._customAttributes[name].id] = false;
if (this._customAttributesNames.indexOf(name) == -1)
this._customAttributesNames.push(name);
}
public updateScale9(targetScaleX: number, targetScaleY: number): void {
throw new AbstractMethodError('UpdateScale9 MUST be overridden by subclass');
}
public prepareScale9(
bounds: Rectangle,
grid: Rectangle,
clone: boolean,
emitUV?: boolean,
uvMatrix?: Matrix
): ElementsBase {
throw new AbstractMethodError('prepareScale9 MUST be overridden by subclass');
}
/**
* Clones the current object
* @return An exact duplicate of the current object.
*/
public clone(): ElementsBase {
throw new AbstractMethodError();
}
public applyTransformation(transform: Matrix3D, count: number = 0, offset: number = 0): void {
throw new AbstractMethodError();
}
/**
* Scales the geometry.
* @param scale The amount by which to scale.
*/
public scale(scale: number, count: number = 0, offset: number = 0): void {
throw new AbstractMethodError();
}
public scaleUV(scaleU: number = 1, scaleV: number = 1, count: number = 0, offset: number = 0): void {
throw new AbstractMethodError();
}
public getBoxBounds(
node: ContainerNode = null,
strokeFlag: boolean = true,
matrix3D: Matrix3D = null,
cache: Box = null,
target: Box = null,
count: number = 0,
offset: number = 0): Box {
throw new AbstractMethodError();
}
public getSphereBounds(
center: Vector3D,
matrix3D: Matrix3D = null,
strokeFlag: boolean = true,
cache: Sphere = null,
target: Sphere = null,
count: number = 0,
offset: number = 0): Sphere {
throw new AbstractMethodError();
}
public hitTestPoint(
node: ContainerNode,
x: number, y: number, z: number,
box: Box,
count: number = 0,
offset: number = 0): boolean {
throw new AbstractMethodError();
}
public invalidateIndices(): void {
if (!this._invalidateIndices)
this._invalidateIndices = new ElementsEvent(ElementsEvent.INVALIDATE_INDICES, this._indices);
this.dispatchEvent(this._invalidateIndices);
}
private clearIndices(): void {
this.dispatchEvent(new ElementsEvent(ElementsEvent.CLEAR_INDICES, this._indices));
}
public invalidateVertices(attributesView: AttributesView): void {
if (!attributesView || this._verticesDirty[attributesView.id])
return;
this._verticesDirty[attributesView.id] = true;
if (!this._invalidateVertices[attributesView.id])
this._invalidateVertices[attributesView.id] = new ElementsEvent(
ElementsEvent.INVALIDATE_VERTICES, attributesView);
this.dispatchEvent(this._invalidateVertices[attributesView.id]);
}
public clearVertices(attributesView: AttributesView): void {
if (!attributesView)
return;
attributesView.dispose();
this.dispatchEvent(new ElementsEvent(ElementsEvent.CLEAR_VERTICES, attributesView));
this._verticesDirty[attributesView.id] = null;
this._invalidateVertices[attributesView.id] = null;
}
public testCollision(
collision: PickingCollision,
box: Box,
closestFlag: boolean,
material: IMaterial,
count: number,
offset: number = 0): boolean {
throw new AbstractMethodError();
}
}