Face FaceNewTriTex(const float3 &v0,const float3 &v1,const float3 &v2,const float2 &t0,const float2 &t1,const float2 &t2) { Face f; f.vertex = {v0,v1,v2}; f.xyz() = TriNormal(v0,v1,v2) ; f.w = -dot(f.xyz(), (v0 + v1 + v2) / 3.0f); FaceExtractMatVals(&f,v0,v1,v2,t0,t1,t2); return f; }
OBB::OBB(Mesh::const_iterator begin, Mesh::const_iterator end) { if (begin == end) { axes = -ZERO_SIZE * Matrix3f::Identity(); //make it inside out (i guess) origin = Vector3f::Zero(); return; } Vector3f centerOfMass = centroid(begin, end); Matrix3f inertiaTensor = Matrix3f::Zero(); auto addPt = [&](const Vector3f& pt, float mass) { Vector3f lpos = pt - centerOfMass; inertiaTensor(0, 0) += (lpos.y()*lpos.y() + lpos.z()*lpos.z()) * mass; inertiaTensor(1, 1) += (lpos.x()*lpos.x() + lpos.z()*lpos.z()) * mass; inertiaTensor(2, 2) += (lpos.x()*lpos.x() + lpos.y()*lpos.y()) * mass; inertiaTensor(1, 0) -= lpos.x()*lpos.y() * mass; inertiaTensor(2, 0) -= lpos.x()*lpos.z() * mass; inertiaTensor(2, 1) -= lpos.y()*lpos.z() * mass; }; for (const auto& tri : make_range(begin, end)) { float area = TriNormal(tri).norm() / 6.f; addPt(tri.col(0), area); addPt(tri.col(1), area); addPt(tri.col(2), area); } Eigen::SelfAdjointEigenSolver<Matrix3f> es; es.computeDirect(inertiaTensor); axes = es.eigenvectors(); float maxflt = std::numeric_limits<float>::max(); Eigen::Vector3f min{ maxflt, maxflt, maxflt }; Eigen::Vector3f max = -min; for (const auto& tri : make_range(begin, end)) { min = min.cwiseMin((axes.transpose() * tri).rowwise().minCoeff()); max = max.cwiseMax((axes.transpose() * tri).rowwise().maxCoeff()); } extent = (max - min).cwiseMax(ZERO_SIZE) / 2.f; origin = axes * (min + extent); }
void gldraw(const std::vector<float3> &verts, const std::vector<int3> &tris) { glBegin(GL_TRIANGLES); glColor4f(1, 1, 1, 0.25f); for (auto t : tris) { auto n = TriNormal(verts[t[0]], verts[t[1]], verts[t[2]]); glNormal3fv(n); auto vn = vabs(n); int k = argmax(&vn.x, 3); for (int j = 0; j < 3; j++) { const auto &v = verts[t[j]]; glTexCoord2f(v[(k + 1) % 3], v[(k + 2) % 3]); glVertex3fv(v); } } glEnd(); }
int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit) { if(verts_count <4) return 0; if(vlimit==0) vlimit=1000000000; int j; btVector3 bmin(*verts),bmax(*verts); btAlignedObjectArray<int> isextreme; isextreme.reserve(verts_count); btAlignedObjectArray<int> allow; allow.reserve(verts_count); for(j=0;j<verts_count;j++) { allow.push_back(1); isextreme.push_back(0); bmin.setMin (verts[j]); bmax.setMax (verts[j]); } btScalar epsilon = (bmax-bmin).length() * btScalar(0.001); btAssert (epsilon != 0.0); int4 p = FindSimplex(verts,verts_count,allow); if(p.x==-1) return 0; // simplex failed btVector3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) / btScalar(4.0); // a valid interior point btHullTriangle *t0 = allocateTriangle(p[2],p[3],p[1]); t0->n=int3(2,3,1); btHullTriangle *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0); btHullTriangle *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3); btHullTriangle *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2); isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1; checkit(t0);checkit(t1);checkit(t2);checkit(t3); for(j=0;j<m_tris.size();j++) { btHullTriangle *t=m_tris[j]; btAssert(t); btAssert(t->vmax<0); btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); t->vmax = maxdirsterid(verts,verts_count,n,allow); t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]); } btHullTriangle *te; vlimit-=4; while(vlimit >0 && ((te=extrudable(epsilon)) != 0)) { int3 ti=*te; int v=te->vmax; btAssert(v != -1); btAssert(!isextreme[v]); // wtf we've already done this vertex isextreme[v]=1; //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already j=m_tris.size(); while(j--) { if(!m_tris[j]) continue; int3 t=*m_tris[j]; if(above(verts,t,verts[v],btScalar(0.01)*epsilon)) { extrude(m_tris[j],v); } } // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle j=m_tris.size(); while(j--) { if(!m_tris[j]) continue; if(!hasvert(*m_tris[j],v)) break; int3 nt=*m_tris[j]; if(above(verts,nt,center,btScalar(0.01)*epsilon) || cross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) ) { btHullTriangle *nb = m_tris[m_tris[j]->n[0]]; btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->id<j); extrude(nb,v); j=m_tris.size(); } } j=m_tris.size(); while(j--) { btHullTriangle *t=m_tris[j]; if(!t) continue; if(t->vmax>=0) break; btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); t->vmax = maxdirsterid(verts,verts_count,n,allow); if(isextreme[t->vmax]) { t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate. } else { t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]); } } vlimit --; } return 1; }
int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon) { btVector3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]); return (dot(n,p-vertices[t[0]]) > epsilon); // EPSILON??? }