Mesh* SGP_MaxInterface::GetMesh( INode* pNode )
{
	if( !IsMesh( pNode ) )
		return NULL;

	TimeValue time = 0;

	// get max mesh instance
	ObjectState os;
	os = pNode->EvalWorldState(time);

	Object* obj = os.obj;
	if( !os.obj )
	{
		assert( false );
		return NULL;
	}
	TriObject* triObj = (TriObject *)obj->ConvertToType( time, triObjectClassID );
	if( !triObj )
	{
		assert( false );
		return NULL;
	}

	Mesh* pMesh = &triObj->GetMesh();

	return pMesh;
}
bool CollisionImport::ImportTriStripsShape(INode *rbody, bhkRigidBodyRef body, bhkNiTriStripsShapeRef shape, INode *parent, Matrix3& tm)
{
	if (shape->GetNumStripsData() != 1)
		return NULL;

	if ( ImpNode *node = ni.i->CreateNode() )
	{
		TriObject *triObject = CreateNewTriObject();
		node->Reference(triObject);

		INode *inode = node->GetINode();

		// Texture
		Mesh& mesh = triObject->GetMesh();
		NiTriStripsDataRef triShapeData = shape->GetStripsData(0);
		if (triShapeData == NULL)
			return false;

		// Temporary shape
		NiTriStripsRef triShape = new NiTriStrips();
		vector<Triangle> tris = triShapeData->GetTriangles();
		ni.ImportMesh(node, triObject, triShape, triShapeData, tris);
		CreatebhkCollisionModifier(inode, bv_type_shapes, shape->GetMaterial(), OL_UNIDENTIFIED, 0);
		ImportBase(body, shape, parent, inode, tm);
		AddShape(rbody, inode);
		return true;
	}
	return false;
}
Exemple #3
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
   }
