UNPKG

pbrtools

Version:
203 lines (202 loc) 7.22 kB
"use strict"; class geo_Vertex { constructor() { this.edge = []; this.face = []; } } exports.geo_Vertex = geo_Vertex; class geo_Edge { } exports.geo_Edge = geo_Edge; class MeshGeo { /** * * @param vb * @param ib * @param fstride {number} vertex的float个数。即vertex的stride/4。 用来计算顶点个数和确定xyz的位置(每个点的前3个) * @param uvoff {number} 用来取出每个点的uv * @param attrib {string} 目前没有用上。 */ constructor(vb, ib, fstride, uvoff, attrib) { this.vertexnum = 0; this.fstride = 0; //faces:geo_Face[]; face直接用ib即可 this.uvfoff = 0; //uv在floatarray的偏移。不是byte,是float this.normoff = 3; this.tmpMem = new Float32Array(32); this.tmpMem1 = new Float32Array(32); this.TB = new Float32Array(6); this.vb = vb; this.ib = ib; this.fstride = fstride; this.attrib = attrib; this.uvfoff = uvoff; this.vertexnum = vb.length / fstride; this.gatherInfo(); } gatherInfo() { this.vertexes = new Array(this.vertexnum).fill(new geo_Vertex()); this.vertexes.forEach((v, i) => { v = this.vertexes[i] = new geo_Vertex(); //每个都要是不同的实例。 var st = 0; while (true) { var vpos = this.ib.indexOf(i, st); if (vpos >= 0) { st = vpos + 1; var fid = Math.floor(vpos / 3); if (v.face.indexOf(fid) < 0) { v.face.push(fid); } } else { break; } } }); } /** * * @param verts * @param p0 * @param p1 * @param p2 * @param uv0 {number} uv0的起点的偏移,单位是float * @param uv1 * @param uv2 * @param normal * @param outverts * @param tangent * @param binormal */ _calcTangent(verts, p0, p1, p2, uv0, uv1, uv2, normal, outverts, tangent, binormal) { this.TB.fill(0); var tb = this.TB; var dx0 = verts[p1] - verts[p0]; var dy0 = verts[p1 + 1] - verts[p0 + 1]; var dz0 = verts[p1 + 2] - verts[p0 + 2]; var dx1 = verts[p2] - verts[p0]; var dy1 = verts[p2 + 1] - verts[p0 + 1]; var dz1 = verts[p2 + 2] - verts[p0 + 2]; var du0 = verts[uv1] - verts[uv0]; var dv0 = verts[uv1 + 1] - verts[uv0 + 1]; var du1 = verts[uv2] - verts[uv0]; var dv1 = verts[uv2 + 1] - verts[uv0 + 1]; var fenmu = du0 * dv1 - du1 * dv0; //这个分母不能忽略,决定了正负 if (fenmu > 0) { tb[0] = dx0 * dv1 - dx1 * dv0; tb[1] = dy0 * dv1 - dy1 * dv0; tb[2] = dz0 * dv1 - dz1 * dv0; tb[3] = -dx0 * du1 + dx1 * du0; tb[4] = -dy0 * du1 + dy1 * du0; tb[5] = -dz0 * du1 + dz1 * du0; } else { tb[0] = -dx0 * dv1 + dx1 * dv0; tb[1] = -dy0 * dv1 + dy1 * dv0; tb[2] = -dz0 * dv1 + dz1 * dv0; tb[3] = dx0 * du1 - dx1 * du0; tb[4] = dy0 * du1 - dy1 * du0; tb[5] = dz0 * du1 - dz1 * du0; } this.vec3_normalize(tb, 0); this.vec3_normalize(tb, 3); //console.log(tb[0],tb[1],tb[2]);console.log(tb[3],tb[4],tb[5]); this.vec3_cross(tb, 0, 3); var tdb = this.tmpMem[0] * verts[normal] + this.tmpMem[1] * verts[normal + 1] + this.tmpMem[2] * verts[normal + 2]; if (tdb < 0.0) { } outverts[tangent] = tb[0]; outverts[tangent + 1] = tb[1]; outverts[tangent + 2] = tb[2]; outverts[binormal] = tb[3]; outverts[binormal + 1] = tb[4]; outverts[binormal + 2] = tb[5]; return true; } vec3_cross(vb, v0, v1) { var ax = vb[v0], ay = vb[v0 + 1], az = vb[v0 + 2]; var bx = vb[v1], by = vb[v1 + 1], bz = vb[v1 + 2]; this.tmpMem[0] = ay * bz - az * by; this.tmpMem[1] = az * bx - ax * bz; this.tmpMem[2] = ax * by - ay * bx; } vec3_length(vb, v0) { var x = vb[v0]; var y = vb[v0 + 1]; var z = vb[v0 + 2]; var l = x * x + y * y + z * z; return Math.sqrt(l); } vec3_normalize(vb, v0) { var l = this.vec3_length(vb, v0); if (l < 1e-9) { vb[v0] = 0; vb[v0 + 1] = 0; vb[v0 + 2] = 0; return; } vb[v0] /= l; vb[v0 + 1] /= l; vb[v0 + 2] /= l; } vec3_copy(vbo, v1, vb, v0) { vbo[v1] = vb[v0]; vbo[v1 + 1] = vb[v0 + 1]; vbo[v1 + 2] = vb[v0 + 2]; } /** * 返回tangent和binormal */ calcTangent() { var ret = { tan: new Float32Array(this.vertexnum * 3), binor: new Float32Array(this.vertexnum * 3) }; this.vertexes.forEach((v, i) => { var sum = 0; // var outarr = new Float32Array(6).fill(0); v.face.forEach((ef, fi) => { var cout = new Float32Array(6); var v0 = this.ib[ef * 3]; var v1 = this.ib[ef * 3 + 1]; var v2 = this.ib[ef * 3 + 2]; /* 加上这个效果就全错了 if(v1==i){ [v0,v1]=[v1,v0]; } else if(v2==i){ [v0,v2]=[v2,v0]; } */ var v0p = v0 * this.fstride; var v1p = v1 * this.fstride; var v2p = v2 * this.fstride; if (!this._calcTangent(this.vb, v0p, v1p, v2p, v0p + this.uvfoff, v1p + this.uvfoff, v2p + this.uvfoff, this.normoff, cout, 0, 3)) return; var dbuff = this.tmpMem1; dbuff[0] = this.vb[v1p] - this.vb[v0p]; //dx dbuff[1] = this.vb[v1p + 1] - this.vb[v0p + 1]; //dy dbuff[2] = this.vb[v1p + 2] - this.vb[v0p + 2]; //dz dbuff[3] = this.vb[v2p] - this.vb[v0p]; //dx1 dbuff[4] = this.vb[v2p + 1] - this.vb[v0p + 1]; //dy1 dbuff[5] = this.vb[v2p + 2] - this.vb[v0p + 2]; //dz1 this.vec3_cross(dbuff, 0, 3); var l = this.vec3_length(this.tmpMem, 0); for (var oi = 0; oi < 6; oi++) { outarr[oi] += cout[oi] * l; } sum += l; }); /* for(var oi=0; oi<6; oi++){ outarr[oi]=outarr[oi]/sum; } */ this.vec3_normalize(outarr, 0); this.vec3_normalize(outarr, 3); this.vec3_copy(ret.tan, i * 3, outarr, 0); this.vec3_copy(ret.binor, i * 3, outarr, 3); }); return ret; } } exports.MeshGeo = MeshGeo;