UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

405 lines (404 loc) 12.4 kB
import Base from "./core/Base.mjs"; import glenum from "./core/glenum.mjs"; import Cache from "./core/Cache.mjs"; import vendor from "./core/vendor.mjs"; function getArrayCtorByType(type) { return { "byte": vendor.Int8Array, "ubyte": vendor.Uint8Array, "short": vendor.Int16Array, "ushort": vendor.Uint16Array }[type] || vendor.Float32Array; } function makeAttrKey(attrName) { return "attr_" + attrName; } function Attribute(name, type, size, semantic) { this.name = name; this.type = type; this.size = size; this.semantic = semantic || ""; this.value = null; switch (size) { case 1: this.get = function(idx) { return this.value[idx]; }; this.set = function(idx, value) { this.value[idx] = value; }; this.copy = function(target, source) { this.value[target] = this.value[target]; }; break; case 2: this.get = function(idx, out) { var arr = this.value; out[0] = arr[idx * 2]; out[1] = arr[idx * 2 + 1]; return out; }; this.set = function(idx, val) { var arr = this.value; arr[idx * 2] = val[0]; arr[idx * 2 + 1] = val[1]; }; this.copy = function(target, source) { var arr = this.value; source *= 2; target *= 2; arr[target] = arr[source]; arr[target + 1] = arr[source + 1]; }; break; case 3: this.get = function(idx, out) { var idx3 = idx * 3; var arr = this.value; out[0] = arr[idx3]; out[1] = arr[idx3 + 1]; out[2] = arr[idx3 + 2]; return out; }; this.set = function(idx, val) { var idx3 = idx * 3; var arr = this.value; arr[idx3] = val[0]; arr[idx3 + 1] = val[1]; arr[idx3 + 2] = val[2]; }; this.copy = function(target, source) { var arr = this.value; source *= 3; target *= 3; arr[target] = arr[source]; arr[target + 1] = arr[source + 1]; arr[target + 2] = arr[source + 2]; }; break; case 4: this.get = function(idx, out) { var arr = this.value; var idx4 = idx * 4; out[0] = arr[idx4]; out[1] = arr[idx4 + 1]; out[2] = arr[idx4 + 2]; out[3] = arr[idx4 + 3]; return out; }; this.set = function(idx, val) { var arr = this.value; var idx4 = idx * 4; arr[idx4] = val[0]; arr[idx4 + 1] = val[1]; arr[idx4 + 2] = val[2]; arr[idx4 + 3] = val[3]; }; this.copy = function(target, source) { var arr = this.value; source *= 4; target *= 4; arr[target] = arr[source]; arr[target + 1] = arr[source + 1]; arr[target + 2] = arr[source + 2]; arr[target + 3] = arr[source + 3]; }; } } Attribute.prototype.init = function(nVertex) { if (!this.value || this.value.length !== nVertex * this.size) { var ArrayConstructor = getArrayCtorByType(this.type); this.value = new ArrayConstructor(nVertex * this.size); } }; Attribute.prototype.fromArray = function(array) { var ArrayConstructor = getArrayCtorByType(this.type); var value; if (array[0] && array[0].length) { var n = 0; var size = this.size; value = new ArrayConstructor(array.length * size); for (var i = 0; i < array.length; i++) { for (var j = 0; j < size; j++) { value[n++] = array[i][j]; } } } else { value = new ArrayConstructor(array); } this.value = value; }; Attribute.prototype.clone = function(copyValue) { var ret = new Attribute(this.name, this.type, this.size, this.semantic); if (copyValue) { console.warn("todo"); } return ret; }; function AttributeBuffer(name, type, buffer, size, semantic) { this.name = name; this.type = type; this.buffer = buffer; this.size = size; this.semantic = semantic; this.symbol = ""; this.needsRemove = false; } function IndicesBuffer(buffer) { this.buffer = buffer; this.count = 0; } var GeometryBase = Base.extend( function() { return { attributes: {}, indices: null, dynamic: true, _enabledAttributes: null, __used: 0 }; }, function() { this._cache = new Cache(); this._attributeList = Object.keys(this.attributes); this.__vaoCache = {}; }, { mainAttribute: "", pick: null, pickByRay: null, dirty: function() { var enabledAttributes = this.getEnabledAttributes(); for (var i = 0; i < enabledAttributes.length; i++) { this.dirtyAttribute(enabledAttributes[i]); } this.dirtyIndices(); this._enabledAttributes = null; this._cache.dirty("any"); }, dirtyIndices: function() { this._cache.dirtyAll("indices"); }, dirtyAttribute: function(attrName) { this._cache.dirtyAll(makeAttrKey(attrName)); this._cache.dirtyAll("attributes"); }, getTriangleIndices: function(idx, out) { if (idx < this.triangleCount && idx >= 0) { if (!out) { out = []; } var indices = this.indices; out[0] = indices[idx * 3]; out[1] = indices[idx * 3 + 1]; out[2] = indices[idx * 3 + 2]; return out; } }, setTriangleIndices: function(idx, arr) { var indices = this.indices; indices[idx * 3] = arr[0]; indices[idx * 3 + 1] = arr[1]; indices[idx * 3 + 2] = arr[2]; }, isUseIndices: function() { return !!this.indices; }, initIndicesFromArray: function(array) { var value; var ArrayConstructor = this.vertexCount > 65535 ? vendor.Uint32Array : vendor.Uint16Array; if (array[0] && array[0].length) { var n = 0; var size = 3; value = new ArrayConstructor(array.length * size); for (var i = 0; i < array.length; i++) { for (var j = 0; j < size; j++) { value[n++] = array[i][j]; } } } else { value = new ArrayConstructor(array); } this.indices = value; }, createAttribute: function(name, type, size, semantic) { var attrib = new Attribute(name, type, size, semantic); if (this.attributes[name]) { this.removeAttribute(name); } this.attributes[name] = attrib; this._attributeList.push(name); return attrib; }, removeAttribute: function(name) { var attributeList = this._attributeList; var idx = attributeList.indexOf(name); if (idx >= 0) { attributeList.splice(idx, 1); delete this.attributes[name]; return true; } return false; }, getAttribute: function(name) { return this.attributes[name]; }, getEnabledAttributes: function() { var enabledAttributes = this._enabledAttributes; var attributeList = this._attributeList; if (enabledAttributes) { return enabledAttributes; } var result = []; var nVertex = this.vertexCount; for (var i = 0; i < attributeList.length; i++) { var name = attributeList[i]; var attrib = this.attributes[name]; if (attrib.value) { if (attrib.value.length === nVertex * attrib.size) { result.push(name); } } } this._enabledAttributes = result; return result; }, getBufferChunks: function(renderer) { var cache = this._cache; cache.use(renderer.__uid__); var isAttributesDirty = cache.isDirty("attributes"); var isIndicesDirty = cache.isDirty("indices"); if (isAttributesDirty || isIndicesDirty) { this._updateBuffer(renderer.gl, isAttributesDirty, isIndicesDirty); var enabledAttributes = this.getEnabledAttributes(); for (var i = 0; i < enabledAttributes.length; i++) { cache.fresh(makeAttrKey(enabledAttributes[i])); } cache.fresh("attributes"); cache.fresh("indices"); } cache.fresh("any"); return cache.get("chunks"); }, _updateBuffer: function(_gl, isAttributesDirty, isIndicesDirty) { var cache = this._cache; var chunks = cache.get("chunks"); var firstUpdate = false; if (!chunks) { chunks = []; chunks[0] = { attributeBuffers: [], indicesBuffer: null }; cache.put("chunks", chunks); firstUpdate = true; } var chunk = chunks[0]; var attributeBuffers = chunk.attributeBuffers; var indicesBuffer = chunk.indicesBuffer; if (isAttributesDirty || firstUpdate) { var attributeList = this.getEnabledAttributes(); var attributeBufferMap = {}; if (!firstUpdate) { for (var i = 0; i < attributeBuffers.length; i++) { attributeBufferMap[attributeBuffers[i].name] = attributeBuffers[i]; } } for (var k = 0; k < attributeList.length; k++) { var name = attributeList[k]; var attribute = this.attributes[name]; var bufferInfo; if (!firstUpdate) { bufferInfo = attributeBufferMap[name]; } var buffer; if (bufferInfo) { buffer = bufferInfo.buffer; } else { buffer = _gl.createBuffer(); } if (cache.isDirty(makeAttrKey(name))) { _gl.bindBuffer(_gl.ARRAY_BUFFER, buffer); _gl.bufferData(_gl.ARRAY_BUFFER, attribute.value, this.dynamic ? _gl.DYNAMIC_DRAW : _gl.STATIC_DRAW); } attributeBuffers[k] = new AttributeBuffer(name, attribute.type, buffer, attribute.size, attribute.semantic); } for (var i = k; i < attributeBuffers.length; i++) { _gl.deleteBuffer(attributeBuffers[i].buffer); } attributeBuffers.length = k; } if (this.isUseIndices() && (isIndicesDirty || firstUpdate)) { if (!indicesBuffer) { indicesBuffer = new IndicesBuffer(_gl.createBuffer()); chunk.indicesBuffer = indicesBuffer; } indicesBuffer.count = this.indices.length; _gl.bindBuffer(_gl.ELEMENT_ARRAY_BUFFER, indicesBuffer.buffer); _gl.bufferData(_gl.ELEMENT_ARRAY_BUFFER, this.indices, this.dynamic ? _gl.DYNAMIC_DRAW : _gl.STATIC_DRAW); } }, dispose: function(renderer) { var cache = this._cache; cache.use(renderer.__uid__); var chunks = cache.get("chunks"); if (chunks) { for (var c = 0; c < chunks.length; c++) { var chunk = chunks[c]; for (var k = 0; k < chunk.attributeBuffers.length; k++) { var attribs = chunk.attributeBuffers[k]; renderer.gl.deleteBuffer(attribs.buffer); } if (chunk.indicesBuffer) { renderer.gl.deleteBuffer(chunk.indicesBuffer.buffer); } } } if (this.__vaoCache) { var vaoExt = renderer.getGLExtension("OES_vertex_array_object"); for (var id in this.__vaoCache) { var vao = this.__vaoCache[id].vao; if (vao) { vaoExt.deleteVertexArrayOES(vao); } } } this.__vaoCache = {}; cache.deleteContext(renderer.__uid__); } } ); if (Object.defineProperty) { Object.defineProperty(GeometryBase.prototype, "vertexCount", { enumerable: false, get: function() { var mainAttribute = this.attributes[this.mainAttribute]; if (!mainAttribute) { mainAttribute = this.attributes[this._attributeList[0]]; } if (!mainAttribute || !mainAttribute.value) { return 0; } return mainAttribute.value.length / mainAttribute.size; } }); Object.defineProperty(GeometryBase.prototype, "triangleCount", { enumerable: false, get: function() { var indices = this.indices; if (!indices) { return 0; } else { return indices.length / 3; } } }); } GeometryBase.STATIC_DRAW = glenum.STATIC_DRAW; GeometryBase.DYNAMIC_DRAW = glenum.DYNAMIC_DRAW; GeometryBase.STREAM_DRAW = glenum.STREAM_DRAW; GeometryBase.AttributeBuffer = AttributeBuffer; GeometryBase.IndicesBuffer = IndicesBuffer; GeometryBase.Attribute = Attribute; var GeometryBase$1 = GeometryBase; export { GeometryBase$1 as default };