void ExtrudeMod::EndEditParams( IObjParam *ip, ULONG flags,Animatable *next) { this->ip = NULL; editMod = NULL; TimeValue t = ip->GetTime(); ClearAFlag(A_MOD_BEING_EDITED); NotifyDependents(Interval(t,t), PART_ALL, REFMSG_END_EDIT); NotifyDependents(Interval(t,t), PART_ALL, REFMSG_MOD_DISPLAY_OFF); DestroyCPParamMap(pmapParam); // Save these values in class variables so the next object created will inherit them. pblock->GetValue(PB_AMOUNT,ip->GetTime(),dlgAmount,FOREVER); pblock->GetValue(PB_SEGS,ip->GetTime(),dlgSegs,FOREVER); if (dlgSegs<1) dlgSegs = 1; pblock->GetValue(PB_CAPSTART,ip->GetTime(),dlgCapStart,FOREVER); pblock->GetValue(PB_CAPEND,ip->GetTime(),dlgCapEnd,FOREVER); pblock->GetValue(PB_CAPTYPE,ip->GetTime(),dlgCapType,FOREVER); pblock->GetValue(PB_OUTPUT,ip->GetTime(),dlgOutput,FOREVER); pblock->GetValue(PB_MAPPING,ip->GetTime(),dlgMapping,FOREVER); pblock->GetValue(PB_GEN_MATIDS,ip->GetTime(),dlgGenMatIDs,FOREVER); pblock->GetValue(PB_USE_SHAPEIDS,ip->GetTime(),dlgUseShapeIDs,FOREVER); pblock->GetValue(PB_SMOOTH,ip->GetTime(),dlgSmooth,FOREVER); }
Interval RelaxMod::GetValidity(TimeValue t) { int i; float f; // Only have to worry about animated parameters. Interval valid = FOREVER; pblock->GetValue (PB_RELAX, t, f, valid); pblock->GetValue (PB_ITER, t, i, valid); return valid; }
Interval ExtrudeMod::GetValidity(TimeValue t) { float f; int i; Interval valid = FOREVER; pblock->GetValue(PB_AMOUNT,t,f,valid); pblock->GetValue(PB_SEGS,t,i,valid); pblock->GetValue(PB_CAPSTART,t,i,valid); pblock->GetValue(PB_CAPEND,t,i,valid); pblock->GetValue(PB_CAPTYPE,t,i,valid); return valid; }
int OptMod::RenderEnd(TimeValue t) { int views, render; pblock->GetValue(PB_VIEWS,0,views,FOREVER); #ifndef NO_OUTPUTRENDERER pblock->GetValue(PB_RENDER,0,render,FOREVER); #else render = views; #endif ClearAFlag(A_RENDER); if (views!=render) { NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE); } return 0; }
Interval FExtrudeMod::LocalValidity(TimeValue t) { // aszabo|feb.05.02 If we are being edited, return NEVER // to forces a cache to be built after previous modifier. if (TestAFlag(A_MOD_BEING_EDITED)) return NEVER; Interval iv = FOREVER; float v; Point3 pt; pblock->GetValue(PB_AMOUNT,t,v,iv); pblock->GetValue(PB_SCALE,t,v,iv); base->GetValue(t,&pt,iv,CTRL_ABSOLUTE); return iv; }
void AFRMod::ModifyObject (TimeValue t, ModContext &mc, ObjectState *os, INode *node) { Interval iv = FOREVER; float f, p, b; int backface; Point3 pt1, pt2; pblock->GetValue(PB_FALLOFF,t,f,iv); pblock->GetValue(PB_PINCH,t,p,iv); pblock->GetValue(PB_BUBBLE,t,b,iv); pblock->GetValue(PB_BACKFACE,t,backface,iv); p1->GetValue(t,&pt1,iv,CTRL_ABSOLUTE); p2->GetValue(t,&pt2,iv,CTRL_ABSOLUTE); if (f==0.0) { os->obj->UpdateValidity(GEOM_CHAN_NUM,iv); return; } Tab<Point3> normals; if (backface) { // Need to get vertex normals. if (os->obj->IsSubClassOf(triObjectClassID)) { TriObject *tobj = (TriObject*)os->obj; AverageVertexNormals (tobj->GetMesh(), normals); } else if (os->obj->IsSubClassOf (polyObjectClassID)) { PolyObject *pobj = (PolyObject *) os->obj; MNMesh &mesh = pobj->GetMesh(); normals.SetCount (mesh.numv); Point3 *vn = normals.Addr(0); for (int i=0; i<mesh.numv; i++) { if (mesh.v[i].GetFlag (MN_DEAD)) vn[i]=Point3(0,0,0); else vn[i] = mesh.GetVertexNormal (i); } #ifndef NO_PATCHES } else if (os->obj->IsSubClassOf (patchObjectClassID)) { PatchObject *pobj = (PatchObject *) os->obj; normals.SetCount (pobj->NumPoints ()); Point3 *vn = normals.Addr(0); for (int i=0; i<pobj->NumPoints(); i++) vn[i] = pobj->VertexNormal (i); #endif } } if (normals.Count()) { AFRDeformer deformer(mc,f,p,b,pt1,pt2,&normals); os->obj->Deform(&deformer, TRUE); } else { AFRDeformer deformer(mc,f,p,b,pt1,pt2); os->obj->Deform(&deformer, TRUE); } os->obj->UpdateValidity(GEOM_CHAN_NUM,iv); }
Interval MatMod::LocalValidity(TimeValue t) { int i; Interval valid = FOREVER; pblock->GetValue(PB_MATID,t,i,valid); return valid; }
void MatMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node) { Interval valid = FOREVER; int id; pblock->GetValue(PB_MATID,t,id,valid); id--; if (id<0) id = 0; if (id>0xffff) id = 0xffff; // 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! #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; for (int i=0; i<pmesh.getNumPatches(); i++) { if (!useSel || pmesh.patchSel[i]) { pmesh.setPatchMtlIndex(i,(MtlID)id); } } pmesh.InvalidateGeomCache(); // Do this because there isn't a topo cache in PatchMesh patchOb->UpdateValidity(TOPO_CHAN_NUM,valid); } else #endif // NO_PATCHES // Process PolyObjects if(os->obj->IsSubClassOf(polyObjectClassID)) { PolyObject *polyOb = (PolyObject *)os->obj; MNMesh &mesh = polyOb->GetMesh(); BOOL useSel = mesh.selLevel == MNM_SL_FACE; for (int i=0; i<mesh.numf; i++) { if (!useSel || mesh.f[i].GetFlag(MN_SEL)) { mesh.f[i].material = (MtlID)id; } } polyOb->UpdateValidity(TOPO_CHAN_NUM,valid); } else // If it's a TriObject, process it if(os->obj->IsSubClassOf(triObjectClassID)) { TriObject *triOb = (TriObject *)os->obj; DoMaterialSet(triOb, id); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); } else // Fallback position: If it can convert to a TriObject, do it! if(os->obj->CanConvertToType(triObjectClassID)) { TriObject *triOb = (TriObject *)os->obj->ConvertToType(t, triObjectClassID); // Now stuff this into the pipeline! os->obj = triOb; DoMaterialSet(triOb, id); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); } else return; // Do nothing if it can't convert to triObject }
int OptMod::RenderBegin(TimeValue t, ULONG flags) { int views, render, man; pblock->GetValue(PB_VIEWS,0,views,FOREVER); #ifndef NO_OUTPUTRENDERER pblock->GetValue(PB_RENDER,0,render,FOREVER); #else render = views; #endif pblock->GetValue(PB_MANUPDATE,0,man,FOREVER); SetAFlag(A_RENDER); if (views!=render || man) { NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE); } return 0; }
Interval AFRMod::LocalValidity(TimeValue t) { // aszabo|feb.05.02 If we are being edited, return NEVER // to forces a cache to be built after previous modifier. if (TestAFlag(A_MOD_BEING_EDITED)) return NEVER; Interval iv = FOREVER; float v; Point3 pt; pblock->GetValue(PB_FALLOFF,t,v,iv); pblock->GetValue(PB_PINCH,t,v,iv); pblock->GetValue(PB_BUBBLE,t,v,iv); p1->GetValue(t,&pt,iv,CTRL_ABSOLUTE); p2->GetValue(t,&pt,iv,CTRL_ABSOLUTE); return iv; }
void BombObject::EnableControls() { if (falloffSpin) { BOOL fallOffOn; pblock->GetValue(PB_FALLOFFON, 0, fallOffOn, FOREVER); falloffSpin->Enable(fallOffOn); } }
//aszabo|feb.06.02 - When LocalValidity is called by ModifyObject, // it returns NEVER and thus the object channels are marked non valid // As a result, the mod stack enters and infinite evaluation of the modifier // ModifyObject now calls GetValidity and CORE calls LocalValidity to // allow for building a cache on the input of this modifier when it's // being edited Interval MirrorMod::GetValidity(TimeValue t) { Interval iv = FOREVER; Matrix3 mat(1); tmControl->GetValue(t,&mat,iv,CTRL_RELATIVE); float o; pblock->GetValue(PB_OFFSET,t,o,iv); return iv; }
// property accessor functions for a new property 'aspect' Value* get_caps_aspect(ReferenceTarget* obj, Value* prop, TimeValue t, Interval& valid) { // compute & return capsule aspect IParamBlock *pb = ((Object*)obj)->GetParamBlock()->GetParamBlock(); float h, r; pb->GetValue(CAPS_HEIGHT, t, h, valid); pb->GetValue(CAPS_RADIUS, t, r, valid); return Float::intern(r * 2.0f / h); }
void WardShader::Update(TimeValue t, Interval &valid) { Point3 p, p2; if( inUpdate ) return; inUpdate = TRUE; if (!ivalid.InInterval(t)) { ivalid.SetInfinite(); // pblock->GetValue( PB_AMBIENT_CLR, t, p, ivalid ); // ambient = LimitColor(Color(p.x,p.y,p.z)); pblock->GetValue( PB_DIFFUSE_CLR, t, p, ivalid ); diffuse= LimitColor(Color(p.x,p.y,p.z)); pblock->GetValue( PB_AMBIENT_CLR, t, p2, ivalid ); if( lockAD && (p!=p2)){ pblock->SetValue( PB_AMBIENT_CLR, t, diffuse); ambient = diffuse; } else { pblock->GetValue( PB_AMBIENT_CLR, t, p, ivalid ); ambient = Bound(Color(p.x,p.y,p.z)); } pblock->GetValue( PB_SPECULAR_CLR, t, p2, ivalid ); if( lockDS && (p!=p2)){ pblock->SetValue( PB_SPECULAR_CLR, t, diffuse); specular = diffuse; } else { pblock->GetValue( PB_SPECULAR_CLR, t, p, ivalid ); specular = Bound(Color(p.x,p.y,p.z)); } // pblock->GetValue( PB_SPECULAR_CLR, t, p, ivalid ); // specular = LimitColor(Color(p.x,p.y,p.z)); pblock->GetValue( PB_GLOSSINESS_X, t, glossinessX, ivalid ); LIMITMINMAX(glossinessX, 0.0001f, 1.0f ); pblock->GetValue( PB_GLOSSINESS_Y, t, glossinessY, ivalid ); LIMITMINMAX(glossinessY, 0.0001f, 1.0f ); pblock->GetValue( PB_SPECULAR_LEV, t, specLevel, ivalid ); LIMITMINMAX(specLevel,0.0f,4.00f); pblock->GetValue( PB_DIFFUSE_LEV, t, diffLevel, ivalid ); LIMITMINMAX(diffLevel,0.0f,2.0f); curTime = t; } valid &= ivalid; inUpdate = FALSE; }
RefResult OptMod::NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message) { switch (message) { case REFMSG_CHANGE: { if (pmapParam && pmapParam->GetParamBlock()==pblock) { pmapParam->Invalidate(); } int man = FALSE; if (pblock) pblock->GetValue(PB_MANUPDATE,0,man,FOREVER); if (man) return REF_STOP; break; } case REFMSG_GET_PARAM_DIM: { GetParamDim *gpd = (GetParamDim*)partID; switch (gpd->index) { case PB_FACETHRESH1: case PB_FACETHRESH2: case PB_EDGETHRESH1: case PB_EDGETHRESH2: gpd->dim = stdAngleDim; break; case PB_MAXEDGE1: case PB_MAXEDGE2: gpd->dim = stdWorldDim; break; default: gpd->dim = defaultDim; break; } return REF_STOP; } case REFMSG_GET_PARAM_NAME: { GetParamName *gpn = (GetParamName*)partID; switch (gpn->index) { case PB_FACETHRESH1: gpn->name = GetString(IDS_RB_FACETHRESHL1); break; case PB_FACETHRESH2: gpn->name = GetString(IDS_RB_FACETHRESHL2); break; case PB_EDGETHRESH1: gpn->name = GetString(IDS_RB_EDGETHRESHL1); break; case PB_EDGETHRESH2: gpn->name = GetString(IDS_RB_EDGETHRESHL2); break; case PB_BIAS1: gpn->name = GetString(IDS_RB_BIASL1); break; case PB_BIAS2: gpn->name = GetString(IDS_RB_BIASL2); break; case PB_MAXEDGE1: gpn->name = GetString(IDS_RB_MAXEDGE1); break; case PB_MAXEDGE2: gpn->name = GetString(IDS_RB_MAXEDGE2); break; default: gpn->name = TSTR(_T("")); break; } return REF_STOP; } } return REF_SUCCEED; }
void MirrorMod::DrawGizmo(float size,PolyLineProc& lp) { Point3 v0(0,0,0), pv0(0,0,0), v1(0,0,0), pv1(0,0,0); int ct=0; int axis; pblock->GetValue(PB_AXIS,0,axis,FOREVER); switch (axis) { case 0: case 1: case 2: v0[axis] = -1.0f; pv0[(axis+1)%3] = 1.0f; pv0[(axis+2)%3] = 1.0f; ct=1; break; case 3: case 4: case 5: v0[(axis)%3] = -1.0f; pv0[(axis+1)%3] = 1.0f; pv0[(axis+2)%3] = 1.0f; v1[(axis+1)%3] = -1.0f; pv1[(axis+2)%3] = 1.0f; pv1[(axis+3)%3] = 1.0f; ct=2; break; } Point3 pts[20]; SetupAxisPoints(v0, pv0, size, pts); lp.proc(pts,5); lp.proc(pts+5,2); lp.proc(pts+7,3); lp.proc(pts+10,3); lp.proc(pts+13,3); lp.proc(pts+16,3); if (ct==2) { SetupAxisPoints(v1, pv1, size, pts); lp.proc(pts,5); lp.proc(pts+5,2); lp.proc(pts+7,3); lp.proc(pts+10,3); lp.proc(pts+13,3); lp.proc(pts+16,3); } }
void TriPatchObject::EndEditParams( IObjParam *ip, ULONG flags, Animatable *next ) { editOb = NULL; this->ip = NULL; if (flags&END_EDIT_REMOVEUI ) { if (pmapTypeIn) DestroyCPParamMap(pmapTypeIn); DestroyCPParamMap(pmapParam); pmapParam = NULL; pmapTypeIn = NULL; } // Save these values in class variables so the next object created will inherit them. pblock->GetValue(PB_TEXTURE,ip->GetTime(),dlgTexture,FOREVER); }
Interval OptMod::LocalValidity(TimeValue t) { float f; Interval valid = FOREVER; int man; pblock->GetValue(PB_MANUPDATE,t,man,valid); if (!man) { pblock->GetValue(PB_FACETHRESH1,t,f,valid); pblock->GetValue(PB_EDGETHRESH1,t,f,valid); pblock->GetValue(PB_BIAS1,t,f,valid); pblock->GetValue(PB_MAXEDGE1,t,f,valid); pblock->GetValue(PB_FACETHRESH2,t,f,valid); pblock->GetValue(PB_EDGETHRESH2,t,f,valid); pblock->GetValue(PB_BIAS2,t,f,valid); pblock->GetValue(PB_MAXEDGE2,t,f,valid); } return valid; }
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(); }
BOOL ExtrudeMod::HasUVW() { BOOL genUVs; Interval v; pblock->GetValue(PB_MAPPING, 0, genUVs, v); return genUVs; }
void FExtrudeMod::ModifyObject( TimeValue t, ModContext &mc, ObjectState *os, INode *node) { if (os->obj->IsSubClassOf(triObjectClassID)) { TriObject *tobj = (TriObject*)os->obj; Mesh &mesh = tobj->GetMesh(); Interval iv = FOREVER; float a, s; Point3 pt, center; int c; pblock->GetValue(PB_AMOUNT,t,a,iv); pblock->GetValue(PB_SCALE,t,s,iv); pblock->GetValue(PB_CENTER,t,c,iv); base->GetValue(t,&pt,iv,CTRL_ABSOLUTE); // Extrude the faces -- this just creates the new faces mesh.ExtrudeFaces(); // Build normals of selected faces only Tab<Point3> normals; if (!c) { normals.SetCount(mesh.getNumVerts()); for (int i=0; i<mesh.getNumVerts(); i++) { normals[i] = Point3(0,0,0); } for (int i=0; i<mesh.getNumFaces(); i++) { if (mesh.faceSel[i]) { Point3 norm = (mesh.verts[mesh.faces[i].v[1]]-mesh.verts[mesh.faces[i].v[0]]) ^ (mesh.verts[mesh.faces[i].v[2]]-mesh.verts[mesh.faces[i].v[1]]); for (int j=0; j<3; j++) { normals[mesh.faces[i].v[j]] += norm; } } } for (int i=0; i<mesh.getNumVerts(); i++) { normals[i] = Normalize(normals[i]); } } else { // Compute the center point base->GetValue(t,¢er,iv,CTRL_ABSOLUTE); } // Mark vertices used by selected faces BitArray sel; sel.SetSize(mesh.getNumVerts()); for (int i=0; i<mesh.getNumFaces(); i++) { if (mesh.faceSel[i]) { for (int j=0; j<3; j++) sel.Set(mesh.faces[i].v[j],TRUE); } } // Move selected verts for (int i=0; i<mesh.getNumVerts(); i++) { if (sel[i]) { if (!c) { mesh.verts[i] += normals[i]*a; } else { Point3 vect = Normalize((mesh.verts[i] * (*mc.tm)) - center); mesh.verts[i] += vect*a; } } } // Scale verts if (s!=100.0f) { s /= 100.0f; AdjEdgeList ae(mesh); AdjFaceList af(mesh,ae); FaceClusterList clust(mesh.faceSel,af); // Make sure each vertex is only scaled once. BitArray done; done.SetSize(mesh.getNumVerts()); // scale each cluster independently for (int i=0; (DWORD)i<clust.count; i++) { // First determine cluster center Point3 cent(0,0,0); int ct=0; for (int j=0; j<mesh.getNumFaces(); j++) { if (clust[j]==(DWORD)i) { for (int k=0; k<3; k++) { cent += mesh.verts[mesh.faces[j].v[k]]; ct++; } } } if (ct) cent /= float(ct); // Now scale the cluster about its center for (int j=0; j<mesh.getNumFaces(); j++) { if (clust[j]==(DWORD)i) { for (int k=0; k<3; k++) { int index = mesh.faces[j].v[k]; if (done[index]) continue; done.Set(index); mesh.verts[index] = (mesh.verts[index]-cent)*s + cent; } } } } } mesh.InvalidateTopologyCache (); os->obj->UpdateValidity(GEOM_CHAN_NUM,iv); } }
BOOL TriPatchObject::HasUVW() { BOOL genUVs; Interval v; pblock->GetValue(PB_TEXTURE, 0, genUVs, v); return genUVs; }
void TriPatchObject::BuildPatch(TimeValue t,PatchMesh& amesh) { int nverts = 4; int nvecs = 16; float l, w; int tex; // Start the validity interval at forever and whittle it down. ivalid = FOREVER; pblock->GetValue( PB_LENGTH, t, l, ivalid ); pblock->GetValue( PB_WIDTH, t, w, ivalid ); pblock->GetValue( PB_TEXTURE, t, tex, ivalid ); amesh.setNumVerts(nverts); amesh.setNumTVerts(tex ? nverts : 0); amesh.setNumVecs(nvecs); amesh.setNumPatches(2); amesh.setNumTVPatches(tex ? 2 : 0); Point3 v0 = Point3(-w, -l, 0.0f) / 2.0f; Point3 v1 = v0 + Point3(w, 0.0f, 0.0f); Point3 v2 = v0 + Point3(w, l, 0.0f); Point3 v3 = v0 + Point3(0.0f, l, 0.0f); // Create the vertices. amesh.verts[0].flags = PVERT_COPLANAR; amesh.verts[1].flags = PVERT_COPLANAR; amesh.verts[2].flags = PVERT_COPLANAR; amesh.verts[3].flags = PVERT_COPLANAR; if(tex) { amesh.setTVert(0, UVVert(0,0,0)); amesh.setTVert(1, UVVert(1,0,0)); amesh.setTVert(2, UVVert(1,1,0)); amesh.setTVert(3, UVVert(0,1,0)); } amesh.setVert(0, v0); amesh.setVert(1, v1); amesh.setVert(2, v2); amesh.setVert(3, v3); // Create the vectors MAKEVEC(0, v0, v1); MAKEVEC(2, v1, v2); MAKEVEC(4, v2, v3); MAKEVEC(6, v3, v0); MAKEVEC(8, v3, v1); // Create patches. amesh.MakeTriPatch(0, 0, 0, 1, 1, 9, 8, 3, 6, 7, 10, 11, 12, 1); amesh.MakeTriPatch(1, 1, 2, 3, 2, 4, 5, 3, 8, 9, 13, 14, 15, 1); Patch &p1 = amesh.patches[0]; Patch &p2 = amesh.patches[1]; if(tex) { amesh.getTVPatch(0).setTVerts(0,1,3); amesh.getTVPatch(1).setTVerts(1,2,3); } // Finish up patch internal linkages (and bail out if it fails!) assert(amesh.buildLinkages()); // Calculate the interior bezier points on the PatchMesh's patches amesh.computeInteriors(); amesh.InvalidateGeomCache(); // Tell the PatchMesh it just got changed amesh.InvalidateMesh(); }
void ExtrudeMod::BuildMeshFromShape(TimeValue t,ModContext &mc, ObjectState * os, Mesh &mesh, BOOL simple) { BOOL texturing; pblock->GetValue(PB_MAPPING, TimeValue(0), texturing, FOREVER); BOOL genMatIDs; pblock->GetValue(PB_GEN_MATIDS, TimeValue(0), genMatIDs, FOREVER); BOOL useShapeIDs; pblock->GetValue(PB_USE_SHAPEIDS, TimeValue(0), useShapeIDs, FOREVER); BOOL smooth; pblock->GetValue(PB_SMOOTH, TimeValue(0), smooth, FOREVER); ShapeObject *shape = (ShapeObject *)os->obj; float amount; int levels,capStart,capEnd,capType; pblock->GetValue(PB_AMOUNT,t,amount,FOREVER); if(simple) { levels = 1; capStart = capEnd = FALSE; } else { 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); LimitValue(amount, -1000000.0f, 1000000.0f); // Get the basic dimension stuff float zSize = (float)fabs(amount); float baseZ = 0.0f; if(amount < 0.0f) baseZ = amount; // Make the shape convert itself to a PolyShape -- This makes our mesh conversion MUCH easier! PolyShape pShape; shape->MakePolyShape(t, pShape); ShapeHierarchy hier; pShape.OrganizeCurves(t, &hier); // Need to flip the reversed curves in the shape! pShape.Reverse(hier.reverse); int polys = pShape.numLines; int levelVerts = 0, levelFaces = 0, levelTVerts = 0; int verts = 0, faces = 0, tVerts = 0; int poly, piece; BOOL anyClosed = FALSE; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; if(line.IsClosed()) { anyClosed = TRUE; levelTVerts++; } levelVerts += line.numPts; levelTVerts += line.numPts; levelFaces += (line.Segments() * 2); } int vertsPerLevel = levelVerts; int numLevels = levels; verts = levelVerts * (levels + 1); tVerts = levelTVerts * (levels + 1); faces = levelFaces * levels; mesh.setNumVerts(verts); mesh.setNumFaces(faces); if(texturing) { mesh.setNumTVerts(tVerts); mesh.setNumTVFaces(faces); } // Create the vertices! int vert = 0; int tvertex = 0; int level; Point3 offset1, offset2; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; if(texturing) { //DebugPrint(_T("Texture Verts:\n")); BOOL usePhysUVs = GetUsePhysicalScaleUVs(); int tp; int texPts = line.numPts + (line.IsClosed() ? 1 : 0); float *texPt = new float [texPts]; float lastPt = (float)(texPts - 1); float cumLen = 0.0f; float totLen = line.CurveLength(); Point3 prevPt = line.pts[0].p; for(tp = 0; tp < texPts; ++tp) { int ltp = tp % line.numPts; if(tp == (texPts - 1)) texPt[tp] = usePhysUVs ? totLen : 1.0f; else { Point3 &pt = line.pts[ltp].p; cumLen += Length(pt - prevPt); if (usePhysUVs) texPt[tp] = cumLen; else texPt[tp] = cumLen / totLen; prevPt = pt; } } float flevels = (float)levels; for(level = 0; level <= levels; ++level) { float tV = (float)level / flevels; float vScale = usePhysUVs ? amount : 1.0f; for(tp = 0; tp < texPts; ++tp) { mesh.setTVert(tvertex++, UVVert(texPt[tp], vScale*tV, 0.0f)); } } delete [] texPt; } int lverts = line.numPts; for(level = 0; level <= levels; ++level) { Point3 offset = Point3(0.0f, 0.0f, baseZ + (float)level / (float)levels * zSize); if(level == 0) offset1 = offset; else if(level == levels) offset2 = offset; for(int v = 0; v < lverts; ++v) { line.pts[v].aux = vert; // Gives the capper this vert's location in the mesh! mesh.setVert(vert++, line.pts[v].p + offset); } } } assert(vert == verts); // If capping, do it! if(anyClosed && (capStart || capEnd)) { MeshCapInfo capInfo; pShape.MakeCap(t, capInfo, capType); // Build information for capping MeshCapper capper(pShape); if(capStart) { vert = 0; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; MeshCapPoly &capline = capper[poly]; int lverts = line.numPts; for(int v = 0; v < lverts; ++v) capline.SetVert(v, vert++); // Gives this vert's location in the mesh! vert += lverts * levels; } // Create a work matrix for grid capping Matrix3 gridMat = TransMatrix(offset1); int oldFaces = mesh.numFaces; capper.CapMesh(mesh, capInfo, TRUE, 16, &gridMat, genMatIDs ? -1 : 0); // If texturing, create the texture faces and vertices if(texturing) MakeMeshCapTexture(mesh, Inverse(gridMat), oldFaces, mesh.numFaces, GetUsePhysicalScaleUVs()); } if(capEnd) { int baseVert = 0; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; MeshCapPoly &capline = capper[poly]; int lverts = line.numPts; vert = baseVert + lverts * levels; for(int v = 0; v < lverts; ++v) capline.SetVert(v, vert++); // Gives this vert's location in the mesh! baseVert += lverts * (levels + 1); } // Create a work matrix for grid capping Matrix3 gridMat = TransMatrix(offset2); int oldFaces = mesh.numFaces; capper.CapMesh(mesh, capInfo, FALSE, 16, &gridMat, genMatIDs ? -1 : 0); // If texturing, create the texture faces and vertices if(texturing) MakeMeshCapTexture(mesh, Inverse(gridMat), oldFaces, mesh.numFaces, GetUsePhysicalScaleUVs()); } } // Create the faces! int face = 0; int TVface = 0; int baseVert = 0; int baseTVert = 0; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; int pieces = line.Segments(); int closed = line.IsClosed(); int segVerts = pieces + ((closed) ? 0 : 1); int segTVerts = pieces + 1; for(level = 0; level < levels; ++level) { int sm = 0; // Initial smoothing group BOOL firstSmooth = (line.pts[0].flags & POLYPT_SMOOTH) ? TRUE : FALSE; for(piece = 0; piece < pieces; ++piece) { int v1 = baseVert + piece; int v2 = baseVert + ((piece + 1) % segVerts); int v3 = v1 + segVerts; int v4 = v2 + segVerts; // If the vertex is not smooth, go to the next group! BOOL thisSmooth = line.pts[piece].flags & POLYPT_SMOOTH; MtlID mtl = useShapeIDs ? line.pts[piece].GetMatID() : 2; if(piece > 0 && !thisSmooth) { sm++; if(sm > 2) sm = 1; } DWORD smoothGroup = 1 << sm; // Advance to the next smoothing group right away if(sm == 0) sm++; // Special case for smoothing from first segment if(piece == 1 && thisSmooth) smoothGroup |= 1; // Special case for smoothing from last segment if((piece == pieces - 1) && firstSmooth) smoothGroup |= 1; mesh.faces[face].setEdgeVisFlags(1,1,0); mesh.faces[face].setSmGroup(smooth ? smoothGroup : 0); mesh.faces[face].setMatID(genMatIDs ? mtl : 0); mesh.faces[face++].setVerts(v1, v2, v4); mesh.faces[face].setEdgeVisFlags(0,1,1); mesh.faces[face].setSmGroup(smooth ? smoothGroup : 0); mesh.faces[face].setMatID(genMatIDs ? mtl : 0); mesh.faces[face++].setVerts(v1, v4, v3); //DebugPrint(_T("BV:%d V:%d v1:%d v2:%d v3:%d v4:%d\n"),baseVert, vert, v1, v2, v3, v4); if(texturing) { int tv1 = baseTVert + piece; int tv2 = tv1 + 1; int tv3 = tv1 + segTVerts; int tv4 = tv2 + segTVerts; mesh.tvFace[TVface++].setTVerts(tv1, tv2, tv4); mesh.tvFace[TVface++].setTVerts(tv1, tv4, tv3); } } baseVert += segVerts; baseTVert += segTVerts; } baseVert += segVerts; // Increment to next poly start (skips last verts of this poly) baseTVert += segTVerts; } assert(face == faces); mesh.InvalidateGeomCache(); }
void LightExporter::exportShadowParameters(GenLight* light) { // Export light shadow attributes if (light->GetShadow()) { // Light casts shadows int shadowType = light->GetShadowType(); if (shadowType == 0) addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_TYPE, SHADOW_TYPE_MAP); else if (shadowType == 1) addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_TYPE, SHADOW_TYPE_RAYTRACE); // GetExclusion list ExclList& exclusions = light->GetExclusionList(); int exclusionsCount = exclusions.Count(); if (exclusionsCount > 0) { String nodeURIs; for (int i = 0; i < exclusionsCount; i++) { INode* affectedNode = exclusions[i]; if ( !affectedNode ) continue; if ( !nodeURIs.empty() ) nodeURIs += " "; ExportNode* affectedExportNode = mExportSceneGraph->getExportNode(affectedNode); String nodeURI = '#' + VisualSceneExporter::getNodeId(*affectedExportNode); nodeURIs += nodeURI; } addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_AFFECTS_LIST_NODES, nodeURIs); if (!exclusions.TestFlag(NT_INCLUDE)) { addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_AFFECTS_LIST_EXCLUDES, 1); } if (exclusions.TestFlag(NT_AFFECT_ILLUM)) { addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_AFFECTS_LIST_ILLUMINATES, 1); } if (exclusions.TestFlag(NT_AFFECT_SHADOWCAST)) { addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_AFFECTS_LIST_CASTS, 1); } } // Export our shadow projection map Texmap* shadowProj = light->GetShadowProjMap(); if (shadowProj) { IParamBlock* pblock = (IParamBlock*)light->GetReference(MaxLight::PBLOCK_REF); int shadowProjectionOn; pblock->GetValue(MaxLight::PB_OMNISHAD_COLMAP, 0, shadowProjectionOn, Interval::FOREVER); if (shadowProjectionOn) { String imageId = exportTexMap(shadowProj); if ( !imageId.empty() ) addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_PROJ_IMAGE, "#" + imageId); } else { // Non-animatable is all they get Point3 shadowColor = light->GetShadColor(mDocumentExporter->getOptions().getAnimationStart()); String shadowColorString = COLLADASW::Utils::toString(shadowColor.x) + COLLADASW::Utils::toString(shadowColor.y) + COLLADASW::Utils::toString(shadowColor.z); addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_PROJ_COLOR, shadowColorString); addExtraChildParameter(SHADOW_ATTRIBS, SHADOW_PROJ_COLOR_MULT, light->GetShadMult(0)); } addExtraChildParameter(SHADOW_ATTRIBS, LIGHT_AFFECTS_SHADOW, light->GetLightAffectsShadow()); } } }
// Load a blend shape animation track Track BlendShape::loadTrack(float start,float stop,float rate,ParamList& params,int targetIndex, int startPoseId) { int i; std::string msg; std::vector<float> times; // Create a track for current clip Track t; t.m_type = TT_POSE; t.m_target = m_target; t.m_index = targetIndex; t.m_vertexKeyframes.clear(); // Calculate times from clip sample rate times.clear(); if (rate <= 0) { FxOgreMaxExporterLog( "invalid sample rate for the clip (must be >0), we skip it\n"); return t; } float time; for (time=start; time<stop; time+=rate) times.push_back(time); times.push_back(stop); // Get animation length float length=0; if (times.size() >= 0) length = times[times.size()-1] - times[0]; if (length < 0) { FxOgreMaxExporterLog( "invalid time range for the clip, we skip it\n"); return t; } // Evaluate animation curves at selected times for (i=0; i<times.size(); i++) { vertexKeyframe key; key.time = times[i] - times[0]; key.poserefs.clear(); poseGroup& pg = m_poseGroups.find(targetIndex)->second; for (int j=0; j<pg.poses.size(); j++) { pose& p = pg.poses[j]; morphChannel* pChan = p.pMChannel; if( pChan ) { IParamBlock* paramBlock = pChan->cblock; float value; TimeValue curTime = times[i] * 4800; Interval junkInterval; paramBlock->GetValue(0, curTime, value, junkInterval); vertexPoseRef poseref; poseref.poseIndex = startPoseId + j; poseref.poseWeight = value / 100.0f; key.poserefs.push_back(poseref); } } t.addVertexKeyframe(key); } // Clip successfully loaded return t; }
void OptMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node) { float faceThresh, edgeThresh, bias, maxEdge; int preserveMat, preserveSmooth, which, render=0, autoEdge; DWORD flags = 0; Interval valid = FOREVER; int nv,nf; int man; pblock->GetValue(PB_MANUPDATE,t,man,valid); if (man && !forceUpdate && !TestAFlag(A_RENDER)) return; forceUpdate = FALSE; if (TestAFlag(A_RENDER)) { pblock->GetValue(PB_RENDER,t,which,valid); } else { pblock->GetValue(PB_VIEWS,t,which,valid); } pblock->GetValue(PB_AUTOEDGE,t,autoEdge,valid); if (which==0) { pblock->GetValue(PB_FACETHRESH1,t,faceThresh,valid); pblock->GetValue(PB_EDGETHRESH1,t,edgeThresh,valid); pblock->GetValue(PB_BIAS1,t,bias,valid); pblock->GetValue(PB_PRESERVEMAT1,t,preserveMat,valid); pblock->GetValue(PB_PRESERVESMOOTH1,t,preserveSmooth,valid); pblock->GetValue(PB_MAXEDGE1,t,maxEdge,valid); } else { pblock->GetValue(PB_FACETHRESH2,t,faceThresh,valid); pblock->GetValue(PB_EDGETHRESH2,t,edgeThresh,valid); pblock->GetValue(PB_BIAS2,t,bias,valid); pblock->GetValue(PB_PRESERVEMAT2,t,preserveMat,valid); pblock->GetValue(PB_PRESERVESMOOTH2,t,preserveSmooth,valid); pblock->GetValue(PB_MAXEDGE2,t,maxEdge,valid); } assert(os->obj->IsSubClassOf(triObjectClassID)); TriObject *triOb = (TriObject *)os->obj; nv = triOb->GetMesh().getNumVerts(); nf = triOb->GetMesh().getNumFaces(); if (preserveMat) flags |= OPTIMIZE_SAVEMATBOUNDRIES; if (preserveSmooth) flags |= OPTIMIZE_SAVESMOOTHBOUNDRIES; if (autoEdge) flags |= OPTIMIZE_AUTOEDGE; if (faceThresh!=0.0f) { GetAsyncKeyState(VK_ESCAPE); // clear the state HCURSOR hCur; if (nf > 2000) hCur = SetCursor(LoadCursor(NULL,IDC_WAIT)); triOb->GetMesh().Optimize( faceThresh,edgeThresh, bias*0.5f, maxEdge, flags,this); if (nf > 200) SetCursor(hCur); } triOb->GetMesh().InvalidateTopologyCache (); triOb->PointsWereChanged(); triOb->UpdateValidity(GEOM_CHAN_NUM,valid); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); triOb->UpdateValidity (TEXMAP_CHAN_NUM, valid); triOb->UpdateValidity (VERT_COLOR_CHAN_NUM, valid); if (pmapParam && pmapParam->GetParamBlock()==pblock && !TestAFlag(A_RENDER)) { TSTR buf; buf.printf("%d / %d",nv,triOb->GetMesh().getNumVerts()); SetWindowText(GetDlgItem(pmapParam->GetHWnd(),IDC_OPT_VERTCOUNT),buf); buf.printf("%d / %d",nf,triOb->GetMesh().getNumFaces()); SetWindowText(GetDlgItem(pmapParam->GetHWnd(),IDC_OPT_FACECOUNT),buf); } }
BOOL ExtrudeMod::GetGenMatIDs() { int sw; Interval v; pblock->GetValue(PB_GEN_MATIDS, 0, sw, v); return sw; }
void NormalMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node) { Interval valid = FOREVER; int flip, unify; pblock->GetValue(PB_FLIP,t,flip,valid); pblock->GetValue(PB_UNIFY,t,unify,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! #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 (unify) pmesh.UnifyNormals(useSel); if (flip) pmesh.FlipPatchNormal(useSel ? -1 : -2); patchOb->UpdateValidity(TOPO_CHAN_NUM,valid); } else // If it's a TriObject, process it #endif // NO_PATCHES if(os->obj->IsSubClassOf(triObjectClassID)) { TriObject *triOb = (TriObject *)os->obj; DoNormalSet(triOb, unify, flip); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); } // Process PolyObjects // note: Since PolyObjects must always have the normals alligned they do not // need to support unify and they do not allow normal flips on selected faces else if(os->obj->IsSubClassOf(polyObjectClassID)) { PolyObject *pPolyOb = (PolyObject *)os->obj; MNMesh& mesh = pPolyOb->GetMesh(); if (flip) { // flip selected faces only if entire elements are selected if (mesh.selLevel == MNM_SL_FACE) { // sca 12/8/2000: Use MNMesh flipping code instead of the code that was here. mesh.FlipElementNormals (MN_SEL); } else { // Flip the entire object if selected elements were not flipped for (int i=0; i<mesh.FNum(); i++) { mesh.f[i].SetFlag (MN_WHATEVER, !mesh.f[i].GetFlag(MN_DEAD)); } mesh.FlipElementNormals (MN_WHATEVER); } // Luna task 747: // We cannot support specified normals here at this time. // NOTE this assumes that both the topo and geo channels are to be freed // this means that the modifier needs to also set the channels changed to // geo and topo otherwise we will be deleting a channel we dont own. mesh.ClearSpecifiedNormals (); } pPolyOb->UpdateValidity(GEOM_CHAN_NUM,valid); pPolyOb->UpdateValidity(TOPO_CHAN_NUM,valid); } else // Fallback position: If it can convert to a TriObject, do it! if(os->obj->CanConvertToType(triObjectClassID)) { TriObject *triOb = (TriObject *)os->obj->ConvertToType(t, triObjectClassID); // Now stuff this into the pipeline! os->obj = triOb; DoNormalSet(triOb, unify, flip); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); } else return; // Do nothing if it can't convert to triObject }
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; } }