void CVDModifier::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node)
{
	if (!os->obj->IsSubClassOf(triObjectClassID)) return;

	// Get a mesh from input object
	TriObject *tobj = (TriObject*)os->obj;
	Mesh* mesh = &tobj->GetMesh();
	int numVert = mesh->getNumVerts();

	// Get parameters from pblock
	float sparam = 0.0f; 
	Interval valid = FOREVER;
	pblock->GetValue(cvd_codev, t, sparam, valid);

		// Take over the channel, realloc with size == number of verts
		mesh->setVDataSupport(MY_CHANNEL,TRUE);

		// Get a pointer back to the floating point array
		float *vdata = mesh->vertexFloat(MY_CHANNEL);
		if(vdata)
		{
			// loop through all verticies
			// Ask the random number generator for a value bound to the
			//	paramblock value
			// and encode it into the vertex.
			for(int i=0;i<numVert;i++)
			{
				vdata[i] = randomGen.getf(sparam);
			}
		}

}
void bhkProxyObject::BuildColCapsule()
{
	proxyMesh.FreeAll();
	MeshDelta md(proxyMesh);
	for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) {
		INode *tnode = NULL;
		pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i);	
		if (tnode)
		{
			ObjectState os = tnode->EvalWorldState(0);
			Matrix3 wm = tnode->GetNodeTM(0);
			TriObject *tri = (TriObject *)os.obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0));
			if (tri)
			{
				Mesh& mesh = tri->GetMesh();
				MeshDelta tmd (mesh);
				md.AttachMesh(proxyMesh, mesh, wm, 0);
				md.Apply(proxyMesh);
			}
		}
	}
	Point3 pt1 = Point3::Origin;
	Point3 pt2 = Point3::Origin;
	float r1 = 0.0;
	float r2 = 0.0;

	if (proxyMesh.getNumVerts() > 3) // Doesn't guarantee that the mesh is not a plane.
	{
		CalcCapsule(proxyMesh, pt1, pt2, r1, r2);
		BuildCapsule(proxyMesh, pt1, pt2, r1, r2);
	}

	proxyPos = Point3::Origin;
	forceRedraw = true;
}
void bhkProxyObject::BuildColBox()
{
	Box3 box; box.Init();
	for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) {
		INode *tnode = NULL;
		pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i);	
		if (tnode)
		{
			ObjectState os = tnode->EvalWorldState(0);
			Matrix3 wm = tnode->GetNodeTM(0);
			TriObject *tri = (TriObject *)os.obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0));
			if (tri)
			{
				Box3 box2; box2.Init();
				Mesh& mesh = tri->GetMesh();
				CalcAxisAlignedBox(mesh, box2, &wm);
				box += box2;
			}
		}
	}
	BuildBox(proxyMesh, box.Max().y-box.Min().y, box.Max().x-box.Min().x, box.Max().z-box.Min().z);

	MNMesh mn(proxyMesh);
	Matrix3 tm(true);
	tm.SetTranslate(box.Center());
	mn.Transform(tm);
	mn.OutToTri(proxyMesh);

	//proxyPos = box.Center();
	proxyPos = Point3::Origin;
	forceRedraw = true;
}
void bhkProxyObject::BuildColConvex()
{
	proxyMesh.FreeAll();
	MeshDelta md(proxyMesh);
	for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) {
		INode *tnode = NULL;
		pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i);	
		if (tnode)
		{
			ObjectState os = tnode->EvalWorldState(0);
			Matrix3 wm = tnode->GetNodeTM(0);
			TriObject *tri = (TriObject *)os.obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0));
			if (tri)
			{
				Mesh& mesh = tri->GetMesh();
				MeshDelta tmd (mesh);
				md.AttachMesh(proxyMesh, mesh, wm, 0);
				md.Apply(proxyMesh);
			}
		}
	}
	compute_convex_hull(proxyMesh, proxyMesh);

	BuildOptimize(proxyMesh);

	proxyPos = Point3::Origin;
	forceRedraw = true;
}
Exemple #8
0
BOOL plDistributor::IReadyRepNodes(plMeshCacheTab& cache) const
{
    int i;
    for( i = 0; i < fRepNodes.Count(); i++ )
    {
        Mesh* mesh = nil;
        TriObject* obj = nil;
        if( IGetMesh(fRepNodes[i], obj, mesh) )
        {
            plMaxNode* repNode = (plMaxNode*)fRepNodes[i];

            int iCache = cache.Count();
            cache.SetCount(iCache + 1);

            cache[iCache].fMesh = new Mesh(*mesh);
            cache[iCache].fFlex = repNode->GetFlexibility();
            
            if( obj )
                obj->DeleteThis();

            BOOL hasXImp = nil != repNode->GetXImposterComp();

            ISetupNormals(repNode, cache[iCache].fMesh, hasXImp);

            ISetupSkinWeights(repNode, cache[iCache].fMesh, cache[iCache].fFlex);
        }
        else
        {
            fRepNodes.Delete(i, 1);
            i--;
        }
    }

    return fRepNodes.Count() > 0;
}
int XTCSample::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags, Object *pObj)
{
	if ( ! vpt || ! vpt->IsAlive() )
	{
		// why are we here
		DbgAssert(!_T("Doing Display() on invalid viewport!"));
		return FALSE;
	}

	if(pObj->ClassID() == XGSPHERE_CLASS_ID || pObj->IsSubClassOf(triObjectClassID))
	{
		return DisplayMesh(t, inode, vpt, flags, GetMesh(pObj));
	}
#ifndef NO_PATCHES
	else if( pObj->IsSubClassOf(patchObjectClassID) )
	{
		return DisplayPatch(t, inode, vpt, flags, (PatchObject *) pObj);
	}
#endif
	else if(pObj->CanConvertToType(triObjectClassID))
	{
		TriObject *pTri = (TriObject *) pObj->ConvertToType(t,triObjectClassID);
		DisplayMesh(t, inode, vpt, flags, &pTri->mesh);
		if(pTri != pObj)
			pTri->DeleteThis();
		
	}
	
	return 0;
}
float plMaxNodeBase::RegionPriority()
{
    TimeValue currTime = 0;//hsConverterUtils::Instance().GetTime(GetInterface());
    Object *obj = EvalWorldState(currTime).obj;
    if( !obj )
        return 0;

    Matrix3 l2w = GetObjectTM(currTime);

    if( obj->ClassID() == Class_ID(DUMMY_CLASS_ID,0) )
    {
        DummyObject* dummy = (DummyObject*)obj;
        Box3 bnd = dummy->GetBox();

        return BoxVolume(bnd, l2w);
    }

    if( obj->CanConvertToType(triObjectClassID) )
    {
        TriObject   *meshObj = (TriObject *)obj->ConvertToType(currTime, triObjectClassID);
        if( !meshObj )
            return 0;

        Mesh& mesh = meshObj->mesh;
        Box3 bnd = mesh.getBoundingBox();
        
        if( meshObj != obj )
            meshObj->DeleteThis();

        return BoxVolume(bnd, l2w);
    }

    // Don't know how to interpret other, it's not contained.
    return 0;
}
hsBool plMaxNodeBase::Contains(const Point3& worldPt)
{
    TimeValue currTime = 0;//hsConverterUtils::Instance().GetTime(GetInterface());
    Object *obj = EvalWorldState(currTime).obj;
    if( !obj )
        return false;

    Matrix3 l2w = GetObjectTM(currTime);
    Matrix3 w2l = Inverse(l2w);
    Point3 pt = w2l * worldPt;

    if( obj->ClassID() == Class_ID(DUMMY_CLASS_ID,0) )
    {
        DummyObject* dummy = (DummyObject*)obj;
        Box3 bnd = dummy->GetBox();
        return bnd.Contains(pt);
    }
    if( obj->CanConvertToType(triObjectClassID) )
    {
        TriObject   *meshObj = (TriObject *)obj->ConvertToType(currTime, triObjectClassID);
        if( !meshObj )
            return false;

        Mesh& mesh = meshObj->mesh;
        Box3 bnd = mesh.getBoundingBox();
        if( !bnd.Contains(pt) )
        {
            if( meshObj != obj )
                meshObj->DeleteThis();
            return false;
        }

        hsBool retVal = true;
        int i;
        for( i = 0; i < mesh.getNumFaces(); i++ )
        {
            Face& face = mesh.faces[i];

            Point3 p0 = mesh.verts[face.v[0]];
            Point3 p1 = mesh.verts[face.v[1]];
            Point3 p2 = mesh.verts[face.v[2]];

            Point3 n = CrossProd(p1 - p0, p2 - p0);

            if( DotProd(pt, n) > DotProd(p0, n) )
            {
                retVal = false;
                break;
            }
        }

        if( meshObj != obj )
            meshObj->DeleteThis();

        return retVal;
    }

    // If we can't figure out what it is, the point isn't inside it.
    return false;
}
bool BakeRadiosity::CreateNewMesh (INode *orgNode, 
                                    Mesh *orgMesh, 
                                    Matrix3 orgMtx)
{
   if((orgNode == NULL)||(orgMesh == NULL)){
	   DebugPrint(_T("Mesh error\n"));
      return false;
   }
   // Creates an instance of a registered class.
   Object *newObj = (Object*)(ip->CreateInstance(
                                       GEOMOBJECT_CLASS_ID,
                                       Class_ID(TRIOBJ_CLASS_ID, 0)));
   if(newObj == NULL){
	   DebugPrint(_T("CreateInstance error\n"));
      return false;
   }
   // Creates a new node in the scene with the given object. 
   INode *newNode = ip->CreateObjectNode(newObj);
   if(newNode == NULL){
	   DebugPrint(_T("CreateObjectNode error\n"));
      return false;
   }
   // Sets the name of the node. 
   if(keepOrgFlag != true){
      newNode->SetName(orgNode->GetName());
   } else {
      TSTR newName;
      newName.printf(_T("%s_BAKED"), orgNode->GetName());
      newNode->SetName(newName);
   }
   // Sets the renderer material used by the node.
   newNode->SetMtl(orgNode->GetMtl());
   // Returns a reference to the mesh data member of new TriObject.
   TriObject *newTriObj = (TriObject *)newObj;
   Mesh &newMesh = newTriObj->GetMesh();
   // Returns the number of vertices from original mesh. 
   int nbVert = orgMesh->getNumVerts();
   // Sets the number of geometric vertices in the new mesh.
   newMesh.setNumVerts(nbVert);
   // The loop will continue until handling all vertices...
   for(int i=0; i<nbVert; i++) { 
      newMesh.verts[i] = orgMtx * orgMesh->verts[i];//Set new vertices
   }
   // Returns the number of faces in the original mesh.
   int nbFace = orgMesh->getNumFaces();
   // Sets the number of faces in the new mesh 
   // and previous faces are discarded.
   newMesh.setNumFaces(nbFace, FALSE);
   // The loop will continue until handling all faces...
   for(int i=0; i<nbFace; i++){ // Set new faces and Material id
      newMesh.faces[i] = orgMesh->faces[i];
      newMesh.faces[i].setMatID(orgMesh->faces[i].getMatID());
   }
   // Makes a complete copy of the specified channels 
   // of the original Mesh object into new Mesh.
   newMesh.DeepCopy(orgMesh, CNVERT_CHANNELS);

   return true;
}
Exemple #13
0
void UnwrapMod::GetFaceSelectionFromMesh(ObjectState *os, ModContext &mc, TimeValue t)
	{
	TriObject *tobj = (TriObject*)os->obj;
	MeshTopoData *d  = (MeshTopoData*)mc.localData;
	if (d)
		{
		d->SetFaceSel(tobj->GetMesh().faceSel, this, t);
		UpdateFaceSelection(d->faceSel);
		}
	}
