/* Create Ball Object (points & springs) */ void CreateBall(void) { int i; for(i=1 ; i <= NUMP ; ++i) // create points { myPoints[i].x = BALLRADIUS * sin( i * (2.0 * 3.14) / NUMP ); myPoints[i].y = BALLRADIUS * cos(i * (2.0 * 3.14) / NUMP ) + SCRSIZE/2; } for(i=1 ; i <= NUMP ; ++i) // create springs AddSpring(i,i,i+1); AddSpring(i-1,i-1,1); }
//************************************************************************************* // Creates Clothes Data Structure for an object. //************************************************************************************* void EERIEOBJECT_AddClothesData(EERIE_3DOBJ * obj) { long sel = -1; long selmounocol = -1; for(size_t i = 0; i < obj->selections.size(); i++) { // TODO iterator if(obj->selections[i].name == "mou") { sel = i; break; } } for(size_t i = 0; i < obj->selections.size(); i++) { // TODO iterator if(obj->selections[i].name == "mounocol") { selmounocol = i; break; } } if(sel == -1) return; if(obj->selections[sel].selected.size() > 0) { obj->cdata = new CLOTHES_DATA(); obj->cdata->nb_cvert = (short)obj->selections[sel].selected.size(); obj->cdata->cvert = new CLOTHESVERTEX[obj->cdata->nb_cvert]; memset(obj->cdata->cvert, 0, sizeof(CLOTHESVERTEX)*obj->cdata->nb_cvert); obj->cdata->backup = new CLOTHESVERTEX[obj->cdata->nb_cvert]; memset(obj->cdata->backup, 0, sizeof(CLOTHESVERTEX)*obj->cdata->nb_cvert); } // There is a Mollesse (TM) (C) Selection if(obj->selections[sel].selected.size() > 0) { for(int i = 0; i < obj->cdata->nb_cvert; i++) { obj->cdata->cvert[i].idx = (short)obj->selections[sel].selected[i]; obj->cdata->cvert[i].pos = obj->vertexlist[obj->cdata->cvert[i].idx].v; obj->cdata->cvert[i].t_pos = obj->vertexlist[obj->cdata->cvert[i].idx].v; obj->cdata->cvert[i].mass = 0.5f; if(selmounocol != -1 && IsInSelection(obj, obj->selections[sel].selected[i], selmounocol) >= 0) { obj->cdata->cvert[i].flags = CLOTHES_FLAG_NORMAL | CLOTHES_FLAG_NOCOL; } else { obj->cdata->cvert[i].flags = CLOTHES_FLAG_NORMAL; } obj->cdata->cvert[i].coll = -1; } for(int i = 0; i < obj->cdata->nb_cvert; i++) { for(long j = 0; j < obj->ndata[obj->cdata->cvert[i].idx].nb_Nvertex; j++) { short vert = obj->ndata[obj->cdata->cvert[i].idx].Nvertex[j]; if(IsInSelection(obj, vert, sel) >= 0) { AddSpring(obj, (short)i, (short)GetIDXVert(obj, vert), 11.f, 0.3f, 0); } else { obj->cdata->cvert[i].flags |= CLOTHES_FLAG_FIX; obj->cdata->cvert[i].coll = -2; obj->cdata->cvert[i].mass = 0.f; } } } // Adds more springs (shear) for(int i = 0; i < obj->cdata->nb_cvert; i++) { for(long j = 0; j < obj->ndata[obj->cdata->cvert[i].idx].nb_Nvertex; j++) { short vert = obj->ndata[obj->cdata->cvert[i].idx].Nvertex[j]; if(vert == obj->cdata->cvert[i].idx) continue; // Cannot add a spring between 1 node :p if(IsInSelection(obj, vert, sel) >= 0) { float distance = glm::distance2(obj->vertexlist[obj->cdata->cvert[i].idx].v, obj->vertexlist[vert].v) * square(1.2f); // We springed it in the previous part of code for(long k = 0; k < obj->ndata[vert].nb_Nvertex; k++) { short ver = obj->ndata[vert].Nvertex[k]; if(IsInSelection(obj, ver, sel) >= 0) { // This time we have one ! if(ver == obj->cdata->cvert[i].idx) continue; float distance2 = glm::distance2(obj->vertexlist[obj->cdata->cvert[i].idx].v, obj->vertexlist[ver].v); if(distance2 < distance) { AddSpring(obj, (short)i, (short)GetIDXVert(obj, ver), 4.2f, 0.7f, 1); } } } } } } // Adds more springs (bend) for(int i = 0; i < obj->cdata->nb_cvert; i++) { for(long j = 0; j < obj->ndata[obj->cdata->cvert[i].idx].nb_Nvertex; j++) { short vert = obj->ndata[obj->cdata->cvert[i].idx].Nvertex[j]; if(vert == obj->cdata->cvert[i].idx) continue; // Cannot add a spring between 1 node :p if(IsInSelection(obj, vert, sel) >= 0) { // We springed it in the previous part of code for(long k = 0; k < obj->ndata[vert].nb_Nvertex; k++) { short ver = obj->ndata[vert].Nvertex[k]; if(IsInSelection(obj, ver, sel) >= 0) { // This time we have one ! float distance = glm::distance2(obj->vertexlist[obj->cdata->cvert[i].idx].v, obj->vertexlist[ver].v) * square(1.2f); for(long k2 = 0; k2 < obj->ndata[ver].nb_Nvertex; k2++) { short ve = obj->ndata[ver].Nvertex[k]; if(ve == vert) continue; if(IsInSelection(obj, ve, sel) >= 0) { // This time we have one ! if(obj->cdata->cvert[(short)GetIDXVert(obj, ve)].flags & CLOTHES_FLAG_FIX) continue; float distance2 = glm::distance2(obj->vertexlist[obj->cdata->cvert[i].idx].v, obj->vertexlist[ve].v); if(distance2 > distance && distance2 < distance * square(2.f)) { AddSpring(obj, (short)i, (short)GetIDXVert(obj, ve), 2.2f, 0.9f, 2); } } } } } } } } } }
bool CSubmeshCandidate::CalculateSpringSystem() { // loop through all the vertex candidates of the submesh candidate unsigned int vertexId; for(vertexId = 0; vertexId < m_vectorVertexCandidate.size(); vertexId++) { // start from the current vertex candidate std::set<int> setNeighbour; setNeighbour.insert(vertexId); // get all the neighbours of the current vertex candidate up to the given level int levelId; for(levelId = 0; levelId < 2; levelId++) { std::set<int> setNeighbourNeighbour; std::set<int>::iterator iteratorNeighbour; for(iteratorNeighbour = setNeighbour.begin(); iteratorNeighbour != setNeighbour.end(); ++iteratorNeighbour) { std::set<int>::iterator iteratorNeighbourNeighbour; for(iteratorNeighbourNeighbour = m_vectorVertexCandidate[*iteratorNeighbour]->GetSetNeighbour().begin(); iteratorNeighbourNeighbour != m_vectorVertexCandidate[*iteratorNeighbour]->GetSetNeighbour().end(); ++iteratorNeighbourNeighbour) { setNeighbourNeighbour.insert(*iteratorNeighbourNeighbour); } } for(iteratorNeighbour = setNeighbourNeighbour.begin(); iteratorNeighbour != setNeighbourNeighbour.end(); ++iteratorNeighbour) { setNeighbour.insert(*iteratorNeighbour); } } // add springs to all these neighbours std::set<int>::iterator iteratorNeighbour; for(iteratorNeighbour = setNeighbour.begin(); iteratorNeighbour != setNeighbour.end(); ++iteratorNeighbour) { AddSpring(vertexId, *iteratorNeighbour); } } /* OLD VERSION // loop through all the faces of the submesh candidate int faceId; for(faceId = 0; faceId < m_vectorFace.size(); faceId++) { // get the face Face& face = m_vectorFace[faceId]; // add all edges to the spring system as springs AddSpring(face.vertexId[0], face.vertexId[1]); AddSpring(face.vertexId[1], face.vertexId[2]); AddSpring(face.vertexId[2], face.vertexId[0]); } */ // loop until we have a stable system bool bModified; do { // clear the modification flag bModified = false; // loop through all the springs of the submesh candidate unsigned int springId; for(springId = 0; springId < m_vectorSpring.size(); springId++) { // get the spring Spring& spring = m_vectorSpring[springId]; // adjust the two vertices connected to the spring bModified |= AdjustSpringVertex(spring.vertexId[0], spring.vertexId[1]); bModified |= AdjustSpringVertex(spring.vertexId[1], spring.vertexId[0]); } } while(bModified); // loop through all the springs of the submesh candidate unsigned int springId; for(springId = 0; springId < m_vectorSpring.size(); springId++) { // get the spring Spring& spring = m_vectorSpring[springId]; // get the physical properties of the two spring vertices CVertexCandidate::PhysicalProperty physicalProperty[2]; m_vectorVertexCandidate[spring.vertexId[0]]->GetPhysicalProperty(physicalProperty[0]); m_vectorVertexCandidate[spring.vertexId[1]]->GetPhysicalProperty(physicalProperty[1]); spring.priority = (physicalProperty[0].constraintDistance < physicalProperty[1].constraintDistance) ? physicalProperty[0].constraintDistance : physicalProperty[1].constraintDistance; } // sort the springs std::sort(m_vectorSpring.begin(), m_vectorSpring.end(), SpringCompare); /* DEBUG for(springId = 0; springId < m_vectorSpring.size(); springId++) { // get the spring Spring& spring = m_vectorSpring[springId]; CString str; str.Format("spring %d: priority: %d, %d <-> %d\n", springId, spring.priority, spring.vertexId[0], spring.vertexId[1]); OutputDebugString(str); } */ return true; }