void UnwrapMod::BuildUsedList(BitArray &usedVerts, ClusterClass *cluster) { usedVerts.SetSize(TVMaps.v.Count()); usedVerts.ClearAll(); for (int j =0; j < cluster->faces.Count(); j++) { int faceIndex = cluster->faces[j]; for (int k = 0; k < TVMaps.f[faceIndex]->count; k++) { //need to put patch handles in here also int index = TVMaps.f[faceIndex]->t[k]; usedVerts.Set(index); if ((TVMaps.f[faceIndex]->flags & FLAG_CURVEDMAPPING) && (TVMaps.f[faceIndex]->vecs)) { index = TVMaps.f[faceIndex]->vecs->handles[k*2]; if ((index >= 0) && (index < usedVerts.GetSize())) usedVerts.Set(index); index = TVMaps.f[faceIndex]->vecs->handles[k*2+1]; if ((index >= 0) && (index < usedVerts.GetSize())) usedVerts.Set(index); if (TVMaps.f[faceIndex]->flags & FLAG_INTERIOR) { index = TVMaps.f[faceIndex]->vecs->interiors[k]; if ((index >= 0) && (index < usedVerts.GetSize())) usedVerts.Set(index); } } } } }
void EChamferMod::ModifyTriObject (TimeValue t, ModContext &mc, TriObject *tobj) { Mesh &mesh = tobj->GetMesh(); Interval iv = FOREVER; float amount; int i, j; m_pblock->GetValue (kEchAmount, t, amount, iv); // Convert existing selection (at whatever level) to edge selection: BitArray targetEdges; targetEdges.SetSize (mesh.numFaces*3); targetEdges.ClearAll (); switch (mesh.selLevel) { case MESH_OBJECT: targetEdges.SetAll (); break; case MESH_VERTEX: for (i=0; i<mesh.numFaces; i++) { for (j=0; j<3; j++) { if (!mesh.vertSel[mesh.faces[i].v[j]]) continue; // Don't select invisible edges: if (mesh.faces[i].getEdgeVis(j)) targetEdges.Set (i*3+j); if (mesh.faces[i].getEdgeVis((j+2)%3)) targetEdges.Set (i*3+(j+2)%3); } } break; case MESH_EDGE: targetEdges = mesh.edgeSel; break; case MESH_FACE: for (i=0; i<mesh.numFaces; i++) { if (!mesh.faceSel[i]) continue; for (j=0; j<3; j++) { // Don't select invisible edges: if (mesh.faces[i].getEdgeVis(j)) targetEdges.Set (i*3+j); } } break; } // Chamfer the edges -- this just does the topological operation. MeshDelta tmd; tmd.InitToMesh (mesh); MeshTempData temp; temp.SetMesh (&mesh); MeshChamferData *mcd = temp.ChamferData(); AdjEdgeList *ae = temp.AdjEList(); tmd.ChamferEdges (mesh, targetEdges, *mcd, ae); tmd.Apply (mesh); // Reset the meshdelta, temp data to deal with the post-chamfered topology: tmd.InitToMesh (mesh); temp.Invalidate (TOPO_CHANNEL); // Generates a new edge list, but preserves chamfer data temp.SetMesh (&mesh); tmd.ChamferMove (mesh, *temp.ChamferData(), amount, temp.AdjEList()); tmd.Apply (mesh); tobj->UpdateValidity(GEOM_CHAN_NUM,iv); }
void XTCSample::DeleteFaces(TimeValue t,Object *obj) { if(bNF_OnOff) { Mesh *mesh = GetMesh(obj); if(!mesh) return; Interval ivalid = FOREVER; int nf; bo->GetParamBlockByID(x_params)->GetValue(pb_nf_spin,t,nf, ivalid); BitArray ba; ba.SetSize(mesh->getNumFaces()); ba.ClearAll(); for(int i = nf ; i < mesh->getNumFaces() ; i++ ) { ba.Set(i); } if(!ba.IsEmpty()) mesh->DeleteFaceSet(ba); } }
void VWeldMod::ConvertTriSelection (Mesh & mesh, BitArray & targetVerts) { targetVerts.SetSize (mesh.numVerts); targetVerts.ClearAll (); int i, j; switch (mesh.selLevel) { case MESH_OBJECT: targetVerts.SetAll (); break; case MESH_VERTEX: targetVerts = mesh.vertSel; break; case MESH_EDGE: for (i=0; i<mesh.numFaces; i++) { for (j=0; j<3; j++) { if (!mesh.edgeSel[i*3+j]) continue; targetVerts.Set (mesh.faces[i].v[j]); targetVerts.Set (mesh.faces[i].v[(j+1)%3]); } } break; case MESH_FACE: for (i=0; i<mesh.numFaces; i++) { if (!mesh.faceSel[i]) continue; for (j=0; j<3; j++) targetVerts.Set (mesh.faces[i].v[j]); } break; } }
void UniformGrid::ClosestPoint(Point3 p, float radius, int &pindex, float &d) { xHitList.ClearAll(); yHitList.ClearAll(); zHitList.ClearAll(); hitList.SetCount(0); //find the cell in the XGrid TagCells(p,radius, 0); //find the cell in the YGrid TagCells(p,radius, 1); //find the cell in the ZGrid TagCells(p,radius, 2); BitArray usedList; usedList.SetSize(pointBase.Count()); usedList.ClearAll(); int closest = -1; d = 0.0f; Box3 localBounds; localBounds.Init(); localBounds += p; localBounds.EnlargeBy(radius); for (int i = 0; i < hitList.Count(); i++) { int index = hitList[i]; if (!usedList[index]) //check to see if we have processed this one or not { if (xHitList[index] && yHitList[index] && zHitList[index]) { usedList.Set(index); Point3 source = pointBase[index]; if (localBounds.Contains(source)) { float dist = LengthSquared(source-p); if ((dist < d) || (closest == -1)) { d = dist; closest = index; } } } } } pindex = closest; d = sqrt(d); }
void SymmetryMod::WeldTriObject (Mesh & mesh, Point3 & N, float offset, float threshold) { // Find vertices in target zone of mirror plane: BitArray targetVerts; targetVerts.SetSize (mesh.numVerts, true); targetVerts.ClearAll (); for (int i=0; i<mesh.numVerts; i++) { float dist = DotProd (N, mesh.verts[i]) - offset; if (fabsf(dist) > threshold) continue; targetVerts.Set (i); } // Weld the suitable border vertices: MeshDelta tmd(mesh); BOOL found = tmd.WeldByThreshold (mesh, targetVerts, threshold); tmd.Apply (mesh); }
void UniformGrid::InRadius(Point3 p, Tab<int> &indexList) { float radius = largestRadius; xHitList.ClearAll(); yHitList.ClearAll(); zHitList.ClearAll(); hitList.SetCount(0); //find the cell in the XGrid TagCells(p,radius, 0); //find the cell in the YGrid TagCells(p,radius, 1); //find the cell in the ZGrid TagCells(p,radius, 2); BitArray usedList; usedList.SetSize(pointBase.Count()); usedList.ClearAll(); int closest = -1; float d = 0.0f; Box3 localBounds; localBounds.Init(); localBounds += p; localBounds.EnlargeBy(radius); for (int i = 0; i < hitList.Count(); i++) { int index = hitList[i]; if (!usedList[index]) //check to see if we have processed this one or not { if (xHitList[index] && yHitList[index] && zHitList[index]) { usedList.Set(index); Point3 source = pointBase[index]; if (localBounds.Contains(source)) { indexList.Append(1,&index,1000); } } } } }
void UVW_ChannelClass::MarkDeadVertices() { BitArray usedVerts; usedVerts.SetSize(v.Count()); usedVerts.ClearAll(); for (int i =0; i < f.Count(); i++) { if (!(f[i]->flags & FLAG_DEAD)) { for (int j=0; j < f[i]->count; j++) { int id = f[i]->t[j]; if (id < usedVerts.GetSize()) usedVerts.Set(id); if ((f[i]->flags & FLAG_CURVEDMAPPING) && (f[i]->vecs)) { id = f[i]->vecs->handles[j*2]; if (id < usedVerts.GetSize()) usedVerts.Set(id); id = f[i]->vecs->handles[j*2+1]; if (id < usedVerts.GetSize()) usedVerts.Set(id); if (f[i]->flags & FLAG_INTERIOR) { id = f[i]->vecs->interiors[j]; if (id < usedVerts.GetSize()) usedVerts.Set(id); } } } } } for (int i =0; i < v.Count(); i++) { if (i < usedVerts.GetSize()) { BOOL isRigPoint = v[i].GetFlag() & FLAG_RIGPOINT; if (!usedVerts[i] && (!isRigPoint)) { v[i].SetDead(); } } } }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestSplitBySource::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator, BitArray& testResult, Tab<float>& testTime) { if (pNode == NULL) return false; bool exactStep = IsExactIntegrationStep(timeEnd, pSystem); int conditionType = pblock()->GetInt(kSplitBySource_conditionType, timeStart); // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container int count = chAmount->Count(); bool isSelectedSource = false; int i, systemHandle = pNode->GetHandle(); for(i=0; i<pblock()->Count(kSplitBySource_sources); i++) { if (systemHandle == pblock()->GetInt(kSplitBySource_sources, 0, i)) { isSelectedSource = true; break; } } // test all particles testResult.SetSize(count); testResult.ClearAll(); testTime.SetCount(count); if (exactStep) { if ((isSelectedSource && (conditionType == kSplitBySource_conditionType_selected)) || (!isSelectedSource && (conditionType == kSplitBySource_conditionType_notSelected))) { testResult.SetAll(); for(i=0; i<count; i++) testTime[i] = 0.0f; } } return true; }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestGoToNextEvent::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator, BitArray& testResult, Tab<float>& testTime) { int conditionType = pblock()->GetInt(kGoToNextEvent_conditionType, timeStart); bool exactStep = IsExactIntegrationStep(timeEnd, pSystem); // get channel container interface IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing info for a particle int count = chAmount->Count(); if (count <= 0) return true; testResult.SetSize(count); testTime.SetCount(count); if((conditionType == kGoToNextEvent_conditionType_all) && exactStep) { testResult.SetAll(); for(int i=0; i<count; i++) testTime[i] = 0.0f; } else { testResult.ClearAll(); } return true; }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestSplitSelected::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator, BitArray& testResult, Tab<float>& testTime) { bool exactStep = IsExactIntegrationStep(timeEnd, pSystem); int conditionType = pblock()->GetInt(kSplitSelected_conditionType, timeStart); // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container int count = chAmount->Count(); IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing info for a particle IParticleChannelBoolR* chSelect = GetParticleChannelSelectionRInterface(pCont); // test all particles testResult.SetSize(count); testResult.ClearAll(); testTime.SetCount(count); for(int i=0; i<count; i++) { bool selected = (chSelect != NULL) ? chSelect->GetValue(i) : false; bool sendOut = ((selected && (conditionType == kSplitSelected_conditionType_selected)) || (!selected && (conditionType == kSplitSelected_conditionType_notSelected))); if (sendOut && exactStep) { testResult.Set(i); testTime[i] = 0.0f; } } return true; }
void SymmetryMod::SliceTriObject (Mesh & mesh, Point3 & N, float offset) { // Steve Anderson 9/14/2002 // Using the new "MESH_TEMP_1" flag to override Slice selection behavior, // which is undesirable here. mesh.SetFlag (MESH_TEMP_1); MeshDelta slicemd; slicemd.Slice (mesh, N, offset, false, true); slicemd.Apply (mesh); mesh.ClearFlag (MESH_TEMP_1); // We need to strip out faces on the mirror plane itself. // (These aren't always removed by slice.) // Mark vertices at the plane boundary: BitArray targetVerts; targetVerts.SetSize (mesh.numVerts); targetVerts.ClearAll (); for (int i=0; i<mesh.numVerts; i++) { float dist = DotProd (N, mesh.verts[i]) - offset; if (fabsf(dist) > MNEPS) continue; targetVerts.Set (i); } BitArray delFaces, delVerts; delFaces.SetSize (mesh.numFaces); for (int i=0; i<mesh.numFaces; i++) { int j; for (j=0; j<3; j++) { if (!targetVerts[mesh.faces[i].v[j]]) break; } if (j<3) continue; // Face needs to be deleted. delFaces.Set (i); } mesh.DeleteFaceSet (delFaces, &delVerts); mesh.DeleteVertSet (delVerts); }
void MeshTopoData::UpdateClusterVertices(Tab<ClusterClass*> &clusterList) { BitArray processedVerts; processedVerts.SetSize(TVMaps.v.Count()); for (int i = 0; i < clusterList.Count(); i++) { if (clusterList[i]->ld == this) { clusterList[i]->verts.SetCount(0); processedVerts.ClearAll(); for (int j = 0; j < clusterList[i]->faces.Count(); j++) { int findex = clusterList[i]->faces[j]; AddVertsToCluster(findex, processedVerts, clusterList[i]); } for (int j = 0; j < clusterList[i]->verts.Count(); j++) { int id = clusterList[i]->verts[j]; } } } }
//pelt void UVW_ChannelClass::EdgeListFromPoints(Tab<int> &selEdges, int source, int target, Point3 vec) { //make sure point a and b are on the same element if not bail Tab<VConnections*> ourConnects; BOOL del = FALSE; BitArray selVerts; selVerts.SetSize(geomPoints.Count()); selVerts.ClearAll(); // if (TRUE) //loop through the edges Tab<int> numberOfConnections; numberOfConnections.SetCount(geomPoints.Count()); for (int i = 0; i < geomPoints.Count(); i++) { numberOfConnections[i] = 0; } //count the number of vertxs connected for (int i = 0; i < gePtrList.Count(); i++) { if (!(gePtrList[i]->flags & FLAG_HIDDENEDGEA)) { int a = gePtrList[i]->a; numberOfConnections[a] +=1; int b = gePtrList[i]->b; numberOfConnections[b] +=1; } } //allocate our connections now ourConnects.SetCount(geomPoints.Count()); for (int i = 0; i < geomPoints.Count(); i++) { ourConnects[i] = new VConnections(); ourConnects[i]->closestNode = NULL; ourConnects[i]->linkedListChild = NULL; ourConnects[i]->linkedListParent = NULL; ourConnects[i]->accumDist = 1.0e+9f; ourConnects[i]->solved = FALSE; ourConnects[i]->vid = i; ourConnects[i]->connectingVerts.SetCount(numberOfConnections[i]); } for (int i = 0; i < geomPoints.Count(); i++) { numberOfConnections[i] = 0; } //build our vconnection data for (int i = 0; i < gePtrList.Count(); i++) { if (!(gePtrList[i]->flags & FLAG_HIDDENEDGEA)) { int a = gePtrList[i]->a; int b = gePtrList[i]->b; int index = numberOfConnections[a]; ourConnects[a]->connectingVerts[index].vertexIndex = b; ourConnects[a]->connectingVerts[index].edgeIndex = i; numberOfConnections[a] +=1; index = numberOfConnections[b]; ourConnects[b]->connectingVerts[index].vertexIndex = a; ourConnects[b]->connectingVerts[index].edgeIndex = i; numberOfConnections[b] +=1; } } del = TRUE; // else ourConnects = vConnects; //spider out till hit our target or no more left BOOL done = FALSE; BOOL hit = FALSE; Tab<int> vertsToDo; BitArray processedVerts; processedVerts.SetSize(ourConnects.Count()); processedVerts.ClearAll(); //if no more left bail int currentVert = source; while (!done) { // int startingNumberProcessed = processedVerts.NumberSet(); int ct = ourConnects[currentVert]->connectingVerts.Count(); processedVerts.Set(currentVert, TRUE); for (int j = 0; j < ct; j++) { int index = ourConnects[currentVert]->connectingVerts[j].vertexIndex; if (index == target) { done = TRUE; hit = TRUE; } if (!processedVerts[index]) vertsToDo.Append(1,&index, 10000); } if (vertsToDo.Count()) { currentVert = vertsToDo[vertsToDo.Count()-1]; vertsToDo.Delete(vertsToDo.Count()-1,1); } if (vertsToDo.Count() == 0) done = TRUE; // int endingNumberProcessed = processedVerts.NumberSet(); if (currentVert == target) { done = TRUE; hit = TRUE; } // if (startingNumberProcessed == endingNumberProcessed) // done = TRUE; } vertsToDo.ZeroCount(); if (hit) { Tab<VConnections*> solvedNodes; ourConnects[source]->accumDist = 0; VConnections* unsolvedNodeHead = ourConnects[source]; VConnections* unsolvedNodeCurrent = unsolvedNodeHead; //put all our vertices in the unsolved list for (int i = 0; i < ourConnects.Count(); i++) { if (ourConnects[i] != unsolvedNodeHead) { unsolvedNodeCurrent->linkedListChild = ourConnects[i]; VConnections *parent = unsolvedNodeCurrent; unsolvedNodeCurrent = ourConnects[i]; unsolvedNodeCurrent->linkedListParent = parent; } } //build our edge distances Tab<float> edgeDistances; edgeDistances.SetCount(gePtrList.Count()); for (int i = 0 ; i < gePtrList.Count(); i++) { int a = gePtrList[i]->a; int b = gePtrList[i]->b; float d = Length(geomPoints[a] - geomPoints[b]); edgeDistances[i] = d; } BOOL done = FALSE; while (!done) { //pop the top unsolved VConnections *top = unsolvedNodeHead; unsolvedNodeHead = unsolvedNodeHead->linkedListChild; top->linkedListChild = NULL; top->linkedListParent = NULL; if (unsolvedNodeHead != NULL) { unsolvedNodeHead->linkedListParent = NULL; //mark it as processed top->solved = TRUE; //put it in our solved list solvedNodes.Append(1,&top,5000); int neighborCount = top->connectingVerts.Count(); //loop through the neighbors for (int i = 0; i < neighborCount; i++) { int index = top->connectingVerts[i].vertexIndex; int eindex = top->connectingVerts[i].edgeIndex; VConnections *neighbor = ourConnects[index]; //make sure it is not procssedd if (!neighbor->solved) { //find the distance from the top to this neighbor float d = neighbor->accumDist; float testAccumDistance = top->accumDist + edgeDistances[eindex]; //see if it accum dist needs to be relaxed if (testAccumDistance<d) { float originalDist = neighbor->accumDist; neighbor->accumDist = testAccumDistance; neighbor->closestNode = top; //sort this node float dist = neighbor->accumDist; if (originalDist == 1.0e+9f) { //start at the top and look down VConnections *currentNode = unsolvedNodeHead; if (neighbor == currentNode) { currentNode = currentNode->linkedListChild; unsolvedNodeHead = currentNode; } VConnections *prevNode = NULL; //unhook node VConnections *parent = neighbor->linkedListParent; VConnections *child = neighbor->linkedListChild; if (parent) parent->linkedListChild = child; if (child) child->linkedListParent = parent; while ((currentNode!= NULL) && (currentNode->accumDist < dist)) { prevNode = currentNode; currentNode = currentNode->linkedListChild; SHORT iret = GetAsyncKeyState (VK_ESCAPE); if (iret==-32767) { done = TRUE; currentNode= NULL; } } //empty list if ((prevNode==NULL) && (currentNode== NULL)) { neighbor->linkedListChild = NULL; neighbor->linkedListParent = NULL; unsolvedNodeHead = neighbor; } //at top else if (currentNode && (prevNode == NULL)) { unsolvedNodeHead->linkedListParent = neighbor; neighbor->linkedListParent = NULL; neighbor->linkedListChild =unsolvedNodeHead; unsolvedNodeHead = neighbor; } //at bottom else if (currentNode == NULL) { prevNode->linkedListChild = neighbor; neighbor->linkedListParent = currentNode; neighbor->linkedListChild = NULL; } else if (currentNode) { //insert VConnections *parent = currentNode->linkedListParent; VConnections *child = currentNode; parent->linkedListChild = neighbor; child->linkedListParent = neighbor; neighbor->linkedListParent = parent; neighbor->linkedListChild = child; } } else { //sort smallest to largest BOOL moveUp = FALSE; if (neighbor->linkedListParent && neighbor->linkedListChild) { float parentDist = neighbor->linkedListParent->accumDist; float childDist = neighbor->linkedListChild->accumDist; //walkup up or down the list till find a spot an unlink and relink if ((dist >= parentDist) && (dist <= childDist)) { //done dont need to move } else if (dist < parentDist) moveUp = FALSE; } else if (neighbor->linkedListParent && (neighbor->linkedListChild==NULL)) { moveUp = TRUE; } else if ((neighbor->linkedListParent==NULL) && (neighbor->linkedListChild)) { moveUp = FALSE; } //unlink the node //unhook node VConnections *parent = neighbor->linkedListParent; VConnections *child = neighbor->linkedListChild; if (parent) parent->linkedListChild = child; else unsolvedNodeHead = child; if (child) child->linkedListParent = parent; VConnections *currentNode = NULL; if (moveUp) currentNode = neighbor->linkedListParent; else currentNode = neighbor->linkedListChild; VConnections *prevNode = NULL; while ((currentNode!= NULL) && (currentNode->accumDist < dist)) { prevNode = currentNode; if (moveUp) currentNode = currentNode->linkedListParent; else currentNode = currentNode->linkedListChild; SHORT iret = GetAsyncKeyState (VK_ESCAPE); if (iret==-32767) { done = TRUE; currentNode= NULL; } } //empty list if ((prevNode==NULL) && (currentNode== NULL)) { neighbor->linkedListChild = NULL; neighbor->linkedListParent = NULL; unsolvedNodeHead = neighbor; } //at top else if (currentNode && (prevNode == NULL)) { unsolvedNodeHead->linkedListParent = neighbor; neighbor->linkedListParent = NULL; neighbor->linkedListChild =unsolvedNodeHead; unsolvedNodeHead = neighbor; } //at bottom else if (currentNode == NULL) { prevNode->linkedListChild = neighbor; neighbor->linkedListParent = currentNode; neighbor->linkedListChild = NULL; } else if (currentNode) { //insert VConnections *parent = currentNode->linkedListParent; VConnections *child = currentNode; parent->linkedListChild = neighbor; child->linkedListParent = neighbor; neighbor->linkedListParent = parent; neighbor->linkedListChild = child; } } } } } } if (unsolvedNodeHead == NULL) done = TRUE; if ((solvedNodes[solvedNodes.Count()-1]) == ourConnects[target]) done = TRUE; } //now get our edge list selEdges.ZeroCount(); VConnections *cNode = ourConnects[target]; while ((cNode->closestNode != NULL) && (cNode != ourConnects[source])) { VConnections *pNode = cNode->closestNode; int ct = cNode->connectingVerts.Count(); int edgeIndex = -1; for (int i = 0; i < ct; i++) { int vindex = cNode->connectingVerts[i].vertexIndex; int eindex = cNode->connectingVerts[i].edgeIndex; if (ourConnects[vindex] == pNode) { edgeIndex = eindex; i = ct; } } if (edgeIndex != -1) selEdges.Append(1,&edgeIndex,500); cNode = pNode; } } if (del) { for (int i = 0; i < geomPoints.Count(); i++) { delete ourConnects[i]; } } }
void MeshTopoData::BuildInitialMapping(MNMesh *msh) { //build bounding box Box3 bbox; bbox.Init(); int vertCount = 0; //normalize the length width height for (int i = 0; i < TVMaps.f.Count(); i++) { int pcount = 3; pcount = TVMaps.f[i]->count; vertCount += pcount; for (int j = 0; j < pcount; j++) { bbox += TVMaps.geomPoints[TVMaps.f[i]->v[j]]; } } vertCount = msh->numv; Tab<int> indexList; indexList.SetCount(vertCount); BitArray usedIndex; usedIndex.SetSize(vertCount); usedIndex.ClearAll(); for (int i = 0; i < vertCount; i++) indexList[i] = -1; for (int i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; pcount = TVMaps.f[i]->count; for (int j = 0; j < pcount; j++) { usedIndex.Set(msh->f[i].vtx[j]); } } } int ct = 0; for (int i = 0; i < usedIndex.GetSize(); i++) { if (usedIndex[i]) indexList[i] = ct++; } TVMaps.v.SetCount(usedIndex.NumberSet()); mVSel.SetSize(usedIndex.NumberSet()); //watje 10-19-99 bug 213437 to prevent a divide by 0 which gives you a huge u,v, or w value if (bbox.Width().x == 0.0f) bbox += Point3(0.5f,0.0f,0.0f); if (bbox.Width().y == 0.0f) bbox += Point3(0.0f,0.5f,0.0f); if (bbox.Width().z == 0.0f) bbox += Point3(0.0f,0.0f,0.5f); for (int i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; pcount = TVMaps.f[i]->count; TVMaps.f[i]->flags &= ~FLAG_DEAD; for (int j = 0; j < pcount; j++) { int index; int a = msh->f[i].vtx[j]; index = indexList[a]; TVMaps.f[i]->t[j] = index; Point3 uv( TVMaps.geomPoints[TVMaps.f[i]->v[j]].x/bbox.Width().x + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->v[j]].y/bbox.Width().y + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->v[j]].z/bbox.Width().z + 0.5f ); TVMaps.v[index].SetP(uv); TVMaps.v[index].SetInfluence(0.f); TVMaps.v[index].SetFlag(0); TVMaps.v[index].SetControlID(-1); } } } }
void UVW_ChannelClass::SplitUVEdges(BitArray esel) { //get our point selection from the edges BitArray pointSel; pointSel.SetSize(v.Count()); pointSel.ClearAll(); for (int i = 0; i < ePtrList.Count(); i++) { if (esel[i]) { int a = ePtrList[i]->a; int b = ePtrList[i]->b; pointSel.Set(a,TRUE); pointSel.Set(b,TRUE); } } //build a lis of egdes for each vert Tab<VEdges*> edgesAtVertex; edgesAtVertex.SetCount(v.Count()); for (int i = 0; i < v.Count(); i++) edgesAtVertex[i] = NULL; for (int i = 0; i < ePtrList.Count(); i++) { int a = ePtrList[i]->a; if (pointSel[a]) { if (edgesAtVertex[a] == NULL) edgesAtVertex[a] = new VEdges(); edgesAtVertex[a]->edgeIndex.Append(1,&i,5); } a = ePtrList[i]->b; if (pointSel[a]) { if (edgesAtVertex[a] == NULL) edgesAtVertex[a] = new VEdges(); edgesAtVertex[a]->edgeIndex.Append(1,&i,5); } } BitArray processedFaces; processedFaces.SetSize(f.Count()); BitArray processedEdges; processedEdges.SetSize(ePtrList.Count()); int originalCount = v.Count(); for (int i = 0; i < originalCount; i++) { if (pointSel[i]) { processedFaces.ClearAll(); processedEdges.ClearAll(); int ct = edgesAtVertex[i]->edgeIndex.Count(); BOOL first = TRUE; for (int j = 0; j < ct; j++) { int currrentEdgeIndex = edgesAtVertex[i]->edgeIndex[j]; //find a selected edge if (esel[currrentEdgeIndex]) { int numFaces = ePtrList[currrentEdgeIndex]->faceList.Count(); for (int m = 0; m < numFaces; m++) { int newVertIndex = -1; if (first) { //just set the index newVertIndex = i; first = FALSE; } else { //create a new vertex UVW_TVVertClass newVert; newVert.SetP(v[i].GetP()); newVert.SetInfluence(0.0f); newVert.SetFlag(0); //create a new handle if we need one v.Append(1,&newVert); newVertIndex = v.Count()-1; } int currentFaceIndex = ePtrList[currrentEdgeIndex]->faceList[m]; if (!processedFaces[currentFaceIndex]) { BOOL done = FALSE; int lastEdge = j; while (!done) { //loop through this face looking for matching vert int deg = f[currentFaceIndex]->count; for (int n = 0; n < deg; n++) { //replace it if (f[currentFaceIndex]->t[n] == i) { f[currentFaceIndex]->t[n] = newVertIndex; } } processedFaces.Set(currentFaceIndex,TRUE); //loop til we find another selected face or an opent edge int nextEdge = -1; for (int n = 0; n < ct; n++) { //mkae sure we are not looking at the current edge int potentialEdge = edgesAtVertex[i]->edgeIndex[n]; if (n != lastEdge) { int nfaces = ePtrList[potentialEdge]->faceList.Count(); if (nfaces != -1) { for (int p = 0; p < nfaces; p++) { if (ePtrList[potentialEdge]->faceList[p] == currentFaceIndex) { nextEdge = potentialEdge; lastEdge = n; p = nfaces; n = ct; } } } } } //if we hit an edge we are done with this cluster if (nextEdge==-1) done = TRUE; else if (ePtrList[nextEdge]->a == ePtrList[nextEdge]->b) done = TRUE; else if (esel[nextEdge]) done = TRUE; else if (nextEdge != -1) { //get the next face int nfaces = ePtrList[nextEdge]->faceList.Count(); BOOL hit = FALSE; for (int p = 0; p < nfaces; p++) { if (ePtrList[nextEdge]->faceList[p]!= currentFaceIndex) { currentFaceIndex = ePtrList[nextEdge]->faceList[p]; hit = TRUE; p = nfaces; } } if (!hit) done = TRUE; } } } } } } } } for (int i = 0; i < originalCount; i++) { if (edgesAtVertex[i]) delete edgesAtVertex[i]; } BuildEdges(); BuildGeomEdges(); Tab<int> numberConnectedEdges; numberConnectedEdges.SetCount(v.Count()); for (int i = 0; i < v.Count(); i++) { numberConnectedEdges[i] = 0; } //loop through our egdes for (int i = 0; i < ePtrList.Count(); i++) { int veca = ePtrList[i]->avec; int vecb = ePtrList[i]->bvec; if (veca != -1) numberConnectedEdges[veca] += 1; if (vecb != -1) numberConnectedEdges[vecb] += 1; } for (int i = 0; i < f.Count(); i++) { if (f[i]->vecs) { int deg = f[i]->count; for (int j = 0; j < deg*2; j++) { int va; va = f[i]->vecs->handles[j]; if (numberConnectedEdges[va] > 1) { //clone the vert UVW_TVVertClass newVert; newVert.SetP(v[va].GetP()); newVert.SetInfluence(0.0f); newVert.SetFlag(0); //create a new handle if we need one v.Append(1,&newVert); int newVertIndex = v.Count()-1; //assign it f[i]->vecs->handles[j] = newVertIndex; //dec our counrt numberConnectedEdges[va] -= 1; } } } } mSystemLockedFlag.SetSize(v.Count(), 1); BuildEdges(); BuildGeomEdges(); }
//+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ //| From IPFTest | //+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ bool PFTestSpeed::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator, BitArray& testResult, Tab<float>& testTime) { bool exactStep = IsExactIntegrationStep(timeEnd, pSystem); // get the constant properties of the test int testType = pblock()->GetInt(kSpeedTest_testType, timeEnd); int condType = pblock()->GetInt(kSpeedTest_conditionType, timeEnd); int syncType = pblock()->GetInt(kSpeedTest_sync, timeEnd); ParamID varParamID = (testType == kSpeedTest_testType_steering) ? kSpeedTest_angleVariation : kSpeedTest_unitVariation; bool hasTestVariation = (pblock()->GetFloat(varParamID, 0) != 0.0f); if (!hasTestVariation) { Control* ctrl = pblock()->GetControllerByID(varParamID); if (ctrl != NULL) hasTestVariation = (ctrl->IsAnimated() != 0); } if (testType >= kSpeedTest_testType_whenAccels) { hasTestVariation = false; syncType = kSpeedTest_sync_time; } bool needPrevValue = (testType >= kSpeedTest_testType_accel); // get channel container interface IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // acquire absolutely necessary particle channels IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if (chAmount == NULL) return false; // can't find number of particles in the container int count = chAmount->Count(); if (count == 0) return true; // no particles to test IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) return false; // can't read timing info for a particle IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if (chNew == NULL) return false; // can't find newly entered particles for duration calculation IParticleChannelPoint3R* chSpeed = GetParticleChannelSpeedRInterface(pCont); if (chSpeed == NULL) return false; // can't read speed values // acquire more particle channels IParticleChannelPTVR* chBirthTime = NULL; if (syncType == kSpeedTest_sync_age && (testType < kSpeedTest_testType_whenAccels)) { chBirthTime = GetParticleChannelBirthTimeRInterface(pCont); if (chBirthTime == NULL) return false; // can't read particle age } IParticleChannelPTVR* chEventStartR = NULL; IParticleChannelPTVW* chEventStartW = NULL; bool initEventStart = false; if (syncType == kSpeedTest_sync_event && (testType < kSpeedTest_testType_whenAccels)) { chEventStartR = (IParticleChannelPTVR*)chCont->EnsureInterface(PARTICLECHANNELEVENTSTARTR_INTERFACE, ParticleChannelPTV_Class_ID, true, PARTICLECHANNELEVENTSTARTR_INTERFACE, PARTICLECHANNELEVENTSTARTW_INTERFACE, false, actionNode, NULL, &initEventStart); if (chEventStartR == NULL) return false; // can't read event start time if (initEventStart) { chEventStartW = GetParticleChannelEventStartWInterface(pCont); if (chEventStartW == NULL) return false; // can't write event start time } } IParticleChannelFloatR* chRandFloatR = NULL; IParticleChannelFloatW* chRandFloatW = NULL; bool initRandFloat = false; if (hasTestVariation) { chRandFloatW = (IParticleChannelFloatW*)chCont->EnsureInterface(PARTICLECHANNELRANDFLOATW_INTERFACE, ParticleChannelFloat_Class_ID, true, PARTICLECHANNELRANDFLOATR_INTERFACE, PARTICLECHANNELRANDFLOATW_INTERFACE, true, actionNode, (Object*)this, &initRandFloat); chRandFloatR = (IParticleChannelFloatR*)chCont->GetPrivateInterface(PARTICLECHANNELRANDFLOATR_INTERFACE, (Object*)this); if ((chRandFloatR == NULL) || (chRandFloatW == NULL)) return false; // can't set rand float value for newly entered particles } IParticleChannelPoint3R* chPrevSpeedR = NULL; IParticleChannelPoint3W* chPrevSpeedW = NULL; IParticleChannelPTVR* chPrevTimeR = NULL; IParticleChannelPTVW* chPrevTimeW = NULL; bool initPrevValue = false; if (needPrevValue) { chPrevSpeedW = (IParticleChannelPoint3W*)chCont->EnsureInterface(PARTICLECHANNELPREVSPEEDW_INTERFACE, ParticleChannelPoint3_Class_ID, true, PARTICLECHANNELPREVSPEEDR_INTERFACE, PARTICLECHANNELPREVSPEEDW_INTERFACE, true, actionNode, (Object*)this, &initPrevValue); chPrevSpeedR = (IParticleChannelPoint3R*)chCont->GetPrivateInterface(PARTICLECHANNELPREVSPEEDR_INTERFACE, (Object*)this); chPrevTimeW = (IParticleChannelPTVW*)chCont->EnsureInterface(PARTICLECHANNELPREVTIMEW_INTERFACE, ParticleChannelPTV_Class_ID, true, PARTICLECHANNELPREVTIMER_INTERFACE, PARTICLECHANNELPREVTIMEW_INTERFACE, true, actionNode, (Object*)this, &initPrevValue); chPrevTimeR = (IParticleChannelPTVR*)chCont->GetPrivateInterface(PARTICLECHANNELPREVTIMER_INTERFACE, (Object*)this); if ((chPrevSpeedR == NULL) || (chPrevSpeedW == NULL) || (chPrevTimeR == NULL) || (chPrevTimeW == NULL)) return false; } // grab the rand generator for test variation RandGenerator* randGen = randLinker().GetRandGenerator(pCont); if (randGen == NULL) return false; // check all particles testResult.SetSize(count); testResult.ClearAll(); testTime.SetCount(count); for(int i=0; i<count; i++) { if (chNew->IsNew(i)) { // initialize some channels if (initEventStart) chEventStartW->SetValue(i, chTime->GetValue(i)); if (initRandFloat) chRandFloatW->SetValue(i, randGen->Rand11()); } PreciseTimeValue prevTime; Point3 prevSpeed; Point3 currentSpeed = chSpeed->GetValue(i); PreciseTimeValue currentTime = chTime->GetValue(i); if (needPrevValue) { prevTime = chPrevTimeR->GetValue(i); prevSpeed = chPrevSpeedR->GetValue(i); chPrevTimeW->SetValue(i, currentTime); chPrevSpeedW->SetValue(i, currentSpeed); if (initPrevValue && chNew->IsNew(i)) continue; // particle just came into the event and doesn't have previous value } PreciseTimeValue syncTime = currentTime; switch(syncType) { case kSpeedTest_sync_age: syncTime -= chBirthTime->GetValue(i); break; case kSpeedTest_sync_event: syncTime -= chEventStartR->GetValue(i); break; } TimeValue syncTimeTV = TimeValue(syncTime); float testValue = 0.0f; if (testType < kSpeedTest_testType_whenAccels) { if (testType == kSpeedTest_testType_steering) { testValue = GetPFFloat(pblock(), kSpeedTest_angleValue, syncTimeTV); if (hasTestVariation) testValue += chRandFloatR->GetValue(i)*GetPFFloat(pblock(), kSpeedTest_angleVariation, syncTimeTV); } else { testValue = GetPFFloat(pblock(), kSpeedTest_unitValue, syncTimeTV); if (hasTestVariation) testValue += chRandFloatR->GetValue(i)*GetPFFloat(pblock(), kSpeedTest_unitVariation, syncTimeTV); } testValue /= TIME_TICKSPERSEC; } float currentValue = 0.0f; bool testSatisfied = false; if (testType < kSpeedTest_testType_whenAccels) { if (testType < kSpeedTest_testType_accel) { switch(testType) { case kSpeedTest_testType_speed: currentValue = Length(currentSpeed); break; case kSpeedTest_testType_speedX: currentValue = currentSpeed.x; break; case kSpeedTest_testType_speedY: currentValue = currentSpeed.y; break; case kSpeedTest_testType_speedZ: currentValue = currentSpeed.z; break; } } else if (testType == kSpeedTest_testType_steering) { float timeDif = float(currentTime - prevTime); if (timeDif <= 0.0f) continue; // no time difference float normFactor = Length(currentSpeed)*Length(prevSpeed); if (normFactor <= 0.0f) continue; // steering rate is not calculatable float vv = DotProd(currentSpeed,prevSpeed)/normFactor; float uu = 0.0; if (vv >= 1.0f) uu = 0.0; else if (vv <= -1.0f) uu = PI; else uu = acos(vv); currentValue = uu/timeDif; } else { // acceleration float timeDif = float(currentTime - prevTime); if (timeDif <= 0.0f) continue; // no time difference Point3 curAccel; switch(testType) { case kSpeedTest_testType_accel: currentValue = Length((currentSpeed - prevSpeed)/timeDif); break; case kSpeedTest_testType_accelX: currentValue = (currentSpeed.x - prevSpeed.x)/timeDif; break; case kSpeedTest_testType_accelY: currentValue = (currentSpeed.y - prevSpeed.y)/timeDif; break; case kSpeedTest_testType_accelZ: currentValue = (currentSpeed.z - prevSpeed.z)/timeDif; break; } testValue /= TIME_TICKSPERSEC; // acceleration is per second squared } testSatisfied = (condType == kSpeedTest_conditionType_less) ? (currentValue < testValue) : (currentValue > testValue); } else { if (testType == kSpeedTest_testType_whenAccels) { testSatisfied = (Length(currentSpeed) > Length(prevSpeed)); } else { testSatisfied = (Length(currentSpeed) < Length(prevSpeed)); } } if (testSatisfied && exactStep) { testResult.Set(i); testTime[i] = 0.0f; } } return true; }
void SelectByChannel::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) { //TODO: Add the code for actually modifying the object //get th map id // TriObject *tobj = (TriObject*)os->obj; // Mesh &mesh = tobj->GetMesh(); Mesh *mesh = NULL; MNMesh *mnmesh = NULL; TriObject *collapsedtobj = NULL; if (os->obj->IsSubClassOf(triObjectClassID)) { TriObject *tobj = (TriObject*)os->obj; mesh = &tobj->GetMesh(); } else if (os->obj->IsSubClassOf(polyObjectClassID)) { PolyObject *pobj = (PolyObject*)os->obj; mnmesh = &pobj->GetMesh(); } int mapID; int subID; int selType; pblock->GetValue(pb_mapid,0,mapID,FOREVER); pblock->GetValue(pb_mapsubid,0,subID,FOREVER); pblock->GetValue(pb_seltype,0,selType,FOREVER); if (subID < 0) subID = 0; if (subID > 2) subID = 2; if (mnmesh) { int numMaps = mnmesh->numm; mnmesh->dispFlags = MNDISP_VERTTICKS|MNDISP_SELVERTS ; mnmesh->selLevel = MNM_SL_VERTEX; if (mapID < numMaps) { UVVert *uvw = mnmesh->M(mapID)->v; MNMapFace *uvwFace = mnmesh->M(mapID)->f; if (uvw && uvwFace) { float *vsw = NULL; MNFace *face = mnmesh->f; vsw = mnmesh->getVSelectionWeights (); if (vsw == NULL) { mnmesh->SupportVSelectionWeights(); vsw = mnmesh->getVSelectionWeights (); } BitArray processed; processed.SetSize(mnmesh->numv); processed.ClearAll(); if (vsw && uvwFace && uvw) { if (selType == 0) { mnmesh->ClearVFlags (MN_SEL); for (int i = 0; i < mnmesh->numv; i++) vsw[i] = 0.0f; } for (int i = 0; i < mnmesh->numf; i++) { int deg = face[i].deg; for (int j = 0; j < deg; j++) { int index = uvwFace[i].tv[j]; int gindex = face[i].vtx[j]; if (!processed[gindex]) { processed.Set(gindex); if (selType == 0) { float w = uvw[index][subID]; if (w >= 1.0f) mnmesh->v[gindex].SetFlag (MN_SEL); // mesh.vertSel.Set(gindex); else vsw[gindex] = uvw[index][subID]; } else if (selType == 1) { float w = uvw[index][subID]; w += vsw[gindex]; if (w >= 1.0f) mnmesh->v[gindex].SetFlag (MN_SEL); // mesh.vertSel.Set(gindex); else vsw[gindex] = uvw[index][subID]; } else if (selType == 2) { float w = uvw[index][subID]; if (mnmesh->v[gindex].GetFlag (MN_SEL))//(mesh.vertSel[gindex]) w = 1.0f - w; else w = vsw[gindex] - w;; if (w < 1.0f) mnmesh->v[gindex].ClearFlag (MN_SEL); // mesh.vertSel.Set(gindex,FALSE); vsw[gindex] = w; } } } } } } } } else if (mesh) { mesh->dispFlags = DISP_VERTTICKS|DISP_SELVERTS; mesh->selLevel = MESH_VERTEX; if (mesh->mapSupport(mapID)) { UVVert *uvw = mesh->mapVerts(mapID); TVFace *uvwFace = mesh->mapFaces(mapID); float *vsw = NULL; Face *face = mesh->faces; vsw = mesh->getVSelectionWeights (); if (vsw == NULL) { mesh->SupportVSelectionWeights(); vsw = mesh->getVSelectionWeights (); } BitArray processed; processed.SetSize(mesh->numVerts); processed.ClearAll(); if (vsw && uvwFace && uvw) { if (selType == 0) { mesh->vertSel.ClearAll(); for (int i = 0; i < mesh->numVerts; i++) vsw[i] = 0.0f; } for (int i = 0; i < mesh->numFaces; i++) { for (int j = 0; j < 3; j++) { int index = uvwFace[i].t[j]; int gindex = face[i].v[j]; if (!processed[gindex]) { processed.Set(gindex); if (selType == 0) { float w = uvw[index][subID]; if (w >= 1.0f) mesh->vertSel.Set(gindex); else vsw[gindex] = uvw[index][subID]; } else if (selType == 1) { float w = uvw[index][subID]; w += vsw[gindex]; if (w >= 1.0f) mesh->vertSel.Set(gindex); else vsw[gindex] = uvw[index][subID]; } else if (selType == 2) { float w = uvw[index][subID]; if (mesh->vertSel[gindex]) w = 1.0f - w; else w = vsw[gindex] - w;; if (w < 1.0f) mesh->vertSel.Set(gindex,FALSE); vsw[gindex] = w; } } } } } } } Interval iv; iv = FOREVER; os->obj->PointsWereChanged(); iv = iv & os->obj->ChannelValidity(t,GEOM_CHAN_NUM); iv = iv & os->obj->ChannelValidity(t,TOPO_CHAN_NUM); iv = iv & os->obj->ChannelValidity(t,SELECT_CHAN_NUM); os->obj->UpdateValidity (SELECT_CHAN_NUM, iv); }
IGeometryChecker::ReturnVal MultipleEdgeChecker::GeometryCheck(TimeValue t,INode *nodeToCheck, IGeometryChecker::OutputVal &val) { val.mIndex.ZeroCount(); if(IsSupported(nodeToCheck)) { LARGE_INTEGER ups,startTime; QueryPerformanceFrequency(&ups); QueryPerformanceCounter(&startTime); //used to see if we need to pop up a dialog bool compute = true; bool checkTime = GetIGeometryCheckerManager()->GetAutoUpdate();//only check time for the dialog if auto update is active! ObjectState os = nodeToCheck->EvalWorldState(t); Object *obj = os.obj; BitArray arrayOfEdges; //we fill this up with the verts, if not empty then we have isolated vets EdgeFaceList edgeList; if(os.obj->IsSubClassOf(triObjectClassID)) { TriObject *tri = dynamic_cast<TriObject *>(os.obj); if(tri) { Mesh &mesh = tri->GetMesh(); edgeList.CreateEdgeFaceList(mesh); if(checkTime) { DialogChecker::Check(checkTime,compute,mesh.numFaces,startTime,ups); if(compute==false) return IGeometryChecker::eFail; } arrayOfEdges.SetSize(CheckerMeshEdge::GetTotalNumEdges(mesh.numFaces)); arrayOfEdges.ClearAll(); } else return IGeometryChecker::eFail; } else if(os.obj->IsSubClassOf(polyObjectClassID)) { PolyObject *poly = dynamic_cast<PolyObject *>(os.obj); if(poly) { MNMesh &mnMesh = poly->GetMesh(); edgeList.CreateEdgeFaceList(mnMesh); if(checkTime) { DialogChecker::Check(checkTime,compute,mnMesh.numf,startTime,ups); if(compute==false) return IGeometryChecker::eFail; } arrayOfEdges.SetSize(mnMesh.nume); arrayOfEdges.ClearAll(); } else return IGeometryChecker::eFail; } #pragma omp parallel for for(int i=0;i<edgeList.mNumVertexEdges;++i) { for(int j=0;j<edgeList.mVertexEdges[i]->mEdges.Count();++j) { EdgeFaceList::Edge *localEdge = edgeList.mVertexEdges[i]->mEdges[j]; if(localEdge) { if(localEdge->mFaces.Count()>2) { #pragma omp critical { arrayOfEdges.Set(localEdge->mEdgeNum); } } } } } if(arrayOfEdges.IsEmpty()==false) //we have an isolated vierts { int localsize= arrayOfEdges.GetSize(); for(int i=0;i<localsize;++i) { if(arrayOfEdges[i]) val.mIndex.Append(1,&i); } } return TypeReturned(); } return IGeometryChecker::eFail; }
void RenderMesh::ConvertFaces(Mesh *Mesh, int MatIndex, Tab<Vert3> &Verts, Tab<Face3> &Faces, bool NegScale) { Face3 TmpFace; Vert3 TmpVert; BitArray Written; int i,j,k,NumFace; int NumUV,UVCount,Index; int NumVert,Count,VIndex; Face *aFace; Tab<BasisVert> FNormals; Tab<VNormal> Normals; UVVert *UVVert; TVFace *UVFace; Point3 S,T,SxT; unsigned long Sg; bool useMeshNorms = false; if(NegScale) { gVIndex[0] = 2; gVIndex[1] = 1; gVIndex[2] = 0; } else { gVIndex[0] = 0; gVIndex[1] = 1; gVIndex[2] = 2; } // Do we have an EditNormal modifier present - if so we use those normals instead. // We only use this if they have been applied on a face with smoothing groups, otherwise // it messes up the tangent space calculation. Probably not the most obtmized route, but it // works... MeshNormalSpec * meshNorm = Mesh->GetSpecifiedNormals(); if(meshNorm && meshNorm->GetNumNormals()) useMeshNorms = true; NumFace = 0; for(i=0; i < Mesh->getNumFaces(); i++) { if(!Mesh->faces[i].Hidden()) { Index = Mesh->getFaceMtlIndex(i) + 1; if(Index == MatIndex || MatIndex == 0) { NumFace++; } } } NumVert = Mesh->getNumVerts(); Verts.SetCount(NumVert); Faces.SetCount(NumFace); if(NumVert == 0 || NumFace == 0) { return; } ComputeVertexNormals(Mesh,FNormals,Normals,NegScale); Written.SetSize(Mesh->getNumVerts()); Written.ClearAll(); NumUV = Mesh->getNumMaps(); if(NumUV) { Count = 0; if(NumUV > MAX_TMUS + 1) { NumUV = MAX_TMUS + 1; } for(i=0; i < Mesh->getNumFaces(); i++) { aFace = &Mesh->faces[i]; TmpFace.m_Num[0] = aFace->v[gVIndex[0]]; TmpFace.m_Num[1] = aFace->v[gVIndex[1]]; TmpFace.m_Num[2] = aFace->v[gVIndex[2]]; Sg = aFace->smGroup; for(j=0; j < 3; j++) { VIndex = aFace->v[gVIndex[j]]; TmpVert.m_Pos = Mesh->verts[VIndex]; if(Sg) { if(useMeshNorms) { int normID = meshNorm->Face(i).GetNormalID(gVIndex[j]); TmpVert.m_Normal = meshNorm->Normal(normID).Normalize(); Normals[VIndex].GetNormal(Sg,S,T,SxT); } else TmpVert.m_Normal = Normals[VIndex].GetNormal(Sg,S,T,SxT); TmpVert.m_S = S; TmpVert.m_T = T; TmpVert.m_SxT = SxT; } else { TmpVert.m_Normal = FNormals[i].m_Normal; TmpVert.m_S = FNormals[i].m_S; TmpVert.m_T = FNormals[i].m_T; TmpVert.m_SxT = FNormals[i].m_SxT; } UVCount = 0; TmpVert.m_Sg = Sg; for(k=0;k<m_MapChannels.Count();k++) { int index = m_MapChannels[k]; if(Mesh->getNumMapVerts(index)) { UVVert = Mesh->mapVerts(index); UVFace = Mesh->mapFaces(index); TmpVert.m_UV[k].x = UVVert[UVFace[i].t[gVIndex[j]]].x; TmpVert.m_UV[k].y = UVVert[UVFace[i].t[gVIndex[j]]].y; } else { TmpVert.m_UV[k].x = 0.0f; TmpVert.m_UV[k].y = 0.0f; } } if(Written[VIndex]) { if((Sg == 0) || (Verts[VIndex].m_Sg != TmpVert.m_Sg) || (!UVVertEqual(Verts[VIndex].m_UV[0],TmpVert.m_UV[0]))) { TmpFace.m_Num[j] = Verts.Count(); Verts.Append(1,&TmpVert,10); } } else { Verts[VIndex] = TmpVert; Written.Set(VIndex); } } if(!Mesh->faces[i].Hidden()) { Index = Mesh->getFaceMtlIndex(i) + 1; if(Index == MatIndex || MatIndex == 0) { Faces[Count++] = TmpFace; } } } } else { for(i=0; i < Mesh->getNumFaces(); i++) { aFace = &Mesh->faces[i]; Faces[i].m_Num[0] = aFace->v[gVIndex[0]]; Faces[i].m_Num[1] = aFace->v[gVIndex[1]]; Faces[i].m_Num[2] = aFace->v[gVIndex[2]]; for(j=0; j < 3; j++) { VIndex = aFace->v[gVIndex[j]]; Verts[VIndex].m_Pos = Mesh->verts[VIndex]; Verts[VIndex].m_Normal = Normals[VIndex].GetNormal(aFace->smGroup,S,T,SxT); Verts[VIndex].m_S = Point3(0.0f,0.0f,0.0f); Verts[VIndex].m_T = Point3(0.0f,0.0f,0.0f); Verts[VIndex].m_SxT = Point3(0.0f,0.0f,0.0f); for(k=0; k < MAX_TMUS; k++) { Verts[VIndex].m_UV[k].x = 0.0f; Verts[VIndex].m_UV[k].y = 0.0f; } } } } Verts.Shrink(); }
///////////////////////////////////////////////////////////////////// // Note: // The vertex color data that is used by the ModifyPolyObject // method was created based on this PolyObject's displayed // TriMesh (Mesh). This data is mapped back to the original // PolyMesh (MNMesh). The mapping relies on the same process // that was used by the method MNMesh::OutToTri() to generate // the Mesh. // Warning: // The mapping used in this method will need to be updated if // anything changes in the way MNMesh generates its displayed Mesh. // Author: // Wayne Catalfano // Date: // August 30, 2000 // /////////////////////////////////////////////////////////////////////// void ApplyVCMod::ModifyPolyObject(PolyObject* pPolyObj, TimeValue t) { static int calls = 0; iValid = FOREVER; Interval valid = GetValidity(t); MNMesh& mesh = pPolyObj->GetMesh(); if (mesh.MNum() < 1) mesh.SetMapNum (1); // get the vertex color map MNMap* pVCMap = mesh.M(0); // initialize to an all white map if necessary if (pVCMap->GetFlag(MN_DEAD)) mesh.InitMap(0); if (mixedVertexColors.Count() > 0) { pVCMap->setNumVerts (mesh.VNum()); pVCMap->setNumFaces (mesh.FNum()); // MNMesh keeps the vertices in the same order when it creates // the Mesh. The Mesh vertices Map directly back to the MNMesh // vertices in the same order. for (int i=0; i<mesh.VNum(); i++) { pVCMap->v[i] = i<mixedVertexColors.Count() ? Point3(mixedVertexColors[i]->r, mixedVertexColors[i]->g, mixedVertexColors[i]->b) : Point3(1.0f, 1.0f, 1.0f); } for (int i=0; i<mesh.FNum(); i++) { if (mesh.F(i)->GetFlag (MN_DEAD)) continue; pVCMap->F(i)->SetSize(mesh.F(i)->deg); for (int j=0; j<mesh.F(i)->deg;++j) { pVCMap->F(i)->tv[j] = mesh.F(i)->vtx[j]; } } } else if (faceColors.Count() > 0) { int numVCVerts = 0; for (int i=0; i<mesh.FNum(); i++) { if (mesh.F(i)->GetFlag (MN_DEAD)) continue; numVCVerts += mesh.F(i)->deg; } pVCMap->setNumVerts (numVCVerts); pVCMap->setNumFaces (mesh.FNum()); // This mapping process mimicks the process used to generate // the Mesh in the method MNMesh::OutToTri(). int faceVert = 0; int triFaceIndx = 0; BitArray faceVertSet; for (int i=0; i<mesh.FNum(); i++) { if (mesh.F(i)->GetFlag (MN_DEAD)) continue; pVCMap->F(i)->SetSize(mesh.F(i)->deg); faceVertSet.SetSize(mesh.F(i)->deg); faceVertSet.ClearAll(); int tnum = mesh.F(i)->TriNum()*3; Tab<int> triVerts; // The method MNFace::GetTriangles is at the heart of the // process used to map Mesh triangles back to MNMesh faces. mesh.F(i)->GetTriangles (triVerts); for (int j=0; j<tnum; j+=3) { for (int k=0; k<3; ++k) { int vertIndex = triVerts[j+k]; // check if we already added a vert for this index if (!faceVertSet[vertIndex]) { pVCMap->v[faceVert] = triFaceIndx<faceColors.Count() ? Point3(faceColors[triFaceIndx]->colors[k].r, faceColors[triFaceIndx]->colors[k].g, faceColors[triFaceIndx]->colors[k].b) : Point3(1.0f, 1.0f, 1.0f); pVCMap->F(i)->tv[vertIndex] = faceVert; faceVertSet.Set(vertIndex); faceVert++; } } ++triFaceIndx; } } } NotifyDependents(Interval(t,t), PART_VERTCOLOR & PART_EXCLUDE_RADIOSITY, REFMSG_CHANGE); NotifyDependents(Interval(t,t), PART_TOPO & PART_EXCLUDE_RADIOSITY, REFMSG_CHANGE); pPolyObj->UpdateValidity(VERT_COLOR_CHAN_NUM, valid); }
void PatchDeformPW::BuildParamData(Object *obj, LocalPatchData *localData,PatchMesh *patch,Matrix3 patchTM,Matrix3 baseTM) { localData->numPatches = patch->numPatches; //put our base mesh data into patch space Matrix3 tmFromBaseToPatch = baseTM * Inverse(patchTM); Matrix3 tmFromPatchToBase = patchTM * Inverse(baseTM); Tab<Point3> pointData; int pointCount = obj->NumPoints(); pointData.SetCount(pointCount); Tab<int> closestPoint; closestPoint.SetCount(pointCount); localData->paramData.SetCount(pointCount); for (int i = 0; i < pointCount; i++) { Point3 p = obj->GetPoint(i); localData->paramData[i].initialLocalPoint = p; p = p * tmFromBaseToPatch; pointData[i] = p; closestPoint[i] = -1; } int numPatches = patch->numPatches; //split the patches into 10x10 chunks Tab<Point3> patchPoints; patchPoints.SetCount(numPatches * 100); int ct = 0; for (int i = 0; i < numPatches; i++) { Patch *p = &patch->patches[i]; if (p->type == PATCH_QUAD) { float u,v; float inc = 1.0f/(10.0f+1.0f); u = inc; v = inc; for (int y = 0; y < 10; y++) { u = inc; for (int x = 0; x < 10; x++) { Point3 pt = p->interp(patch, u, v); patchPoints[ct] = pt; ct++; u += inc; } v += inc; } } else ct += 100; } for (int i = 0; i < pointCount; i++) { int closest = -1; float d= 0.0f; for (int j = 0; j < ct; j++) { float len = LengthSquared(patchPoints[j]-pointData[i]); if ((closest == -1) || (len<d)) { d = len; closest = j; } } closestPoint[i] = closest/100; } BitArray usedPatches; usedPatches.SetSize(numPatches); usedPatches.ClearAll(); for (int i = 0; i < pointCount; i++) { usedPatches.Set(closestPoint[i]); } int sampleRate; Interval iv; iv = FOREVER; pblock->GetValue(pb_samplerate,0,sampleRate,iv); patchPoints.SetCount(sampleRate*sampleRate); for (int i = 0; i < numPatches; i++) { Patch *p = &patch->patches[i]; if (ip) { TSTR name; name.printf(GetString(IDS_COMPLETED_PCT),(float) i / numPatches *100.0f); SetWindowText(GetDlgItem(hWnd,IDC_STATUS),name); } float inc = 1.0f/(sampleRate+1.0f); if ( (usedPatches[i]) && (p->type == PATCH_QUAD)) { float u,v; u = inc; v = inc; ct = 0; for (int y = 0; y < sampleRate; y++) { u = inc; for (int x = 0; x < sampleRate; x++) { Point3 pt = p->interp(patch, u, v); patchPoints[ct] = pt; ct++; u += inc; } v += inc; } for (int j = 0; j < pointCount; j++) { if ((ip) && ((j%10) == 0)) { TSTR name; name.printf(GetString(IDS_COMPLETED_PCT_W_COUNT),(float) i / numPatches *100.0f,j,pointCount); SetWindowText(GetDlgItem(hWnd,IDC_STATUS),name); } if (closestPoint[j] == i) { int closest = -1; float d= 0.0f; for (int k = 0; k < sampleRate*sampleRate; k++) { float len = LengthSquared(patchPoints[k]-pointData[j]); if ((closest == -1) || (len<d)) { d = len; closest = k; } } localData->paramData[j].uv.y = float (closest/sampleRate); localData->paramData[j].uv.x = float (closest - (localData->paramData[j].uv.y*sampleRate)); localData->paramData[j].uv.y = (localData->paramData[j].uv.y +1) * inc; localData->paramData[j].uv.x = (localData->paramData[j].uv.x +1) * inc; localData->paramData[j].patchIndex = i; //get the u vec float u = localData->paramData[j].uv.x; float v = localData->paramData[j].uv.y; float delta = 1.0f/(sampleRate+1.0f)*0.5f; float du = u-delta; float dv = v-delta; if (du <= 0.0f) DebugPrint(_T("error du 0.0f \n")); if (dv <= 0.0f) DebugPrint(_T("error dv 0.0f \n")); if (du >= 1.0f) DebugPrint(_T("error du 1.0f \n")); if (dv >= 1.0f) DebugPrint(_T("error dv 1.0f \n")); localData->incDelta = delta; Patch *p = &patch->patches[i]; Point3 uVec = Normalize(p->interp(patch, du, v)-patchPoints[closest]); //get the v vec Point3 vVec = Normalize(p->interp(patch, u, dv)-patchPoints[closest]); Point3 xAxis,yAxis,zAxis; xAxis = uVec; zAxis = CrossProd(uVec,vVec); yAxis = CrossProd(xAxis,zAxis); Point3 center = patchPoints[closest]; Matrix3 tm(xAxis,yAxis,zAxis,center); /*DebugPrint(_T("init %d\n"),j);*/ /*DebugPrint(_T("%f %f %f\n"),xAxis.x,xAxis.y,xAxis.z); DebugPrint(_T("%f %f %f\n"),yAxis.x,yAxis.y,yAxis.z); DebugPrint(_T("%f %f %f\n"),zAxis.x,zAxis.y,zAxis.z); DebugPrint(_T("%f %f %f\n"),center.x,center.y,center.z);*/ localData->paramData[j].initialPoint = pointData[j]*Inverse(tm); //DebugPrint(_T("init %d\n"),j); } } } } if (ip) { TSTR name; name.printf(_T("%s"),GetString(IDS_PICK)); SetWindowText(GetDlgItem(hWnd,IDC_STATUS),name); } //split the patch into sub samples chunk }
IGeometryChecker::ReturnVal MissingUVCoordinatesChecker::GeometryCheck(TimeValue t,INode *nodeToCheck, IGeometryChecker::OutputVal &val) { val.mIndex.ZeroCount(); if(IsSupported(nodeToCheck)) { LARGE_INTEGER ups,startTime; QueryPerformanceFrequency(&ups); QueryPerformanceCounter(&startTime); //used to see if we need to pop up a dialog bool compute = true; bool checkTime = GetIGeometryCheckerManager()->GetAutoUpdate();//only check time for the dialog if auto update is active! UVWChannel uvmesh; ObjectState os = nodeToCheck->EvalWorldState(t); Object *obj = os.obj; if(os.obj->IsSubClassOf(triObjectClassID)) { TriObject *tri = dynamic_cast<TriObject *>(os.obj); if(tri) { BitArray arrayOfVertices; arrayOfVertices.SetSize(tri->mesh.numVerts); arrayOfVertices.ClearAll(); IGeometryChecker::ReturnVal returnval=IGeometryChecker::eFail; int numChannels = tri->mesh.getNumMaps(); int index; for(int i=0;i<numChannels;++i) { if(tri->mesh.mapSupport(i)) { MeshMap *map = &tri->mesh.Map(i); if(map->getNumVerts()>0 &&map->getNumFaces()>0) { returnval= TypeReturned(); int numFaces = map->getNumFaces(); TVFace * tvFaces = map->tf; UVVert * uvVerts= map->tv; #pragma omp parallel for for(int faceIndex =0;faceIndex<numFaces;++faceIndex) { if(compute) { TVFace& tvFace = tvFaces[faceIndex]; Point3 tv = uvVerts[tvFace.t[0]]; if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z)) { index = tri->mesh.faces[faceIndex].v[0]; if(index>=0&&index<tri->mesh.numVerts) { #pragma omp critical { arrayOfVertices.Set(index); } } } tv = uvVerts[tvFace.t[1]]; if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z)) { index = tri->mesh.faces[faceIndex].v[1]; if(index>=0&&index<tri->mesh.numVerts) { #pragma omp critical { arrayOfVertices.Set(index); } } } tv = uvVerts[tvFace.t[2]]; if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z)) { index = tri->mesh.faces[faceIndex].v[2]; if(index>=0&&index<tri->mesh.numVerts) { #pragma omp critical { arrayOfVertices.Set(index); } } } if(checkTime==true) { #pragma omp critical { DialogChecker::Check(checkTime,compute,numFaces,startTime,ups); } } } } } } } if(arrayOfVertices.IsEmpty()==false) //we have overlapping faces { int localsize= arrayOfVertices.GetSize(); for(int i=0;i<localsize;++i) { if(arrayOfVertices[i]) val.mIndex.Append(1,&i); } } return returnval; } else return IGeometryChecker::eFail; } else if(os.obj->IsSubClassOf(polyObjectClassID)) { PolyObject *poly = dynamic_cast<PolyObject *>(os.obj); if(poly) { BitArray arrayOfVertices; arrayOfVertices.SetSize(poly->GetMesh().numv); arrayOfVertices.ClearAll(); IGeometryChecker::ReturnVal returnval=IGeometryChecker::eFail; int numChannels= poly->GetMesh().MNum(); int index; for(int i=0;i<numChannels;++i) { if(poly->GetMesh().M(i)) { MNMesh *mesh = &(poly->GetMesh()); MNMap *mnmap = mesh->M(i); if(mnmap&&mnmap->numv>0&&mnmap->numf>0) { returnval= TypeReturned(); int numFaces = mnmap->numf; #pragma omp parallel for for(int faceIndex =0;faceIndex<numFaces;++faceIndex) { if(compute) { Point3 tv; int a,b,c; MNMapFace *face = mnmap->F(faceIndex); UVVert * uvVerts= mnmap->v; for(int j=0;j<(face->deg);++j) { if(j==(face->deg-2)) { a = j; b = j+1; c = 0; } else if(j==(face->deg-1)) { a = j; b = 0; c = 1; } else { a = j; b = j+1; c = j+2; } tv = uvVerts[face->tv[a]]; if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z)) { index = mesh->f->vtx[a]; if(index>=0&&index<mesh->numv) { #pragma omp critical { arrayOfVertices.Set(index); } } } tv = uvVerts[face->tv[b]]; if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z)) { index = mesh->f->vtx[b]; if(index>=0&&index<mesh->numv) { #pragma omp critical { arrayOfVertices.Set(index); } } } tv = uvVerts[face->tv[c]]; if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z)) { index = mesh->f->vtx[c]; if(index>=0&&index<mesh->numv) { #pragma omp critical { arrayOfVertices.Set(index); } } } if(checkTime==true) { #pragma omp critical { DialogChecker::Check(checkTime,compute,numFaces,startTime,ups); } } } } } } } } if(arrayOfVertices.IsEmpty()==false) //we have overlapping faces { int localsize= arrayOfVertices.GetSize(); for(int i=0;i<localsize;++i) { if(arrayOfVertices[i]) val.mIndex.Append(1,&i); } } return returnval; } else return IGeometryChecker::eFail; } } return IGeometryChecker::eFail; }
void UnwrapMod::BuildInitialMapping(Mesh *msh) { //build bounding box Box3 bbox; bbox.Init(); //normalize the length width height for (int i = 0; i < TVMaps.f.Count(); i++) { int pcount = 3; // if (TVMaps.f[i].flags & FLAG_QUAD) pcount = TVMaps.f[i]->count; for (int j = 0; j < pcount; j++) { bbox += TVMaps.geomPoints[TVMaps.f[i]->v[j]]; } } Tab<int> indexList; indexList.SetCount(TVMaps.f.Count() *4); BitArray usedIndex; usedIndex.SetSize(TVMaps.f.Count() *4); usedIndex.ClearAll(); for (i = 0; i < TVMaps.f.Count()*4; i++) indexList[i] = -1; for (i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; // if (TVMaps.f[i].flags & FLAG_QUAD) pcount = 4; pcount = TVMaps.f[i]->count; for (int j = 0; j < pcount; j++) { usedIndex.Set(msh->faces[i].v[j]); } } } int ct = 0; for (i = 0; i < usedIndex.GetSize(); i++) { if (usedIndex[i]) indexList[i] = ct++; } TVMaps.v.SetCount(usedIndex.NumberSet()); TVMaps.cont.SetCount(usedIndex.NumberSet()); vsel.SetSize(usedIndex.NumberSet()); //watje 10-19-99 bug 213437 to prevent a divide by 0 which gives you a huge u,v, or w value if (bbox.Width().x == 0.0f) bbox += Point3(0.5f,0.0f,0.0f); if (bbox.Width().y == 0.0f) bbox += Point3(0.0f,0.5f,0.0f); if (bbox.Width().z == 0.0f) bbox += Point3(0.0f,0.0f,0.5f); for (i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; // if (TVMaps.f[i].flags & FLAG_QUAD) pcount = 4; pcount = TVMaps.f[i]->count; TVMaps.f[i]->flags &= ~FLAG_DEAD; for (int j = 0; j < pcount; j++) { int index; int a = msh->faces[i].v[j]; index = indexList[a]; TVMaps.f[i]->t[j] = index; TVMaps.v[index].p.x = TVMaps.geomPoints[TVMaps.f[i]->v[j]].x/bbox.Width().x + 0.5f; TVMaps.v[index].p.y = TVMaps.geomPoints[TVMaps.f[i]->v[j]].y/bbox.Width().y + 0.5f; TVMaps.v[index].p.z = TVMaps.geomPoints[TVMaps.f[i]->v[j]].z/bbox.Width().z + 0.5f; TVMaps.v[index].influence = 0.f; TVMaps.v[index].flags = 0.f; TVMaps.cont[index] = NULL; } } } }
void UnwrapMod::CopySelectionMesh(ObjectState *os, ModContext &mc, int CurrentChannel, TimeValue t) { objType = IS_MESH; TriObject *tobj = (TriObject*)os->obj; MeshTopoData *d = (MeshTopoData*)mc.localData; if (!d) { mc.localData = d = new MeshTopoData(tobj->GetMesh()); d->SetFaceSel(tobj->GetMesh().faceSel, this, t); UpdateFaceSelection(d->faceSel); } if ( ((editMod==this) && (!d->GetMesh())) || (updateCache)) { d->SetCache(tobj->GetMesh()); d->SetFaceSel(tobj->GetMesh().faceSel, this, t); updateCache = FALSE; UpdateFaceSelection(d->faceSel); SyncTVToGeomSelection(d); hiddenPolygons.SetSize(tobj->GetMesh().getNumFaces()); hiddenPolygons.ClearAll(); for (int i = 0; i < tobj->GetMesh().getNumFaces(); i++) { if (tobj->GetMesh().faces[i].Hidden()) hiddenPolygons.Set(i,TRUE); } } BitArray faceSel = d->faceSel; faceSel.SetSize(tobj->GetMesh().getNumFaces(),TRUE); if ( (ip && (ip->GetSubObjectLevel() > 0) )) { tobj->GetMesh().faceSel = faceSel; if (showVerts) { //select verts based on the current tverts; BitArray vertSel; vertSel.SetSize(tobj->GetMesh().getNumVerts(),TRUE); vertSel.ClearAll(); for(int sv = 0; sv < TVMaps.f.Count();sv++) { if (!(TVMaps.f[sv]->flags & FLAG_DEAD)) { int pcount = 3; // if (TVMaps.f[sv].flags & FLAG_QUAD) pcount = 4; pcount = TVMaps.f[sv]->count; for (int j = 0; j < pcount ; j++) { int index = TVMaps.f[sv]->t[j]; //6-29--99 watje if ((index < vsel.GetSize()) && (vsel[index] ==1) && (sv<tobj->GetMesh().numFaces)) // if (vsel[index] ==1) { int findex = tobj->GetMesh().faces[sv].v[j]; //6-29--99 watje if ((findex < vertSel.GetSize()) && (findex >=0)) vertSel.Set(findex,1); } } } } tobj->GetMesh().vertSel = vertSel; tobj->GetMesh().SetDispFlag(DISP_SELFACES|DISP_VERTTICKS|DISP_SELVERTS); //done++; } else { tobj->GetMesh().SetDispFlag(DISP_SELFACES); } //UNFOLD STUFF Face *faces = tobj->GetMesh().faces; for (int i =0; i < tobj->GetMesh().getNumFaces(); i++) { if ( (i < hiddenPolygons.GetSize()) && (hiddenPolygons[i]) ) faces[i].Hide(); else faces[i].Show(); } } if (!tmControl || (flags&CONTROL_OP) || (flags&CONTROL_INITPARAMS)) InitControl(t); //if planar mode build vert and face list if ( (ip && (ip->GetSubObjectLevel() == 1) )) { MeshUpdateGData(&tobj->GetMesh(),faceSel); } }
void UnwrapMod::fnUnfoldSelectedPolygons(int unfoldMethod, BOOL normalize) { // flatten selected polygons BailStart(); BitArray *polySel = fnGetSelectedPolygons(); BitArray holdPolySel; if (polySel == NULL) return; if (TVMaps.f.Count() == 0) return; if (!theHold.Holding()) { theHold.SuperBegin(); theHold.Begin(); } holdPolySel.SetSize(polySel->GetSize()); holdPolySel = *polySel; HoldPointsAndFaces(); Point3 normal(0.0f,0.0f,1.0f); BitArray oldSel = *fnGetSelectedPolygons(); Tab<Point3> mapNormal; mapNormal.SetCount(0); BOOL bContinue = BuildCluster( mapNormal, 5.0f, TRUE, TRUE); TSTR statusMessage; BitArray sel; sel.SetSize(TVMaps.f.Count()); if (bContinue) { for (int i =0; i < clusterList.Count(); i++) { sel.ClearAll(); for (int j = 0; j < clusterList[i]->faces.Count();j++) sel.Set(clusterList[i]->faces[j]); fnSelectPolygonsUpdate(&sel, FALSE); PlanarMapNoScale(clusterList[i]->normal); int per = (i * 100)/clusterList.Count(); statusMessage.printf("%s %d%%.",GetString(IDS_PW_STATUS_MAPPING),per); if (Bail(ip,statusMessage)) { i = clusterList.Count(); bContinue = FALSE; } } if ( (bContinue) && (clusterList.Count() > 1) ) { if (!ip) return; ModContextList mcList; INodeTab nodes; ip->GetModContexts(mcList,nodes); int objects = mcList.Count(); MeshTopoData *md = (MeshTopoData*)mcList[0]->localData; if (md == NULL) { theHold.Cancel(); theHold.SuperCancel(); return; } Tab<Point3> objNormList; BuildNormals(md,objNormList); //remove internal edges BitArray *selectedPolygons = fnGetSelectedPolygons(); Tab<int> clusterGroups; clusterGroups.SetCount(TVMaps.f.Count()); for (i =0; i < clusterGroups.Count(); i++) { clusterGroups[i] = -1; } //loop through all tagged edges and remove any that onely have one edhes selected for (i = 0; i < clusterList.Count(); i++) { for (int j = 0; j < clusterList[i]->faces.Count(); j++) { int faceIndex = clusterList[i]->faces[j]; clusterGroups[faceIndex] = i; } } BitArray processedClusters; processedClusters.SetSize(clusterList.Count()); processedClusters.ClearAll(); Tab<BorderClass> edgesToBeProcessed; BOOL done = FALSE; int currentCluster = 0; processedClusters.Set(0); clusterList[0]->newX = 0.0f; clusterList[0]->newY = 0.0f; // clusterList[0]->angle = 0.0f; for (int i = 0; i < clusterList[0]->borderData.Count(); i++) { int outerFaceIndex = clusterList[0]->borderData[i].outerFace; int connectedClusterIndex = clusterGroups[outerFaceIndex]; if ((connectedClusterIndex != 0) && (connectedClusterIndex != -1)) { edgesToBeProcessed.Append(1,&clusterList[0]->borderData[i]); } } BitArray seedFaceList; seedFaceList.SetSize(clusterGroups.Count()); seedFaceList.ClearAll(); for (i = 0; i < seedFaces.Count(); i++) { seedFaceList.Set(seedFaces[i]); } while (!done) { Tab<int> clustersJustProcessed; clustersJustProcessed.ZeroCount(); done = TRUE; int edgeToAlign = -1; float angDist = PI*2; if (unfoldMethod == 1) angDist = PI*2; else if (unfoldMethod == 2) angDist = 0; for (i = 0; i < edgesToBeProcessed.Count(); i++) { int outerFace = edgesToBeProcessed[i].outerFace; int connectedClusterIndex = clusterGroups[outerFace]; if (!processedClusters[connectedClusterIndex]) { int innerFaceIndex = edgesToBeProcessed[i].innerFace; int outerFaceIndex = edgesToBeProcessed[i].outerFace; //get angle Point3 innerNorm, outerNorm; innerNorm = objNormList[innerFaceIndex]; outerNorm = objNormList[outerFaceIndex]; float dot = DotProd(innerNorm,outerNorm); float angle = 0.0f; if (dot == -1.0f) angle = PI; else if (dot == 1.0f) angle = 0.f; else angle = acos(dot); if (unfoldMethod == 1) { if (seedFaceList[outerFaceIndex]) angle = 0.0f; if (angle < angDist) { angDist = angle; edgeToAlign = i; } } else if (unfoldMethod == 2) { if (seedFaceList[outerFaceIndex]) angle = 180.0f; if (angle > angDist) { angDist = angle; edgeToAlign = i; } } } } if (edgeToAlign != -1) { int innerFaceIndex = edgesToBeProcessed[edgeToAlign].innerFace; int outerFaceIndex = edgesToBeProcessed[edgeToAlign].outerFace; int edgeIndex = edgesToBeProcessed[edgeToAlign].edge; int connectedClusterIndex = clusterGroups[outerFaceIndex]; seedFaceList.Set(outerFaceIndex, FALSE); processedClusters.Set(connectedClusterIndex); clustersJustProcessed.Append(1,&connectedClusterIndex); AlignCluster(i,connectedClusterIndex,innerFaceIndex, outerFaceIndex,edgeIndex); done = FALSE; } //build new cluster list for (int j = 0; j < clustersJustProcessed.Count(); j++) { int clusterIndex = clustersJustProcessed[j]; for (int i = 0; i < clusterList[clusterIndex]->borderData.Count(); i++) { int outerFaceIndex = clusterList[clusterIndex]->borderData[i].outerFace; int connectedClusterIndex = clusterGroups[outerFaceIndex]; if ((!processedClusters[connectedClusterIndex]) && (connectedClusterIndex != 0) && (connectedClusterIndex != -1)) { edgesToBeProcessed.Append(1,&clusterList[clusterIndex]->borderData[i]); } } } } } vsel.SetSize(TVMaps.v.Count()); vsel.ClearAll(); for (i = 0; i < clusterList.Count(); i++) { for (int j =0; j < clusterList[i]->faces.Count(); j++) { int faceIndex = clusterList[i]->faces[j]; for (int k =0; k < TVMaps.f[faceIndex]->count; k++) { int vertexIndex = TVMaps.f[faceIndex]->t[k]; vsel.Set(vertexIndex); } } } //now weld the verts if (normalize) { NormalizeCluster(); } float tempWeld = weldThreshold; weldThreshold = 0.001f; WeldSelected(FALSE); weldThreshold = tempWeld; } FreeClusterList(); if (bContinue) { theHold.Accept(_T(GetString(IDS_PW_PLANARMAP))); theHold.SuperAccept(_T(GetString(IDS_PW_PLANARMAP))); fnSelectPolygonsUpdate(&holdPolySel, FALSE); theHold.Suspend(); fnSyncTVSelection(); theHold.Resume(); } else { theHold.Cancel(); theHold.SuperCancel(); } RebuildEdges(); theHold.Suspend(); fnSyncGeomSelection(); theHold.Resume(); NotifyDependents(FOREVER,PART_SELECT,REFMSG_CHANGE); InvalidateView(); }
void UnwrapMod::CleanUpDeadVertices() { for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; BitArray usedList; usedList.SetSize(ld->GetNumberTVVerts());//TVMaps.v.Count()); usedList.ClearAll(); for (int i = 0; i < ld->GetNumberFaces(); i++)//TVMaps.f.Count(); i++) { if (!ld->GetFaceDead(i)) { int degree = ld->GetFaceDegree(i); for (int j = 0; j < degree; j++) { int vertIndex = ld->GetFaceTVVert(i,j);//TVMaps.f[i]->t[j]; usedList.Set(vertIndex); //index into the geometric vertlist if ((ld->GetFaceHasVectors(i)/*TVMaps.f[i]->vecs*/) && (j < 4)) { vertIndex = ld->GetFaceTVInterior(i,j);//TVMaps.f[i]->vecs->interiors[j]; if ((vertIndex>=0) && (vertIndex < usedList.GetSize())) usedList.Set(vertIndex); vertIndex = ld->GetFaceTVHandle(i,j*2);//TVMaps.f[i]->vecs->handles[j*2]; if ((vertIndex>=0) && (vertIndex < usedList.GetSize())) usedList.Set(vertIndex); vertIndex = ld->GetFaceTVHandle(i,j*2+1);//TVMaps.f[i]->vecs->handles[j*2+1]; if ((vertIndex>=0) && (vertIndex < usedList.GetSize())) usedList.Set(vertIndex); } } } } int vInitalDeadCount = 0; int vFinalDeadCount = 0; for (int i =0; i < ld->GetNumberTVVerts(); i++)//TVMaps.v.Count(); i++) { if (ld->GetTVVertDead(i))//TVMaps.v[i].flags & FLAG_DEAD) vInitalDeadCount++; } for (int i =0; i < usedList.GetSize(); i++) { BOOL isRigPoint = ld->GetTVVertFlag(i) & FLAG_RIGPOINT; if (!usedList[i] && (!isRigPoint)) { ld->DeleteTVVert(i,this); // TVMaps.v[i].flags |= FLAG_DEAD; } } for (int i =0; i < ld->GetNumberTVVerts(); i++) { if (ld->GetTVVertDead(i))//TVMaps.v[i].flags & FLAG_DEAD) vFinalDeadCount++; } #ifdef DEBUGMODE if (gDebugLevel >= 3) ScriptPrint(_T("Cleaning Dead Verts Total Verts %d Initial Dead Verts %d Final Dead Verts %d \n"),vTotalCount,vInitalDeadCount,vFinalDeadCount); #endif } }
IGeometryChecker::ReturnVal OverlappedUVWFacesChecker::GeometryCheck(TimeValue t,INode *nodeToCheck, IGeometryChecker::OutputVal &val) { val.mIndex.ZeroCount(); if(IsSupported(nodeToCheck)) { UVWChannel uvmesh; ObjectState os = nodeToCheck->EvalWorldState(t); Object *obj = os.obj; if(os.obj->IsSubClassOf(triObjectClassID)) { TriObject *tri = dynamic_cast<TriObject *>(os.obj); if(tri) { BitArray arrayOfFaces; arrayOfFaces.SetSize(tri->mesh.numFaces); arrayOfFaces.ClearAll(); IGeometryChecker::ReturnVal returnval=IGeometryChecker::eFail; int numChannels = tri->mesh.getNumMaps(); for(int i=0;i<numChannels;++i) { if(tri->mesh.mapSupport(i)) { uvmesh.DeleteData(); uvmesh.SetWithMesh(&tri->mesh,i); if(uvmesh.GetNumOfFaces()>1) { //okay now run it with that uvmesh returnval = GeometryCheckWithUVMesh(uvmesh,t, nodeToCheck,arrayOfFaces); if(returnval ==IGeometryChecker::eFail) return returnval; } } } if(arrayOfFaces.IsEmpty()==false) //we have overlapping faces { int localsize= arrayOfFaces.GetSize(); for(int i=0;i<localsize;++i) { if(arrayOfFaces[i]) val.mIndex.Append(1,&i); } } return returnval; } else return IGeometryChecker::eFail; } else if(os.obj->IsSubClassOf(polyObjectClassID)) { PolyObject *poly = dynamic_cast<PolyObject *>(os.obj); if(poly) { BitArray arrayOfFaces; arrayOfFaces.SetSize(poly->GetMesh().numf); arrayOfFaces.ClearAll(); IGeometryChecker::ReturnVal returnval=IGeometryChecker::eFail; int numChannels= poly->GetMesh().MNum();//do this! for(int i=0;i<numChannels;++i) { if(poly->GetMesh().M(i)) { uvmesh.DeleteData(); uvmesh.SetWithMesh(&poly->GetMesh(),i); if(uvmesh.GetNumOfFaces()>1) { //okay now run it with that uvmesh returnval = GeometryCheckWithUVMesh(uvmesh,t, nodeToCheck,arrayOfFaces); if(returnval ==IGeometryChecker::eFail) return returnval; } } } if(arrayOfFaces.IsEmpty()==false) //we have overlapping faces { int localsize= arrayOfFaces.GetSize(); for(int i=0;i<localsize;++i) { if(arrayOfFaces[i]) val.mIndex.Append(1,&i); } } return returnval; } else return IGeometryChecker::eFail; } } return IGeometryChecker::eFail; }
void MeshTopoData::BuildInitialMapping(PatchMesh *msh) { //build bounding box Box3 bbox; bbox.Init(); //normalize the length width height for (int i = 0; i < TVMaps.f.Count(); i++) { int pcount = 3; pcount = TVMaps.f[i]->count; for (int j = 0; j < pcount; j++) { bbox += TVMaps.geomPoints[TVMaps.f[i]->v[j]]; if (TVMaps.f[i]->flags & FLAG_CURVEDMAPPING) { if (TVMaps.f[i]->vecs) { bbox += TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2]]; bbox += TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2+1]]; if (TVMaps.f[i]->flags & FLAG_INTERIOR) { bbox += TVMaps.geomPoints[TVMaps.f[i]->vecs->vinteriors[j]]; } } } } } Tab<int> indexList; int vct = msh->numVecs+msh->numVerts; indexList.SetCount(vct); BitArray usedIndex; usedIndex.SetSize(vct); usedIndex.ClearAll(); for (int i = 0; i < vct; i++) indexList[i] = -1; for (int i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; pcount = TVMaps.f[i]->count; for (int j = 0; j < pcount; j++) { // usedIndex.Set(TVMaps.f[i].t[j]); usedIndex.Set(msh->patches[i].v[j]); if (TVMaps.f[i]->flags & FLAG_CURVEDMAPPING) { if (TVMaps.f[i]->vecs) { usedIndex.Set(msh->patches[i].vec[j*2]+msh->numVerts); usedIndex.Set(msh->patches[i].vec[j*2+1]+msh->numVerts); if (TVMaps.f[i]->flags & FLAG_INTERIOR) { usedIndex.Set(msh->patches[i].interior[j]+msh->numVerts); } } } } } } int ct = 0; for (int i = 0; i < usedIndex.GetSize(); i++) { if (usedIndex[i]) indexList[i] = ct++; } TVMaps.v.SetCount(usedIndex.NumberSet()); mVSel.SetSize(usedIndex.NumberSet()); //watje 10-19-99 bug 213437 to prevent a divide by 0 which gives you a huge u,v, or w value if (bbox.Width().x == 0.0f) bbox += Point3(0.5f,0.0f,0.0f); if (bbox.Width().y == 0.0f) bbox += Point3(0.0f,0.5f,0.0f); if (bbox.Width().z == 0.0f) bbox += Point3(0.0f,0.0f,0.5f); for (int i = 0; i < TVMaps.f.Count(); i++) { if (!(TVMaps.f[i]->flags & FLAG_DEAD)) { int pcount = 3; pcount = TVMaps.f[i]->count; TVMaps.f[i]->flags &= ~FLAG_DEAD; for (int j = 0; j < pcount; j++) { int index; int a = msh->patches[i].v[j]; index = indexList[a]; TVMaps.f[i]->t[j] = index; Point3 uv( TVMaps.geomPoints[TVMaps.f[i]->v[j]].x/bbox.Width().x + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->v[j]].y/bbox.Width().y + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->v[j]].z/bbox.Width().z + 0.5f); TVMaps.v[index].SetP(uv); TVMaps.v[index].SetInfluence(0.f); TVMaps.v[index].SetFlag(0); TVMaps.v[index].SetControlID(-1); if (TVMaps.f[i]->flags & FLAG_CURVEDMAPPING) { if (TVMaps.f[i]->vecs) { // usedIndex.Set(msh->patches[i].vec[j*2]+msh->numVerts); // usedIndex.Set(msh->patches[i].vec[j*2+1]+msh->numVerts); int index; int a = msh->patches[i].vec[j*2]+msh->numVerts; index = indexList[a]; TVMaps.f[i]->vecs->handles[j*2] = index; Point3 uv( TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2]].x/bbox.Width().x + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2]].y/bbox.Width().y + 0.5f, TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2]].z/bbox.Width().z + 0.5f); TVMaps.v[index].SetP(uv); TVMaps.v[index].SetInfluence(0.f); TVMaps.v[index].SetFlag(0); TVMaps.v[index].SetControlID(-1); a = msh->patches[i].vec[j*2+1]+msh->numVerts; index = indexList[a]; TVMaps.f[i]->vecs->handles[j*2+1] = index; uv.x = TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2+1]].x/bbox.Width().x + 0.5f; uv.y = TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2+1]].y/bbox.Width().y + 0.5f; uv.z = TVMaps.geomPoints[TVMaps.f[i]->vecs->vhandles[j*2+1]].z/bbox.Width().z + 0.5f; TVMaps.v[index].SetP(uv); TVMaps.v[index].SetInfluence(0.f); TVMaps.v[index].SetFlag(0); TVMaps.v[index].SetControlID(-1); if (TVMaps.f[i]->flags & FLAG_INTERIOR) { int index; int a = msh->patches[i].interior[j]+msh->numVerts; index = indexList[a]; TVMaps.f[i]->vecs->interiors[j] = index; uv.x = TVMaps.geomPoints[TVMaps.f[i]->vecs->vinteriors[j]].x/bbox.Width().x + 0.5f; uv.y = TVMaps.geomPoints[TVMaps.f[i]->vecs->vinteriors[j]].y/bbox.Width().y + 0.5f; uv.z = TVMaps.geomPoints[TVMaps.f[i]->vecs->vinteriors[j]].z/bbox.Width().z + 0.5f; TVMaps.v[index].SetP(uv); TVMaps.v[index].SetInfluence(0.f); TVMaps.v[index].SetFlag(0); TVMaps.v[index].SetControlID(-1); } } } } } } }
void UnwrapMod::AlignCluster(int baseCluster, int moveCluster, int innerFaceIndex, int outerFaceIndex,int edgeIndex) { //get edges that are coincedent int vInner[2]; int vOuter[2]; int vInnerVec[2]; int vOuterVec[2]; int ct = 0; int vct = 0; for (int i = 0; i < TVMaps.f[innerFaceIndex]->count; i++) { int innerIndex = TVMaps.f[innerFaceIndex]->v[i]; for (int j = 0; j < TVMaps.f[outerFaceIndex]->count; j++) { int outerIndex = TVMaps.f[outerFaceIndex]->v[j]; if (innerIndex == outerIndex) { vInner[ct] = TVMaps.f[innerFaceIndex]->t[i]; vOuter[ct] = TVMaps.f[outerFaceIndex]->t[j]; ct++; } } } vInnerVec[0] = -1; vInnerVec[1] = -1; vOuterVec[0] = -1; vOuterVec[1] = -1; ct = 0; if ( (TVMaps.f[innerFaceIndex]->flags & FLAG_CURVEDMAPPING) && (TVMaps.f[innerFaceIndex]->vecs) && (TVMaps.f[outerFaceIndex]->flags & FLAG_CURVEDMAPPING) && (TVMaps.f[outerFaceIndex]->vecs) ) { for (i = 0; i < TVMaps.f[innerFaceIndex]->count*2; i++) { int innerIndex = TVMaps.f[innerFaceIndex]->vecs->vhandles[i]; for (int j = 0; j < TVMaps.f[outerFaceIndex]->count*2; j++) { int outerIndex = TVMaps.f[outerFaceIndex]->vecs->vhandles[j]; if (innerIndex == outerIndex) { int vec = TVMaps.f[innerFaceIndex]->vecs->handles[i]; vInnerVec[ct] = vec; vec = TVMaps.f[outerFaceIndex]->vecs->handles[j]; vOuterVec[ct] = vec; ct++; } } } } //get align vector Point3 pInner[2]; Point3 pOuter[2]; pInner[0] = TVMaps.v[vInner[0]].p; pInner[1] = TVMaps.v[vInner[1]].p; pOuter[0] = TVMaps.v[vOuter[0]].p; pOuter[1] = TVMaps.v[vOuter[1]].p; Point3 offset = pInner[0] - pOuter[0]; Point3 vecA, vecB; vecA = Normalize(pInner[1] - pInner[0]); vecB = Normalize(pOuter[1] - pOuter[0]); float dot = DotProd(vecA,vecB); float angle = 0.0f; if (dot == -1.0f) angle = PI; else if (dot == 1.0f) angle = 0.f; else angle = acos(dot); if ((_isnan(angle)) || (!_finite(angle))) angle = 0.0f; // DebugPrint("Stop\n"); // angle = acos(dot); //DebugPrint("angle %f dot %f \n",angle, dot); /* DebugPrint(" VecA %f %f %f \n",vecA.x,vecA.y,vecA.z); DebugPrint(" VecB %f %f %f \n",vecB.x,vecB.y,vecB.z); */ Matrix3 tempMat(1); tempMat.RotateZ(angle); Point3 vecC = VectorTransform(tempMat,vecB); float negAngle = -angle; Matrix3 tempMat2(1); tempMat2.RotateZ(negAngle); Point3 vecD = VectorTransform(tempMat2,vecB); float la,lb; la = Length(vecA-vecC); lb = Length(vecA-vecD); if (la > lb) angle = negAngle; clusterList[moveCluster]->newX = offset.x; clusterList[moveCluster]->newY = offset.y; //build vert list //move those verts BitArray processVertList; processVertList.SetSize(TVMaps.v.Count()); processVertList.ClearAll(); for (i =0; i < clusterList[moveCluster]->faces.Count(); i++) { int faceIndex = clusterList[moveCluster]->faces[i]; for (int j =0; j < TVMaps.f[faceIndex]->count; j++) { int vertexIndex = TVMaps.f[faceIndex]->t[j]; processVertList.Set(vertexIndex); if ( (objType == IS_PATCH) && (TVMaps.f[faceIndex]->flags & FLAG_CURVEDMAPPING) && (TVMaps.f[faceIndex]->vecs)) { int vertIndex; if (TVMaps.f[faceIndex]->flags & FLAG_INTERIOR) { vertIndex = TVMaps.f[faceIndex]->vecs->interiors[j]; if ((vertIndex >=0) && (vertIndex < processVertList.GetSize())) processVertList.Set(vertIndex); } vertIndex = TVMaps.f[faceIndex]->vecs->handles[j*2]; if ((vertIndex >=0) && (vertIndex < processVertList.GetSize())) processVertList.Set(vertIndex); vertIndex = TVMaps.f[faceIndex]->vecs->handles[j*2+1]; if ((vertIndex >=0) && (vertIndex < processVertList.GetSize())) processVertList.Set(vertIndex); } } } for (i = 0; i < processVertList.GetSize(); i++) { if (processVertList[i]) { //DebugPrint("%d ",i); Point3 p = TVMaps.v[i].p; //move to origin p -= pOuter[0]; //rotate Matrix3 mat(1); mat.RotateZ(angle); p = p * mat; //move to anchor point p += pInner[0]; TVMaps.v[i].p = p; if (TVMaps.cont[i]) TVMaps.cont[i]->SetValue(0,&TVMaps.v[i].p); } } if ((vInnerVec[0] != -1) && (vInnerVec[1] != -1) && (vOuterVec[0] != -1) && (vOuterVec[1] != -1)) { TVMaps.v[vOuterVec[0]].p = TVMaps.v[vInnerVec[0]].p; if (TVMaps.cont[vOuterVec[0]]) TVMaps.cont[vOuterVec[0]]->SetValue(0,&TVMaps.v[vInnerVec[0]].p); TVMaps.v[vOuterVec[1]].p = TVMaps.v[vInnerVec[1]].p; if (TVMaps.cont[vOuterVec[1]]) TVMaps.cont[vOuterVec[1]]->SetValue(0,&TVMaps.v[vInnerVec[1]].p); } }