Exemple #14
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);	
	}
INode *CollisionImport::ImportCollisionMesh(
	const vector<Vector3>& verts, 
	const vector<Triangle>& tris,
	const vector<Vector3>& norms,
	Matrix3& tm,
	INode *parent
	)
{
	INode *returnNode = NULL;
	if ( ImpNode *node = ni.i->CreateNode() )
	{
		TriObject *triObject = CreateNewTriObject();
		node->Reference(triObject);

		Mesh& mesh = triObject->GetMesh();
		INode *tnode = node->GetINode();

		// Vertex info
		{
			int nVertices = verts.size();
			mesh.setNumVerts(nVertices);
			for (int i=0; i < nVertices; ++i){
				Vector3 v = verts[i] * ni.bhkScaleFactor;
				mesh.verts[i].Set(v.x, v.y, v.z);
			}
		}

		// Triangles and texture vertices
		ni.SetTriangles(mesh, tris);
		//ni.SetNormals(mesh, tris, norms);

		MNMesh mn(mesh);
		mn.Transform(tm);
		mn.OutToTri(mesh);
		mesh.checkNormals(TRUE);

		ni.i->AddNodeToScene(node);   

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

		if (parent != NULL)
			parent->AttachChild(tnode, 1);
	}
	return returnNode;
}
Exemple #16
0
Object *TriObject::MakeShallowCopy(ChannelMask channels) {
	TriObject* newob = CreateNewTriObject();
#ifdef TRIPIPE_DEBUG
	DebugPrint ("TriObject(%08x)::MakeShallowCopy (%08x): %08x\n", this, channels, newob);
#endif
	newob->ShallowCopy(this,channels);
	
	/* Redundant code NS:03-15-00
	newob->mesh.ShallowCopy(&mesh,channels);
	newob->CopyValidity(this,channels);
	newob->mDispApprox = mDispApprox;
	newob->mSubDivideDisplacement = mSubDivideDisplacement;
	newob->mSplitMesh = mSplitMesh;
	newob->mDisableDisplacement = mDisableDisplacement;
	*/
	return newob;
	}
