Beispiel #1
0
void Exporter::ExportMesh(INode* node, TimeValue t, int indentLevel)
{
	int i;
	Mtl* nodeMtl = node->GetMtl();
	Matrix3 tm = node->GetObjTMAfterWSM(t);
	BOOL negScale = TMNegParity(tm);
	int vx1, vx2, vx3;
	TSTR indent;
	
	ObjectState os = node->EvalWorldState(t);
	if (!os.obj || os.obj->SuperClassID()!=GEOMOBJECT_CLASS_ID) {
		return; // Safety net. This shouldn't happen.
	}
	
	// Order of the vertices. Get 'em counter clockwise if the objects is
	// negatively scaled.
	if (negScale) {
		vx1 = 2;
		vx2 = 1;
		vx3 = 0;
	}
	else {
		vx1 = 0;
		vx2 = 1;
		vx3 = 2;
	}
	
	BOOL needDel;
	TriObject* tri = GetTriObjectFromNode(node, t, needDel);
	if (!tri) {
		return;
	}
	
	Mesh* mesh = &tri->mesh;
	
	mesh->buildNormals();
	
	{	// make vertices and faces
		rsm->mesh->nV=mesh->getNumVerts();
		rsm->mesh->nF=mesh->getNumFaces();
		rsm->mesh->ver=new rvertex[mesh->getNumVerts()];
		rsm->mesh->face=new rface[mesh->getNumFaces()];
	}
	
	// Export the vertices
	for (i=0; i<mesh->getNumVerts(); i++) {
		Point3 v = tm * mesh->verts[i];
		rsm->mesh->ver[i].coord=rvector(v);
		rsm->mesh->ver[i].normal=rvector(0,0,0);
	}
	
	// To determine visibility of a face, get the vertices in clockwise order.
	// If the objects has a negative scaling, we must compensate for that by
	// taking the vertices counter clockwise
	for (i=0; i<mesh->getNumFaces(); i++) {
		
		rsm->mesh->face[i].a=(WORD)mesh->faces[i].v[vx1];
		rsm->mesh->face[i].c=(WORD)mesh->faces[i].v[vx2];
		rsm->mesh->face[i].b=(WORD)mesh->faces[i].v[vx3];
		rsm->mesh->face[i].nMaterial=mesh->faces[i].getMatID();
	}
	
	// Export face map texcoords if we have them...
	if (!CheckForAndExportFaceMap(nodeMtl, mesh, indentLevel+1)) {
		// If not, export standard tverts
		int numTVx = mesh->getNumTVerts();

		if (numTVx) {
			rface *f=rsm->mesh->face;
			for (i=0; i<mesh->getNumFaces(); i++) {
// dubble added
				TVFace *tvf=&mesh->tvFace[i];
				f->u[0]=mesh->tVerts[tvf->t[vx1]].x;
				f->v[0]=1.0f-mesh->tVerts[tvf->t[vx1]].y;
				f->u[2]=mesh->tVerts[tvf->t[vx2]].x;
				f->v[2]=1.0f-mesh->tVerts[tvf->t[vx2]].y;
				f->u[1]=mesh->tVerts[tvf->t[vx3]].x;
				f->v[1]=1.0f-mesh->tVerts[tvf->t[vx3]].y;  // good
				f++;
// end of dubble added
			}
		}
	}

	{
		// Export mesh (face + vertex) normals
		
		Point3 fn;  // Face normal
		Point3 vn;  // Vertex normal
		int  vert;
		Face* f;
		
		// Face and vertex normals.
		// In MAX a vertex can have more than one normal (but doesn't always have it).
		// This is depending on the face you are accessing the vertex through.
		// To get all information we need to export all three vertex normals
		// for every face.
		Matrix3 pivot = node->GetNodeTM(GetStaticFrame());
		pivot.NoTrans();

		for (i=0; i<mesh->getNumFaces(); i++) {
			f = &mesh->faces[i];
			fn = mesh->getFaceNormal(i);
			rsm->mesh->face[i].normal=fn;
			
			vert = f->getVert(vx1);
			vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert));
			rsm->mesh->face[i].vnormals[0]=pivot*vn;
			rsm->mesh->ver[rsm->mesh->face[i].a].normal+=vn;
			
			vert = f->getVert(vx2);
			vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert));
			rsm->mesh->face[i].vnormals[2]=pivot*vn;
			rsm->mesh->ver[rsm->mesh->face[i].b].normal+=vn;
			
			vert = f->getVert(vx3);
			vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert));
			rsm->mesh->face[i].vnormals[1]=pivot*vn;
			rsm->mesh->ver[rsm->mesh->face[i].c].normal+=vn;
		}
	}
	
	if (needDel) {
		delete tri;
	}
}
Beispiel #2
0
void XsiExp::ExportMesh( INode * node, TimeValue t, int indentLevel)
{
	ObjectState os = node->EvalWorldState(t);
	if (!os.obj || os.obj->SuperClassID() != GEOMOBJECT_CLASS_ID)
  {
		return; // Safety net. This shouldn't happen.
	}
	BOOL needDel;
	TriObject * tri = GetTriObjectFromNode(node, t, needDel);
	if (!tri)
  {
    // no tri object
		return;
	}
  // prepare mesh
  Mesh * mesh = &tri->GetMesh();
  mesh->buildNormals();

  // object offset matrix; apply to verts
  // swap y and z; max to soft correction
  Matrix3 matrix(1);
  //  translate
  matrix.PreTranslate( Point3( node->GetObjOffsetPos().x, node->GetObjOffsetPos().z, -node->GetObjOffsetPos().y));

  // rotate
  AngAxis aa( node->GetObjOffsetRot());
  float temp = aa.axis.z;
  aa.axis.z = -aa.axis.y;
  aa.axis.y = temp;
  PreRotateMatrix(matrix, Quat( aa));

  // scale
  ScaleValue scale = node->GetObjOffsetScale();
  aa.Set( scale.q);
  temp = aa.axis.z;
  aa.axis.z = -aa.axis.y;
  aa.axis.y = temp;
  scale.q.Set( aa);
  temp = scale.s.z;
  scale.s.z = scale.s.y;
  scale.s.y = temp;
  ApplyScaling(matrix, scale);

  // apply root transform
  matrix = matrix * topMatrix;
  // only rotation for normals
  AffineParts ap;
  Matrix3 rotMatrix(1);
  decomp_affine( matrix, &ap);
  PreRotateMatrix( rotMatrix, ap.q);

  // set winding order
	int vx1 = 0, vx2 = 1, vx3 = 2;
	if (TMNegParity( node->GetNodeTM(GetStaticFrame())) != TMNegParity( matrix) )
  {
    // negative scaling; invert winding order and normal rotation
		vx1 = 2;	vx2 = 1;	vx3 = 0;
    rotMatrix = rotMatrix * Matrix3( Point3(-1,0,0), Point3(0,-1,0), Point3(0,0,-1), Point3(0,0,0));
	}

  // header
	TSTR indent = GetIndent(indentLevel+1);
	fprintf(pStream, "%s%s %s {\n",indent.data(), "Mesh", FixupName(node->GetName()));

  // write number of verts
  int numLoop = mesh->getNumVerts();
	fprintf(pStream, "%s\t%d;\n",indent.data(), numLoop);

  // write verts
	for (int i = 0; i < numLoop; i++)
  {
		Point3 v = mesh->verts[i];
		float temp = v.z;
    v.z = -v.y;
    v.y = temp;
		v = matrix * v;
		fprintf(pStream, "%s\t%.6f;%.6f;%.6f;%s\n", indent.data(), v.x, v.y, v.z, 
      i == numLoop - 1 ? ";\n" : ",");
	}
  // write number of faces
  numLoop = mesh->getNumFaces();
  fprintf(pStream, "%s\t%d;\n", indent.data(), numLoop);

  // write faces
	for (i = 0; i < numLoop; i++)
  {
		fprintf(pStream, "%s\t3;%d,%d,%d;%s\n",
			indent.data(),
			mesh->faces[i].v[vx1],
			mesh->faces[i].v[vx2],
			mesh->faces[i].v[vx3], 
      i == numLoop - 1 ? ";\n" : ",");
	}

  // face materials
	Mtl * nodeMtl = node->GetMtl();
  int numMtls = !nodeMtl || !nodeMtl->NumSubMtls() ? 1 : nodeMtl->NumSubMtls();

	// write face material list header	
	fprintf(pStream, "%s\tMeshMaterialList {\n", indent.data());
  // write number of materials
	fprintf(pStream, "%s\t\t%d;\n", indent.data(), numMtls);
  // write number of faces
  fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

  // write face material indices (1 for each face)
  for (i = 0; i < numLoop; i++)
  {
    int index = numMtls ? mesh->faces[i].getMatID() % numMtls : 0;
		fprintf(pStream,"%s\t\t%d%s\n",
			indent.data(),
      index,
      i == numLoop - 1 ? ";\n" : ",");
	}

  // write the materials
  ExportMaterial( node, indentLevel+2);

  // verts close brace
	fprintf(pStream, "%s\t}\n\n",indent.data());

  // write normals header
	fprintf(pStream, "%s\t%s {\n", indent.data(), "SI_MeshNormals");
	// write number of normals
  fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop * 3);

  // write normals (3 for each face)
	for (i = 0; i < numLoop; i++)
  {
		Face * f = &mesh->faces[i];
		int vert = f->getVert(vx1);

		Point3 vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert));
    float temp = vn.z;
    vn.z = -vn.y;
    vn.y = temp;
		vn = rotMatrix * vn;
		fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;,\n", indent.data(), vn.x, vn.y, vn.z);

		vert = f->getVert(vx2);
		vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert));
    temp = vn.z;
    vn.z = -vn.y;
    vn.y = temp;
		vn = rotMatrix * vn;
		fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;,\n", indent.data(), vn.x, vn.y, vn.z);
    
		vert = f->getVert(vx3);
		vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert));
    temp = vn.z;
    vn.z = -vn.y;
    vn.y = temp;
		vn = rotMatrix * vn;
		fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;%s\n", indent.data(), vn.x, vn.y, vn.z,
      i == numLoop - 1 ? ";\n" : ",");
	}
  // write number of faces
  fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

  // write faces
  for (i = 0; i < numLoop; i++)
  {
	  fprintf(pStream, "%s\t\t%d;3;%d,%d,%d;%s\n",
		  indent.data(),
      i,
      i * 3 + vx1, i * 3 + vx2, i * 3 + vx3,
      i == numLoop - 1 ? ";\n" : ",");
  }
  // normals close brace
	fprintf(pStream, "%s\t}\n\n",indent.data());

	// texcoords
	if (nodeMtl && mesh && (nodeMtl->Requirements(-1) & MTLREQ_FACEMAP))
  {
    // facemapping
    numLoop = mesh->getNumFaces() * 3;

    // write texture coords header
    fprintf(pStream, "%s\tSI_MeshTextureCoords {\n", indent.data());
    // write number of texture coords
    fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

    // write texture coords
	  for (int i = 0; i < numLoop; i++)
    {
		  Point3 tv[3];
		  Face * f = &mesh->faces[i];
		  make_face_uv( f, tv);
		  fprintf(pStream, "%s\t\t%.6f;%.6f;,\n",  indent.data(), tv[0].x, tv[0].y);
		  fprintf(pStream, "%s\t\t%.6f;%.6f;,\n",  indent.data(), tv[1].x, tv[1].y);
		  fprintf(pStream, "%s\t\t%.6f;%.6f;%s\n", indent.data(), tv[2].x, tv[2].y,
        i == numLoop - 1 ? ";\n" : ",");
	  }
    // write number of faces
    numLoop = mesh->getNumFaces();
	  fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

    // write faces
	  for (i = 0; i < numLoop; i++)
    {
		  fprintf(pStream,"%s\t\t%d;3;%d,%d,%d;%s\n",
			  indent.data(),
			  i,
			  mesh->tvFace[i].t[vx1],
			  mesh->tvFace[i].t[vx2],
			  mesh->tvFace[i].t[vx3],
        i == numLoop - 1 ? ";\n" : ",");
	  }
    // texture coords close brace
	  fprintf(pStream, "%s\t}\n\n", indent.data());
  }
  else
  {
		numLoop = mesh->getNumTVerts();

		if (numLoop)
    {
      // write texture coords header
  		fprintf(pStream, "%s\tSI_MeshTextureCoords {\n", indent.data());
      // write number of texture coords
  		fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

      // write texture coords
			for (i = 0; i < numLoop; i++)
      {
				UVVert tv = mesh->tVerts[i];
				fprintf(pStream, "%s\t\t%.6f;%.6f;%s\n", indent.data(), tv.x, tv.y,
        i == numLoop - 1 ? ";\n" : ",");
			}
      // write number of faces
      numLoop = mesh->getNumFaces();
			fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

      // write faces
			for (i = 0; i < numLoop; i++)
      {
				fprintf(pStream,"%s\t\t%d;3;%d,%d,%d;%s\n",
					indent.data(),
					i,
					mesh->tvFace[i].t[vx1],
					mesh->tvFace[i].t[vx2],
					mesh->tvFace[i].t[vx3],
          i == numLoop - 1 ? ";\n" : ",");
			}
      // texture coords close brace
			fprintf(pStream, "%s\t}\n\n", indent.data());
		}
  }

