UNPKG

mdx-m3-viewer

Version:

A browser WebGL model viewer. Mainly focused on models of the games Warcraft 3 and Starcraft 2.

138 lines (111 loc) 4.5 kB
import {mat4} from 'gl-matrix'; import Bucket from '../../bucket'; // Heap allocations needed for this module. let matrixHeap = mat4.create(); /** * An M3 bucket. */ export default class M3Bucket extends Bucket { /** * @param {TexturedModelView} modelView */ constructor(modelView) { super(modelView); const model = modelView.model; const gl = model.viewer.gl; this.gl = gl; let numberOfBones = model.initialReference.length; let batchSize = model.batchSize; this.boneArrayInstanceSize = numberOfBones * 16; this.boneArray = new Float32Array(this.boneArrayInstanceSize * batchSize); this.boneTexture = gl.createTexture(); this.boneTextureWidth = numberOfBones * 4; this.boneTextureHeight = batchSize; this.vectorSize = 1 / this.boneTextureWidth; this.rowSize = 1 / this.boneTextureHeight; gl.activeTexture(gl.TEXTURE15); gl.bindTexture(gl.TEXTURE_2D, this.boneTexture); model.viewer.webgl.setTextureMode(gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, gl.NEAREST, gl.NEAREST); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.boneTextureWidth, this.boneTextureHeight, 0, gl.RGBA, gl.FLOAT, this.boneArray); // Team colors (per instance) this.teamColorArray = new Uint8Array(batchSize); this.teamColorBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.teamColorBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.teamColorArray, gl.DYNAMIC_DRAW); // Vertex color (per instance) this.vertexColorArray = new Uint8Array(4 * batchSize).fill(255); // Vertex color initialized to white this.vertexColorBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexColorBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.vertexColorArray, gl.DYNAMIC_DRAW); } /** * @override * @param {ModelInstance} instance */ renderInstance(instance) { let model = this.modelView.model; let initialReferences = model.initialReference; let boneLookup = model.boneLookup; let boneArray = this.boneArray; let teamColorArray = this.teamColorArray; let vertexColorArray = this.vertexColorArray; let instanceOffset = this.count; let vertexColor = instance.vertexColor; let base = instanceOffset * this.boneArrayInstanceSize; let sequence = instance.sequence; let nodes = instance.skeleton.nodes; let finalMatrix; if (sequence === -1) { finalMatrix = instance.worldMatrix; } else { finalMatrix = matrixHeap; mat4.identity(finalMatrix); } for (let i = 0, l = boneLookup.length; i < l; i++) { let offset = base + i * 16; if (sequence !== -1) { let bone = boneLookup[i]; mat4.multiply(finalMatrix, nodes[bone].worldMatrix, initialReferences[bone]); } boneArray[offset] = finalMatrix[0]; boneArray[offset + 1] = finalMatrix[1]; boneArray[offset + 2] = finalMatrix[2]; boneArray[offset + 3] = finalMatrix[3]; boneArray[offset + 4] = finalMatrix[4]; boneArray[offset + 5] = finalMatrix[5]; boneArray[offset + 6] = finalMatrix[6]; boneArray[offset + 7] = finalMatrix[7]; boneArray[offset + 8] = finalMatrix[8]; boneArray[offset + 9] = finalMatrix[9]; boneArray[offset + 10] = finalMatrix[10]; boneArray[offset + 11] = finalMatrix[11]; boneArray[offset + 12] = finalMatrix[12]; boneArray[offset + 13] = finalMatrix[13]; boneArray[offset + 14] = finalMatrix[14]; boneArray[offset + 15] = finalMatrix[15]; } // Team color teamColorArray[instanceOffset] = instance.teamColor; // Vertex color vertexColorArray[instanceOffset * 4] = vertexColor[0]; vertexColorArray[instanceOffset * 4 + 1] = vertexColor[1]; vertexColorArray[instanceOffset * 4 + 2] = vertexColor[2]; vertexColorArray[instanceOffset * 4 + 3] = vertexColor[3]; this.count += 1; } /** * @override */ updateBuffers() { if (this.count) { let gl = this.modelView.model.viewer.gl; gl.activeTexture(gl.TEXTURE15); gl.bindTexture(gl.TEXTURE_2D, this.boneTexture); gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.boneTextureWidth, this.count, gl.RGBA, gl.FLOAT, this.boneArray); gl.bindBuffer(gl.ARRAY_BUFFER, this.teamColorBuffer); gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.teamColorArray); gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexColorBuffer); gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexColorArray); } } }