void bhkProxyObject::BuildColOBB()
{
	proxyMesh.FreeAll();
	MeshDelta md(proxyMesh);
	for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) {
		INode *tnode = NULL;
		pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i);	
		if (tnode)
		{
			ObjectState os = tnode->EvalWorldState(0);
			Matrix3 wm = tnode->GetNodeTM(0);
			TriObject *tri = (TriObject *)os.obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0));
			if (tri)
			{
				Mesh& mesh = tri->GetMesh();
				MeshDelta tmd (mesh);
				md.AttachMesh(proxyMesh, mesh, wm, 0);
				md.Apply(proxyMesh);
			}
		}
	}
	Matrix3 rtm(true);
	Point3 center = Point3::Origin;;
	float udim = 0.0f, vdim = 0.0f, ndim = 0.0f;

	if (proxyMesh.getNumVerts() > 3) // Doesn't guarantee that the mesh is not a plane.
	{
		// First build a convex mesh to put the box around;
		// the method acts oddly if extra vertices are present.
		BuildColConvex();
		CalcOrientedBox(proxyMesh, udim, vdim, ndim, center, rtm);
		BuildBox(proxyMesh, vdim, udim, ndim);
	}

	MNMesh mn(proxyMesh);
	mn.Transform(rtm);
	mn.OutToTri(proxyMesh);

	proxyPos = Point3::Origin;
	forceRedraw = true;
}
Object* bhkProxyObject::ConvertToType(TimeValue t, Class_ID obtype)
{
	if (obtype == triObjectClassID)
	{
		int bvType = 0;
		pblock2->GetValue(PB_BOUND_TYPE, 0, bvType, FOREVER, 0);
		if (bvType != 0) 
		{
			TriObject *ob = CreateNewTriObject();
#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+
			ob->GetMesh().CopyBasics(proxyMesh);
#else
			ob->GetMesh() = proxyMesh;
#endif
			ob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t));
			ob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t));
			return ob;
		}
	}
	return 0;
}
Exemple #19
0
int
OBJImport::DoImport(const TCHAR *filename,ImpInterface *i,Interface *gi, BOOL suppressPrompts) {
	TriObject *object = CreateNewTriObject();
	if(!object)
		return 0;
	if(objFileRead(filename, &object->GetMesh())) {
		ImpNode *node = i->CreateNode();
		if(!node) {
			delete object;
			return 0;
			}
		Matrix3 tm;
		tm.IdentityMatrix();
		node->Reference(object);
		node->SetTransform(0,tm);
		i->AddNodeToScene(node);
		node->SetName(GetString(IDS_TH_WAVE_OBJ_NAME));
		i->RedrawViews();
		return 1;
		}
	return 0;
	}
