Object* SimpleObject::ConvertToType(TimeValue t, Class_ID obtype) { if (obtype==defObjectClassID||obtype==triObjectClassID||obtype==mapObjectClassID) { TriObject *triob; UpdateMesh(t); triob = CreateNewTriObject(); triob->GetMesh() = mesh; triob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t)); triob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t)); return triob; } #ifndef NO_PATCHES if (obtype == patchObjectClassID) { UpdateMesh(t); PatchObject *patchob = new PatchObject(); patchob->patch = mesh; // Handy Mesh->PatchMesh conversion patchob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t)); patchob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t)); return patchob; } #endif if (Object::CanConvertToType (obtype)) { UpdateMesh (t); return Object::ConvertToType(t,obtype); } if (CanConvertTriObject(obtype)) { UpdateMesh (t); TriObject *triob = CreateNewTriObject (); triob->GetMesh() = mesh; triob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t)); triob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t)); Object *ob = triob->ConvertToType (t, obtype); if (ob != triob) triob->DeleteThis (); // (ob should never = tob.) return ob; } return NULL; }
Object* bhkProxyObject::ConvertToType(TimeValue t, Class_ID obtype) { if (obtype == triObjectClassID) { int bvType = 0; pblock2->GetValue(PB_BOUND_TYPE, 0, bvType, FOREVER, 0); if (bvType != 0) { TriObject *ob = CreateNewTriObject(); #if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+ ob->GetMesh().CopyBasics(proxyMesh); #else ob->GetMesh() = proxyMesh; #endif ob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t)); ob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t)); return ob; } } return 0; }
Object* SimpleObject::ConvertToType(TimeValue t, Class_ID obtype) { if (obtype==defObjectClassID||obtype==triObjectClassID||obtype==mapObjectClassID) { TriObject *triob; UpdateMesh(t); triob = CreateNewTriObject(); triob->GetMesh() = mesh; triob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t)); triob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t)); return triob; } else if (obtype == patchObjectClassID) { UpdateMesh(t); PatchObject *patchob = new PatchObject(); patchob->patch = mesh; // Handy Mesh->PatchMesh conversion patchob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t)); patchob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t)); return patchob; } return Object::ConvertToType(t,obtype); }
void SmoothMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node) { Interval valid = FOREVER; int autoSmooth, bits = 0, prevent = 0; float thresh = 0.0f; pblock->GetValue(sm_autosmooth, t, autoSmooth, valid); if (autoSmooth) { pblock->GetValue(sm_threshold, t, thresh, valid); pblock->GetValue(sm_prevent_indirect, t, prevent, valid); } else { pblock->GetValue(sm_smoothbits, t, bits, valid); } // For version 4 and later, we process patch meshes as they are and pass them on. Earlier // versions converted to TriMeshes (done below). For adding other new types of objects, add // them here! bool done = false; #ifndef NO_PATCHES if(version >= MATMOD_VER4 && os->obj->IsSubClassOf(patchObjectClassID)) { PatchObject *patchOb = (PatchObject *)os->obj; PatchMesh &pmesh = patchOb->GetPatchMesh(t); BOOL useSel = pmesh.selLevel >= PO_PATCH; if (autoSmooth) pmesh.AutoSmooth (thresh, useSel, prevent); else { for (int i=0; i<pmesh.getNumPatches(); i++) { if (!useSel || pmesh.patchSel[i]) pmesh.patches[i].smGroup = (DWORD)bits; } } pmesh.InvalidateGeomCache(); // Do this because there isn't a topo cache in PatchMesh patchOb->UpdateValidity(TOPO_CHAN_NUM,valid); done = true; } #endif // NO_PATCHES if (!done && os->obj->IsSubClassOf (polyObjectClassID)) { PolyObject *pPolyOb = (PolyObject *)os->obj; MNMesh &mesh = pPolyOb->GetMesh(); BOOL useSel = (mesh.selLevel == MNM_SL_FACE); if (autoSmooth) mesh.AutoSmooth (thresh, useSel, prevent); else { for (int faceIndex=0; faceIndex<mesh.FNum(); faceIndex++) { if (!useSel || mesh.F(faceIndex)->GetFlag(MN_SEL)) { mesh.F(faceIndex)->smGroup = (DWORD)bits; } } } // Luna task 747 // We need to rebuild the smoothing-group-based normals in the normalspec, if any: if (mesh.GetSpecifiedNormals()) { mesh.GetSpecifiedNormals()->SetParent (&mesh); mesh.GetSpecifiedNormals()->BuildNormals (); mesh.GetSpecifiedNormals()->ComputeNormals (); } pPolyOb->UpdateValidity(TOPO_CHAN_NUM,valid); done = true; } TriObject *triOb = NULL; if (!done) { if (os->obj->IsSubClassOf(triObjectClassID)) triOb = (TriObject *)os->obj; else { // Convert to triobject if we can. if(os->obj->CanConvertToType(triObjectClassID)) { TriObject *triOb = (TriObject *)os->obj->ConvertToType(t, triObjectClassID); // We'll need to stuff this back into the pipeline: os->obj = triOb; // Convert validities: Interval objValid = os->obj->ChannelValidity (t, TOPO_CHAN_NUM); triOb->SetChannelValidity (TOPO_CHAN_NUM, objValid); triOb->SetChannelValidity (GEOM_CHAN_NUM, objValid & os->obj->ChannelValidity (t, GEOM_CHAN_NUM)); triOb->SetChannelValidity (TEXMAP_CHAN_NUM, objValid & os->obj->ChannelValidity (t, TEXMAP_CHAN_NUM)); triOb->SetChannelValidity (VERT_COLOR_CHAN_NUM, objValid & os->obj->ChannelValidity (t, VERT_COLOR_CHAN_NUM)); triOb->SetChannelValidity (DISP_ATTRIB_CHAN_NUM, objValid & os->obj->ChannelValidity (t, DISP_ATTRIB_CHAN_NUM)); } } } if (triOb) { // one way or another, there's a triobject to smooth. Mesh & mesh = triOb->GetMesh(); BOOL useSel = mesh.selLevel == MESH_FACE; if (autoSmooth) mesh.AutoSmooth (thresh, useSel, prevent); else { for (int i=0; i<mesh.getNumFaces(); i++) { if (!useSel || mesh.faceSel[i]) mesh.faces[i].smGroup = (DWORD)bits; } } triOb->GetMesh().InvalidateTopologyCache(); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); } }
void RelaxMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) { // Get our personal validity interval... Interval valid = GetValidity(t); // and intersect it with the channels we use as input (see ChannelsUsed) valid &= os->obj->ChannelValidity (t, GEOM_CHAN_NUM); valid &= os->obj->ChannelValidity (t, TOPO_CHAN_NUM); valid &= os->obj->ChannelValidity (t, SUBSEL_TYPE_CHAN_NUM); valid &= os->obj->ChannelValidity (t, SELECT_CHAN_NUM); Matrix3 modmat,minv; if (mc.localData == NULL) mc.localData = new RelaxModData; RelaxModData *rd = (RelaxModData *) mc.localData; TriObject *triObj = NULL; PatchObject *patchObj = NULL; PolyObject *polyObj = NULL; BOOL converted = FALSE; // For version 4 and later, we process patch or poly meshes as they are and pass them on. // Earlier versions converted to TriMeshes (done below). // For adding other new types of objects, add them here! #ifndef NO_PATCHES if(version >= RELAXMOD_VER4 && os->obj->IsSubClassOf(patchObjectClassID)) { patchObj = (PatchObject *)os->obj; } else // If it's a TriObject, process it #endif // NO_PATCHES if(os->obj->IsSubClassOf(triObjectClassID)) { triObj = (TriObject *)os->obj; } else if (os->obj->IsSubClassOf (polyObjectClassID)) { polyObj = (PolyObject *) os->obj; } else // If it can convert to a TriObject, do it if(os->obj->CanConvertToType(triObjectClassID)) { triObj = (TriObject *)os->obj->ConvertToType(t, triObjectClassID); converted = TRUE; } else return; // We can't deal with it! Mesh *mesh = triObj ? &(triObj->GetMesh()) : NULL; #ifndef NO_PATCHES PatchMesh &pmesh = patchObj ? patchObj->GetPatchMesh(t) : *((PatchMesh *)NULL); #else PatchMesh &pmesh = *((PatchMesh *)NULL); #endif // NO_PATCHES float relax, wtdRelax; // mjm - 4.8.99 int iter; BOOL boundary, saddle; pblock->GetValue (PB_RELAX, t, relax, FOREVER); pblock->GetValue (PB_ITER, t, iter, FOREVER); pblock->GetValue (PB_BOUNDARY, t, boundary, FOREVER); pblock->GetValue (PB_SADDLE, t, saddle, FOREVER); LimitValue (relax, MIN_RELAX, MAX_RELAX); LimitValue (iter, MIN_ITER, MAX_ITER); if(triObj) { int i, j, max; DWORD selLevel = mesh->selLevel; // mjm - 4.8.99 - add support for soft selection // sca - 4.29.99 - extended soft selection support to cover EDGE and FACE selection levels. float *vsw = (selLevel!=MESH_OBJECT) ? mesh->getVSelectionWeights() : NULL; if (rd->ivalid.InInterval(t) && (mesh->numVerts != rd->vnum)) { // Shouldn't happen, but does with Loft bug and may with other bugs. rd->ivalid.SetEmpty (); } if (!rd->ivalid.InInterval(t)) { rd->SetVNum (mesh->numVerts); for (i=0; i<rd->vnum; i++) { rd->fnum[i]=0; rd->nbor[i].ZeroCount(); } rd->sel.ClearAll (); DWORD *v; int k1, k2, origmax; for (i=0; i<mesh->numFaces; i++) { v = mesh->faces[i].v; for (j=0; j<3; j++) { if ((selLevel==MESH_FACE) && mesh->faceSel[i]) rd->sel.Set(v[j]); if ((selLevel==MESH_EDGE) && mesh->edgeSel[i*3+j]) rd->sel.Set(v[j]); if ((selLevel==MESH_EDGE) && mesh->edgeSel[i*3+(j+2)%3]) rd->sel.Set(v[j]); origmax = max = rd->nbor[v[j]].Count(); rd->fnum[v[j]]++; for (k1=0; k1<max; k1++) if (rd->nbor[v[j]][k1] == v[(j+1)%3]) break; if (k1==max) { rd->nbor[v[j]].Append (1, v+(j+1)%3, 1); max++; } for (k2=0; k2<max; k2++) if (rd->nbor[v[j]][k2] == v[(j+2)%3]) break; if (k2==max) { rd->nbor[v[j]].Append (1, v+(j+2)%3, 1); max++; } if (max>origmax) rd->vis[v[j]].SetSize (max, TRUE); if (mesh->faces[i].getEdgeVis (j)) rd->vis[v[j]].Set (k1); else if (k1>=origmax) rd->vis[v[j]].Clear (k1); if (mesh->faces[i].getEdgeVis ((j+2)%3)) rd->vis[v[j]].Set (k2); else if (k2>= origmax) rd->vis[v[j]].Clear (k2); } } // mjm - begin - 4.8.99 // if (selLevel==MESH_VERTEX) rd->sel = mesh->vertSel; if (selLevel==MESH_VERTEX) rd->sel = mesh->vertSel; else if (selLevel==MESH_OBJECT) rd->sel.SetAll (); // mjm - end rd->ivalid = os->obj->ChannelValidity (t, TOPO_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SUBSEL_TYPE_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SELECT_CHAN_NUM); } Tab<float> vangles; if (saddle) vangles.SetCount (rd->vnum); Point3 *hold = new Point3[rd->vnum]; int act; for (int k=0; k<iter; k++) { for (i=0; i<rd->vnum; i++) hold[i] = triObj->GetPoint(i); if (saddle) mesh->FindVertexAngles (vangles.Addr(0)); for (i=0; i<rd->vnum; i++) { // mjm - begin - 4.8.99 // if ((selLevel!=MESH_OBJECT) && (!rd->sel[i])) continue; if ( (!rd->sel[i] ) && (!vsw || vsw[i] == 0) ) continue; // mjm - end if (saddle && (vangles[i] <= 2*PI*.99999f)) continue; max = rd->nbor[i].Count(); if (boundary && (rd->fnum[i] < max)) continue; if (max<1) continue; Point3 avg(0.0f, 0.0f, 0.0f); for (j=0,act=0; j<max; j++) { if (!rd->vis[i][j]) continue; act++; avg += hold[rd->nbor[i][j]]; } if (act<1) continue; // mjm - begin - 4.8.99 wtdRelax = (!rd->sel[i]) ? relax * vsw[i] : relax; triObj->SetPoint (i, hold[i]*(1-wtdRelax) + avg*wtdRelax/((float)act)); // triObj->SetPoint (i, hold[i]*(1-relax) + avg*relax/((float)act)); // mjm - end } } delete [] hold; } if (polyObj) { int i, j, max; MNMesh & mm = polyObj->mm; float *vsw = (mm.selLevel!=MNM_SL_OBJECT) ? mm.getVSelectionWeights() : NULL; if (rd->ivalid.InInterval(t) && (mm.numv != rd->vnum)) { // Shouldn't happen, but does with Loft bug and may with other bugs. rd->ivalid.SetEmpty (); } if (!rd->ivalid.InInterval(t)) { rd->SetVNum (mm.numv); for (i=0; i<rd->vnum; i++) { rd->fnum[i]=0; rd->nbor[i].ZeroCount(); } rd->sel = mm.VertexTempSel (); int k1, k2, origmax; for (i=0; i<mm.numf; i++) { int deg = mm.f[i].deg; int *vtx = mm.f[i].vtx; for (j=0; j<deg; j++) { Tab<DWORD> & nbor = rd->nbor[vtx[j]]; origmax = max = nbor.Count(); rd->fnum[vtx[j]]++; DWORD va = vtx[(j+1)%deg]; DWORD vb = vtx[(j+deg-1)%deg]; for (k1=0; k1<max; k1++) if (nbor[k1] == va) break; if (k1==max) { nbor.Append (1, &va, 1); max++; } for (k2=0; k2<max; k2++) if (nbor[k2] == vb) break; if (k2==max) { nbor.Append (1, &vb, 1); max++; } } } rd->ivalid = os->obj->ChannelValidity (t, TOPO_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SUBSEL_TYPE_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SELECT_CHAN_NUM); } Tab<float> vangles; if (saddle) vangles.SetCount (rd->vnum); Tab<Point3> hold; hold.SetCount (rd->vnum); int act; for (int k=0; k<iter; k++) { for (i=0; i<rd->vnum; i++) hold[i] = mm.P(i); if (saddle) FindVertexAngles (mm, vangles.Addr(0)); for (i=0; i<rd->vnum; i++) { if ((!rd->sel[i]) && (!vsw || vsw[i] == 0) ) continue; if (saddle && (vangles[i] <= 2*PI*.99999f)) continue; max = rd->nbor[i].Count(); if (boundary && (rd->fnum[i] < max)) continue; if (max<1) continue; Point3 avg(0.0f, 0.0f, 0.0f); for (j=0,act=0; j<max; j++) { act++; avg += hold[rd->nbor[i][j]]; } if (act<1) continue; wtdRelax = (!rd->sel[i]) ? relax * vsw[i] : relax; polyObj->SetPoint (i, hold[i]*(1-wtdRelax) + avg*wtdRelax/((float)act)); } } } #ifndef NO_PATCHES else if(patchObj) { int i, j, max; DWORD selLevel = pmesh.selLevel; // mjm - 4.8.99 - add support for soft selection // sca - 4.29.99 - extended soft selection support to cover EDGE and FACE selection levels. float *vsw = (selLevel!=PATCH_OBJECT) ? pmesh.GetVSelectionWeights() : NULL; if (rd->ivalid.InInterval(t) && (pmesh.numVerts != rd->vnum)) { // Shouldn't happen, but does with Loft bug and may with other bugs. rd->ivalid.SetEmpty (); } if (!rd->ivalid.InInterval(t)) { int vecBase = pmesh.numVerts; rd->SetVNum (pmesh.numVerts + pmesh.numVecs); for (i=0; i<rd->vnum; i++) { rd->fnum[i]=1; // For patches, this means it's not a boundary rd->nbor[i].ZeroCount(); } rd->sel.ClearAll (); for (i=0; i<pmesh.numPatches; i++) { Patch &p = pmesh.patches[i]; int vecLimit = p.type * 2; for (j=0; j<p.type; j++) { PatchEdge &e = pmesh.edges[p.edge[j]]; BOOL isBoundary = (e.patches.Count() < 2) ? TRUE : FALSE; int theVert = p.v[j]; int nextVert = p.v[(j+1)%p.type]; int nextVec = p.vec[j*2] + vecBase; int nextVec2 = p.vec[j*2+1] + vecBase; int prevEdge = (j+p.type-1)%p.type; int prevVec = p.vec[prevEdge*2+1] + vecBase; int prevVec2 = p.vec[prevEdge*2] + vecBase; int theInterior = p.interior[j] + vecBase; // Establish selection bits if ((selLevel==PATCH_PATCH) && pmesh.patchSel[i]) { rd->sel.Set(theVert); rd->sel.Set(nextVec); rd->sel.Set(prevVec); rd->sel.Set(theInterior); } else if ((selLevel==PATCH_EDGE) && pmesh.edgeSel[p.edge[j]]) { rd->sel.Set(e.v1); rd->sel.Set(e.vec12 + vecBase); rd->sel.Set(e.vec21 + vecBase); rd->sel.Set(e.v2); } else if ((selLevel==PATCH_VERTEX) && pmesh.vertSel[theVert]) { rd->sel.Set(theVert); rd->sel.Set(nextVec); rd->sel.Set(prevVec); rd->sel.Set(theInterior); } // Set boundary flags if necessary if(isBoundary) { rd->fnum[theVert] = 0; rd->fnum[nextVec] = 0; rd->fnum[nextVec2] = 0; rd->fnum[nextVert] = 0; } // First process the verts int work = theVert; max = rd->nbor[work].Count(); // Append the neighboring vectors rd->MaybeAppendNeighbor(work, nextVec, max); rd->MaybeAppendNeighbor(work, prevVec, max); rd->MaybeAppendNeighbor(work, theInterior, max); // Now process the edge vectors work = nextVec; max = rd->nbor[work].Count(); // Append the neighboring points rd->MaybeAppendNeighbor(work, theVert, max); rd->MaybeAppendNeighbor(work, theInterior, max); rd->MaybeAppendNeighbor(work, prevVec, max); rd->MaybeAppendNeighbor(work, nextVec2, max); rd->MaybeAppendNeighbor(work, p.interior[(j+1)%p.type] + vecBase, max); work = prevVec; max = rd->nbor[work].Count(); // Append the neighboring points rd->MaybeAppendNeighbor(work, theVert, max); rd->MaybeAppendNeighbor(work, theInterior, max); rd->MaybeAppendNeighbor(work, nextVec, max); rd->MaybeAppendNeighbor(work, prevVec2, max); rd->MaybeAppendNeighbor(work, p.interior[(j+p.type-1)%p.type] + vecBase, max); // Now append the interior, if not auto if(!p.IsAuto()) { work = theInterior; max = rd->nbor[work].Count(); // Append the neighboring points rd->MaybeAppendNeighbor(work, p.v[j], max); rd->MaybeAppendNeighbor(work, nextVec, max); rd->MaybeAppendNeighbor(work, nextVec2, max); rd->MaybeAppendNeighbor(work, prevVec, max); rd->MaybeAppendNeighbor(work, prevVec2, max); for(int k = 1; k < p.type; ++k) rd->MaybeAppendNeighbor(work, p.interior[(j+k)%p.type] + vecBase, max); } } } // mjm - begin - 4.8.99 if (selLevel==PATCH_VERTEX) { for (int i=0; i<pmesh.numVerts; ++i) { if (pmesh.vertSel[i]) rd->sel.Set(i); } } else if (selLevel==PATCH_OBJECT) rd->sel.SetAll(); // mjm - end rd->ivalid = os->obj->ChannelValidity (t, TOPO_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SUBSEL_TYPE_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SELECT_CHAN_NUM); } Tab<float> vangles; if (saddle) vangles.SetCount (rd->vnum); Point3 *hold = new Point3[rd->vnum]; int act; for (int k=0; k<iter; k++) { for (i=0; i<rd->vnum; i++) hold[i] = patchObj->GetPoint(i); if (saddle) FindVertexAngles(pmesh, vangles.Addr(0)); for (i=0; i<rd->vnum; i++) { // mjm - begin - 4.8.99 // if ((selLevel!=MESH_OBJECT) && (!rd->sel[i])) continue; if ( (!rd->sel[i] ) && (!vsw || vsw[i] == 0) ) continue; // mjm - end if (saddle && (i < pmesh.numVerts) && (vangles[i] <= 2*PI*.99999f)) continue; max = rd->nbor[i].Count(); if (boundary && !rd->fnum[i]) continue; if (max<1) continue; Point3 avg(0.0f, 0.0f, 0.0f); for (j=0,act=0; j<max; j++) { act++; avg += hold[rd->nbor[i][j]]; } if (act<1) continue; // mjm - begin - 4.8.99 wtdRelax = (!rd->sel[i]) ? relax * vsw[i] : relax; patchObj->SetPoint (i, hold[i]*(1-wtdRelax) + avg*wtdRelax/((float)act)); // patchObj->SetPoint (i, hold[i]*(1-relax) + avg*relax/((float)act)); // mjm - end } } delete [] hold; patchObj->patch.computeInteriors(); patchObj->patch.ApplyConstraints(); } #endif // NO_PATCHES if(!converted) { os->obj->SetChannelValidity(GEOM_CHAN_NUM, valid); } else { // Stuff converted object into the pipeline! triObj->SetChannelValidity(TOPO_CHAN_NUM, valid); triObj->SetChannelValidity(GEOM_CHAN_NUM, valid); triObj->SetChannelValidity(TEXMAP_CHAN_NUM, valid); triObj->SetChannelValidity(MTL_CHAN_NUM, valid); triObj->SetChannelValidity(SELECT_CHAN_NUM, valid); triObj->SetChannelValidity(SUBSEL_TYPE_CHAN_NUM, valid); triObj->SetChannelValidity(DISP_ATTRIB_CHAN_NUM, valid); os->obj = triObj; } }
void ExtrudeMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) { //DebugPrint(_T("Extrude modifying object\n")); // Get our personal validity interval... Interval valid = GetValidity(t); // and intersect it with the channels we use as input (see ChannelsUsed) valid &= os->obj->ChannelValidity(t,TOPO_CHAN_NUM); valid &= os->obj->ChannelValidity(t,GEOM_CHAN_NUM); int output; pblock->GetValue(PB_OUTPUT, TimeValue(0), output, FOREVER); switch (output) { case NURBS_OUTPUT: #ifndef NO_NURBS { // Here is where all the fun stuff happens -- GenerateExtrudeSurface fills in the EM, // then we stuff the EditableSurface into the pipeline. ShapeObject *shape = (ShapeObject *)os->obj; float amount; BOOL texturing, genMatIds, useShapeIDs; pblock->GetValue(PB_MAPPING, TimeValue(0), texturing, FOREVER); pblock->GetValue(PB_GEN_MATIDS, TimeValue(0), genMatIds, FOREVER); pblock->GetValue(PB_USE_SHAPEIDS, TimeValue(0), useShapeIDs, FOREVER); int levels,capStart,capEnd,capType; pblock->GetValue(PB_SEGS,t,levels,FOREVER); if (levels<1) levels = 1; pblock->GetValue(PB_CAPSTART,t,capStart,FOREVER); pblock->GetValue(PB_CAPEND,t,capEnd,FOREVER); pblock->GetValue(PB_CAPTYPE,t,capType,FOREVER); pblock->GetValue(PB_AMOUNT,t,amount,FOREVER); LimitValue(amount, -1000000.0f, 1000000.0f); BOOL suspended = FALSE; if (theHold.Holding()) { theHold.Suspend(); suspended = TRUE; } Object *nobj = CreateNURBSExtrudeShape(ip, GetString(IDS_RB_EXTRUDE), t, shape, amount, capStart, capEnd, capType, texturing, genMatIds, useShapeIDs); if (suspended) { theHold.Resume(); } // We only set geom validity because we preserve animation on clone // and copying other cahnnels causes problems -- SCM 9/2/97 nobj->SetChannelValidity(GEOM_CHAN_NUM, valid); os->obj = nobj; break;} #endif #ifndef NO_PATCHES case PATCH_OUTPUT: { // Here is where all the fun stuff happens -- BuildPatchFromShape fills in the PatchObject's patch mesh, // then we stuff the PatchObject into the pipeline. PatchObject *pat = new PatchObject; BuildPatchFromShape(t, mc, os, pat->patch); pat->SetChannelValidity(TOPO_CHAN_NUM, valid); pat->SetChannelValidity(GEOM_CHAN_NUM, valid); pat->SetChannelValidity(TEXMAP_CHAN_NUM, valid); pat->SetChannelValidity(MTL_CHAN_NUM, valid); pat->SetChannelValidity(SELECT_CHAN_NUM, valid); pat->SetChannelValidity(SUBSEL_TYPE_CHAN_NUM, valid); pat->SetChannelValidity(DISP_ATTRIB_CHAN_NUM, valid); os->obj = pat; break;} #endif // NO_PATCHES case MESH_OUTPUT: { // Here is where all the fun stuff happens -- BuildMeshFromShape fills in the TriObject's mesh, // then we stuff the TriObj into the pipeline. TriObject *tri = CreateNewTriObject(); BuildMeshFromShape(t, mc, os, tri->GetMesh()); tri->SetChannelValidity(TOPO_CHAN_NUM, valid); tri->SetChannelValidity(GEOM_CHAN_NUM, valid); tri->SetChannelValidity(TEXMAP_CHAN_NUM, valid); tri->SetChannelValidity(MTL_CHAN_NUM, valid); tri->SetChannelValidity(SELECT_CHAN_NUM, valid); tri->SetChannelValidity(SUBSEL_TYPE_CHAN_NUM, valid); tri->SetChannelValidity(DISP_ATTRIB_CHAN_NUM, valid); os->obj = tri; break; } #ifdef XXDESIGN_VER case AMSOLID_OUTPUT: { //Create an extrusion solid using Facet Modeler Object* solid = (Object*)CreateInstance(GEOMOBJECT_CLASS_ID, GENERIC_AMSOLID_CLASS_ID); assert(solid); if(solid) { IGeomImp* cacheptr = (IGeomImp*)(solid->GetInterface(I_GEOMIMP)); assert(cacheptr); if(cacheptr) { bool res = BuildAMSolidFromShape(t, mc, os, cacheptr); solid->ReleaseInterface(I_GEOMIMP, cacheptr); if(!res) { valid.SetInstant(t); // assert(!cacheptr->isNull()); } for(int i=0; i<NUM_OBJ_CHANS;i++) solid->SetChannelValidity(i, valid); os->obj = solid; } } break; } #endif } os->obj->UnlockObject(); }