Пример #1
0
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);
	}
Пример #2
0
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;
}
Пример #3
0
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;
	}
Пример #4
0
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;
	}
Пример #5
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;
	}
Пример #6
0
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);	
	}
Пример #7
0
Interval MatMod::LocalValidity(TimeValue t)
   {
   int i;
   Interval valid = FOREVER;
   pblock->GetValue(PB_MATID,t,i,valid);  
   return valid;
   }
Пример #8
0
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
   }
Пример #9
0
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;
	}
Пример #10
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;
	}
Пример #11
0
void BombObject::EnableControls()
	{
	if (falloffSpin)
		{
		BOOL fallOffOn;
		pblock->GetValue(PB_FALLOFFON, 0, fallOffOn, FOREVER);
		falloffSpin->Enable(fallOffOn);
		}
	}
Пример #12
0
//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;
}
Пример #13
0
// 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);
}
Пример #14
0
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;
}
Пример #15
0
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;
	}
Пример #16
0
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);
		}
	}
Пример #17
0
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);	
	}
Пример #18
0
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;
	}
Пример #19
0
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();
	}
Пример #20
0
BOOL ExtrudeMod::HasUVW() { 
	BOOL genUVs;
	Interval v;
	pblock->GetValue(PB_MAPPING, 0, genUVs, v);
	return genUVs; 
	}
Пример #21
0
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,&center,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);		
		}
	}
Пример #22
0
BOOL TriPatchObject::HasUVW() { 
	BOOL genUVs;
	Interval v;
	pblock->GetValue(PB_TEXTURE, 0, genUVs, v);
	return genUVs; 
	}
Пример #23
0
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();
	}
Пример #24
0
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());
			}
		}
	}
Пример #26
0
	// 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;
	}
Пример #27
0
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);
		}
	}
Пример #28
0
BOOL ExtrudeMod::GetGenMatIDs() {
	int sw;
	Interval v;
	pblock->GetValue(PB_GEN_MATIDS, 0, sw, v);
	return sw;
	}
Пример #29
0
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
   }
Пример #30
0
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;
	}
}