Exemple #20
0
BOOL FaceDataExport::nodeEnum(INode* node,Interface *ip) {	
	if(!exportSelected || node->Selected()) {
		ObjectState os = node->EvalWorldState(ip->GetTime());

		IFaceDataMgr *pFDMgr = NULL;
		if (os.obj->IsSubClassOf(triObjectClassID)) {
			TriObject *tobj = (TriObject *)os.obj;
			Mesh* mesh = &tobj->GetMesh();
			pFDMgr = static_cast<IFaceDataMgr*>(mesh->GetInterface( FACEDATAMGR_INTERFACE ));
		} else if (os.obj->IsSubClassOf (polyObjectClassID)) {
			PolyObject *pobj = (PolyObject *)os.obj;
			MNMesh *mesh = &pobj->GetMesh();
			pFDMgr = static_cast<IFaceDataMgr*>(mesh->GetInterface( FACEDATAMGR_INTERFACE ));
		}
		if (pFDMgr == NULL) return FALSE;

		SampleFaceData* SampleDataChan = NULL; 
		IFaceDataChannel* fdc = pFDMgr->GetFaceDataChan( FACE_MAXSAMPLEUSE_CLSID );
		if ( fdc != NULL ) SampleDataChan = dynamic_cast<SampleFaceData*>(fdc);
		if ( SampleDataChan == NULL) {
			fileStream.Printf(_T("Node %s does not have our Face Data\n"),node->GetName());
			return false;
		}

		//OK so We have Face data lets dump it out..
		fileStream.Printf(_T("\nNode %s has %d faces with FaceFloats\n"),node->GetName(), SampleDataChan->Count());
		for(ULONG i=0;i<SampleDataChan->Count();i++) {
			float data = SampleDataChan->data[i];
			fileStream.Printf(_T("Face %d, float %f\n"),i,data);
		}
	}

	// Recurse through this node's children, if any
	for (int c = 0; c < node->NumberOfChildren(); c++) {
		if (!nodeEnum(node->GetChildNode(c), ip)) return FALSE;
	}

	return TRUE;
}
Exemple #21
0
Object* SimpleObject::ConvertToType(TimeValue t, Class_ID obtype) 
	{
	if (obtype==defObjectClassID||obtype==triObjectClassID||obtype==mapObjectClassID) {
		TriObject *triob;
		UpdateMesh(t);
		triob = CreateNewTriObject();
		triob->GetMesh() = mesh;
		triob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t));
		triob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t));		
		return triob;
		}
	else
	if (obtype == patchObjectClassID) {
		UpdateMesh(t);
		PatchObject *patchob = new PatchObject();
		patchob->patch = mesh;		// Handy Mesh->PatchMesh conversion
		patchob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t));
		patchob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t));		
		return patchob;
		}
	return Object::ConvertToType(t,obtype);
	}
Exemple #22
0
void EditFaceDataMod::ModifyObject (TimeValue t, ModContext &mc, ObjectState *os, INode *node) {
	if (mDisabled) return;

	EditFaceDataModData *d  = (EditFaceDataModData*)mc.localData;
	if (!d) mc.localData = d = new EditFaceDataModData();

	if (os->obj->IsSubClassOf(triObjectClassID)) {
		// Access the Mesh:
		TriObject *tobj = (TriObject*)os->obj;
		Mesh & mesh = tobj->GetMesh();

		// Apply our modifier's changes:
		d->ApplyChanges (mesh);

		// Update the cache used for display and hit testing:
		if (!d->GetCacheMesh()) d->SetCacheMesh(mesh);

		// Set display flags according to SO level:
		mesh.dispFlags = 0;
		mesh.SetDispFlag (levelDispFlags[selLevel]);

	} else if (os->obj->IsSubClassOf(polyObjectClassID)) {

		// Access the Mesh:
		PolyObject *pobj = (PolyObject*)os->obj;
		MNMesh & mesh = pobj->GetMesh();

		// Apply our modifier's changes:
		d->ApplyChanges (mesh);

		// Update the cache used for display and hit testing:
		if (!d->GetCacheMNMesh()) d->SetCacheMNMesh(mesh);

		// Set display flags according to SO level:
		mesh.dispFlags = 0;
		mesh.SetDispFlag (mnlevelDispFlags[selLevel]);
	}
}
bool NifImporter::ImportMesh(NiTriStripsRef triStrips)
{
   bool ok = true;

   ImpNode *node = i->CreateNode();
   if(!node)
	   return false;
   INode *inode = node->GetINode();
   TriObject *triObject = CreateNewTriObject();
   node->Reference(triObject);
   wstring name = wide(triStrips->GetName());
   node->SetName(name.c_str());

   // Texture
   Mesh& mesh = triObject->GetMesh();
   NiTriStripsDataRef triStripsData = DynamicCast<NiTriStripsData>(triStrips->GetData());
   if (triStripsData == NULL)
      return false;

   vector<Triangle> tris = triStripsData->GetTriangles();
   ok |= ImportMesh(node, triObject, triStrips, triStripsData, tris);
   return ok;
}
Exemple #24
0
Object* SimpleObject::ConvertToType(TimeValue t, Class_ID obtype) 
	{
	if (obtype==defObjectClassID||obtype==triObjectClassID||obtype==mapObjectClassID) {
		TriObject *triob;
		UpdateMesh(t);
		triob = CreateNewTriObject();
		triob->GetMesh() = mesh;
		triob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t));
		triob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t));		
		return triob;
		}
