123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- /*global define*/
- define([
- '../Core/ComponentDatatype',
- '../Core/defaultValue',
- '../Core/defined',
- '../Core/defineProperties',
- '../Core/destroyObject',
- '../Core/DeveloperError'
- ], function(
- ComponentDatatype,
- defaultValue,
- defined,
- defineProperties,
- destroyObject,
- DeveloperError) {
- "use strict";
- function addAttribute(attributes, attribute, index) {
- var hasVertexBuffer = defined(attribute.vertexBuffer);
- var hasValue = defined(attribute.value);
- var componentsPerAttribute = attribute.value ? attribute.value.length : attribute.componentsPerAttribute;
- //>>includeStart('debug', pragmas.debug);
- if (!hasVertexBuffer && !hasValue) {
- throw new DeveloperError('attribute must have a vertexBuffer or a value.');
- }
- if (hasVertexBuffer && hasValue) {
- throw new DeveloperError('attribute cannot have both a vertexBuffer and a value. It must have either a vertexBuffer property defining per-vertex data or a value property defining data for all vertices.');
- }
- if ((componentsPerAttribute !== 1) &&
- (componentsPerAttribute !== 2) &&
- (componentsPerAttribute !== 3) &&
- (componentsPerAttribute !== 4)) {
- if (hasValue) {
- throw new DeveloperError('attribute.value.length must be in the range [1, 4].');
- }
- throw new DeveloperError('attribute.componentsPerAttribute must be in the range [1, 4].');
- }
- if (defined(attribute.componentDatatype) && !ComponentDatatype.validate(attribute.componentDatatype)) {
- throw new DeveloperError('attribute must have a valid componentDatatype or not specify it.');
- }
- if (defined(attribute.strideInBytes) && (attribute.strideInBytes > 255)) {
- // WebGL limit. Not in GL ES.
- throw new DeveloperError('attribute must have a strideInBytes less than or equal to 255 or not specify it.');
- }
- //>>includeEnd('debug');
- // Shallow copy the attribute; we do not want to copy the vertex buffer.
- var attr = {
- index : defaultValue(attribute.index, index),
- enabled : defaultValue(attribute.enabled, true),
- vertexBuffer : attribute.vertexBuffer,
- value : hasValue ? attribute.value.slice(0) : undefined,
- componentsPerAttribute : componentsPerAttribute,
- componentDatatype : defaultValue(attribute.componentDatatype, ComponentDatatype.FLOAT),
- normalize : defaultValue(attribute.normalize, false),
- offsetInBytes : defaultValue(attribute.offsetInBytes, 0),
- strideInBytes : defaultValue(attribute.strideInBytes, 0)
- };
- if (hasVertexBuffer) {
- // Common case: vertex buffer for per-vertex data
- attr.vertexAttrib = function(gl) {
- gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer._getBuffer());
- gl.vertexAttribPointer(this.index, this.componentsPerAttribute, this.componentDatatype, this.normalize, this.strideInBytes, this.offsetInBytes);
- gl.enableVertexAttribArray(this.index);
- };
- attr.disableVertexAttribArray = function(gl) {
- gl.disableVertexAttribArray(this.index);
- };
- } else {
- // Less common case: value array for the same data for each vertex
- switch (attr.componentsPerAttribute) {
- case 1:
- attr.vertexAttrib = function(gl) {
- gl.vertexAttrib1fv(this.index, this.value);
- };
- break;
- case 2:
- attr.vertexAttrib = function(gl) {
- gl.vertexAttrib2fv(this.index, this.value);
- };
- break;
- case 3:
- attr.vertexAttrib = function(gl) {
- gl.vertexAttrib3fv(this.index, this.value);
- };
- break;
- case 4:
- attr.vertexAttrib = function(gl) {
- gl.vertexAttrib4fv(this.index, this.value);
- };
- break;
- }
- attr.disableVertexAttribArray = function(gl) {
- };
- }
- attributes.push(attr);
- }
- function bind(gl, attributes, indexBuffer) {
- for ( var i = 0; i < attributes.length; ++i) {
- var attribute = attributes[i];
- if (attribute.enabled) {
- attribute.vertexAttrib(gl);
- }
- }
- if (defined(indexBuffer)) {
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer._getBuffer());
- }
- }
- /**
- * @private
- */
- var VertexArray = function(gl, vertexArrayObject, attributes, indexBuffer) {
- //>>includeStart('debug', pragmas.debug);
- if (!defined(attributes)) {
- throw new DeveloperError('attributes is required.');
- }
- //>>includeEnd('debug');
- var i;
- var vaAttributes = [];
- var numberOfVertices = 1; // if every attribute is backed by a single value
- for (i = 0; i < attributes.length; ++i) {
- addAttribute(vaAttributes, attributes[i], i);
- }
- for (i = 0; i < vaAttributes.length; ++i) {
- var attribute = vaAttributes[i];
- if (defined(attribute.vertexBuffer)) {
- // This assumes that each vertex buffer in the vertex array has the same number of vertices.
- var bytes = attribute.strideInBytes || (attribute.componentsPerAttribute * ComponentDatatype.getSizeInBytes(attribute.componentDatatype));
- numberOfVertices = attribute.vertexBuffer.sizeInBytes / bytes;
- break;
- }
- }
- // Verify all attribute names are unique
- var uniqueIndices = {};
- for ( var j = 0; j < vaAttributes.length; ++j) {
- var index = vaAttributes[j].index;
- if (uniqueIndices[index]) {
- throw new DeveloperError('Index ' + index + ' is used by more than one attribute.');
- }
- uniqueIndices[index] = true;
- }
- var vao;
- // Setup VAO if extension is supported
- if (defined(vertexArrayObject)) {
- vao = vertexArrayObject.createVertexArrayOES();
- vertexArrayObject.bindVertexArrayOES(vao);
- bind(gl, vaAttributes, indexBuffer);
- vertexArrayObject.bindVertexArrayOES(null);
- }
- this._numberOfVertices = numberOfVertices;
- this._gl = gl;
- this._vaoExtension = vertexArrayObject;
- this._vao = vao;
- this._attributes = vaAttributes;
- this._indexBuffer = indexBuffer;
- };
- defineProperties(VertexArray.prototype, {
- numberOfAttributes : {
- get : function() {
- return this._attributes.length;
- }
- },
- numberOfVertices : {
- get : function() {
- return this._numberOfVertices;
- }
- },
- indexBuffer : {
- get : function() {
- return this._indexBuffer;
- }
- }
- });
- /**
- * index is the location in the array of attributes, not the index property of an attribute.
- */
- VertexArray.prototype.getAttribute = function(index) {
- //>>includeStart('debug', pragmas.debug);
- if (!defined(index)) {
- throw new DeveloperError('index is required.');
- }
- //>>includeEnd('debug');
- return this._attributes[index];
- };
- VertexArray.prototype._bind = function() {
- if (defined(this._vao)) {
- this._vaoExtension.bindVertexArrayOES(this._vao);
- } else {
- bind(this._gl, this._attributes, this._indexBuffer);
- }
- };
- VertexArray.prototype._unBind = function() {
- if (defined(this._vao)) {
- this._vaoExtension.bindVertexArrayOES(null);
- } else {
- var attributes = this._attributes;
- var gl = this._gl;
- for ( var i = 0; i < attributes.length; ++i) {
- var attribute = attributes[i];
- if (attribute.enabled) {
- attribute.disableVertexAttribArray(gl);
- }
- }
- if (this._indexBuffer) {
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
- }
- }
- };
- VertexArray.prototype.isDestroyed = function() {
- return false;
- };
- VertexArray.prototype.destroy = function() {
- var attributes = this._attributes;
- for ( var i = 0; i < attributes.length; ++i) {
- var vertexBuffer = attributes[i].vertexBuffer;
- if (defined(vertexBuffer) && !vertexBuffer.isDestroyed() && vertexBuffer.vertexArrayDestroyable) {
- vertexBuffer.destroy();
- }
- }
- var indexBuffer = this._indexBuffer;
- if (defined(indexBuffer) && !indexBuffer.isDestroyed() && indexBuffer.vertexArrayDestroyable) {
- indexBuffer.destroy();
- }
- if (defined(this._vao)) {
- this._vaoExtension.deleteVertexArrayOES(this._vao);
- }
- return destroyObject(this);
- };
- return VertexArray;
- });
|