/*
	// Export color per vertex info
	if (GetIncludeVertexColors()) {
		int numCVx = mesh->numCVerts;

		fprintf(pStream, "%s\t%s %d\n",indent.data(), ID_MESH_NUMCVERTEX, numCVx);
		if (numCVx) {
			fprintf(pStream,"%s\t%s {\n",indent.data(), ID_MESH_CVERTLIST);
			for (i=0; i<numCVx; i++) {
				Point3 vc = mesh->vertCol[i];
				fprintf(pStream, "%s\t\t%s %d\t%s\n",indent.data(), ID_MESH_VERTCOL, i, Format(vc));
			}
			fprintf(pStream,"%s\t}\n",indent.data());
			
			fprintf(pStream, "%s\t%s %d\n",indent.data(), ID_MESH_NUMCVFACES, mesh->getNumFaces());

			fprintf(pStream, "%s\t%s {\n",indent.data(), ID_MESH_CFACELIST);
			for (i=0; i<mesh->getNumFaces(); i++) {
				fprintf(pStream,"%s\t\t%s %d\t%d\t%d\t%d\n",
					indent.data(),
					ID_MESH_CFACE, i,
					mesh->vcFace[i].t[vx1],
					mesh->vcFace[i].t[vx2],
					mesh->vcFace[i].t[vx3]);
			}
			fprintf(pStream, "%s\t}\n",indent.data());
		}
	}
*/

  // Mesh close brace
	fprintf(pStream, "%s}\n",indent.data());
  
  // dispose of tri object
  if (needDel)
  {
		delete tri;
	}
}
Beispiel #3
0
CVertexCandidate *CMaxMesh::GetVertexCandidate(CSkeletonCandidate *pSkeletonCandidate, int faceId, int faceVertexId)
{
    // check for valid mesh and physique modifier
    if((m_pIMesh == 0))
    {
        theExporter.SetLastError("Invalid handle.", __FILE__, __LINE__);
        return 0;
    }

    // check if face id is valid
    if((faceId < 0) || (faceId >= m_pIMesh->getNumFaces()))
    {
        theExporter.SetLastError("Invalid face id found.", __FILE__, __LINE__);
        return 0;
    }

    // check if face vertex id is valid
    if((faceVertexId < 0) || (faceVertexId >= 3))
    {
        theExporter.SetLastError("Invalid face vertex id found.", __FILE__, __LINE__);
        return 0;
    }

    // allocate a new vertex candidate
    CVertexCandidate *pVertexCandidate;
    pVertexCandidate = new CVertexCandidate();
    if(pVertexCandidate == 0)
    {
        theExporter.SetLastError("Memory allocation failed.", __FILE__, __LINE__);
        return 0;
    }

    // create the new vertex candidate
    if(!pVertexCandidate->Create())
    {
        delete pVertexCandidate;
        return 0;
    }

    // get vertex id
    int vertexId;
    vertexId = m_pIMesh->faces[faceId].v[faceVertexId];

    // get the absolute vertex position
    Point3 vertex;
    vertex = m_pIMesh->getVert(vertexId) * m_tm;

    // set the vertex candidate position
    pVertexCandidate->SetPosition(vertex.x, vertex.y, vertex.z);
    pVertexCandidate->SetUniqueId(vertexId);

    // get the absolute vertex normal
    Point3 normal;
    normal = GetVertexNormal(faceId, vertexId);
    normal = normal * Inverse(Transpose(m_tm));
    normal = normal.Normalize();

    // set the vertex candidate normal
    pVertexCandidate->SetNormal(normal.x, normal.y, normal.z);
 
  if(m_pIMesh->numCVerts > 0)
  { 
        VertColor vc;
        vc = m_pIMesh->vertCol[m_pIMesh->vcFace[faceId].t[faceVertexId]];
    CalVector vcCal(vc.x, vc.y, vc.z);
    pVertexCandidate->SetVertColor(vcCal);
  }  
 
    // get the vertex weight array
    float *pVertexWeights;
    pVertexWeights = m_pIMesh->getVertexWeights();
  //if( pVertexWeights == NULL ) {
    //    delete pVertexCandidate;
    //    theExporter.SetLastError("Mesh has no vertex weights", __FILE__, __LINE__);
    //    return 0;
  //}

    // get the vertex weight (if possible)
    float weight;
    if(pVertexWeights != 0)
    {
        weight = pVertexWeights[vertexId];
    }
    else
    {
        weight = 0.0f;
    }

    // another 3ds max weird behaviour:
    // zero out epsilon weights
    if(weight < 0.0005f) weight = 0.0f;

    // set the vertex candidate weight
    pVertexCandidate->SetPhysicalProperty(weight);

    // get the material id of the face
    int materialId;
    materialId = GetFaceMaterialId(faceId);

    if((materialId < 0) || (materialId >= (int)m_vectorStdMat.size()))
    {
        delete pVertexCandidate;
        theExporter.SetLastError("Invalid material id found.", __FILE__, __LINE__);
        return 0;
    }

    // get the material of the face
    StdMat *pStdMat;
    pStdMat = m_vectorStdMat[materialId];

    // loop through all the mapping channels and extract texture coordinates
    int mapId;
    for(mapId = 0; mapId < pStdMat->NumSubTexmaps(); mapId++)
    {
        // get texture map
        Texmap *pTexMap;
        pTexMap = pStdMat->GetSubTexmap(mapId);

        // check if map is valid
        if((pTexMap != 0) && (pStdMat->MapEnabled(mapId)))
        {
            // get the mapping channel
            int channel;
            channel = pTexMap->GetMapChannel();

            bool bValidUV;
            bValidUV = false;

            // extract the texture coordinate
            UVVert uvVert;
            if(m_pIMesh->mapSupport(channel))
            {
                TVFace *pTVFace;
                pTVFace = m_pIMesh->mapFaces(channel);

                UVVert *pUVVert;
                pUVVert = m_pIMesh->mapVerts(channel);

                uvVert = pUVVert[pTVFace[faceId].t[faceVertexId]];
                bValidUV = true;
            }
            else if(m_pIMesh->numTVerts > 0)
            {
                uvVert = m_pIMesh->tVerts[m_pIMesh->tvFace[faceId].t[faceVertexId]];
                bValidUV = true;
            }

            // if we found valid texture coordinates, add them to the vertex candidate
            if(bValidUV)
            {
                // apply a possible uv generator
                StdUVGen *pStdUVGen;
                pStdUVGen = (StdUVGen *)pTexMap->GetTheUVGen();
                if(pStdUVGen != 0)
                {
                    Matrix3 tmUV;
                    pStdUVGen->GetUVTransform(tmUV);
                    uvVert = uvVert * tmUV;
                }

                // add texture coordinate to the vertex candidate, inverting the y coordinate
                pVertexCandidate->AddTextureCoordinate(uvVert.x, 1.0f - uvVert.y);
            }
        }
    }

    // check for physique modifier
    if(m_modifierType == MODIFIER_PHYSIQUE)
    {
        // create a physique export interface
        IPhysiqueExport *pPhysiqueExport;
        pPhysiqueExport = (IPhysiqueExport *)m_pModifier->GetInterface(I_PHYINTERFACE);
        if(pPhysiqueExport == 0)
        {
            delete pVertexCandidate;
            theExporter.SetLastError("Physique modifier interface not found.", __FILE__, __LINE__);
            return 0;
        }

        // create a context export interface
        IPhyContextExport *pContextExport;
        pContextExport = (IPhyContextExport *)pPhysiqueExport->GetContextInterface(m_pINode);
        if(pContextExport == 0)
        {
            m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
            delete pVertexCandidate;
            theExporter.SetLastError("Context export interface not found.", __FILE__, __LINE__);
            return 0;
        }

        // set the flags in the context export interface
        pContextExport->ConvertToRigid(TRUE);
        pContextExport->AllowBlending(TRUE);

        // get the vertex export interface
        IPhyVertexExport *pVertexExport;
        pVertexExport = (IPhyVertexExport *)pContextExport->GetVertexInterface(vertexId);
        if(pVertexExport == 0)
        {
            pPhysiqueExport->ReleaseContextInterface(pContextExport);
            m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
            delete pVertexCandidate;
            theExporter.SetLastError("Vertex export interface not found.", __FILE__, __LINE__);
            return 0;
        }

        // get the vertex type
        int vertexType;
        vertexType = pVertexExport->GetVertexType();

        // handle the specific vertex type
        if(vertexType == RIGID_TYPE)
        {
            // typecast to rigid vertex
            IPhyRigidVertex *pTypeVertex;
            pTypeVertex = (IPhyRigidVertex *)pVertexExport;

                // add the influence to the vertex candidate
            // get the influencing bone
            if(!AddBoneInfluence(pSkeletonCandidate, pVertexCandidate, pTypeVertex->GetNode(), 1.0f))
            {
                pPhysiqueExport->ReleaseContextInterface(pContextExport);
                m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
                delete pVertexCandidate;
                theExporter.SetLastError("Invalid bone assignment.", __FILE__, __LINE__);
                return 0;
            }
        }
        else if(vertexType == RIGID_BLENDED_TYPE)
        {
            // typecast to blended vertex
            IPhyBlendedRigidVertex *pTypeVertex;
            pTypeVertex = (IPhyBlendedRigidVertex *)pVertexExport;

            // loop through all influencing bones
            int nodeId;
            for(nodeId = 0; nodeId < pTypeVertex->GetNumberNodes(); nodeId++)
            {
                // add the influence to the vertex candidate
                if(!AddBoneInfluence(pSkeletonCandidate, pVertexCandidate, pTypeVertex->GetNode(nodeId), pTypeVertex->GetWeight(nodeId)))
                {
                    pPhysiqueExport->ReleaseContextInterface(pContextExport);
                    m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
                    delete pVertexCandidate;
                    theExporter.SetLastError("Invalid bone assignment.", __FILE__, __LINE__);
                    return 0;
                }
            }
        }

        // release all interfaces
        pPhysiqueExport->ReleaseContextInterface(pContextExport);
        m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
    }
#if MAX_RELEASE >= 4000
    // check for skin modifier
    else if(m_modifierType == MODIFIER_SKIN)
    {
        // create a skin interface
        ISkin *pSkin;
        pSkin = (ISkin*)m_pModifier->GetInterface(I_SKIN);
        if(pSkin == 0)
        {
            delete pVertexCandidate;
            theExporter.SetLastError("Skin modifier interface not found.", __FILE__, __LINE__);
            return 0;
        }

        // create a skin context data interface
        ISkinContextData *pSkinContextData;
        pSkinContextData = (ISkinContextData *)pSkin->GetContextInterface(m_pINode);
        if(pSkinContextData == 0)
        {
            m_pModifier->ReleaseInterface(I_SKIN, pSkin);
            delete pVertexCandidate;
            theExporter.SetLastError("Skin context data interface not found.", __FILE__, __LINE__);
            return 0;
        }

        // loop through all influencing bones
        int nodeId;
        for(nodeId = 0; nodeId < pSkinContextData->GetNumAssignedBones(vertexId); nodeId++)
        {
            // get the bone id
            int boneId;
            boneId = pSkinContextData->GetAssignedBone(vertexId, nodeId);
            if(boneId < 0) continue;

            // add the influence to the vertex candidate
            if(!AddBoneInfluence(pSkeletonCandidate, pVertexCandidate, pSkin->GetBone(boneId), pSkinContextData->GetBoneWeight(vertexId, nodeId)))
            {
                m_pModifier->ReleaseInterface(I_SKIN, pSkin);
                delete pVertexCandidate;
                theExporter.SetLastError("Invalid bone assignment.", __FILE__, __LINE__);
                return 0;
            }
        }

        // release all interfaces
        m_pModifier->ReleaseInterface(I_SKIN, pSkin);
    }
#endif
        else if( m_modifierType == MODIFIER_MORPHER || m_modifierType == MODIFIER_NONE ) {
        }
        else 
    {
          theExporter.SetLastError("No physique/skin/morpher modifier found.", __FILE__, __LINE__);
          return 0;
    }

    return pVertexCandidate;
}
Beispiel #4
0
void CSMFRenderer::DrawSquare(RSquare& q, const vec3f& v, const CReadMap* rm, const float* hm) {
	const float d = v.flen2D() - 0.01f;
	const int xshift = GetXLOD(d, viewRadius, squareSizeX, lodDists);
	const int zshift = GetZLOD(d, viewRadius, squareSizeZ, lodDists);
	const int xlod = (1 << xshift);
	const int zlod = (1 << zshift);

	const int xverts = (squareSizeX / xlod) + 1;		// #vertices in the x-direction for this square
	const int zverts = (squareSizeZ / zlod) + 1;		// #vertices in the z-direction for this square
	const int numQuads = (xverts - 1) * (zverts - 1);	// #quads needed to cover square at wanted LOD
	const bool wantList = (xlod == 1 && zlod == 1);		// highest-LOD squares are rendered from dlists

	int vertex = 0;
	int offset = 0;


	const float r = 1.0f - (xshift * 0.1667f), g = 0.333f, b = (zshift * 0.1667f);
	glColor3f(r, g, b);


	if (q.hasDisLst && wantList) {
		// note: for deformable terrain, the list
		// would possibly need to be invalidated
		glCallList(q.disLstID);
	} else {
		if (!q.hasDisLst && wantList) {
			q.disLstID = glGenLists(1);
			glNewList(q.disLstID, GL_COMPILE);
		}

		va.Initialize();
		va.EnlargeArrays(numQuads * 4, 0, VA_SIZE_N);

		// note: LESS OR EQUAL, so that when {x, z}lod == squareSize{X, Z}
		// four vertices (two in each direction) are added instead of one
		for (int x = 0; x <= squareSizeX; x += xlod) {
			for (int z = 0; z <= squareSizeZ; z += zlod) {
				vec3f tl(q.tlp.x + x, 0.0f, q.tlp.z + z); tl.y = GetHeight(hm, tl.x, tl.z);
				vec3f nv = GetVertexNormal(hm, q, tl, rm->maxxpos, rm->maxzpos, x, xlod, z, zlod);

				va.AddVertexN(tl, nv);

				// the bottom- and right-most row and column
				// of vertices do not define any new quads
				// if ((x < squareSizeX && z < squareSizeZ)) {
				if (!(x & squareSizeX) && !(z & squareSizeZ)) {
					indices[offset++] = vertex + 0;          // tl
					indices[offset++] = vertex + zverts;     // tr
					indices[offset++] = vertex + zverts + 1; // br
					indices[offset++] = vertex + 1;          // bl
				}

				vertex++;
			}
		}

		/// FIXME: add indexed drawing to VA class
		/// va.Draw(numQuads, indices);
		va.DrawArrayN(GL_QUADS);

		if (!q.hasDisLst && wantList) {
			q.hasDisLst = true;
			glEndList();
		}
	}

	glColor3f(1.0f, 1.0f, 1.0f);
}
//----------------------------------------------------------------------------
void SceneBuilder::SplitGeometry(Mesh *maxMesh, int mtlIndex, 
								 std::vector<UniMaterialMesh*> &uMeshes)
{
	// 如果这个Mesh有多个material并且使用两个或者多个material。这个网格需要
	// 被拆分,因为Phoenix2是一个物体只对应一个material。
	//
	// maxMesh:
	//		要分割的Max网格。
	// mtlIndex:
	//		材质ID
	// uMeshes:
	//		UniMaterialMesh集合,Max的mesh被拆分后放里面。

	int i, j;
	PX2::Float3 *normalsAll = 0;
	if (mSettings->IncludeNormals)
	{
		maxMesh->buildNormals();
		normalsAll = new1<PX2::Float3>(maxMesh->numVerts);
		for (i=0; i<maxMesh->numFaces; i++)
		{
			Face &face = maxMesh->faces[i];
			for (j=0; j<3; j++)
			{
				int vertexIndex = face.getVert(j);
				normalsAll[vertexIndex] = GetVertexNormal(maxMesh, i, vertexIndex);
			}
		}
	}

	// 没有材质
	if (mtlIndex < 0)
	{
		UniMaterialMesh *triMesh = new0 UniMaterialMesh;
		triMesh->SetMaterialInstance(PX2::VertexColor4Material::CreateUniqueInstance());

		std::vector<int> faceIndexs;
		int faceIndex = -1;
		for (faceIndex=0; faceIndex<maxMesh->numFaces; faceIndex++)
		{
			faceIndexs.push_back(faceIndex);
		}

		PackVertices(triMesh, maxMesh, faceIndexs, normalsAll);

		if (mSettings->IncludeVertexColors && maxMesh->numCVerts>0)
		{
			PackColors(triMesh, maxMesh, faceIndexs);
		}

		if (mSettings->IncludeTargentBiNormal && maxMesh->numTVerts>0)
		{
			triMesh->SetExportTargentBinormal(true);
		}
		else
		{
			triMesh->SetExportTargentBinormal(false);
		}

		if (mSettings->IncludeTexCoords && maxMesh->numTVerts>0)
		{
			triMesh->SetNumTexcoordToExport(mSettings->NumTexCoords);
			PackTextureCoords(triMesh, maxMesh, faceIndexs);
		}

		uMeshes.push_back(triMesh);

		triMesh->DuplicateGeometry();
	}
	else
	{
		// 获得Mtl的子材质数量
		MtlTree &tree = mMtlTreeList[mtlIndex];
		int subQuantity = 0; // 子材质数量
		if (mtlIndex >= 0)
		{
			subQuantity = tree.GetMChildQuantity();
		}

		// 计算几何图形所使用的最大附加材质索引
		int faceIndex, subID, maxSubID = -1;
		for (faceIndex=0; faceIndex<maxMesh->numFaces; faceIndex++)
		{
			subID = maxMesh->faces[faceIndex].getMatID();
			if (subID >= subQuantity)
			{
				if (subQuantity > 0)
				{
					subID = subID % subQuantity;
				}
				else
				{
					subID = 0;
				}
			}

			if (subID > maxSubID)
			{
				maxSubID = subID;
			}
		}

		if (-1 != maxSubID)
		{
			// 根据material ID,将每个三角形面分类
			std::vector<int> *faceIndexPartByMtl = new1<std::vector<int> >(maxSubID+1);
			for (faceIndex=0; faceIndex<maxMesh->numFaces; faceIndex++)
			{
				subID = maxMesh->faces[faceIndex].getMatID();
				if (subID >= subQuantity)
				{
					if (subQuantity > 0)
					{
						subID = subID % subQuantity;
					}
					else
					{
						subID = 0;
					}
				}
				//  将每个面按照材质分类
				faceIndexPartByMtl[subID].push_back(faceIndex);
			}

			// 对每种材质类型,分配网格
			for (subID=0; subID<=maxSubID; subID++)
			{
				if (faceIndexPartByMtl[subID].size() == 0)
				{
					// 这种材质没有三角形面
					continue;
				}

				// 为每种材质新建一个mesh
				UniMaterialMesh *triMesh = new0 UniMaterialMesh;
				if (mtlIndex >= 0)
				{
					if (subQuantity > 0)
					{
						MtlTree &subtree = tree.GetMChild(subID);
						triMesh->SetShineProperty(subtree.GetShine());
						triMesh->SetMaterialInstance(subtree.GetMaterialInstance());
					}
					else
					{
						triMesh->SetShineProperty(tree.GetShine());
						triMesh->SetMaterialInstance(tree.GetMaterialInstance());
					}
				}

				PackVertices(triMesh, maxMesh, faceIndexPartByMtl[subID], normalsAll);

				if (mSettings->IncludeVertexColors && maxMesh->numCVerts>0)
				{
					PackColors(triMesh, maxMesh, faceIndexPartByMtl[subID]);
				}

				if (mSettings->IncludeTargentBiNormal && maxMesh->numTVerts>0)
				{
					triMesh->SetExportTargentBinormal(true);
				}
				else
				{
					triMesh->SetExportTargentBinormal(false);
				}
				triMesh->SetExportSkin(mSettings->IncludeSkins);

				if (mSettings->IncludeTexCoords && maxMesh->numTVerts>0)
				{
					triMesh->SetNumTexcoordToExport(mSettings->NumTexCoords);
					PackTextureCoords(triMesh, maxMesh, faceIndexPartByMtl[subID]);
				}

				uMeshes.push_back(triMesh);
			}

			delete1(faceIndexPartByMtl);
		}

		for (i=0; i<(int)uMeshes.size(); i++)
		{
			uMeshes[i]->DuplicateGeometry();
		}
	}

	delete1(normalsAll);
}
Beispiel #6
0
/*
int MshExp::ExportMeshTiles(Interface* ip,INode* node,TimeValue t_start,TimeValue t_end,int tiles_count)
{
	// Get animation range
	Interval animRange = ip->GetAnimRange();

	TimeValue curtime;

	curtime = animRange.Start();
}
*/
int MshExp::ExportMesh(const TCHAR *filename,Interface* i,INode* node,TimeValue curtime)
{
	char buf[4096];
	void* cur=buf;
	void* end=buf+sizeof(buf);

	// Verifie les arguments
	if(node==0){
		NP_LOG("ExportMesh: !node");
		return 0;
	}
	
	/*-----------------------------------------------------
		Obtient l'objet Mesh
	-----------------------------------------------------*/

	// Frame a exporter
	if(curtime<0)
		curtime = i->GetTime();
	
	// Obtient la matrice de transformation
	Matrix3 tm = TransformNode(node,curtime,this->exportTransform);

	// Evalue l'objet a partir du noeud
	ObjectState os = node->EvalWorldState(curtime);
	if(!os.obj || os.obj->SuperClassID()!=GEOMOBJECT_CLASS_ID){
		NP_LOG("ExportMesh: !ObjectState");
		return 0;
	}
	Interval objRange = os.obj->ObjectValidity(curtime);

	// convertie l'objet en Tiangles
	BOOL needDel;
	TriObject* tri = GetTriObjectFromNode(node, curtime, needDel);
	if (!tri) {
		NP_LOG("ExportMesh: !TriObject");
		return 0;
	}
	// obtient le maillage
	Mesh* mesh = &tri->GetMesh();

	// obtient le nombre de points
	uint npoint=(uint)mesh->getNumVerts();

	// construit les normals
	mesh->buildNormals();

	// obtient le nombre de faces
	uint nfaces=(uint)mesh->getNumFaces();
	
	//Supprime l'objet TriObject, si necessaire
	if(needDel) {
		delete tri;
	}

	/*-----------------------------------------------------
		Exporte les triangles
	-----------------------------------------------------*/
	
	//Obtient la matrice de transformation
	tm = TransformNode(node,curtime,this->exportTransform);

	// Evalue l'objet a partir du node
	os = node->EvalWorldState(curtime);
	objRange = os.obj->ObjectValidity(curtime);

	// convertie l'objet en Tiangles
	tri = GetTriObjectFromNode(node, curtime, needDel);
	if (!tri) {
		NP_LOG("ExportMesh: !TriObject");
		return 0;
	}
	// obtient le maillage
	mesh = &tri->GetMesh();
	// construit les normals
	mesh->buildNormals();

	// copie les faces
	for(uint y=0; y<nfaces; y++)
	{
		Face* face;
		uint facenumber=0;//numero de la face dans l'index du maillage 3DS

		//obtient la face en cours
		face = &mesh->faces[y];
		facenumber = y;
		
		//////////////////////////////////////////////
		// Definit les 3 points de la face
		//////////////////////////////////////////////
		for(uint w=0;w<3;w++)
		{
			if((cur = descWriteText(cur,end,"point")==0)
				return 0;

			Point3 pos;
			Point3 nml;
			Point3 clr;
			UVVert tex;
			uint nvertex;

			// obtient le point
			nvertex = face->v[w];
			pos = tm * mesh->verts[nvertex];
			float point[3]={pos.x,pos.y,pos.z};
			if((cur = descWriteStruct(cur,end,Point3_t,sizeof(Point3_t)/sizeof(Point3_t[0]),&point))==0)
				return 0;

			// obtient les normals
			nvertex = face->getVert(w);
			nml = GetVertexNormal(mesh, face, mesh->getRVertPtr(nvertex));
			float normal[3]={nml.x,nml.y,nml.z};
			if((cur = descWriteStruct(cur,end,Normal_t,sizeof(Normal_t)/sizeof(Normal_t[0]),&normal))==0)
				return 0;

			// obtient les coordonnees de texture
			if(mesh->tvFace){
				nvertex = mesh->tvFace[facenumber].t[w];
				tex = mesh->tVerts[nvertex];
				float textureMap[3]={tex.x,tex.y,tex.z};
				if((cur = descWriteStruct(cur,end,TextureMap_t,sizeof(TextureMap_t)/sizeof(TextureMap_t[0]),&textureMap))==0)
					return 0;
			}

			// obtient la couleur
			if(mesh->vcFace){
				nvertex = mesh->vcFace[facenumber].t[w];
				clr = mesh->vertCol[nvertex];
				float color[3]={clr.x,clr.y,clr.z};
				if((cur = descWriteStruct(cur,end,Color_t,sizeof(Color_t)/sizeof(Color_t[0]),&color))==0)
					return 0;
			}
		}
	}

	//Supprime l'objet TriObject, si necessaire
	if(needDel) {
		delete tri;
	}
	
	/* ecrit les donnees de la structure */
	if(!fileWrite(filename,0,buf,(char*)cur))
		return 0;
	
	NP_LOG("done");

	return 1;
}