#ifndef NO_PATCHES
	if (obtype == patchObjectClassID) {
		UpdateMesh(t);
		PatchObject *patchob = new PatchObject();
		patchob->patch = mesh;		// Handy Mesh->PatchMesh conversion
		patchob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t));
		patchob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t));		
		return patchob;
		}
#endif
	if (Object::CanConvertToType (obtype)) {
		UpdateMesh (t);
	return Object::ConvertToType(t,obtype);
	}
	if (CanConvertTriObject(obtype)) {
		UpdateMesh (t);
		TriObject *triob = CreateNewTriObject ();
		triob->GetMesh() = mesh;
		triob->SetChannelValidity(TOPO_CHAN_NUM,ObjectValidity(t));
		triob->SetChannelValidity(GEOM_CHAN_NUM,ObjectValidity(t));		
		Object *ob = triob->ConvertToType (t, obtype);
		if (ob != triob) triob->DeleteThis ();	// (ob should never = tob.)
		return ob;
	}
	return NULL;
}
Exemple #25
0
Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue t)
{
	ObjectState os = node->EvalWorldState(t);

	bool local = !mFlattenHierarchy;

	TriObject *tri = (TriObject *)os.obj->ConvertToType(t, Class_ID(TRIOBJ_CLASS_ID, 0));
	if (!tri)
		return Skip;

	Mesh *copymesh = NULL;
	Mesh *mesh = &tri->GetMesh();

	Matrix3 mtx(true), rtx(true);
	if (Exporter::mCollapseTransforms)
	{
		mtx = GetNodeLocalTM(node, t);
		mtx.NoTrans();
		Quat q(mtx);
		q.MakeMatrix(rtx);
		mesh = copymesh = new Mesh(*mesh);
		{
			int n = mesh->getNumVerts();
			for ( unsigned int i = 0; i < n; ++i ) {
				Point3& vert = mesh->getVert(i);
				vert = mtx * vert;
			}
			mesh->checkNormals(TRUE);
#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 6+
			MeshNormalSpec *specNorms = mesh->GetSpecifiedNormals ();
			if (NULL != specNorms) {
				specNorms->CheckNormals();
				for ( unsigned int i = 0; i < specNorms->GetNumNormals(); ++i ) {
					Point3& norm = specNorms->Normal(i);
					norm = (rtx * norm).Normalize();
				}
			}
#endif
		}
	}
	// Note that calling setVCDisplayData will clear things like normals so we set this up first
	vector<Color4> vertColors;
	if (mVertexColors)
	{
		bool hasvc = false;
		if (mesh->mapSupport(MAP_ALPHA))
		{
			mesh->setVCDisplayData(MAP_ALPHA);         int n = mesh->getNumVertCol();
			if (n > vertColors.size())
				vertColors.assign(n, Color4(1.0f, 1.0f, 1.0f, 1.0f));
			VertColor *vertCol = mesh->vertColArray;
			if (vertCol) {
				for (int i=0; i<n; ++i) {
					VertColor c = vertCol[ i ];
					float a = (c.x + c.y + c.z) / 3.0f;
					vertColors[i].a = a;
					hasvc |= (a != 1.0f);
				}
			}
		}
		if (mesh->mapSupport(0))
		{
			mesh->setVCDisplayData(0);
			VertColor *vertCol = mesh->vertColArray;
			int n = mesh->getNumVertCol();
			if (n > vertColors.size())
				vertColors.assign(n, Color4(1.0f, 1.0f, 1.0f, 1.0f));
			if (vertCol) {
				for (int i=0; i<n; ++i) {
					VertColor col = vertCol[ i ];
					vertColors[i] = Color4(col.x, col.y, col.z, vertColors[i].a);
					hasvc |= (col.x != 1.0f || col.y != 1.0f || col.z != 1.0f);
				}
			}
		}
		if (!hasvc) vertColors.clear();
	}

#if VERSION_3DSMAX <= ((5000<<16)+(15<<8)+0) // Version 5
	mesh->checkNormals(TRUE);
#else
	MeshNormalSpec *specNorms = mesh->GetSpecifiedNormals ();
	if (NULL != specNorms) {
		specNorms->CheckNormals();
		if (specNorms->GetNumNormals() == 0)
			mesh->checkNormals(TRUE);
	} else {
		mesh->checkNormals(TRUE);
	}
#endif

	Result result = Ok;

	Modifier* geomMorpherMod = GetMorpherModifier(node);
	bool noSplit = FALSE;
//	bool noSplit = (NULL != geomMorpherMod);

	while (1)
	{
		FaceGroups grps;
		if (!splitMesh(node, *mesh, grps, t, vertColors, noSplit))
		{
			result = Error;
			break;
		}
		bool exportStrips = mTriStrips && (Exporter::mNifVersionInt > VER_4_2_2_0);

		Matrix44 tm = Matrix44::IDENTITY;
		if ( mExportExtraNodes || (mExportType != NIF_WO_ANIM && isNodeKeyed(node) ) ) {
			tm = TOMATRIX4(getObjectTransform(node, t, false) * Inverse(getNodeTransform(node, t, false)));
		} else {
			Matrix33 rot; Vector3 trans;
			objectTransform(rot, trans, node, t, local);
			tm = Matrix44(trans, rot, 1.0f);
		}
		tm = TOMATRIX4(Inverse(mtx)) * tm;

		TSTR basename = node->NodeName();
		TSTR format = (!basename.isNull() && grps.size() > 1) ? "%s:%d" : "%s";

		int i=1;
		FaceGroups::iterator grp;
		for (grp=grps.begin(); grp!=grps.end(); ++grp, ++i)
		{
			string name = FormatString(format, basename.data(), i);
			NiTriBasedGeomRef shape = makeMesh(ninode, getMaterial(node, grp->first), grp->second, exportStrips);
			if (shape == NULL)
			{
				result = Error;
				break;
			}

			if (node->IsHidden())
				shape->SetVisibility(false);

			shape->SetName(name);
			shape->SetLocalTransform(tm);

			if (Exporter::mZeroTransforms) {
				shape->ApplyTransforms();
			}

			makeSkin(shape, node, grp->second, t);

			if (geomMorpherMod) {
				vector<Vector3> verts = shape->GetData()->GetVertices();
				exportGeomMorpherControl(geomMorpherMod, verts, shape->GetData()->GetVertexIndices(), shape);
				shape->GetData()->SetConsistencyFlags(CT_VOLATILE);
			}

		}

		break;
	}

	if (tri != os.obj)
		tri->DeleteMe();

	if (copymesh)
		delete copymesh;

	return result;
}
Exemple #26
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
   }
