// draw periodic cell, if active void OpenGLRenderer::drawPeriodicCell(){ if(!scene->isPeriodic) return; glColor3v(cellColor); glPushMatrix(); // Vector3r size=scene->cell->getSize(); const Matrix3r& hSize=scene->cell->hSize; if(dispScale!=Vector3r::Ones()){ const Matrix3r& refHSize(scene->cell->refHSize); Matrix3r scaledHSize; for(int i=0; i<3; i++) scaledHSize.col(i)=refHSize.col(i)+dispScale.cwiseProduct(Vector3r(hSize.col(i)-refHSize.col(i))); GLUtils::Parallelepiped(scaledHSize.col(0),scaledHSize.col(1),scaledHSize.col(2)); } else { GLUtils::Parallelepiped(hSize.col(0),hSize.col(1),hSize.col(2)); } glPopMatrix(); }
// draw periodic cell, if active void Renderer::drawPeriodicCell(){ if(!scene->isPeriodic || !cell) return; glColor3v(Vector3r(1,1,0)); glPushMatrix(); const Matrix3r& hSize=scene->cell->hSize; if(scaleOn && dispScale!=Vector3r::Ones()){ const Matrix3r& refHSize(scene->cell->refHSize); Matrix3r scaledHSize; for(int i=0; i<3; i++) scaledHSize.col(i)=refHSize.col(i)+((dispScale-Vector3r::Ones()).array()*Vector3r(hSize.col(i)-refHSize.col(i)).array()).matrix(); GLUtils::Parallelepiped(scaledHSize.col(0),scaledHSize.col(1),scaledHSize.col(2)); } else { GLUtils::Parallelepiped(hSize.col(0),hSize.col(1),hSize.col(2)); } glPopMatrix(); }
void Cell::integrateAndUpdate(Real dt){ //incremental displacement gradient _trsfInc=dt*gradV; // total transformation; M = (Id+G).M = F.M trsf+=_trsfInc*trsf; _invTrsf=trsf.inverse(); if(trsfUpperTriangular) checkTrsfUpperTriangular(); // hSize contains colums with updated base vectors Matrix3r prevHsize=hSize; // remember old value if(homoDeform==HOMO_GRADV2) hSize=(Matrix3r::Identity()-gradV*dt/2.).inverse()*(Matrix3r::Identity()+gradV*dt/2.)*hSize; else hSize+=_trsfInc*hSize; pprevHsize=.5*(prevHsize+hSize); // average of previous and current value if(hSize.determinant()==0){ throw std::runtime_error("Cell is degenerate (zero volume)."); } // lengths of transformed cell vectors, skew cosines Matrix3r Hnorm; // normalized transformed base vectors for(int i=0; i<3; i++){ Vector3r base(hSize.col(i)); _size[i]=base.norm(); base/=_size[i]; //base is normalized now Hnorm(0,i)=base[0]; Hnorm(1,i)=base[1]; Hnorm(2,i)=base[2]; }; // skew cosines for(int i=0; i<3; i++){ int i1=(i+1)%3, i2=(i+2)%3; // sin between axes is cos of skew _cos[i]=(Hnorm.col(i1).cross(Hnorm.col(i2))).squaredNorm(); } // pure shear trsf: ones on diagonal _shearTrsf=Hnorm; // pure unshear transformation _unshearTrsf=_shearTrsf.inverse(); // some parts can branch depending on presence/absence of shear _hasShear=(hSize(0,1)!=0 || hSize(0,2)!=0 || hSize(1,0)!=0 || hSize(1,2)!=0 || hSize(2,0)!=0 || hSize(2,1)!=0); // OpenGL shear matrix (used frequently) fillGlShearTrsfMatrix(_glShearTrsfMatrix); if(!(homoDeform==HOMO_NONE || homoDeform==HOMO_POS || homoDeform==HOMO_VEL || homoDeform==HOMO_VEL_2ND || homoDeform==HOMO_GRADV2)) throw std::invalid_argument("Cell.homoDeform must be in {0,1,2,3,4}."); }
bool PositionBasedElasticRod::ComputeDarbouxVector(const Matrix3r& dA, const Matrix3r& dB, const float mid_edge_length, Vector3r& darboux_vector) { float factor = 1.0f + dA.col(0).dot(dB.col(0)) + dA.col(1).dot(dB.col(1)) + dA.col(2).dot(dB.col(2)); factor = 2.0f / (mid_edge_length * factor); for (int c = 0; c < 3; ++c) { const int i = permutation[c][0]; const int j = permutation[c][1]; const int k = permutation[c][2]; darboux_vector[i] = dA.col(j).dot(dB.col(k)) - dA.col(k).dot(dB.col(j)); } darboux_vector *= factor; return true; }
// ---------------------------------------------------------------------------------------------- bool PositionBasedElasticRod::ComputeMaterialFrame( const Vector3r& pA, const Vector3r& pB, const Vector3r& pG, Matrix3r& frame) { frame.col(2) = (pB - pA); frame.col(2).normalize(); frame.col(1) = (frame.col(2).cross(pG - pA)); frame.col(1).normalize(); frame.col(0) = frame.col(1).cross(frame.col(2)); // frame.col(0).normalize(); return true; }
void Membrane::setRefConf(){ if(!node) node=make_shared<Node>(); // set initial node position and orientation node->pos=this->getCentroid(); // for orientation, there is a few choices which one to pick enum {INI_CS_SIMPLE=0,INI_CS_NODE0_AT_X}; const int ini_cs=INI_CS_NODE0_AT_X; //const int ini_cs=INI_CS_SIMPLE; switch(ini_cs){ case INI_CS_SIMPLE: node->ori.setFromTwoVectors(Vector3r::UnitZ(),this->getNormal()); break; case INI_CS_NODE0_AT_X:{ Matrix3r T; T.col(0)=(nodes[0]->pos-node->pos).normalized(); // QQQ: row->col T.col(2)=this->getNormal(); T.col(1)=T.col(2).cross(T.col(0)); assert(T.col(0).dot(T.col(2))<1e-12); node->ori=Quaternionr(T); break; } }; // reference nodal positions for(int i:{0,1,2}){ // Vector3r nl=node->ori.conjugate()*(nodes[i]->pos-node->pos); // QQQ Vector3r nl=node->glob2loc(nodes[i]->pos); assert(nl[2]<1e-6*(max(abs(nl[0]),abs(nl[1])))); // z-coord should be zero refPos.segment<2>(2*i)=nl.head<2>(); } // reference nodal rotations refRot.resize(3); for(int i:{0,1,2}){ // facet node orientation minus vertex node orientation, in local frame (read backwards) /// QQQ: refRot[i]=node->ori*nodes[i]->ori.conjugate(); refRot[i]=nodes[i]->ori.conjugate()*node->ori; //LOG_WARN("refRot["<<i<<"]="<<AngleAxisr(refRot[i]).angle()<<"/"<<AngleAxisr(refRot[i]).axis().transpose()); }; // set displacements to zero uXy=phiXy=Vector6r::Zero(); #ifdef MEMBRANE_DEBUG_ROT drill=Vector3r::Zero(); currRot.resize(3); #endif // delete stiffness matrices to force their re-creating KKcst.resize(0,0); KKdkt.resize(0,0); };
bool PositionBasedElasticRod::ComputeDarbouxGradient( const Vector3r& darboux_vector, const float length, const Matrix3r& da, const Matrix3r& db, //const Matrix3r(*dajpi)[3], const Matrix3r(*dbjpi)[3], const Matrix3r dajpi[3][3], const Matrix3r dbjpi[3][3], const Vector3r& bendAndTwistKs, Matrix3r& omega_pa, Matrix3r& omega_pb, Matrix3r& omega_pc, Matrix3r& omega_pd, Matrix3r& omega_pe ) { //float x = 1.0f + da[0] * db[0] + da[1] * db[1] + da[2] * db[2]; float x = 1.0f + da.col(0).dot(db.col(0)) + da.col(1).dot(db.col(1)) + da.col(2).dot(db.col(2)); x = 2.0f / (length * x); for (int c = 0; c < 3; ++c) { const int i = permutation[c][0]; const int j = permutation[c][1]; const int k = permutation[c][2]; // pa { Vector3r term1(0,0,0); Vector3r term2(0,0,0); Vector3r tmp(0,0,0); // first term //dj::MulVecMatrix3x3<real>(db[k](), (real(*)[3]) &dajpi[j][0], term1()); //dj::MulVecMatrix3x3<real>(db[j](), (real(*)[3]) &dajpi[k][0], tmp()); //DOUBLE CHECK !!! term1 = dajpi[j][0].transpose() * db.col(k); tmp = dajpi[k][0].transpose() * db.col(j); term1 = term1 - tmp; // second term for (int n = 0; n < 3; ++n) { //dj::MulVecMatrix3x3<real>(db[n](), (real(*)[3]) &dajpi[n][0], tmp()); //DOUBLE CHECK !!! tmp = dajpi[n][0].transpose() * db.col(n); term2 = term2 + tmp; } omega_pa.col(i) = (term1)-(0.5f * darboux_vector[i] * length) * (term2); omega_pa.col(i) *= (x * bendAndTwistKs[i]); } // pb { Vector3r term1(0, 0, 0); Vector3r term2(0, 0, 0); Vector3r tmp(0, 0, 0); // first term //dj::MulVecMatrix3x3<real>(db[k](), (real(*)[3]) &dajpi[j][1], term1()); //dj::MulVecMatrix3x3<real>(db[j](), (real(*)[3]) &dajpi[k][1], tmp()); term1 = dajpi[j][1].transpose() * db.col(k); tmp = dajpi[k][1].transpose() * db.col(j); term1 = term1 - tmp; // third term //dj::MulVecMatrix3x3<real>(da[k](), (real(*)[3]) &dbjpi[j][0], tmp()); tmp = dbjpi[j][0].transpose() * da.col(k); term1 = term1 - tmp; //dj::MulVecMatrix3x3<real>(da[j](), (real(*)[3]) &dbjpi[k][0], tmp()); tmp = dbjpi[k][0].transpose() * da.col(j); term1 = term1 + tmp; // second term for (int n = 0; n < 3; ++n) { //dj::MulVecMatrix3x3<real>(db[n](), (real(*)[3]) &dajpi[n][1], tmp()); tmp = dajpi[n][1].transpose() * db.col(n); term2 = term2 + tmp; //dj::MulVecMatrix3x3<real>(da[n](), (real(*)[3]) &dbjpi[n][0], tmp()); tmp = dbjpi[n][0].transpose() * da.col(n); term2 = term2 + tmp; } omega_pb.col(i) = (term1)-(0.5f * darboux_vector[i] * length) * (term2); omega_pb.col(i) *= (x * bendAndTwistKs[i]); } // pc { Vector3r term1(0, 0, 0); Vector3r term2(0, 0, 0); Vector3r tmp(0, 0, 0); // first term //dj::MulVecMatrix3x3<real>(da[k](), (real(*)[3]) &dbjpi[j][1], term1()); //dj::MulVecMatrix3x3<real>(da[j](), (real(*)[3]) &dbjpi[k][1], tmp()); term1 = dbjpi[j][1].transpose() * da.col(k); tmp = dbjpi[k][1].transpose() * da.col(j); term1 = term1 - tmp; // second term for (int n = 0; n < 3; ++n) { //dj::MulVecMatrix3x3<real>(da[n](), (real(*)[3]) &dbjpi[n][1], tmp()); tmp = dbjpi[n][1].transpose() * da.col(n); term2 = term2 + tmp; } omega_pc.col(i) = (term1)+(0.5f * darboux_vector[i] * length) * (term2); omega_pc.col(i) *= (-x * bendAndTwistKs[i]); } // pd { Vector3r term1(0, 0, 0); Vector3r term2(0, 0, 0); Vector3r tmp(0, 0, 0); // first term //dj::MulVecMatrix3x3<real>(db[k](), (real(*)[3]) &dajpi[j][2], term1()); //dj::MulVecMatrix3x3<real>(db[j](), (real(*)[3]) &dajpi[k][2], tmp()); term1 = dajpi[j][2].transpose() * db.col(k); tmp = dajpi[k][2].transpose() * db.col(j); term1 = term1 - tmp; // second term for (int n = 0; n < 3; ++n) { //dj::MulVecMatrix3x3<real>(db[n](), (real(*)[3]) &dajpi[n][2], tmp()); tmp = dajpi[n][2].transpose() * db.col(n); term2 = term2 + tmp; } omega_pd.col(i) = (term1)-(0.5f * darboux_vector[i] * length) * (term2); omega_pd.col(i) *= (x * bendAndTwistKs[i]); } // pe { Vector3r term1(0, 0, 0); Vector3r term2(0, 0, 0); Vector3r tmp(0, 0, 0); // first term //dj::MulVecMatrix3x3<real>(da[k](), (real(*)[3]) &dbjpi[j][2], term1()); //dj::MulVecMatrix3x3<real>(da[j](), (real(*)[3]) &dbjpi[k][2], tmp()); term1 = dbjpi[j][2].transpose() * da.col(k); tmp = dbjpi[k][2].transpose() * da.col(j); term1 -= tmp; // second term for (int n = 0; n < 3; ++n) { //WARNING!!! &dbjpi[n][2][0][0] ??? //dj::MulVecMatrix3x3<real>(da[n](), (real(*)[3]) &dbjpi[n][2][0][0], tmp()); tmp = dbjpi[n][2].transpose() * da.col(n); term2 += tmp; } omega_pe.col(i) = (term1)+(0.5f * darboux_vector[i] * length) * (term2); omega_pe.col(i) *= (-x * bendAndTwistKs[i]); } } return true; }
bool PositionBasedElasticRod::ComputeMaterialFrameDerivative( const Vector3r& p0, const Vector3r& p1, const Vector3r& p2, const Matrix3r& d, Matrix3r& d1p0, Matrix3r& d1p1, Matrix3r& d1p2, Matrix3r& d2p0, Matrix3r& d2p1, Matrix3r& d2p2, Matrix3r& d3p0, Matrix3r& d3p1, Matrix3r& d3p2) { // d3pi Vector3r p01 = p1 - p0; float length_p01 = p01.norm(); d3p0.col(0) = d.col(2)[0] * d.col(2); d3p0.col(1) = d.col(2)[1] * d.col(2); d3p0.col(2) = d.col(2)[2] * d.col(2); d3p0.col(0)[0] -= 1.0f; d3p0.col(1)[1] -= 1.0f; d3p0.col(2)[2] -= 1.0f; d3p0.col(0) *= (1.0f / length_p01); d3p0.col(1) *= (1.0f / length_p01); d3p0.col(2) *= (1.0f / length_p01); d3p1.col(0) = -d3p0.col(0); d3p1.col(1) = -d3p0.col(1); d3p1.col(2) = -d3p0.col(2); d3p2.col(0).setZero(); d3p2.col(1).setZero(); d3p2.col(2).setZero(); ////>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //// d2pi Vector3r p02 = p2 - p0; Vector3r p01_cross_p02 = p01.cross(p02); float length_cross = p01_cross_p02.norm(); Matrix3r mat; mat.col(0) = d.col(1)[0] * d.col(1); mat.col(1) = d.col(1)[1] * d.col(1); mat.col(2) = d.col(1)[2] * d.col(1); mat.col(0)[0] -= 1.0f; mat.col(1)[1] -= 1.0f; mat.col(2)[2] -= 1.0f; mat.col(0) *= (-1.0f / length_cross); mat.col(1) *= (-1.0f / length_cross); mat.col(2) *= (-1.0f / length_cross); Matrix3r product_matrix; MathFunctions::crossProductMatrix(p2 - p1, product_matrix); d2p0 = mat * product_matrix; MathFunctions::crossProductMatrix(p0 - p2, product_matrix); d2p1 = mat * product_matrix; MathFunctions::crossProductMatrix(p1 - p0, product_matrix); d2p2 = mat * product_matrix; ////>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //// d1pi Matrix3r product_mat_d3; Matrix3r product_mat_d2; Matrix3r m1, m2; MathFunctions::crossProductMatrix(d.col(2), product_mat_d3); MathFunctions::crossProductMatrix(d.col(1), product_mat_d2); //dj::MulMatrix3x3<real>(&product_mat_d3[0][0], &d2p0[0][0], &m1[0][0]); //dj::MulMatrix3x3<real>(&product_mat_d2[0][0], &d3p0[0][0], &m2[0][0]); d1p0 = product_mat_d2 * d3p0 - product_mat_d3 * d2p0; //dj::MulMatrix3x3<real>(&product_mat_d3[0][0], &d2p1[0][0], &m1[0][0]); //dj::MulMatrix3x3<real>(&product_mat_d2[0][0], &d3p1[0][0], &m2[0][0]); d1p1 = product_mat_d2 * d3p1 - product_mat_d3 * d2p1; /*dj::MulMatrix3x3<real>(&product_mat_d3[0][0], &d2p2[0][0], &d1p2[0][0]);*/ d1p2 = product_mat_d3 * d2p2; d1p2.col(0) *= -1.0f; d1p2.col(1) *= -1.0f; d1p2.col(2) *= -1.0f; return true; }