@pixi/core
Version:
Core PixiJS
196 lines (193 loc) • 6.3 kB
JavaScript
import { BUFFER_TYPE } from '@pixi/constants';
import { Runner } from '@pixi/runner';
import { getBufferType } from '@pixi/utils';
import { Attribute } from './Attribute.mjs';
import { Buffer } from './Buffer.mjs';
import { interleaveTypedArrays } from './utils/interleaveTypedArrays.mjs';
const byteSizeMap = { 5126: 4, 5123: 2, 5121: 1 };
let UID = 0;
const map = {
Float32Array,
Uint32Array,
Int32Array,
Uint8Array,
Uint16Array
};
class Geometry {
constructor(buffers = [], attributes = {}) {
this.buffers = buffers;
this.indexBuffer = null;
this.attributes = attributes;
this.glVertexArrayObjects = {};
this.id = UID++;
this.instanced = false;
this.instanceCount = 1;
this.disposeRunner = new Runner("disposeGeometry");
this.refCount = 0;
}
addAttribute(id, buffer, size = 0, normalized = false, type, stride, start, instance = false) {
if (!buffer) {
throw new Error("You must pass a buffer when creating an attribute");
}
if (!(buffer instanceof Buffer)) {
if (buffer instanceof Array) {
buffer = new Float32Array(buffer);
}
buffer = new Buffer(buffer);
}
const ids = id.split("|");
if (ids.length > 1) {
for (let i = 0; i < ids.length; i++) {
this.addAttribute(ids[i], buffer, size, normalized, type);
}
return this;
}
let bufferIndex = this.buffers.indexOf(buffer);
if (bufferIndex === -1) {
this.buffers.push(buffer);
bufferIndex = this.buffers.length - 1;
}
this.attributes[id] = new Attribute(bufferIndex, size, normalized, type, stride, start, instance);
this.instanced = this.instanced || instance;
return this;
}
getAttribute(id) {
return this.attributes[id];
}
getBuffer(id) {
return this.buffers[this.getAttribute(id).buffer];
}
addIndex(buffer) {
if (!(buffer instanceof Buffer)) {
if (buffer instanceof Array) {
buffer = new Uint16Array(buffer);
}
buffer = new Buffer(buffer);
}
buffer.type = BUFFER_TYPE.ELEMENT_ARRAY_BUFFER;
this.indexBuffer = buffer;
if (!this.buffers.includes(buffer)) {
this.buffers.push(buffer);
}
return this;
}
getIndex() {
return this.indexBuffer;
}
interleave() {
if (this.buffers.length === 1 || this.buffers.length === 2 && this.indexBuffer)
return this;
const arrays = [];
const sizes = [];
const interleavedBuffer = new Buffer();
let i;
for (i in this.attributes) {
const attribute = this.attributes[i];
const buffer = this.buffers[attribute.buffer];
arrays.push(buffer.data);
sizes.push(attribute.size * byteSizeMap[attribute.type] / 4);
attribute.buffer = 0;
}
interleavedBuffer.data = interleaveTypedArrays(arrays, sizes);
for (i = 0; i < this.buffers.length; i++) {
if (this.buffers[i] !== this.indexBuffer) {
this.buffers[i].destroy();
}
}
this.buffers = [interleavedBuffer];
if (this.indexBuffer) {
this.buffers.push(this.indexBuffer);
}
return this;
}
getSize() {
for (const i in this.attributes) {
const attribute = this.attributes[i];
const buffer = this.buffers[attribute.buffer];
return buffer.data.length / (attribute.stride / 4 || attribute.size);
}
return 0;
}
dispose() {
this.disposeRunner.emit(this, false);
}
destroy() {
this.dispose();
this.buffers = null;
this.indexBuffer = null;
this.attributes = null;
}
clone() {
const geometry = new Geometry();
for (let i = 0; i < this.buffers.length; i++) {
geometry.buffers[i] = new Buffer(this.buffers[i].data.slice(0));
}
for (const i in this.attributes) {
const attrib = this.attributes[i];
geometry.attributes[i] = new Attribute(attrib.buffer, attrib.size, attrib.normalized, attrib.type, attrib.stride, attrib.start, attrib.instance);
}
if (this.indexBuffer) {
geometry.indexBuffer = geometry.buffers[this.buffers.indexOf(this.indexBuffer)];
geometry.indexBuffer.type = BUFFER_TYPE.ELEMENT_ARRAY_BUFFER;
}
return geometry;
}
static merge(geometries) {
const geometryOut = new Geometry();
const arrays = [];
const sizes = [];
const offsets = [];
let geometry;
for (let i = 0; i < geometries.length; i++) {
geometry = geometries[i];
for (let j = 0; j < geometry.buffers.length; j++) {
sizes[j] = sizes[j] || 0;
sizes[j] += geometry.buffers[j].data.length;
offsets[j] = 0;
}
}
for (let i = 0; i < geometry.buffers.length; i++) {
arrays[i] = new map[getBufferType(geometry.buffers[i].data)](sizes[i]);
geometryOut.buffers[i] = new Buffer(arrays[i]);
}
for (let i = 0; i < geometries.length; i++) {
geometry = geometries[i];
for (let j = 0; j < geometry.buffers.length; j++) {
arrays[j].set(geometry.buffers[j].data, offsets[j]);
offsets[j] += geometry.buffers[j].data.length;
}
}
geometryOut.attributes = geometry.attributes;
if (geometry.indexBuffer) {
geometryOut.indexBuffer = geometryOut.buffers[geometry.buffers.indexOf(geometry.indexBuffer)];
geometryOut.indexBuffer.type = BUFFER_TYPE.ELEMENT_ARRAY_BUFFER;
let offset = 0;
let stride = 0;
let offset2 = 0;
let bufferIndexToCount = 0;
for (let i = 0; i < geometry.buffers.length; i++) {
if (geometry.buffers[i] !== geometry.indexBuffer) {
bufferIndexToCount = i;
break;
}
}
for (const i in geometry.attributes) {
const attribute = geometry.attributes[i];
if ((attribute.buffer | 0) === bufferIndexToCount) {
stride += attribute.size * byteSizeMap[attribute.type] / 4;
}
}
for (let i = 0; i < geometries.length; i++) {
const indexBufferData = geometries[i].indexBuffer.data;
for (let j = 0; j < indexBufferData.length; j++) {
geometryOut.indexBuffer.data[j + offset2] += offset;
}
offset += geometries[i].buffers[bufferIndexToCount].data.length / stride;
offset2 += indexBufferData.length;
}
}
return geometryOut;
}
}
export { Geometry };
//# sourceMappingURL=Geometry.mjs.map