Exemple #27
0
void SmoothMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node) {
   Interval valid = FOREVER;
   int autoSmooth, bits = 0, prevent = 0;
   float thresh = 0.0f;
   pblock->GetValue(sm_autosmooth, t, autoSmooth, valid);
   if (autoSmooth) {
      pblock->GetValue(sm_threshold, t, thresh, valid);
      pblock->GetValue(sm_prevent_indirect, t, prevent, valid);
   } else {
      pblock->GetValue(sm_smoothbits, t, bits, valid);
   }
   // For version 4 and later, we process patch meshes as they are and pass them on.  Earlier
   // versions converted to TriMeshes (done below).  For adding other new types of objects, add
   // them here!
   bool done = false;
#ifndef NO_PATCHES
   if(version >= MATMOD_VER4 && os->obj->IsSubClassOf(patchObjectClassID)) {
      PatchObject *patchOb = (PatchObject *)os->obj;
      PatchMesh &pmesh = patchOb->GetPatchMesh(t);
      BOOL useSel = pmesh.selLevel >= PO_PATCH;

      if (autoSmooth) pmesh.AutoSmooth (thresh, useSel, prevent);
      else {
         for (int i=0; i<pmesh.getNumPatches(); i++) {
            if (!useSel || pmesh.patchSel[i]) pmesh.patches[i].smGroup = (DWORD)bits;
         }
      }
      pmesh.InvalidateGeomCache();  // Do this because there isn't a topo cache in PatchMesh
      patchOb->UpdateValidity(TOPO_CHAN_NUM,valid);
      done = true;
   }
#endif // NO_PATCHES
   if (!done && os->obj->IsSubClassOf (polyObjectClassID)) {
      PolyObject *pPolyOb = (PolyObject *)os->obj;
      MNMesh &mesh = pPolyOb->GetMesh();

      BOOL useSel = (mesh.selLevel == MNM_SL_FACE);
      if (autoSmooth) mesh.AutoSmooth (thresh, useSel, prevent);
      else {
         for (int faceIndex=0; faceIndex<mesh.FNum(); faceIndex++) {
            if (!useSel || mesh.F(faceIndex)->GetFlag(MN_SEL)) {
               mesh.F(faceIndex)->smGroup = (DWORD)bits;
            }
         }
      }

      // Luna task 747
      // We need to rebuild the smoothing-group-based normals in the normalspec, if any:
      if (mesh.GetSpecifiedNormals()) {
         mesh.GetSpecifiedNormals()->SetParent (&mesh);
         mesh.GetSpecifiedNormals()->BuildNormals ();
         mesh.GetSpecifiedNormals()->ComputeNormals ();
      }

      pPolyOb->UpdateValidity(TOPO_CHAN_NUM,valid);
      done = true;
   }

   TriObject *triOb = NULL;
   if (!done) {
      if (os->obj->IsSubClassOf(triObjectClassID)) triOb = (TriObject *)os->obj;
      else {
         // Convert to triobject if we can.
         if(os->obj->CanConvertToType(triObjectClassID)) {
            TriObject  *triOb = (TriObject *)os->obj->ConvertToType(t, triObjectClassID);

            // We'll need to stuff this back into the pipeline:
            os->obj = triOb;

            // Convert validities:
            Interval objValid = os->obj->ChannelValidity (t, TOPO_CHAN_NUM);
            triOb->SetChannelValidity (TOPO_CHAN_NUM, objValid);
            triOb->SetChannelValidity (GEOM_CHAN_NUM,
               objValid & os->obj->ChannelValidity (t, GEOM_CHAN_NUM));
            triOb->SetChannelValidity (TEXMAP_CHAN_NUM,
               objValid & os->obj->ChannelValidity (t, TEXMAP_CHAN_NUM));
            triOb->SetChannelValidity (VERT_COLOR_CHAN_NUM,
               objValid & os->obj->ChannelValidity (t, VERT_COLOR_CHAN_NUM));
            triOb->SetChannelValidity (DISP_ATTRIB_CHAN_NUM,
               objValid & os->obj->ChannelValidity (t, DISP_ATTRIB_CHAN_NUM));
         }
      }
   }

   if (triOb) {   // one way or another, there's a triobject to smooth.
      Mesh & mesh = triOb->GetMesh();
      BOOL useSel = mesh.selLevel == MESH_FACE;
      if (autoSmooth) mesh.AutoSmooth (thresh, useSel, prevent);
      else {
         for (int i=0; i<mesh.getNumFaces(); i++) {
            if (!useSel || mesh.faceSel[i]) mesh.faces[i].smGroup = (DWORD)bits;
         }
      }
      triOb->GetMesh().InvalidateTopologyCache();
      triOb->UpdateValidity(TOPO_CHAN_NUM,valid);     
   }
}
Exemple #28
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);		
		}
	}
