|
- /*
- * TSDGLDataBuffer.js
- * Keynote HTML Player
- *
- * Created by Tungwei Cheng
- * Copyright (c) 2018 Apple Inc. All rights reserved.
- */
-
- var CHAR_MAX = 127;
- var UCHAR_MAX = 255;
- var SHRT_MAX = 32767;
- var USHRT_MAX = 65535;
-
- /* Boolean */
- var GL_FALSE = 0;
- var GL_TRUE = 1;
-
- /* BeginMode */
- var GL_POINTS = 0x0000;
- var GL_LINES = 0x0001;
- var GL_LINE_LOOP = 0x0002;
- var GL_LINE_STRIP = 0x0003;
- var GL_TRIANGLES = 0x0004;
- var GL_TRIANGLE_STRIP = 0x0005;
- var GL_TRIANGLE_FAN = 0x0006;
-
- /* DataType */
- var GL_BYTE = 0x1400;
- var GL_UNSIGNED_BYTE = 0x1401;
- var GL_SHORT = 0x1402;
- var GL_UNSIGNED_SHORT = 0x1403;
- var GL_INT = 0x1404;
- var GL_UNSIGNED_INT = 0x1405;
- var GL_FLOAT = 0x1406;
- var GL_DOUBLE = 0x140A;
-
- var GL_STREAM_DRAW = 0x88E0;
- var GL_STATIC_DRAW = 0x88E4;
- var GL_DYNAMIC_DRAW = 0x88E8;
-
- var GL_FLOAT_VEC2 = 0x8B50;
- var GL_FLOAT_VEC3 = 0x8B51;
- var GL_FLOAT_VEC4 = 0x8B52;
- var GL_INT_VEC2 = 0x8B53;
- var GL_INT_VEC3 = 0x8B54;
- var GL_INT_VEC4 = 0x8B55;
- var GL_BOOL = 0x8B56;
- var GL_BOOL_VEC2 = 0x8B57;
- var GL_BOOL_VEC3 = 0x8B58;
- var GL_BOOL_VEC4 = 0x8B59;
- var GL_FLOAT_MAT2 = 0x8B5A;
- var GL_FLOAT_MAT3 = 0x8B5B;
- var GL_FLOAT_MAT4 = 0x8B5C;
- var GL_SAMPLER_1D = 0x8B5D;
- var GL_SAMPLER_2D = 0x8B5E;
- var GL_SAMPLER_3D = 0x8B5F;
- var GL_SAMPLER_CUBE = 0x8B60;
-
- var TSDGLDataBufferDataTypeUnknown = 0;
- var TSDGLDataBufferDataTypeByte = GL_BYTE;
- var TSDGLDataBufferDataTypeUnsignedByte = GL_UNSIGNED_BYTE;
- var TSDGLDataBufferDataTypeShort = GL_SHORT;
- var TSDGLDataBufferDataTypeUnsignedShort = GL_UNSIGNED_SHORT;
- var TSDGLDataBufferDataTypeFloat = GL_FLOAT;
-
- function TSDGLDataBufferDataTypeAsGLEnum(dataType) {
- var result = 0;
- switch (dataType) {
- case TSDGLDataBufferDataTypeByte:
- result = GL_BYTE;
- break;
- case TSDGLDataBufferDataTypeUnsignedByte:
- result = GL_UNSIGNED_BYTE;
- break;
- case TSDGLDataBufferDataTypeUnsignedShort:
- result = GL_UNSIGNED_SHORT;
- break;
- case TSDGLDataBufferDataTypeShort:
- result = GL_SHORT;
- break;
- case TSDGLDataBufferDataTypeFloat:
- result = GL_FLOAT;
- break;
- case TSDGLDataBufferDataTypeUnknown:
- console.log("Unknown TSDGLdataBufferDataType!");
- break;
- }
-
- return result;
- }
-
- function TSDGLDataBufferDataTypeSize(dataType) {
- var result = 0;
- switch (dataType) {
- case GL_BYTE:
- result = 1;
- break;
- case GL_UNSIGNED_BYTE:
- result = 1;
- break;
- case GL_SHORT:
- result = 2;
- break;
- case GL_UNSIGNED_SHORT:
- result = 2;
- break;
- case GL_FLOAT:
- result = 4;
- break;
- default:
- break;
- }
-
- return result;
- }
-
- function TSDGLPoint2DByteFromPoint2D(aPoint, isNormalized) {
- var x = TSDGLbyteFromFloat(aPoint.x, isNormalized);
- var y = TSDGLbyteFromFloat(aPoint.y, isNormalized);
-
- var p = new Int8Array(2);
- p.set([x, y], 0);
-
- return p;
- }
-
- function TSDGLbyteFromFloat(aFloat, isNormalized) {
- if (isNormalized) {
- aFloat *= CHAR_MAX;
- }
-
- return aFloat;
- }
-
- function TSDGLPoint2DUnsignedByteFromPoint2D(aPoint, isNormalized) {
- var x = TSDGLubyteFromFloat(aPoint.x, isNormalized);
- var y = TSDGLubyteFromFloat(aPoint.y, isNormalized);
-
- var p = new Uint8Array(2);
-
- p.set([x, y], 0);
-
- return p;
- }
-
- function TSDGLubyteFromFloat(aFloat, isNormalized) {
- if (isNormalized) {
- aFloat *= UCHAR_MAX;
- }
-
- return aFloat;
- }
-
- function TSDGLPoint2DShortFromPoint2D(aPoint, isNormalized) {
- var x = TSDGLshortFromFloat(aPoint.x, isNormalized);
- var y = TSDGLshortFromFloat(aPoint.y, isNormalized);
-
- var p = new Int16Array(4);
- p.set([x, y], 0);
-
- return p;
- }
-
- function TSDGLshortFromFloat(aFloat, isNormalized) {
- if (isNormalized) {
- aFloat *= SHRT_MAX;
- }
-
- return aFloat;
- }
-
- function TSDGLPoint2DUnsignedShortFromPoint2D(aPoint, isNormalized) {
- var x = TSDGLushortFromFloat(aPoint.x, isNormalized);
- var y = TSDGLushortFromFloat(aPoint.y, isNormalized);
-
- var p = new Uint16Array(4);
- p.set([x, y], 0);
-
- return p;
- }
-
- function TSDGLushortFromFloat(aFloat, isNormalized) {
- if (isNormalized) {
- aFloat *= USHRT_MAX;
- }
- return aFloat;
- }
-
- function TSDGLDataBufferSetGLPoint2DWithDataType(mGLData, bufferOffset, dataType, isNormalized, aPoint2D) {
- switch (dataType) {
- case TSDGLDataBufferDataTypeByte:
- var value = TSDGLPoint2DByteFromPoint2D(aPoint2D, isNormalized);
- var typedArray = new Int8Array(mGLData);
- typedArray.set(value, bufferOffset);
-
- break;
-
- case TSDGLDataBufferDataTypeUnsignedByte:
- var value = TSDGLPoint2DUnsignedByteFromPoint2D(aPoint2D, isNormalized);
- var typedArray = new Uint8Array(mGLData);
- typedArray.set(value, bufferOffset);
-
- break;
-
- case TSDGLDataBufferDataTypeShort:
- var value = TSDGLPoint2DShortFromPoint2D(aPoint2D, isNormalized);
- var typedArray = new Int16Array(mGLData);
- typedArray.set(value, bufferOffset/2);
-
- break;
-
- case TSDGLDataBufferDataTypeUnsignedShort:
- var value = TSDGLPoint2DUnsignedShortFromPoint2D(aPoint2D, isNormalized);
- var typedArray = new Uint16Array(mGLData);
- typedArray.set(value, bufferOffset/2);
-
- break;
-
- case TSDGLDataBufferDataTypeFloat:
- var typedArray = new Float32Array(mGLData);
- typedArray.set([aPoint2D.x, aPoint2D.y], bufferOffset/4);
-
- break;
- case TSDGLDataBufferDataTypeUnknown:
- console.log("Unknown data type!");
- break;
- }
- }
-
- var TSDGLDataBufferAttribute = Class.create({
- initialize: function(name, bufferUsage, dataType, normalized, componentCount) {
- this.locationInShader = -1;
- this.bufferOffset = null;
- this.dataArrayBuffer = null;
- this.dataBuffer = null;
-
- this.initWithName(name, bufferUsage, dataType, normalized, componentCount);
- },
-
- initWithName: function(attributeName, bufferUsage, dataType, isNormalized, componentCount) {
- this.name = attributeName;
- this.bufferUsage = bufferUsage;
- this.dataType = dataType;
-
- if (this.dataType === GL_SHORT) {
- this.dataType = GL_FLOAT;
- }
-
- this.componentCount = componentCount;
- this.isNormalized = isNormalized;
-
- this.locationInShader = -1;
- }
- });
-
- var TSDGLDataArrayBuffer = Class.create({
- initialize: function(gl) {
- this.gl = gl;
-
- this._vertexAttributes = null;
- this.mVertexCount = 0;
-
- // data type size in bytes
- this._dataTypeSizeInBytes = 0;
-
- // GL_STATIC_DRAW, GL_STREAM_DRAW, etc
- this._bufferUsage = 0;
-
- this.mNeedsUpdateFirstIndex = [];
- this.mNeedsUpdateLastIndex = [];
-
- this.mGLData = null;
-
- // GL vertex data buffer
- this.mGLDataBufferHasBeenSetup = false;
-
- this.mGLDataBuffers = [];
-
- this.mAttributeOffsetsDictionary = null;
-
- this.GLDataBufferEntrySize = 0;
-
- // for double-buffering
- this.bufferCount = 1;
- this.currentBufferIndex = 0;
- },
-
- initWithVertexAttributes: function(attributes, vertexCount, bufferCount) {
- this._vertexAttributes = attributes.slice();
- this.mVertexCount = vertexCount;
- this.mAttributeOffsetsDictionary = {};
-
- // Sort the attributes into buffers by buffer usage type
- var bufferSizeIfFloats = 0;
-
- var bufferOffset = 0;
-
- for (var i = 0, length = this._vertexAttributes.length; i < length; i++) {
- var attribute = this._vertexAttributes[i];
-
- // Assign data array buffer to attribute
- attribute.dataArrayBuffer = this;
-
- var dataTypeSizeInBytes = TSDGLDataBufferDataTypeSize(attribute.dataType);
-
- if (this._bufferUsage === 0) {
- this._bufferUsage = attribute.bufferUsage;
- }
-
- // Assign buffer offset
- attribute.bufferOffset = bufferOffset;
-
- var paddedSize = attribute.componentCount * dataTypeSizeInBytes;
-
- paddedSize = (paddedSize + 3) & ~3;
-
- bufferOffset += paddedSize;
-
- bufferSizeIfFloats += attribute.componentCount * 4;
- }
-
- // Create the buffer data (if necessary)
- this.GLDataBufferEntrySize = bufferOffset;
-
- // We need to give the arraybuffer a size
- if (this.GLDataBufferEntrySize > 0) {
- this.mGLData = new ArrayBuffer(this.mVertexCount * this.GLDataBufferEntrySize);
- }
-
- this.bufferCount = bufferCount;
-
- this.mNeedsUpdateFirstIndex = [];
- this.mNeedsUpdateLastIndex = [];
-
- for (var i = 0; i < bufferCount; i++) {
- this.mNeedsUpdateFirstIndex[i] = -1;
- this.mNeedsUpdateLastIndex[i] = -1;
- }
- },
-
- p_setupGLDataBufferIfNecessary: function() {
- var gl = this.gl;
-
- // Sets up GL buffers
- if (this.mGLDataBufferHasBeenSetup) {
- return;
- }
-
- for (var i = 0; i < this.bufferCount; i++) {
- this.mGLDataBuffers[i] = gl.createBuffer();
-
- gl.bindBuffer(gl.ARRAY_BUFFER, this.mGLDataBuffers[i]);
-
- gl.bufferData(gl.ARRAY_BUFFER, this.mGLData, this._bufferUsage);
-
- this.mNeedsUpdateFirstIndex[i] = -1;
- this.mNeedsUpdateLastIndex[i] = -1;
- }
-
- this.mGLDataBufferHasBeenSetup = true;
- },
-
- updateDataBufferIfNecessary: function() {
- this.p_setupGLDataBufferIfNecessary();
-
- if (!this.hasUpdatedData()) {
- // Nothing needs to be updated!
- return;
- }
-
- if (this._bufferUsage == GL_STATIC_DRAW) {
- console.log("We're GL_STATIC_DRAW but trying (and FAILING) to update the array after initial setup!");
- return;
- }
-
- var gl = this.gl;
- // Combine all buffer's updated ranges, in case they're not the same...
- var firstIndex = Number.MAX_SAFE_INTEGER;
- var lastIndex = -1;
-
- for (var i = 0; i < this.bufferCount; i++) {
- var thisFirstIndex = this.mNeedsUpdateFirstIndex[i];
- if (thisFirstIndex !== -1) {
- firstIndex = Math.min(firstIndex, thisFirstIndex);
- }
- var thisLastIndex = this.mNeedsUpdateLastIndex[i];
- if (thisLastIndex !== -1) {
- lastIndex = Math.max(lastIndex, this.mNeedsUpdateLastIndex[i]);
- }
- }
-
- var offset = firstIndex;
- var size = lastIndex + 1 - firstIndex;
- offset *= this.GLDataBufferEntrySize;
- size *= this.GLDataBufferEntrySize;
-
- gl.bindBuffer(gl.ARRAY_BUFFER, this.mGLDataBuffers[this.currentBufferIndex]);
- gl.bufferSubData(gl.ARRAY_BUFFER, offset, this.mGLData);
-
- this.mNeedsUpdateFirstIndex[this.currentBufferIndex] = -1;
- this.mNeedsUpdateLastIndex[this.currentBufferIndex] = -1;
- },
-
- p_bufferOffsetOfAttribute: function(attribute, index, component) {
- var bufferOffset = index * this.GLDataBufferEntrySize;
-
- bufferOffset += attribute.bufferOffset;
-
- if (component !== 0) {
- bufferOffset += TSDGLDataBufferDataTypeSize(attribute.dataType) * component;
- }
-
- return bufferOffset;
- },
-
- setGLPoint2D: function(aPoint2D, attribute, index) {
- var bufferOffset = this.p_bufferOffsetOfAttribute(attribute, index, 0);
- TSDGLDataBufferSetGLPoint2DWithDataType(this.mGLData, bufferOffset, attribute.dataType, attribute.isNormalized, aPoint2D);
-
- this.addIndexNeedsUpdate(index);
- },
-
- enableVertexAttributeArrayBuffersWithShader: function(shader) {
- var gl = this.gl;
-
- this.updateDataBufferIfNecessary();
-
- gl.bindBuffer(gl.ARRAY_BUFFER, this.mGLDataBuffers[this.currentBufferIndex]);
-
- for (var i = 0, length = this._vertexAttributes.length; i < length; i++) {
- var attribute = this._vertexAttributes[i];
- var locationInShader = attribute.locationInShader;
-
- if (locationInShader === -1) {
- locationInShader = shader.locationForAttribute(attribute.name);
-
- if (locationInShader === -1) {
- console.log("Could not find attribute " + attribute.name + "in shader!");
- }
-
- attribute.locationInShader = locationInShader;
- }
-
- var stride = 0;
-
- if (this._vertexAttributes.length > 1) {
- // we're not tight-packed, so need to specify how many elements to skip when iterating
- stride = this.GLDataBufferEntrySize;
- }
-
- var dataType = TSDGLDataBufferDataTypeAsGLEnum(attribute.dataType);
-
- gl.enableVertexAttribArray(locationInShader);
- gl.vertexAttribPointer(locationInShader, attribute.componentCount, dataType, attribute.isNormalized ? GL_TRUE : GL_FALSE, stride, attribute.bufferOffset);
- }
- },
-
- disableVertexAttributeArrayBuffersWithShader: function(shader) {
- var gl = this.gl;
-
- for (var i = 0, length = this._vertexAttributes.length; i < length; i++) {
- var attribute = this._vertexAttributes[i];
- gl.disableVertexAttribArray(attribute.locationInShader);
- }
-
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
- },
-
- hasUpdatedData: function() {
- for (var i = 0; i < this.bufferCount; i++) {
- if (this.mNeedsUpdateFirstIndex[i] !== -1) {
- return true;
- }
- }
- return false;
- },
-
- addIndexNeedsUpdate: function(index) {
- var currentBufferIndex = this.currentBufferIndex;
- var mNeedsUpdateFirstIndex = this.mNeedsUpdateFirstIndex;
- var mNeedsUpdateLastIndex = this.mNeedsUpdateLastIndex;
-
- mNeedsUpdateFirstIndex[currentBufferIndex] = (mNeedsUpdateFirstIndex[currentBufferIndex] == -1) ? index : Math.min(mNeedsUpdateFirstIndex[currentBufferIndex], index);
- mNeedsUpdateLastIndex[currentBufferIndex] = (mNeedsUpdateLastIndex[currentBufferIndex] == -1) ? index : Math.max(mNeedsUpdateLastIndex[currentBufferIndex], index);
- }
-
- });
-
- var TSDGLDataBuffer = Class.create({
- initialize: function(gl) {
- this.gl = gl;
-
- this.mCurrentBufferIndex = 0;
- this.mArrayBuffers = [];
- this.mAttributeToArrayBuffersDictionary = {};
-
- // Element array buffer
- this.mElementArrayCount = 0;
- this.mGLElementData = null;
- this.mGLElementDataBufferWasSetup = false;
- this.mGLElementDataBuffer = null;
-
- this.mGLElementMeshSize = {
- width: 0,
- height: 0
- }
-
- this.mGLElementQuadParticleCount = 0;
- },
-
- p_setupGLElementArrayBufferIfNecessary: function() {
- var gl = this.gl;
-
- if (this.mGLElementDataBufferWasSetup) {
- return;
- }
-
- if (!this.mGLElementData) {
- this.mGLElementDataBufferWasSetup = true;
- return;
- }
-
- var useIndexCounter = false;
- var indexCounter = 0;
-
- if (!CGSizeEqualToSize(this.mGLElementMeshSize, CGSizeZero)) {
- useIndexCounter = true;
-
- // set up grid-based element array data
- for (var y = 0; y < this.mGLElementMeshSize.height - 1; ++y) {
- for (var x = 0; x < this.mGLElementMeshSize.width; ++x) {
- this.setGLushort((y + 0) * this.mGLElementMeshSize.width + x, indexCounter++);
- this.setGLushort((y + 1) * this.mGLElementMeshSize.width + x, indexCounter++);
- }
- }
- } else if (this.mGLElementQuadParticleCount != 0) {
- useIndexCounter = true;
- this.drawMode = GL_TRIANGLES;
-
- // set up quad particle-based element array data
- for (var i = 0; i < this.mGLElementQuadParticleCount; ++i) {
- // First triangle
- this.setGLushort((4 * i + 0), indexCounter++);
- this.setGLushort((4 * i + 1), indexCounter++);
- this.setGLushort((4 * i + 2), indexCounter++);
-
- // Second triangle
- this.setGLushort((4 * i + 0), indexCounter++);
- this.setGLushort((4 * i + 2), indexCounter++);
- this.setGLushort((4 * i + 3), indexCounter++);
- }
- }
-
- this.mGLElementDataBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.mGLElementDataBuffer);
-
- this.mGLElementDataBufferWasSetup = true;
- },
-
- newDataBufferWithVertexAttributes: function(attributes, meshSize, isDoubleBuffered) {
- var vertexCount = meshSize.width * meshSize.height;
- var indexCount = meshSize.width * 2 * (meshSize.height - 1);
-
- this.initWithVertexAttributesDesignated(attributes, vertexCount, indexCount, isDoubleBuffered);
-
- this.mGLElementMeshSize = meshSize;
- },
-
- initWithVertexAttributes: function(attributes, meshSize) {
- var vertexCount = meshSize.width * meshSize.height;
- var indexCount = meshSize.width * 2 * (meshSize.height - 1);
-
- this.initWithVertexAttributesDesignated(attributes, vertexCount, indexCount, false);
-
- this.mGLElementMeshSize = meshSize;
- },
-
- initWithVertexAttributesDesignated: function(attributes, vertexCount, indexElementCount, isDoubleBuffered) {
- this._doubleBuffered = isDoubleBuffered;
- this.drawMode = GL_TRIANGLE_STRIP;
- this._vertexAttributes = attributes;
- this._vertexCount = vertexCount;
-
- this.mArrayBuffers = [];
- this.mAttributeToArrayBuffersDictionary = {};
-
- var attributesToArrange = attributes.slice();
-
- while (attributesToArrange.length > 0) {
- var thisAttribute = attributesToArrange[0];
- var currentAttributes = [];
-
- for (var i = 0, length = attributesToArrange.length; i < length; i++) {
- var attribute = attributesToArrange[i];
-
- if (attribute.bufferUsage == thisAttribute.bufferUsage) {
- currentAttributes.push(attribute);
- }
- }
-
- var bufferCount = ((isDoubleBuffered && thisAttribute.bufferUsage !== GL_STATIC_DRAW) ? 2 : 1);
-
- var arrayBuffer = new TSDGLDataArrayBuffer(this.gl);
-
- arrayBuffer.initWithVertexAttributes(currentAttributes, vertexCount, bufferCount);
-
- for (var i = 0, length = currentAttributes.length; i < length; i++) {
- var attribute = currentAttributes[i];
-
- // this will cause circular reference
- attribute.dataBuffer = this;
- this.mAttributeToArrayBuffersDictionary[attribute.name] = arrayBuffer;
- }
-
- this.mArrayBuffers.push(arrayBuffer);
-
- for (var i = 0, length = currentAttributes.length; i < length; i++) {
- var element = currentAttributes[i];
- attributesToArrange.splice(attributesToArrange.indexOf(element), 1);
- }
- }
-
- if (indexElementCount > 0) {
- this.mElementArrayCount = indexElementCount;
-
- this.mGLElementData = new ArrayBuffer(this.mElementArrayCount * 2);
- }
-
-
- },
-
- initWithVertexRect: function(vertexRect, textureRect, meshSize, isTextureFlipped, includeCenterAttribute) {
- var gl = this.gl;
-
- var shouldSetupTexCoords = !CGRectEqualToRect(textureRect, CGRectZero);
-
- var quadAttributes = [];
- var positionAttribute = new TSDGLDataBufferAttribute("Position", GL_STATIC_DRAW, GL_FLOAT, false, 2);
-
- quadAttributes.push(positionAttribute);
-
- var texCoordAttribute;
- if (shouldSetupTexCoords) {
- var dataType = GL_SHORT;
-
- if (CGRectEqualToRect(textureRect, CGRectMake(0, 0, 1, 1)) && CGSizeEqualToSize(meshSize, CGSizeMake(2, 2))) {
- // If we're just passing in the unit rectangle, we can use lower precision texcoords!
- dataType = GL_UNSIGNED_BYTE;
- }
-
- texCoordAttribute = new TSDGLDataBufferAttribute("TexCoord", GL_STATIC_DRAW, dataType, true, 2);
-
- quadAttributes.push(texCoordAttribute);
- }
-
- var centerAttribute;
- if (includeCenterAttribute) {
- centerAttribute = new TSDGLDataBufferAttribute("Center", GL_STATIC_DRAW, GL_FLOAT, false, 2);
-
- quadAttributes.push(centerAttribute);
- }
-
- this.initWithVertexAttributes(quadAttributes, meshSize);
-
- var index = 0;
-
- // This is TSDGLPoint2D in native which is a struct of float type
- var center = TSDCenterOfRect(vertexRect);
-
- var verticesWide = parseInt(meshSize.width - 1);
- var verticesHigh = parseInt(meshSize.height - 1);
-
- for (var row = 0; row <= verticesHigh; ++row) {
- for (var col = 0; col <= verticesWide; ++col) {
- var point = WebGraphics.makePoint(col / verticesWide, row / verticesHigh);
-
- // This is TSDGLPoint2D in native which is a struct of float type
- var vertex = TSDPointFromNormalizedRect(point, vertexRect);
-
- this.setGLPoint2D(vertex, positionAttribute, index);
-
- if (shouldSetupTexCoords) {
- var texCoord = TSDPointFromNormalizedRect(point, textureRect);
- if (isTextureFlipped) {
- texCoord = WebGraphics.makePoint(texCoord.x, 1.0 - texCoord.y);
- }
- this.setGLPoint2D(texCoord, texCoordAttribute, index);
- }
- if (includeCenterAttribute) {
- this.setGLPoint2D(center, centerAttribute, index);
- }
-
- index++;
- }
- }
-
- },
-
- setGLPoint2D: function(aPoint2D, attribute, index) {
- attribute.dataArrayBuffer.setGLPoint2D(aPoint2D, attribute, index);
- },
-
- setGLushort: function(aShort, index) {
- var bufferOffset = index;
- var typedArray = new Uint16Array(this.mGLElementData);
-
- typedArray.set([aShort], bufferOffset);
- },
-
- enableElementArrayBuffer: function() {
- var gl = this.gl;
-
- this.p_setupGLElementArrayBufferIfNecessary();
-
- if (this.mGLElementDataBufferWasSetup) {
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.mGLElementDataBuffer);
- }
- },
-
- disableElementArrayBuffer: function() {
- var gl = this.gl;
-
- if (this.mGLElementDataBufferWasSetup) {
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
- }
- },
-
- enableDataBufferWithShader: function(shader) {
- // Vertex Array Object is an expension in WebGL and currently not implemented in Safari
- if (!shader.isActive) {
- shader.activate();
- }
-
- for (var i = 0, length = this.mArrayBuffers.length; i < length; i++) {
- var buffer = this.mArrayBuffers[i];
- buffer.enableVertexAttributeArrayBuffersWithShader(shader);
- }
-
- this.enableElementArrayBuffer();
-
- this._enabledShader = shader;
- this._isEnabled = true;
- },
-
- disableDataBufferWithShader: function(shader) {
- if (!this._isEnabled) {
- return;
- }
-
- this.disableElementArrayBuffer();
-
- for (var i = 0, length = this.mArrayBuffers.length; i < length; i++) {
- var buffer = this.mArrayBuffers[i];
- buffer.disableVertexAttributeArrayBuffersWithShader(shader);
- }
-
- this._enabledShader = null;
- this._isEnabled = false;
-
- },
-
- drawWithShader: function(shader, shouldDeactivateShader) {
- var gl = this.gl;
- var range = {
- location: 0,
- length: this.mElementArrayCount > 0 ? this.mElementArrayCount : this._vertexCount
- };
-
- this.enableDataBufferWithShader(shader);
-
- if (this.mGLElementDataBufferWasSetup && this.mElementArrayCount > 0) {
- // we need to send element data to element array buffer, e.g. [0, 2, 1, 3]
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.mGLElementData, gl.STATIC_DRAW);
-
- if (!CGSizeEqualToSize(this.mGLElementMeshSize, CGSizeZero)) {
- // Draw mesh by rows
- var width = this.mGLElementMeshSize.width;
-
- for (var y = 0; y < this.mGLElementMeshSize.height - 1; ++y) {
- // location is vertex location, so need to multiply by two to get index location
- gl.drawElements(this.drawMode, width * 2, gl.UNSIGNED_SHORT, 2 * y * width * 2);
- }
- } else {
- // just draw everything
- gl.drawElements(this.drawMode, range.length, gl.UNSIGNED_SHORT, 2 * range.location);
- }
- } else {
- // No element data; just pass vertices straight down
- gl.drawArrays(this.drawMode, range.location, range.length);
- }
-
- this.disableDataBufferWithShader(shader);
-
- // Swap buffers
- if (this.isDoubleBuffered) {
- this.mCurrentBufferIndex = (this.mCurrentBufferIndex + 1) % 2;
-
- for (var i = 0, length = this.mArrayBuffers.length; i < length; i++) {
- var buffer = this.mArrayBuffers[i];
-
- if (buffer.bufferCount != 1) {
- buffer.currentBufferIndex = this.mCurrentBufferIndex;
- }
- }
- }
-
- if (shouldDeactivateShader) {
- shader.deactivate();
- }
- },
-
- vertexAttributeNamed: function(attributeName) {
- for (var attrib in this._vertexAttributes) {
- var attribute = this._vertexAttributes[attrib];
-
- if (attribute.name === attributeName) {
- return attribute;
- }
- }
-
- return null;
- }
- });
|