void cloth::addWindForcesForTriangle(Particle *p1,Particle *p2,Particle *p3, const vec3 direction) { vec3 normal = calcTriangleNormal(p1,p2,p3); vec3 d = normalize(normal); vec3 force = normal*(dot(d,direction)); p1->addForce(force); p2->addForce(force); p3->addForce(force); }
void cloth::updateFaceNormal() { for(int x = 0; x<num_particles_width-1; x++) { for(int y=0; y<num_particles_height-1; y++) { vec3 normal = calcTriangleNormal(getParticle(x+1,y),getParticle(x,y),getParticle(x,y+1)); getParticle(x+1,y)->addToNormal(normal); getParticle(x,y)->addToNormal(normal); getParticle(x,y+1)->addToNormal(normal); normal = calcTriangleNormal(getParticle(x+1,y+1),getParticle(x+1,y),getParticle(x,y+1)); getParticle(x+1,y+1)->addToNormal(normal); getParticle(x+1,y)->addToNormal(normal); getParticle(x,y+1)->addToNormal(normal); } } }
/* A private method used by windForce() to calcualte the wind force for a single triangle defined by p1,p2,p3*/ void addWindForcesForTriangle(Particle *p1,Particle *p2,Particle *p3, const Vec3 direction) { Vec3 normal = calcTriangleNormal(p1,p2,p3); Vec3 d = normal.normalized(); Vec3 force = normal*(d.dot(direction)); p1->addForce(force); p2->addForce(force); p3->addForce(force); }
/* drawing the cloth as a smooth shaded (and colored according to column) OpenGL triangular mesh Called from the display() method The cloth is seen as consisting of triangles for four particles in the grid as follows: (x,y) *--* (x+1,y) | /| |/ | (x,y+1) *--* (x+1,y+1) */ void drawShaded() { // reset normals (which where written to last frame) std::vector<Particle>::iterator particle; for(particle = particles.begin(); particle != particles.end(); particle++) { (*particle).resetNormal(); } //create smooth per particle normals by adding up all the (hard) triangle normals that each particle is part of for(int x = 0; x<num_particles_width-1; x++) { for(int y=0; y<num_particles_height-1; y++) { Vec3 normal = calcTriangleNormal(getParticle(x+1,y),getParticle(x,y),getParticle(x,y+1)); getParticle(x+1,y)->addToNormal(normal); getParticle(x,y)->addToNormal(normal); getParticle(x,y+1)->addToNormal(normal); normal = calcTriangleNormal(getParticle(x+1,y+1),getParticle(x+1,y),getParticle(x,y+1)); getParticle(x+1,y+1)->addToNormal(normal); getParticle(x+1,y)->addToNormal(normal); getParticle(x,y+1)->addToNormal(normal); } } glBegin(GL_TRIANGLES); for(int x = 0; x<num_particles_width-1; x++) { for(int y=0; y<num_particles_height-1; y++) { Vec3 color(0,0,0); if (x%2) // red and white color is interleaved according to which column number color = Vec3(0.6f,0.2f,0.2f); else color = Vec3(1.0f,1.0f,1.0f); drawTriangle(getParticle(x+1,y),getParticle(x,y),getParticle(x,y+1),color); drawTriangle(getParticle(x+1,y+1),getParticle(x+1,y),getParticle(x,y+1),color); } } glEnd(); }
void cloth::generateFace(Particle *p1,Particle *p2,Particle *p3) { Face face; face.particleA = p1; face.particleB = p2; face.particleC = p3; face.normal = normalize(calcTriangleNormal(p1,p2,p3)); face.centerPos.x =(p1->getPos().x+p2->getPos().x+p3->getPos().x)/3; face.centerPos.y =(p1->getPos().y+p2->getPos().y+p3->getPos().y)/3; face.centerPos.z =(p1->getPos().z+p2->getPos().z+p3->getPos().z)/3; faces.push_back(face); }
char* parseTriangle(char *start, std::vector<rpm_triangle_t> &tris, int texId, std::vector<int> &parentBones) { rpm_triangle_t tri; tri.iTexID = texId; for( int i = 0; i < 3; i++ ) // 3 vertexes { int mainParent = 0; float pos[3] = {0.0f}; float norm[3] = {0.0f}; float uv[2] = {0.0f}; int numRead = 0; //sscanf_s(start, "%i%[ \t]%f%[ \t]%f%[ \t]%f%[ \t]%f%[ \t]%f%[ \t]%f%[ \t]%f%[ \t]%f%n", sscanf_s(start, "%i %f %f %f %f %f %f %f %f%n", &mainParent, &pos[0], &pos[1], &pos[2], &norm[0], &norm[1], &norm[2], &uv[0], &uv[1], &numRead); if( numRead > 0 ) { rpm_vertex_t &v = tri.vertex3[i]; for( int k = 0; k < 3; k++ ) v.pos3[k] = pos[k]; for( int k = 0; k < 3; k++ ) v.norm3[k] = norm[k]; for( int k = 0; k < 2; k++ ) v.uv2[k] = uv[k]; //Try to read additional bone weights char *boneWeightStart = start + numRead; int links; int boneId; float weight; int numRead = 0; int ret = sscanf_s(boneWeightStart, " %i %i %f", &links, &boneId, &weight); if( ret == 3 ) parentBones.push_back(boneId); else parentBones.push_back(mainParent); } char *endLn = strchr(start, '\n'); start = endLn + 1; } calcTriangleNormal(tri); tris.push_back(tri); return start; }
bool cloth::testTriangleIntersect(Particle* currentParticle) { bool testResult = false; //test each particles, see if it's collide with the plane(face) //plane equation: ax+by+cz=d, n=(a,b,c) //ray equation: r = p+t*dirc; for (int i = 0; i<faces.size(); i++) { if (faces[i].particleA->particleIndex != currentParticle->particleIndex && faces[i].particleB->particleIndex != currentParticle->particleIndex && faces[i].particleC->particleIndex != currentParticle->particleIndex) { Face currentface = faces[i]; glm::vec3 n = normalize(calcTriangleNormal(faces[i].particleA,faces[i].particleB,faces[i].particleC)); //glm::vec3 p = currentParticle->pos; glm::vec3 rayDirection = currentParticle->pos - currentParticle->old_pos; float nDotD = glm::dot(rayDirection, n); if (abs(nDotD) <= 0.00001 || nDotD ==0) { return false; } else { float d = glm::dot(n, faces[i].particleA->getPos()); //float d = n.x * faces[i].particleA->getPos().x+n.y * faces[i].particleA->getPos().y+n.z * faces[i].particleA->getPos().z; //find out the intersect point float t = (d-glm::dot(n,currentParticle->old_pos))/nDotD; //float t = dot(n,(faces[i].particleA->getPos()-currentParticle->old_pos))/(nDotD); intersectQ = currentParticle->old_pos + t*rayDirection; if (((intersectQ.x)>=max(currentParticle->pos.x,currentParticle->old_pos.x)) || ((intersectQ.y)>=max(currentParticle->pos.y,currentParticle->old_pos.y)) || ((intersectQ.z)>=max(currentParticle->pos.z,currentParticle->old_pos.z)) || ((intersectQ.x)<=min(currentParticle->pos.x,currentParticle->old_pos.x)) || ((intersectQ.y)<=min(currentParticle->pos.y,currentParticle->old_pos.y)) || ((intersectQ.z)<=min(currentParticle->pos.z,currentParticle->old_pos.z)) ) { return false; } ////test if Q inside line AB //glm::vec3 AB = faces[i].particleB->getPos() - faces[i].particleA->getPos(); //glm::vec3 AQ = intersectQ - faces[i].particleA->getPos(); //glm::vec3 testAB = glm::cross(AB,AQ); ////test if Q inside line BC //glm::vec3 BC = faces[i].particleC->getPos() - faces[i].particleB->getPos(); //glm::vec3 BQ = intersectQ - faces[i].particleB->getPos(); //glm::vec3 testBC = glm::cross(BC,BQ); ////test if Q inside line AC //glm::vec3 CA = faces[i].particleA->getPos() - faces[i].particleC->getPos(); //glm::vec3 CQ = intersectQ - faces[i].particleC->getPos(); //glm::vec3 testAC = glm::cross(CA,CQ); /*if (glm::dot(testAB,n)>=0 && glm::dot(testBC,n)>=0 && glm::dot(testAC,n)>=0) { return true; }*/ if(PointinTriangle(faces[i].particleA->getPos(),faces[i].particleB->getPos(),faces[i].particleC->getPos(),intersectQ)) { currentParticle->pos = currentParticle->old_pos; printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); return true; } } } } return false; }
void ParticleSystem::calculateNormals() { assert(mFaceNormals != NULL && mVertexNormals != NULL); #define IDX(u,v) ( (u)+((v)*mWidth) ) // normals calculation // calculate normals to faces for (int y=0; y<mHeight-1; y++) { for (int x=0; x<mWidth-1; x++) { Vector3d &p1 = getParticlePos(x, y); Vector3d &p2 = getParticlePos(x, y+1); Vector3d &p4 = getParticlePos(x+1, y); Vector3d v1 = p2-p1; Vector3d v2 = p4-p1; mFaceNormals[IDX(x,y)] = v1.cross(v2); mFaceNormals[IDX(x,y)].normalize(); } } // calculate normals to vertices Vector3d normal1, normal2, normal3, normal4; Vector3d normal; for (int y=0; y<mHeight; y++) { for (int x=0; x<mWidth; x++) { // corners if (x==0 && y==0) { Vector3d &p1 = getParticlePos(x, y); Vector3d &p2 = getParticlePos(x+1, y); Vector3d &p3 = getParticlePos(x, y+1); normal = calcTriangleNormal( p1, p2, p3); } else if (x==0 && y==mHeight-1) { Vector3d &p1 = getParticlePos(x, y); Vector3d &p2 = getParticlePos(x, y-1); Vector3d &p3 = getParticlePos(x+1, y); normal = calcTriangleNormal( p1, p2, p3); } else if (x==mWidth-1 && y==0) { Vector3d &p1 = getParticlePos(x, y); Vector3d &p2 = getParticlePos(x, y+1); Vector3d &p3 = getParticlePos(x-1, y); normal = calcTriangleNormal( p1, p2, p3); } else if (x==mWidth-1 && y==mHeight-1) { Vector3d &p1 = getParticlePos(x, y); Vector3d &p2 = getParticlePos(x-1, y); Vector3d &p3 = getParticlePos(x, y-1); normal = calcTriangleNormal( p1, p2, p3); } // edges else if (x==0) { Vector3d &p1 = getParticlePos(x, y); Vector3d &p2 = getParticlePos(x, y-1); Vector3d &p3 = getParticlePos(x+1, y); Vector3d &p4 = getParticlePos(x, y+1); normal1 = calcTriangleNormal( p1, p2, p3); normal2 = calcTriangleNormal( p1, p3, p4); normal = normal1 + normal2; } else if (x==mWidth-1) { Vector3d &p1 = getParticlePos(x, y); Vector3d &p2 = getParticlePos(x, y+1); Vector3d &p3 = getParticlePos(x-1, y); Vector3d &p4 = getParticlePos(x, y-1); normal1 = calcTriangleNormal( p1, p2, p3); normal2 = calcTriangleNormal( p1, p3, p4); normal = normal1 + normal2; } else if (y==0) { Vector3d &p1 = getParticlePos(x, y); Vector3d &p2 = getParticlePos(x+1, y); Vector3d &p3 = getParticlePos(x, y+1); Vector3d &p4 = getParticlePos(x-1, y); normal1 = calcTriangleNormal( p1, p2, p3); normal2 = calcTriangleNormal( p1, p3, p4); normal = normal1 + normal2; } else if (y==mHeight-1) { Vector3d &p1 = getParticlePos(x, y); Vector3d &p2 = getParticlePos(x-1, y); Vector3d &p3 = getParticlePos(x, y-1); Vector3d &p4 = getParticlePos(x+1, y); normal1 = calcTriangleNormal( p1, p2, p3); normal2 = calcTriangleNormal( p1, p3, p4); normal = normal1 + normal2; } // inner vertices else { Vector3d &p1 = getParticlePos(x, y); Vector3d &p2 = getParticlePos(x-1, y); Vector3d &p3 = getParticlePos(x, y-1); Vector3d &p4 = getParticlePos(x+1, y); Vector3d &p5 = getParticlePos(x, y+1); normal1 = calcTriangleNormal( p1, p2, p3); normal2 = calcTriangleNormal( p1, p3, p4); normal3 = calcTriangleNormal( p1, p4, p5); normal4 = calcTriangleNormal( p1, p5, p2); normal = normal1 + normal2 + normal3 + normal4; } normal.normalize(); mVertexNormals[IDX(x,y)] = normal; } } #undef IDX }