cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
365 lines (364 loc) • 12.7 kB
JavaScript
import vendor from "./core/vendor.mjs";
import vec3 from "./glmatrix/vec3.mjs";
import mat4 from "./glmatrix/mat4.mjs";
import BoundingBox from "./math/BoundingBox.mjs";
import GeometryBase from "./GeometryBase.mjs";
var vec3Create = vec3.create;
var vec3Add = vec3.add;
var vec3Set = vec3.set;
var Attribute = GeometryBase.Attribute;
var Geometry = GeometryBase.extend(
function() {
return {
attributes: {
position: new Attribute("position", "float", 3, "POSITION"),
texcoord0: new Attribute("texcoord0", "float", 2, "TEXCOORD_0"),
texcoord1: new Attribute("texcoord1", "float", 2, "TEXCOORD_1"),
normal: new Attribute("normal", "float", 3, "NORMAL"),
tangent: new Attribute("tangent", "float", 4, "TANGENT"),
color: new Attribute("color", "float", 4, "COLOR"),
weight: new Attribute("weight", "float", 3, "WEIGHT"),
joint: new Attribute("joint", "float", 4, "JOINT"),
barycentric: new Attribute("barycentric", "float", 3, null)
},
boundingBox: null
};
},
{
mainAttribute: "position",
updateBoundingBox: function() {
var bbox = this.boundingBox;
if (!bbox) {
bbox = this.boundingBox = new BoundingBox();
}
var posArr = this.attributes.position.value;
if (posArr && posArr.length) {
var min = bbox.min;
var max = bbox.max;
var minArr = min.array;
var maxArr = max.array;
vec3.set(minArr, posArr[0], posArr[1], posArr[2]);
vec3.set(maxArr, posArr[0], posArr[1], posArr[2]);
for (var i = 3; i < posArr.length; ) {
var x = posArr[i++];
var y = posArr[i++];
var z = posArr[i++];
if (x < minArr[0]) {
minArr[0] = x;
}
if (y < minArr[1]) {
minArr[1] = y;
}
if (z < minArr[2]) {
minArr[2] = z;
}
if (x > maxArr[0]) {
maxArr[0] = x;
}
if (y > maxArr[1]) {
maxArr[1] = y;
}
if (z > maxArr[2]) {
maxArr[2] = z;
}
}
min._dirty = true;
max._dirty = true;
}
},
generateVertexNormals: function() {
if (!this.vertexCount) {
return;
}
var indices = this.indices;
var attributes = this.attributes;
var positions = attributes.position.value;
var normals = attributes.normal.value;
if (!normals || normals.length !== positions.length) {
normals = attributes.normal.value = new vendor.Float32Array(positions.length);
} else {
for (var i = 0; i < normals.length; i++) {
normals[i] = 0;
}
}
var p1 = vec3Create();
var p2 = vec3Create();
var p3 = vec3Create();
var v21 = vec3Create();
var v32 = vec3Create();
var n = vec3Create();
var len = indices ? indices.length : this.vertexCount;
var i1, i2, i3;
for (var f = 0; f < len; ) {
if (indices) {
i1 = indices[f++];
i2 = indices[f++];
i3 = indices[f++];
} else {
i1 = f++;
i2 = f++;
i3 = f++;
}
vec3Set(p1, positions[i1 * 3], positions[i1 * 3 + 1], positions[i1 * 3 + 2]);
vec3Set(p2, positions[i2 * 3], positions[i2 * 3 + 1], positions[i2 * 3 + 2]);
vec3Set(p3, positions[i3 * 3], positions[i3 * 3 + 1], positions[i3 * 3 + 2]);
vec3.sub(v21, p1, p2);
vec3.sub(v32, p2, p3);
vec3.cross(n, v21, v32);
for (var i = 0; i < 3; i++) {
normals[i1 * 3 + i] = normals[i1 * 3 + i] + n[i];
normals[i2 * 3 + i] = normals[i2 * 3 + i] + n[i];
normals[i3 * 3 + i] = normals[i3 * 3 + i] + n[i];
}
}
for (var i = 0; i < normals.length; ) {
vec3Set(n, normals[i], normals[i + 1], normals[i + 2]);
vec3.normalize(n, n);
normals[i++] = n[0];
normals[i++] = n[1];
normals[i++] = n[2];
}
this.dirty();
},
generateFaceNormals: function() {
if (!this.vertexCount) {
return;
}
if (!this.isUniqueVertex()) {
this.generateUniqueVertex();
}
var indices = this.indices;
var attributes = this.attributes;
var positions = attributes.position.value;
var normals = attributes.normal.value;
var p1 = vec3Create();
var p2 = vec3Create();
var p3 = vec3Create();
var v21 = vec3Create();
var v32 = vec3Create();
var n = vec3Create();
if (!normals) {
normals = attributes.normal.value = new Float32Array(positions.length);
}
var len = indices ? indices.length : this.vertexCount;
var i1, i2, i3;
for (var f = 0; f < len; ) {
if (indices) {
i1 = indices[f++];
i2 = indices[f++];
i3 = indices[f++];
} else {
i1 = f++;
i2 = f++;
i3 = f++;
}
vec3Set(p1, positions[i1 * 3], positions[i1 * 3 + 1], positions[i1 * 3 + 2]);
vec3Set(p2, positions[i2 * 3], positions[i2 * 3 + 1], positions[i2 * 3 + 2]);
vec3Set(p3, positions[i3 * 3], positions[i3 * 3 + 1], positions[i3 * 3 + 2]);
vec3.sub(v21, p1, p2);
vec3.sub(v32, p2, p3);
vec3.cross(n, v21, v32);
vec3.normalize(n, n);
for (var i = 0; i < 3; i++) {
normals[i1 * 3 + i] = n[i];
normals[i2 * 3 + i] = n[i];
normals[i3 * 3 + i] = n[i];
}
}
this.dirty();
},
generateTangents: function() {
if (!this.vertexCount) {
return;
}
var nVertex = this.vertexCount;
var attributes = this.attributes;
if (!attributes.tangent.value) {
attributes.tangent.value = new Float32Array(nVertex * 4);
}
var texcoords = attributes.texcoord0.value;
var positions = attributes.position.value;
var tangents = attributes.tangent.value;
var normals = attributes.normal.value;
if (!texcoords) {
console.warn("Geometry without texcoords can't generate tangents.");
return;
}
var tan1 = [];
var tan2 = [];
for (var i = 0; i < nVertex; i++) {
tan1[i] = [0, 0, 0];
tan2[i] = [0, 0, 0];
}
var sdir = [0, 0, 0];
var tdir = [0, 0, 0];
var indices = this.indices;
var len = indices ? indices.length : this.vertexCount;
var i1, i2, i3;
for (var i = 0; i < len; ) {
if (indices) {
i1 = indices[i++];
i2 = indices[i++];
i3 = indices[i++];
} else {
i1 = i++;
i2 = i++;
i3 = i++;
}
var st1s = texcoords[i1 * 2], st2s = texcoords[i2 * 2], st3s = texcoords[i3 * 2], st1t = texcoords[i1 * 2 + 1], st2t = texcoords[i2 * 2 + 1], st3t = texcoords[i3 * 2 + 1], p1x = positions[i1 * 3], p2x = positions[i2 * 3], p3x = positions[i3 * 3], p1y = positions[i1 * 3 + 1], p2y = positions[i2 * 3 + 1], p3y = positions[i3 * 3 + 1], p1z = positions[i1 * 3 + 2], p2z = positions[i2 * 3 + 2], p3z = positions[i3 * 3 + 2];
var x1 = p2x - p1x, x2 = p3x - p1x, y1 = p2y - p1y, y2 = p3y - p1y, z1 = p2z - p1z, z2 = p3z - p1z;
var s1 = st2s - st1s, s2 = st3s - st1s, t1 = st2t - st1t, t2 = st3t - st1t;
var r = 1 / (s1 * t2 - t1 * s2);
sdir[0] = (t2 * x1 - t1 * x2) * r;
sdir[1] = (t2 * y1 - t1 * y2) * r;
sdir[2] = (t2 * z1 - t1 * z2) * r;
tdir[0] = (s1 * x2 - s2 * x1) * r;
tdir[1] = (s1 * y2 - s2 * y1) * r;
tdir[2] = (s1 * z2 - s2 * z1) * r;
vec3Add(tan1[i1], tan1[i1], sdir);
vec3Add(tan1[i2], tan1[i2], sdir);
vec3Add(tan1[i3], tan1[i3], sdir);
vec3Add(tan2[i1], tan2[i1], tdir);
vec3Add(tan2[i2], tan2[i2], tdir);
vec3Add(tan2[i3], tan2[i3], tdir);
}
var tmp = vec3Create();
var nCrossT = vec3Create();
var n = vec3Create();
for (var i = 0; i < nVertex; i++) {
n[0] = normals[i * 3];
n[1] = normals[i * 3 + 1];
n[2] = normals[i * 3 + 2];
var t = tan1[i];
vec3.scale(tmp, n, vec3.dot(n, t));
vec3.sub(tmp, t, tmp);
vec3.normalize(tmp, tmp);
vec3.cross(nCrossT, n, t);
tangents[i * 4] = tmp[0];
tangents[i * 4 + 1] = tmp[1];
tangents[i * 4 + 2] = tmp[2];
tangents[i * 4 + 3] = vec3.dot(nCrossT, tan2[i]) < 0 ? -1 : 1;
}
this.dirty();
},
isUniqueVertex: function() {
if (this.isUseIndices()) {
return this.vertexCount === this.indices.length;
} else {
return true;
}
},
generateUniqueVertex: function() {
if (!this.vertexCount || !this.indices) {
return;
}
if (this.indices.length > 65535) {
this.indices = new vendor.Uint32Array(this.indices);
}
var attributes = this.attributes;
var indices = this.indices;
var attributeNameList = this.getEnabledAttributes();
var oldAttrValues = {};
for (var a = 0; a < attributeNameList.length; a++) {
var name = attributeNameList[a];
oldAttrValues[name] = attributes[name].value;
attributes[name].init(this.indices.length);
}
var cursor = 0;
for (var i = 0; i < indices.length; i++) {
var ii = indices[i];
for (var a = 0; a < attributeNameList.length; a++) {
var name = attributeNameList[a];
var array = attributes[name].value;
var size = attributes[name].size;
for (var k = 0; k < size; k++) {
array[cursor * size + k] = oldAttrValues[name][ii * size + k];
}
}
indices[i] = cursor;
cursor++;
}
this.dirty();
},
generateBarycentric: function() {
if (!this.vertexCount) {
return;
}
if (!this.isUniqueVertex()) {
this.generateUniqueVertex();
}
var attributes = this.attributes;
var array = attributes.barycentric.value;
var indices = this.indices;
if (array && array.length === indices.length * 3) {
return;
}
array = attributes.barycentric.value = new Float32Array(indices.length * 3);
for (var i = 0; i < (indices ? indices.length : this.vertexCount / 3); ) {
for (var j = 0; j < 3; j++) {
var ii = indices ? indices[i++] : i * 3 + j;
array[ii * 3 + j] = 1;
}
}
this.dirty();
},
applyTransform: function(matrix) {
var attributes = this.attributes;
var positions = attributes.position.value;
var normals = attributes.normal.value;
var tangents = attributes.tangent.value;
matrix = matrix.array;
var inverseTransposeMatrix = mat4.create();
mat4.invert(inverseTransposeMatrix, matrix);
mat4.transpose(inverseTransposeMatrix, inverseTransposeMatrix);
var vec3TransformMat4 = vec3.transformMat4;
var vec3ForEach = vec3.forEach;
vec3ForEach(positions, 3, 0, null, vec3TransformMat4, matrix);
if (normals) {
vec3ForEach(normals, 3, 0, null, vec3TransformMat4, inverseTransposeMatrix);
}
if (tangents) {
vec3ForEach(tangents, 4, 0, null, vec3TransformMat4, inverseTransposeMatrix);
}
if (this.boundingBox) {
this.updateBoundingBox();
}
},
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__);
}
}
);
Geometry.STATIC_DRAW = GeometryBase.STATIC_DRAW;
Geometry.DYNAMIC_DRAW = GeometryBase.DYNAMIC_DRAW;
Geometry.STREAM_DRAW = GeometryBase.STREAM_DRAW;
Geometry.AttributeBuffer = GeometryBase.AttributeBuffer;
Geometry.IndicesBuffer = GeometryBase.IndicesBuffer;
Geometry.Attribute = Attribute;
var Geometry$1 = Geometry;
export { Geometry$1 as default };