Exemple #29
0
ObjectHandle TriPatchObject::CreateTriObjRep(TimeValue t) {
	TriObject *tri = CreateNewTriObject();
	PrepareMesh(t);	// Turn it into a mesh
	tri->GetMesh() = patch.GetMesh();	// Place it into the TriObject
	return(ObjectHandle(tri));
	}
BOOL Building_collision_exp::ExportOneMesh(INode* node, CExportDataBuf* pDataBuf)
{

    if(node && pDataBuf)
    {
        pDataBuf->strName = node->GetName();

        ObjectState os = node->EvalWorldState(0);

        if (!os.obj)
        {
            return FALSE;
        }

        // Targets are actually geomobjects, but we will export them
        // from the camera and light objects, so we skip them here.
        if (os.obj->ClassID() == Class_ID(TARGET_CLASS_ID, 0))
        {
            return FALSE;
        }

        int i;		// 以后需要用到的循环变量.

        Matrix3 tm = node->GetObjTMAfterWSM(0);

        // 三角形面的索引值.
        int vx1 = 0, vx2 = 1, vx3 = 2;

        BOOL needDel;
        TriObject* tri = GetTriObjectFromNode(node, 0, needDel);
        if (!tri)
        {
            return FALSE;
        }

        Mesh* mesh = &tri->GetMesh();

        pDataBuf->m_iFaceCount     = mesh->getNumFaces();
        pDataBuf->m_posVectorCount = mesh->getNumVerts();

        Point3 v;
        POS    pos;
        for (i=0; i<mesh->getNumVerts(); i++)
        {
            v = tm * mesh->verts[i];
            pos.x = v.x;
            pos.y = v.z;
            pos.z = -v.y;
            pDataBuf->m_posVector.push_back(pos);

        }


        FACE face;
        for (i=0; i<mesh->getNumFaces(); i++)
        {
            face.iF1 = (WORD)mesh->faces[i].v[vx1];
            face.iF2 = (WORD)mesh->faces[i].v[vx2];
            face.iF3 = (WORD)mesh->faces[i].v[vx3];

            pDataBuf->m_posFaceVector.push_back(face);
        }

        if (needDel)
        {
            delete tri;
        }

    }

    m_bIsExport = TRUE;
    return TRUE;
}