void SolidifyPW::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) 
{

	//TODO: Add the code for actually modifying the object
	meshInfo.Free();

	if (os->obj->IsSubClassOf(triObjectClassID)) {
		TriObject *tobj = (TriObject*)os->obj;
		Mesh &mesh = tobj->GetMesh();
		Interval iv = FOREVER;
		float a,oa;
		
		pblock->GetValue(pb_amount,t,a,iv);
		pblock->GetValue(pb_oamount,t,oa,iv);

		if (a == oa)
			oa += 0.00001f;

		BOOL overrideMatID;
		int matid;

		pblock->GetValue(pb_overridematid,t,overrideMatID,iv);
		pblock->GetValue(pb_matid,t,matid,iv);
		matid--;

		if (!overrideMatID) matid = -1;


		BOOL overridesg;
		int sg;
		pblock->GetValue(pb_overridesg,t,overridesg,iv);
		pblock->GetValue(pb_sg,t,sg,iv);
		

		if (!overridesg) sg = -1;

		int edgeMap;
		pblock->GetValue(pb_edgemap,t,edgeMap,iv);

		float tvOffset;
		pblock->GetValue(pb_tvoffset,t,tvOffset,iv);


		BOOL ioverrideMatID;
		int imatid;

		pblock->GetValue(pb_overrideinnermatid,t,ioverrideMatID,iv);
		pblock->GetValue(pb_innermatid,t,imatid,iv);
		imatid--;

		if (!ioverrideMatID) imatid = -1;


		BOOL ooverrideMatID;
		int omatid;

		pblock->GetValue(pb_overrideoutermatid,t,ooverrideMatID,iv);
		pblock->GetValue(pb_outermatid,t,omatid,iv);
		omatid--;

		if (!ooverrideMatID) omatid = -1;


		BOOL selEdges, selInner,selOuter;

		static BOOL selEdgesPrev = FALSE;
		static BOOL selInnerPrev = FALSE;
		static BOOL selOuterPrev = FALSE;
		
		BOOL updateUI = FALSE;
		
		pblock->GetValue(pb_seledges,t,selEdges,iv);
		pblock->GetValue(pb_selinner,t,selInner,iv);
		pblock->GetValue(pb_selouter,t,selOuter,iv);
		
		if (selEdges && (!selEdgesPrev))
			updateUI = TRUE;
		if (selInner && (!selInnerPrev))
			updateUI = TRUE;
		if (selOuter && (!selOuterPrev))
			updateUI = TRUE;
			
		selEdgesPrev = selEdges;
		selInnerPrev = selInner;			
		selOuterPrev = selOuter;			

		if (selEdges || selInner|| selOuter)
			{
			mesh.dispFlags = DISP_SELFACES;
			mesh.selLevel = MESH_FACE;
			}



		int segments = 1;

		pblock->GetValue(pb_segments,t,segments,iv);
		if (segments < 1) segments = 1;


		BOOL fixupCorners;
		pblock->GetValue(pb_fixupcorners,t,fixupCorners,iv);


		BOOL autoSmooth;
		float smoothAngle;
		pblock->GetValue(pb_autosmooth,t,autoSmooth,iv);
		pblock->GetValue(pb_autosmoothangle,t,smoothAngle,iv);

		BOOL bevel;
		INode *node;
		pblock->GetValue(pb_bevel,t,bevel,iv);
		pblock->GetValue(pb_bevelshape,t,node,iv);

		PolyShape shape;
		if ((bevel) && node)
		{
			ObjectState nos = node->EvalWorldState(t);
			if (nos.obj->IsShapeObject()) 
			{
				ShapeObject *pathOb = (ShapeObject*)nos.obj;

				if (!pathOb->NumberOfCurves()) 
				{
					bevel = FALSE;
				}
				else
				{
					pathOb->MakePolyShape(t, shape,PSHAPE_BUILTIN_STEPS,TRUE);
					if (shape.lines[0].IsClosed())
						bevel = FALSE;

;
				}
			
			}
		}


		DWORD selLevel = mesh.selLevel;
		
		mesh.faceSel.ClearAll();

		if (bevel)
			meshInfo.MakeSolid(&mesh,segments, a,oa,matid, sg,edgeMap,tvOffset,imatid,omatid,selEdges,selInner,selOuter,fixupCorners,autoSmooth,smoothAngle,&shape.lines[0]);
		else meshInfo.MakeSolid(&mesh,segments, a,oa,matid, sg,edgeMap,tvOffset,imatid,omatid,selEdges,selInner,selOuter,fixupCorners,autoSmooth,smoothAngle,NULL);

		
		mesh.selLevel = selLevel;

		mesh.InvalidateTopologyCache ();


		for (int i = 0; i < mesh.numFaces; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				int index = mesh.faces[j].v[j];
				if ((index < 0) || (index >= mesh.numVerts))
					DebugPrint(_T("Invalid face %d(%d) %d\n"),i,j,index);
			}
		}
		
		int numMaps = mesh.getNumMaps();


		for (int mp = -NUM_HIDDENMAPS; mp < numMaps; mp++)
		{

			if (!mesh.mapSupport(mp)) continue;
			Point3 *uvw = mesh.mapVerts(mp);
			TVFace *uvwFace = mesh.mapFaces(mp);

			if ((uvw) && (uvwFace))
			{
				int numberTVVerts = mesh.getNumMapVerts(mp);
				for (int i = 0; i < mesh.numFaces; i++)
				{
					for (int j = 0; j < 3; j++)
					{
						int index = uvwFace[i].t[j];
						if ((index < 0) || (index >= numberTVVerts))
							DebugPrint(_T("Invalid Map %d tvface %d(%d) %d\n"),mp,i,j,index);
					}
				}

			}
		}



		os->obj->UpdateValidity(GEOM_CHAN_NUM,iv);
		os->obj->UpdateValidity(TOPO_CHAN_NUM,iv);
		
		MeshNormalSpec *pNormSpec = (MeshNormalSpec *) mesh.GetInterface (MESH_NORMAL_SPEC_INTERFACE);
		if (pNormSpec && pNormSpec->GetNumFaces() > 0)
		{
			pNormSpec->SetParent(&mesh);
			pNormSpec->BuildNormals();
			pNormSpec->ComputeNormals();
		}

		if ((updateUI) && (ip))
		{
			ip->PipeSelLevelChanged();
		}
		}
	EnableUIControls();

}
bool NifImporter::ImportMultipleGeometry(NiNodeRef parent, vector<NiTriBasedGeomRef>& glist)
{
   bool ok = true;
   if (glist.empty()) return false;

   ImpNode *node = i->CreateNode();
   if(!node) return false;

   INode *inode = node->GetINode();
   TriObject *triObject = CreateNewTriObject();
   node->Reference(triObject);

   string name = parent->GetName();
   node->SetName(wide(name).c_str());

   // Texture
   Mesh& mesh = triObject->GetMesh();

   vector< pair<int, int> > vert_range, tri_range;
   vector<Triangle> tris;
   vector<Vector3> verts;
   int submats = glist.size();

   // Build list of vertices and triangles.  Optional components like normals will be handled later.
   for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr) {
      NiTriBasedGeomDataRef triGeomData = StaticCast<NiTriBasedGeomData>((*itr)->GetData());

      // Get verts and collapse local transform into them
      int nVertices = triGeomData->GetVertexCount();
      vector<Vector3> subverts = triGeomData->GetVertices();
      Matrix44 transform = (*itr)->GetLocalTransform();
      //Apply the transformations
      if (transform != Matrix44::IDENTITY) {
         for ( unsigned int i = 0; i < subverts.size(); ++i )
            subverts[i] = transform * subverts[i];
      }
      vert_range.push_back( pair<int,int>( verts.size(), verts.size() + subverts.size()) );
      verts.insert(verts.end(), subverts.begin(), subverts.end());

      vector<Triangle> subtris = triGeomData->GetTriangles();
      for (vector<Triangle>::iterator itr = subtris.begin(), end = subtris.end(); itr != end; ++itr) {
         (*itr).v1 += nVertices, (*itr).v2 += nVertices, (*itr).v3 += nVertices;
      }
      tri_range.push_back( pair<int,int>( tris.size(), tris.size() + subtris.size()) );
      tris.insert(tris.end(), subtris.begin(), subtris.end());
   }

   // Transform up-to-parent
   Matrix44 baseTM = (importBones) ? Matrix44::IDENTITY : parent->GetWorldTransform();
   node->SetTransform(0,TOMATRIX3(baseTM));  

   // Set vertices and triangles
   mesh.setNumVerts(verts.size());
   mesh.setNumTVerts(verts.size(), TRUE);
   for (int i=0, n=verts.size(); i < n; ++i){
      Vector3 &v = verts[i];
      mesh.verts[i].Set(v.x, v.y, v.z);
   }
   mesh.setNumFaces(tris.size());
   mesh.setNumTVFaces(tris.size());
   for (int submat=0; submat<submats; ++submat) {
      int t_start = tri_range[submat].first, t_end = tri_range[submat].second;
      for (int i=t_start; i<t_end; ++i) {
         Triangle& t = tris[i];
         Face& f = mesh.faces[i];
         f.setVerts(t.v1, t.v2, t.v3);
         f.Show();
         f.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS);
         f.setMatID(-1);
         TVFace& tf = mesh.tvFace[i];
         tf.setTVerts(t.v1, t.v2, t.v3);
      }
   }
   mesh.buildNormals();
   bool bSpecNorms = false;

   MultiMtl *mtl = NULL;
   int igeom = 0;
   for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr, ++igeom) 
   {
      NiTriBasedGeomDataRef triGeomData = StaticCast<NiTriBasedGeomData>((*itr)->GetData());

      int v_start = vert_range[igeom].first, v_end = vert_range[igeom].second;
      int t_start = tri_range[igeom].first, t_end = tri_range[igeom].second;

      // Normals
      vector<Vector3> subnorms = triGeomData->GetNormals();
      Matrix44 rotation = (*itr)->GetLocalTransform().GetRotation();
      if (rotation != Matrix44::IDENTITY) {
         for ( unsigned int i = 0; i < subnorms.size(); ++i )
            subnorms[i] = rotation * subnorms[i];
      }
      if (!subnorms.empty())
      {
#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5
         // Initialize normals if necessary
         if (!bSpecNorms) {
            bSpecNorms = true;
            mesh.SpecifyNormals();
            MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals();
            if (NULL != specNorms) {
               specNorms->BuildNormals();
               //specNorms->ClearAndFree();
               //specNorms->SetNumFaces(tris.size());
               //specNorms->SetNumNormals(n.size());
            }
         }
         MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals();
         if (NULL != specNorms)
         {
            Point3* norms = specNorms->GetNormalArray();
            for (int i=0, n=subnorms.size(); i<n; i++){
               Vector3& v = subnorms[i];
               norms[i+v_start] = Point3(v.x, v.y, v.z);
            }
            //MeshNormalFace* pFaces = specNorms->GetFaceArray();
            //for (int i=0; i<tris.size(); i++){
            //   Triangle& tri = tris[i];
            //   MeshNormalFace& face = pFaces[i+t_start];
            //   face.SpecifyNormalID(0, tri.v1);
            //   face.SpecifyNormalID(1, tri.v2);
            //   face.SpecifyNormalID(2, tri.v3);
            //}
#if VERSION_3DSMAX > ((7000<<16)+(15<<8)+0) // Version 7+
			specNorms->SetAllExplicit(true);
#endif
            specNorms->CheckNormals();
         }
#endif
      }
      // uv texture info
      if (triGeomData->GetUVSetCount() > 0) {
         vector<TexCoord> texCoords = triGeomData->GetUVSet(0);
         for (int i=0, n = texCoords.size(); i<n; ++i) {
            TexCoord& texCoord = texCoords[i];
            mesh.tVerts[i+v_start].Set(texCoord.u, (flipUVTextures) ? 1.0f-texCoord.v : texCoord.v, 0);
         }
      }
      vector<Color4> cv = triGeomData->GetColors();
      ImportVertexColor(inode, triObject, tris, cv, v_start);

      if ( StdMat2* submtl = ImportMaterialAndTextures(node, (*itr)) )
      {
         if (mtl == NULL) {
            mtl = NewDefaultMultiMtl();
            gi->GetMaterialLibrary().Add(mtl);
            inode->SetMtl(mtl);
         }
         // SubMatIDs do not have to be contiguous so we just use the offset
         mtl->SetSubMtlAndName(igeom, submtl, submtl->GetName());
         for (int i=t_start; i<t_end; ++i)
            mesh.faces[i].setMatID(igeom);
      }
      if (enableSkinSupport)
         ImportSkin(node, (*itr));
   }

   this->i->AddNodeToScene(node);   

   inode = node->GetINode();
   inode->EvalWorldState(0);

   for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr) 
   {
      // attach child
      if (INode *parent = GetNode((*itr)->GetParent()))
         parent->AttachChild(inode, 1);
      inode->Hide((*itr)->GetVisibility() ? FALSE : TRUE);
   }
   if (removeDegenerateFaces)
      mesh.RemoveDegenerateFaces();
   if (removeIllegalFaces)
      mesh.RemoveIllegalFaces();
   if (weldVertices)
	   WeldVertices(mesh);
   if (enableAutoSmooth)
      mesh.AutoSmooth(TORAD(autoSmoothAngle), FALSE, FALSE);
   return ok;
}