@awayjs/renderer
Version:
Renderer for AwayJS
298 lines (244 loc) • 7.65 kB
text/typescript
import { Stage, Short3Attributes, AttributesView, _Stage_AttributesBuffer } from '@awayjs/stage';
import { AbstractionBase, AbstractMethodError, AssetEvent } from '@awayjs/core';
import { ElementsEvent } from '../events/ElementsEvent';
import { ElementsUtils } from '../utils/ElementsUtils';
import { IElements } from './IElements';
import { IRenderable } from './IRenderable';
import { IShaderBase } from './IShaderBase';
/**
*
* @class away.pool._Stage_ElementsBaseBase
*/
export class _Stage_ElementsBase extends AbstractionBase {
public usages: number = 0;
private _elements: IElements;
public _stage: Stage;
private _onInvalidateIndicesDelegate: (event: ElementsEvent) => void;
private _onClearIndicesDelegate: (event: ElementsEvent) => void;
private _onInvalidateVerticesDelegate: (event: ElementsEvent) => void;
private _onClearVerticesDelegate: (event: ElementsEvent) => void;
private _overflow: _Stage_ElementsBase;
public _indices: _Stage_AttributesBuffer;
private _indicesUpdated: boolean;
private _vertices: Record<number, _Stage_AttributesBuffer> = {};
private _verticesUpdated: Record<number, boolean> = {};
public _indexMappings: Array<number> = Array<number>();
private _numIndices: number = 0;
private _numVertices: number;
public get elements(): IElements {
return this._elements;
}
/**
*
*/
public get numIndices(): number {
return this._numIndices;
}
/**
*
*/
public get numVertices(): number {
return this._numVertices;
}
constructor() {
super();
this._onInvalidateIndicesDelegate = (event: ElementsEvent) => this._onInvalidateIndices(event);
this._onClearIndicesDelegate = (event: ElementsEvent) => this._onClearIndices(event);
this._onInvalidateVerticesDelegate = (event: ElementsEvent) => this._onInvalidateVertices(event);
this._onClearVerticesDelegate = (event: ElementsEvent) => this._onClearVertices(event);
}
public init(elements: IElements, stage: Stage): void {
super.init(elements, stage);
this._elements = elements;
this._stage = stage;
this._elements.addEventListener(ElementsEvent.CLEAR_INDICES, this._onClearIndicesDelegate);
this._elements.addEventListener(ElementsEvent.INVALIDATE_INDICES, this._onInvalidateIndicesDelegate);
this._elements.addEventListener(ElementsEvent.CLEAR_VERTICES, this._onClearVerticesDelegate);
this._elements.addEventListener(ElementsEvent.INVALIDATE_VERTICES, this._onInvalidateVerticesDelegate);
}
/**
*
*/
public getIndexMappings(): Array<number> {
if (!this._indicesUpdated)
this._updateIndices();
return this._indexMappings;
}
/**
*
*/
public getIndexBufferGL(): _Stage_AttributesBuffer {
if (!this._indicesUpdated)
this._updateIndices();
return this._indices;
}
/**
*
*/
public getVertexBufferGL(attributesView: AttributesView): _Stage_AttributesBuffer {
//first check if indices need updating which may affect vertices
if (!this._indicesUpdated)
this._updateIndices();
const bufferId: number = attributesView.attributesBuffer.id;
if (!this._verticesUpdated[bufferId])
this._updateVertices(attributesView);
return this._vertices[bufferId];
}
/**
*
*/
public activateVertexBufferVO(
index: number, attributesView: AttributesView,
dimensions: number = 0, offset: number = 0): void {
this.getVertexBufferGL(attributesView)
.activate(
index,
attributesView.size,
dimensions || attributesView.dimensions,
attributesView.offset + offset,
attributesView.unsigned);
}
/**
*
*/
public onClear(event: AssetEvent): void {
super.onClear(event);
this._elements.removeEventListener(ElementsEvent.CLEAR_INDICES, this._onClearIndicesDelegate);
this._elements.removeEventListener(ElementsEvent.INVALIDATE_INDICES, this._onInvalidateIndicesDelegate);
this._elements.removeEventListener(ElementsEvent.CLEAR_VERTICES, this._onClearVerticesDelegate);
this._elements.removeEventListener(ElementsEvent.INVALIDATE_VERTICES, this._onInvalidateVerticesDelegate);
this._elements = null;
if (this._overflow) {
this._overflow.onClear(event);
this._overflow = null;
}
this._indices = null;
this._indicesUpdated = false;
this._vertices = {};
this._verticesUpdated = {};
}
public _setRenderState(renderable: IRenderable, shader: IShaderBase): void {
if (!this._verticesUpdated)
this._updateIndices();
//TODO replace overflow system with something sensible
//this._render(renderable, camera, viewProjection);
//
// if (this._overflow)
// this._overflow._iRender(renderable, camera, viewProjection);
}
public draw(renderable: IRenderable, shader: IShaderBase, count: number, offset: number): void {
throw new AbstractMethodError();
}
/**
* //TODO
*
* @private
*/
public _updateIndices(indexOffset: number = 0): void {
const indices: Short3Attributes = this._elements.indices;
if (indices) {
const sub = ElementsUtils.getSubIndices(
indices,
this._elements.numVertices,
this._indexMappings, indexOffset);
this._indices = sub.getAbstraction<_Stage_AttributesBuffer>(this._stage);
this._numIndices = this._indices._attributesBuffer.count * indices.dimensions;
} else {
this._indices = null;
this._numIndices = 0;
this._indexMappings = Array<number>();
}
indexOffset += this._numIndices;
//check if there is more to split
if (indices && indexOffset < indices.count * this._elements.indices.dimensions) {
if (!this._overflow)
this._overflow = this._pGetOverflowElements();
this._overflow._updateIndices(indexOffset);
} else if (this._overflow) {
this._overflow.onClear(null);
this._overflow = null;
}
this._indicesUpdated = true;
//invalidate vertices if index mappings exist
if (this._indexMappings.length)
for (const key in this._verticesUpdated)
this._verticesUpdated[key] = false;
}
/**
* //TODO
*
* @param attributesView
* @private
*/
private _updateVertices(attributesView: AttributesView): void {
this._numVertices = this._elements.numVertices;
const bufferId: number = attributesView.attributesBuffer.id;
const sub = ElementsUtils.getSubVertices(attributesView.attributesBuffer, this._indexMappings);
this._vertices[bufferId] = sub.getAbstraction<_Stage_AttributesBuffer>(this._stage);
this._verticesUpdated[bufferId] = true;
}
/**
* //TODO
*
* @param event
* @private
*/
public _onInvalidateIndices(event: ElementsEvent): void {
if (!event.attributesView)
return;
this._indicesUpdated = false;
}
/**
* //TODO
*
* @param event
* @private
*/
public _onClearIndices(event: ElementsEvent): void {
if (!event.attributesView)
return;
this._indices.onClear(null);
this._indices = null;
}
/**
* //TODO
*
* @param event
* @private
*/
public _onInvalidateVertices(event: ElementsEvent): void {
if (!event.attributesView)
return;
const bufferId: number = event.attributesView.attributesBuffer.id;
this._verticesUpdated[bufferId] = false;
}
/**
* //TODO
*
* @param event
* @private
*/
public _onClearVertices(event: ElementsEvent): void {
if (!event.attributesView)
return;
const bufferId: number = event.attributesView.attributesBuffer.id;
if (this._vertices[bufferId]) {
this._vertices[bufferId].onClear(null);
delete this._vertices[bufferId];
delete this._verticesUpdated[bufferId];
}
}
/**
* //TODO
*
* @param pool
* @param renderable
* @param level
* @param indexOffset
* @returns {away.pool.GL_ShapeRenderable}
* @protected
*/
public _pGetOverflowElements(): _Stage_ElementsBase {
throw new AbstractMethodError();
}
}