UNPKG

pbrtools

Version:
207 lines (192 loc) 7.03 kB
export class geo_Vertex{ edge:number[]=[]; face:number[]=[]; } export class geo_Edge{ v0:number; v1:number; } export class MeshGeo{ vb:Float32Array; ib:Uint16Array; vertexnum=0; fstride=0; attrib:string; //faces:geo_Face[]; face直接用ib即可 uvfoff=0;//uv在floatarray的偏移。不是byte,是float normoff=3; vertexes:geo_Vertex[]; edges:geo_Edge[]; tmpMem=new Float32Array(32); tmpMem1=new Float32Array(32); TB = new Float32Array(6); /** * * @param vb * @param ib * @param fstride {number} vertex的float个数。即vertex的stride/4。 用来计算顶点个数和确定xyz的位置(每个点的前3个) * @param uvoff {number} 用来取出每个点的uv * @param attrib {string} 目前没有用上。 */ constructor(vb:Float32Array, ib:Uint16Array, fstride:number, uvoff:number, attrib:string){ 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<geo_Vertex>(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:Float32Array, p0:number, p1:number, p2:number, uv0:number, uv1:number, uv2:number, normal:number, outverts:Float32Array, tangent:number, binormal:number){ 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){ //tb.forEach((v,i)=>{tb[i]=-tb[i];}); } 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:Float32Array, v0:number, v1:number){ 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:Float32Array, v0:number){ 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:Float32Array, 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:Float32Array, v1:number, vb:Float32Array, v0:number ){ 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; } }