コード例 #1
0
BOOL CEditableObject::ParseMultiMaterial(MultiMtl* src, u32 mid, CSurface* dest)
{
	R_ASSERT(src);
	R_ASSERT(src->ClassID()==Class_ID(MULTI_CLASS_ID,0));
	Mtl* M = src->GetSubMtl(mid);
	if (M){
		if (M->ClassID()==Class_ID(DMTL_CLASS_ID,0)){
			StdMat *smtl = (StdMat*)src->GetSubMtl(mid);
			if (!ParseStdMaterial(smtl,dest)){
				ELog.Msg(mtError,"'%s' -> bad submaterial",src->GetName());
				return FALSE;
			}
			return TRUE;
		}else if (M->ClassID()==XRAYMTL_CLASS_ID){
			XRayMtl *smtl = (XRayMtl*)src->GetSubMtl(mid);
			if (!ParseXRayMaterial(smtl,mid,dest)){
				ELog.Msg(mtError,"'%s' -> bad submaterial",src->GetName());
				return FALSE;
			}
		} 
		return TRUE;
	}else{
		ELog.Msg(mtError,"'%s' -> can't extract multi-material items.",src->GetName());
		return FALSE;
	}
}
コード例 #2
0
/**
*  @brief
*    Creates a material
*/
PLSceneMaterial *PLSceneMaterial::Create(PLScene &cScene, IGameMaterial *pParentIGameMaterial, IGameMaterial &cIGameMaterial, const String &sName)
{
	// Get the 3ds Max material... I don't use IGame for this because I didn't get it working using it...
	Mtl *pMaxMaterial = cIGameMaterial.GetMaxMaterial();
	if (pMaxMaterial) {
		// DxMaterial or extend?
		IDxMaterial2 *pFXMaterial = static_cast<IDxMaterial2*>(pMaxMaterial->GetInterface(IDXMATERIAL2_INTERFACE));
		if (!pFXMaterial && pParentIGameMaterial)
			pFXMaterial = static_cast<IDxMaterial2*>(pParentIGameMaterial->GetMaxMaterial()->GetInterface(IDXMATERIAL2_INTERFACE));
		if (pFXMaterial) { // Get information from the DirectX Shader material
			// Get effect filename
		#if MAX_RELEASE >= 12000	// For R12 release
			Url cUrl = pFXMaterial->GetEffectFile().GetFullFilePath().data();
		#else
			Url cUrl = pFXMaterial->GetEffectFilename();
		#endif
			String sEffectFilenameName = cUrl.GetFilename();

			// Our effect?
			if (sEffectFilenameName == "PixelLight_SRShaderLighting.fx")
				return new PLSceneMaterialSRShaderLighting(cScene, pParentIGameMaterial, cIGameMaterial, sName);
			else
				return new PLSceneMaterialFX(cScene, pParentIGameMaterial, cIGameMaterial, sName);
		} else {
			// Is this a shell material used for 'backed texture'?
			if (pMaxMaterial->ClassID() == Class_ID(BAKE_SHELL_CLASS_ID, 0))
				return new PLSceneMaterialBakeShell(cScene, pParentIGameMaterial, cIGameMaterial, sName);
			else
				return new PLSceneMaterialStandard(cScene, pParentIGameMaterial, cIGameMaterial, sName);
		}
	}

	// Error!
	return nullptr;
}
コード例 #3
0
bool MaterialUIHandler::SetupMtlSubNameCombo (HWND hWnd, EPolyMod *pMod) {
	INode *singleNode = GetNode(pMod);
	Mtl *nodeMtl = (singleNode) ? singleNode->GetMtl() : NULL;
	// check for scripted material
	if(nodeMtl){
		MSPlugin* plugin = (MSPlugin*)((ReferenceTarget*)nodeMtl)->GetInterface(I_MAXSCRIPTPLUGIN);
		if(plugin)
			nodeMtl = dynamic_cast<Mtl*>( plugin->get_delegate() );
	} 


	if (nodeMtl == NULL || nodeMtl->ClassID() != Class_ID(MULTI_CLASS_ID, 0)) {    //no UI for cloned nodes, and not MultiMtl 
		SendMessage(GetDlgItem(hWnd, IDC_MTLID_NAMES_COMBO), CB_RESETCONTENT, 0, 0);
		EnableWindow(GetDlgItem(hWnd, IDC_MTLID_NAMES_COMBO), false);
		return false;
	}

	NumList mtlIDList;
	NumList mtlIDMeshList;
	GetMtlIDList (nodeMtl, mtlIDList);
	GetMtlIDList (pMod, singleNode, mtlIDMeshList);
	MultiMtl *nodeMulti = (MultiMtl*) nodeMtl;
	EnableWindow(GetDlgItem(hWnd, IDC_MTLID_NAMES_COMBO), true);
	SendMessage(GetDlgItem(hWnd, IDC_MTLID_NAMES_COMBO), CB_RESETCONTENT, 0, 0);

	for (int i=0; i<mtlIDList.Count(); i++){
		TSTR idname, buf;
		if(mtlIDMeshList.Find(mtlIDList[i]) != -1) {
			nodeMulti->GetSubMtlName(mtlIDList[i], idname); 
			if (idname.isNull())
				idname = GetString(IDS_MTL_NONAME);                                 //az: 042503  - FIGS
			buf.printf(_T("%s - ( %d )"), idname.data(), mtlIDList[i]+1);
			int ith = SendMessage(GetDlgItem(hWnd, IDC_MTLID_NAMES_COMBO), CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)buf.data());
			SendMessage(GetDlgItem(hWnd, IDC_MTLID_NAMES_COMBO), CB_SETITEMDATA, ith, (LPARAM)mtlIDList[i]);
		}
	}
	return true;
}
コード例 #4
0
ファイル: G3DMExport.cpp プロジェクト: sundoom/glow
/*
====================
GatherMesh
====================
*/
void G3DMExport::GatherMesh(INode* i_node)
{
	// convert to the triangle type
	Mesh* i_mesh = NULL;
	Object* obj = i_node->EvalWorldState(mTime).obj;
	if(obj && ( obj->SuperClassID() == GEOMOBJECT_CLASS_ID ))
	{
		if(obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) 
		{ 
			TriObject *tri_obj = (TriObject*)obj->ConvertToType(mTime, Class_ID(TRIOBJ_CLASS_ID, 0)); MAX_CHECK(tri_obj);
			i_mesh = &tri_obj->mesh;
		}
	}
	if(i_mesh==NULL||i_mesh->getNumFaces()==0||i_mesh->getNumVerts()==0) return;

	MESH mesh;

	// get the mesh name
	mesh.name = i_node->GetName();

	// get the material
	mesh.texture = "textures/default.tga";
	Mtl* mtl = i_node->GetMtl();
	if(mtl && (mtl->ClassID()==Class_ID(DMTL_CLASS_ID, 0)) && ((StdMat*)mtl)->MapEnabled(ID_DI)) 
	{
		Texmap *texmap = mtl->GetSubTexmap(ID_DI);
		if(texmap && texmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0x00))
		{
			mesh.texture = UnifySlashes(((BitmapTex *)texmap)->GetMapName());
			if( !strstr( mesh.texture.c_str(), mPath.c_str() ) )
			{
				G3DAssert("The material(%s) is error : the texture path(%s) is illegal!",mtl->GetName(), mesh.texture.c_str());
				return;
			}
			else
			{
				mesh.texture = strstr(mesh.texture.c_str(),mPath.c_str()) + strlen(mPath.c_str());
			}
		}
	}

	// if it has uvs
	int map_count = i_mesh->getNumMaps();
	bool has_uvs = i_mesh->getNumTVerts() && i_mesh->tvFace;
	if(!(has_uvs&&map_count)) return;

	// get the transform
	Matrix3 transform = i_node->GetObjectTM(mTime);

	// get the points
	mesh.points.assign(i_mesh->verts, i_mesh->verts+i_mesh->getNumVerts());

	// get the triangles
	for(int i = 0; i < i_mesh->getNumFaces(); i++)
	{
		Face& face = i_mesh->faces[i];

		TRIANGLE tri;		
		tri.smoothing = face.smGroup;
		for(int j = 0; j < 3; j++)
		{
			VTNIS v;
			v.pos = transform * i_mesh->verts[face.v[j]];

			// get the uv
			UVVert * map_verts = i_mesh->mapVerts(1);
			TVFace * map_faces = i_mesh->mapFaces(1);
			v.uv = reinterpret_cast<Point2&>(map_verts[map_faces[i].t[j]]);
			v.uv.y = 1 - v.uv.y;

			// initialize the normal
			v.normal = Point3::Origin;

			// get the vertex index
			v.index = face.v[j];

			// get the smoothing group
			v.smoothing = face.smGroup;			

			// set the index for the triangle
			tri.index0[j] = v.index;

			// reassemble the vertex list
			tri.index1[j] = AddVertex(mesh, v);
		}

		// add the triangle to the table
		mesh.triangles.push_back(tri);
	}

	// build the index map
	for( int i = 0; i < mesh.vertexes.size(); i++ )
	{
		mesh.vertex_index_map[mesh.vertexes[i].index].push_back(i);
	}

	// build the normal space
	BuildNormal(mesh);

	// calculate the bounding box	
	mesh.box.Init();
	for(int i = 0; i < mesh.vertexes.size(); i++)
	{
		mesh.box += mesh.vertexes[i].pos;
	}

	// add the mesh to the table
	mMeshes.push_back(mesh);
}
コード例 #5
0
ファイル: Export.cpp プロジェクト: MagistrAVSH/node3d
void Exporter::DumpMaterial(MaxMaterial *maxm,Mtl* mtl, int mtlID, int subNo, int indentLevel)
{
	int i;
	TimeValue t = GetStaticFrame();
	
	if (!mtl) return;
	
//	for(i=0;i<indentLevel;i++) { log("   "); }
//	log("material %s adding. type : ",mtl->GetName());
	
	// We know the Standard material, so we can get some extra info
	if (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0)) {			// top level & standard material

//		log("standard \n");
		StdMat* std = (StdMat*)mtl;

		MaxStdMaterial *stdm=new MaxStdMaterial;
		strcpy(stdm->name,mtl->GetName());
		stdm->Ambient=rvector(std->GetAmbient(t));
		stdm->Ambient.x=-stdm->Ambient.x;
		stdm->Diffuse=rvector(std->GetDiffuse(t));
		stdm->Diffuse.x=-stdm->Diffuse.x;
		stdm->Specular=rvector(std->GetSpecular(t));
		stdm->Specular.x=-stdm->Specular.x;				// 축의 바뀜때문에 만들어 놓은.. 으흑..
		stdm->TwoSide=std->GetTwoSided();
		if(std->GetTransparencyType()==TRANSP_ADDITIVE)
			stdm->ShadeMode=RSSHADEMODE_ADD;
		else stdm->ShadeMode=RSSHADEMODE_NORMAL;
		
		if(rsm->MaxStdMaterialList.GetByName(stdm->name)==-1)	// 이미 있는 standard material 이면 더하지 않음.
		{
			rsm->MaxStdMaterialList.Add(stdm);
			stdm->RMLIndex=rsm->MaxStdMaterialList.GetCount()-1;
			for (i=0; i<mtl->NumSubTexmaps(); i++) {
				Texmap* subTex = mtl->GetSubTexmap(i);
				float amt = 1.0f;
				if (subTex) {
					// If it is a standard material we can see if the map is enabled.
					if (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0)) {
						if (!((StdMat*)mtl)->MapEnabled(i))
							continue;
						amt = ((StdMat*)mtl)->GetTexmapAmt(i, 0);
						
					}
					DumpTexture(stdm, subTex, mtl->ClassID(), i, amt, indentLevel+1);
				}
			}
		}
		else
		{
			delete stdm;
		}

		maxm->nSubMaterial=1;
		maxm->SubMaterials=new int[1];
		maxm->SubMaterials[0]=rsm->MaxStdMaterialList.GetByName(mtl->GetName());
	}

	if (mtl->NumSubMtls() > 0)  {
//		log("multi/sub ( count : %d )\n",mtl->NumSubMtls());
		maxm->nSubMaterial=mtl->NumSubMtls();
		maxm->SubMaterials=new int[maxm->nSubMaterial];
		maxm->pSubMaterials=new MaxMaterial*[maxm->nSubMaterial];

		for (i=0; i<mtl->NumSubMtls(); i++) {
			Mtl* subMtl = mtl->GetSubMtl(i);
			if (subMtl) {
				maxm->pSubMaterials[i]=new MaxMaterial;
				DumpMaterial(maxm->pSubMaterials[i],subMtl, 0, i, indentLevel+1);
				if(subMtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
				{
					maxm->SubMaterials[i]= rsm->MaxStdMaterialList.GetByName(subMtl->GetName());
				}
				else
					maxm->SubMaterials[i]= maxm->pSubMaterials[i]->SubMaterials[0];
			}
			else
			{
				maxm->pSubMaterials[i]=NULL;
				maxm->SubMaterials[i]=-1;
			}
		}
	}
}
コード例 #6
0
void plCompositeMtl::Shade(ShadeContext& sc) 
{
    // Get the background color
    Color backColor, backTrans;
    //sc.GetBGColor(backColor, backTrans);
    backColor.Black();
    backTrans.White();

    Point3 vtxIllum, vtxAlpha;
    plPassMtl::GetInterpVtxValue(MAP_ALPHA, sc, vtxAlpha);
    plPassMtl::GetInterpVtxValue(MAP_SHADING, sc, vtxIllum);
    int count = NumSubMtls();
    for (int i = 0; i < count; i++)
    {
        if (i > 0 && fPassesPB->GetInt(kCompOn, 0, i - 1) == 0) // Material is unchecked, skip it.
            continue;

        Mtl *mtl = GetSubMtl(i);
        if (mtl == NULL || mtl->ClassID() != PASS_MTL_CLASS_ID)
            continue;

        float opacity;
        if (i == 0)
        {
            opacity = 1.0f;
        }
        else
        {
            int blendMethod = fPassesPB->GetInt(kCompBlend, 0, i - 1);
            switch(blendMethod)
            {
            case kCompBlendVertexAlpha:
            case kCompBlendInverseVtxAlpha:
                opacity = vtxAlpha.x;
                break;
            case kCompBlendVertexIllumRed:
            case kCompBlendInverseVtxIllumRed:
                opacity = vtxIllum.x;
                break;
            case kCompBlendVertexIllumGreen:
            case kCompBlendInverseVtxIllumGreen:
                opacity = vtxIllum.y;
                break;
            case kCompBlendVertexIllumBlue:
            case kCompBlendInverseVtxIllumBlue:
                opacity = vtxIllum.z;
                break;
            default:
                opacity = 1.0f;
                break;
            }
            if (IsInverseBlend(blendMethod))
                opacity = 1 - opacity;
        }

        plPassMtl *passMtl = (plPassMtl*)mtl;
        passMtl->ShadeWithBackground(sc, backColor, false); // Don't include the vtx alpha, that's OUR job
        float currTrans = (1 - (1 - sc.out.t.r) * opacity);
        backTrans *= currTrans;
        backColor = backColor * currTrans + sc.out.c * opacity; 
    }

    sc.out.t = backTrans;
    sc.out.c = backColor;
}
コード例 #7
0
ファイル: smdlexp.cpp プロジェクト: jlecorre/hlinvasion
//=================================================================
// Methods for DumpModelTEP
//
int DumpModelTEP::callback(INode *pnode)
{
	Object*	pobj;
	int	fHasMat = TRUE;

	// clear physique export parameters
	m_mcExport = NULL;
	m_phyExport = NULL;
    m_phyMod = NULL;

	ASSERT_MBOX(!(pnode)->IsRootNode(), "Encountered a root node!");

	if (::FNodeMarkedToSkip(pnode))
		return TREE_CONTINUE;
	
	int iNode = ::GetIndexOfINode(pnode);
	TSTR strNodeName(pnode->GetName());
	
	// The Footsteps node apparently MUST have a dummy mesh attached!  Ignore it explicitly.
	if (FStrEq((char*)strNodeName, "Bip01 Footsteps"))
		return TREE_CONTINUE;

	// Helper nodes don't have meshes
	pobj = pnode->GetObjectRef();
	if (pobj->SuperClassID() == HELPER_CLASS_ID)
		return TREE_CONTINUE;

	// The model's root is a child of the real "scene root"
	INode *pnodeParent = pnode->GetParentNode();
	BOOL fNodeIsRoot = pnodeParent->IsRootNode( );

	// Get node's material: should be a multi/sub (if it has a material at all)
	Mtl *pmtlNode = pnode->GetMtl();
	if (pmtlNode == NULL)
	{
		return TREE_CONTINUE;
		fHasMat = FALSE;
	}
	else if (!(pmtlNode->ClassID() == Class_ID(MULTI_CLASS_ID, 0) && pmtlNode->IsMultiMtl()))
	{
		// sprintf(st_szDBG, "ERROR--Material on node %s isn't a Multi/Sub-Object", (char*)strNodeName);
		// ASSERT_AND_ABORT(FALSE, st_szDBG);
		fHasMat = FALSE;
	}
	
	// Get Node's object, convert to a triangle-mesh object, so I can access the Faces
	ObjectState os = pnode->EvalWorldState(m_tvToDump);
	pobj = os.obj;
	TriObject *ptriobj;
	BOOL fConvertedToTriObject = 
		pobj->CanConvertToType(triObjectClassID) &&
		(ptriobj = (TriObject*)pobj->ConvertToType(m_tvToDump, triObjectClassID)) != NULL;
	if (!fConvertedToTriObject)
		return TREE_CONTINUE;
	Mesh *pmesh = &ptriobj->mesh;

	// Shouldn't have gotten this far if it's a helper object
	if (pobj->SuperClassID() == HELPER_CLASS_ID)
	{
		sprintf(st_szDBG, "ERROR--Helper node %s has an attached mesh, and it shouldn't.", (char*)strNodeName);
		ASSERT_AND_ABORT(FALSE, st_szDBG);
	}

	// Ensure that the vertex normals are up-to-date
	pmesh->buildNormals();

	// We want the vertex coordinates in World-space, not object-space
	Matrix3 mat3ObjectTM = pnode->GetObjectTM(m_tvToDump);


	// initialize physique export parameters
    m_phyMod = FindPhysiqueModifier(pnode);
    if (m_phyMod)
	{
		// Physique Modifier exists for given Node
	    m_phyExport = (IPhysiqueExport *)m_phyMod->GetInterface(I_PHYINTERFACE);

        if (m_phyExport)
        {
            // create a ModContext Export Interface for the specific node of the Physique Modifier
           m_mcExport = (IPhyContextExport *)m_phyExport->GetContextInterface(pnode);

		   if (m_mcExport)
		   {
		       // convert all vertices to Rigid 
                m_mcExport->ConvertToRigid(TRUE);
		   }
		}
	}

	// Dump the triangle face info
	int cFaces = pmesh->getNumFaces();
	for (int iFace = 0; iFace < cFaces; iFace++)
	{
		Face*	pface		= &pmesh->faces[iFace];
		TVFace*	ptvface		= &pmesh->tvFace[iFace];
		DWORD	smGroupFace	= pface->getSmGroup();

		// Get face's 3 indexes into the Mesh's vertex array(s).
		DWORD iVertex0 = pface->getVert(0);
		DWORD iVertex1 = pface->getVert(1);
		DWORD iVertex2 = pface->getVert(2);
		ASSERT_AND_ABORT((int)iVertex0 < pmesh->getNumVerts(), "Bogus Vertex 0 index");
		ASSERT_AND_ABORT((int)iVertex1 < pmesh->getNumVerts(), "Bogus Vertex 1 index");
		ASSERT_AND_ABORT((int)iVertex2 < pmesh->getNumVerts(), "Bogus Vertex 2 index");
		
		// Get the 3 Vertex's for this face
		Point3 pt3Vertex0 = pmesh->getVert(iVertex0);
		Point3 pt3Vertex1 = pmesh->getVert(iVertex1);
		Point3 pt3Vertex2 = pmesh->getVert(iVertex2);

		// Get the 3 RVertex's for this face
		// NOTE: I'm using getRVertPtr instead of getRVert to work around a 3DSMax bug
		RVertex *prvertex0 = pmesh->getRVertPtr(iVertex0);
		RVertex *prvertex1 = pmesh->getRVertPtr(iVertex1);
		RVertex *prvertex2 = pmesh->getRVertPtr(iVertex2);
		
		// Find appropriate normals for each RVertex
		// A vertex can be part of multiple faces, so the "smoothing group"
		// is used to locate the normal for this face's use of the vertex.
		Point3 pt3Vertex0Normal;
		Point3 pt3Vertex1Normal;
		Point3 pt3Vertex2Normal;
		if (smGroupFace) 
		{
			pt3Vertex0Normal = Pt3GetRVertexNormal(prvertex0, smGroupFace);
			pt3Vertex1Normal = Pt3GetRVertexNormal(prvertex1, smGroupFace);
			pt3Vertex2Normal = Pt3GetRVertexNormal(prvertex2, smGroupFace);
		}
		else 
		{
			pt3Vertex0Normal = pmesh->getFaceNormal( iFace );
			pt3Vertex1Normal = pmesh->getFaceNormal( iFace );
			pt3Vertex2Normal = pmesh->getFaceNormal( iFace );
		}
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus orig normal 0" );
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus orig normal 1" );
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus orig normal 2" );
	
		// Get Face's sub-material from node's material, to get the bitmap name.
		// And no, there isn't a simpler way to get the bitmap name, you have to
		// dig down through all these levels.
		TCHAR szBitmapName[256] = "null.bmp";
		if (fHasMat)
		{
			MtlID mtlidFace = pface->getMatID();
			if (mtlidFace >= pmtlNode->NumSubMtls())
			{
				sprintf(st_szDBG, "ERROR--Bogus sub-material index %d in node %s; highest valid index is %d",
					mtlidFace, (char*)strNodeName, pmtlNode->NumSubMtls()-1);
				// ASSERT_AND_ABORT(FALSE, st_szDBG);
				mtlidFace = 0;
			}
			Mtl *pmtlFace = pmtlNode->GetSubMtl(mtlidFace);
			ASSERT_AND_ABORT(pmtlFace != NULL, "NULL Sub-material returned");
 
			if ((pmtlFace->ClassID() == Class_ID(MULTI_CLASS_ID, 0) && pmtlFace->IsMultiMtl()))
			{
				// it's a sub-sub material.  Gads.
				pmtlFace = pmtlFace->GetSubMtl(mtlidFace);			
				ASSERT_AND_ABORT(pmtlFace != NULL, "NULL Sub-material returned");
			}

			if (!(pmtlFace->ClassID() == Class_ID(DMTL_CLASS_ID, 0)))
			{

				sprintf(st_szDBG,
					"ERROR--Sub-material with index %d (used in node %s) isn't a 'default/standard' material [%x].",
					mtlidFace, (char*)strNodeName, pmtlFace->ClassID());
				ASSERT_AND_ABORT(FALSE, st_szDBG);
			}
			StdMat *pstdmtlFace = (StdMat*)pmtlFace;
			Texmap *ptexmap = pstdmtlFace->GetSubTexmap(ID_DI);
			// ASSERT_AND_ABORT(ptexmap != NULL, "NULL diffuse texture")
			if (ptexmap != NULL) 
			{
				if (!(ptexmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)))
				{
					sprintf(st_szDBG,
						"ERROR--Sub-material with index %d (used in node %s) doesn't have a bitmap as its diffuse texture.",
						mtlidFace, (char*)strNodeName);
					ASSERT_AND_ABORT(FALSE, st_szDBG);
				}
				BitmapTex *pbmptex = (BitmapTex*)ptexmap;
				strcpy(szBitmapName, pbmptex->GetMapName());
				TSTR strPath, strFile;
				SplitPathFile(TSTR(szBitmapName), &strPath, &strFile);
				strcpy(szBitmapName,strFile);
			}
		}

		UVVert UVvertex0( 0, 0, 0 );
		UVVert UVvertex1( 1, 0, 0 );
		UVVert UVvertex2( 0, 1, 0 );
		
		// All faces must have textures assigned to them
		if (pface->flags & HAS_TVERTS)
		{
			// Get TVface's 3 indexes into the Mesh's TVertex array(s).
			DWORD iTVertex0 = ptvface->getTVert(0);
			DWORD iTVertex1 = ptvface->getTVert(1);
			DWORD iTVertex2 = ptvface->getTVert(2);
			ASSERT_AND_ABORT((int)iTVertex0 < pmesh->getNumTVerts(), "Bogus TVertex 0 index");
			ASSERT_AND_ABORT((int)iTVertex1 < pmesh->getNumTVerts(), "Bogus TVertex 1 index");
			ASSERT_AND_ABORT((int)iTVertex2 < pmesh->getNumTVerts(), "Bogus TVertex 2 index");

			// Get the 3 TVertex's for this TVFace
			// NOTE: I'm using getRVertPtr instead of getRVert to work around a 3DSMax bug
			UVvertex0 = pmesh->getTVert(iTVertex0);
			UVvertex1 = pmesh->getTVert(iTVertex1);
			UVvertex2 = pmesh->getTVert(iTVertex2);
		}
		else 
		{
			//sprintf(st_szDBG, "ERROR--Node %s has a textureless face.  All faces must have an applied texture.", (char*)strNodeName);
			//ASSERT_AND_ABORT(FALSE, st_szDBG);
		}
		
		/*
		const char *szExpectedExtension = ".bmp";
		if (stricmp(szBitmapName+strlen(szBitmapName)-strlen(szExpectedExtension), szExpectedExtension) != 0)
			{
			sprintf(st_szDBG, "Node %s uses %s, which is not a %s file", (char*)strNodeName, szBitmapName, szExpectedExtension);
			ASSERT_AND_ABORT(FALSE, st_szDBG);
			}
		*/

		// Determine owning bones for the vertices.
		int iNodeV0, iNodeV1, iNodeV2;
		if (m_mcExport)
		{
			// The Physique add-in allows vertices to be assigned to bones arbitrarily
			iNodeV0 = InodeOfPhyVectex( iVertex0 );
			iNodeV1 = InodeOfPhyVectex( iVertex1 );
			iNodeV2 = InodeOfPhyVectex( iVertex2 );
		}
		else
		{
			// Simple 3dsMax model: the vertices are owned by the object, and hence the node
			iNodeV0 = iNode;
			iNodeV1 = iNode;
			iNodeV2 = iNode;
		}
		
		// Rotate the face vertices out of object-space, and into world-space space
		Point3 v0 = pt3Vertex0 * mat3ObjectTM;
		Point3 v1 = pt3Vertex1 * mat3ObjectTM;
		Point3 v2 = pt3Vertex2 * mat3ObjectTM;


		Matrix3 mat3ObjectNTM = mat3ObjectTM;
		mat3ObjectNTM.NoScale( );
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus pre normal 0" );
		pt3Vertex0Normal = VectorTransform(mat3ObjectNTM, pt3Vertex0Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus post normal 0" );
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus pre normal 1" );
		pt3Vertex1Normal = VectorTransform(mat3ObjectNTM, pt3Vertex1Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus post normal 1" );
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus pre normal 2" );
		pt3Vertex2Normal = VectorTransform(mat3ObjectNTM, pt3Vertex2Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus post normal 2" );

		// Finally dump the bitmap name and 3 lines of face info
		fprintf(m_pfile, "%s\n", szBitmapName);
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n",
				iNodeV0, v0.x, v0.y, v0.z,
				pt3Vertex0Normal.x, pt3Vertex0Normal.y, pt3Vertex0Normal.z,
				UVvertex0.x, UVvertex0.y);
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n",
				iNodeV1, v1.x, v1.y, v1.z,
				pt3Vertex1Normal.x, pt3Vertex1Normal.y, pt3Vertex1Normal.z,
				UVvertex1.x, UVvertex1.y);
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n",
				iNodeV2, v2.x, v2.y, v2.z,
				pt3Vertex2Normal.x, pt3Vertex2Normal.y, pt3Vertex2Normal.z,
				UVvertex2.x, UVvertex2.y);
	}

	cleanup( );	
	return TREE_CONTINUE;
}
コード例 #8
0
ファイル: evalcol.cpp プロジェクト: artemeliy/inf4715
//***************************************************************************
// Calculate ambient or diffuse color at each vertex.
// Pass in TRUE as the "diffuse" parameter to calculate the diffuse color.
// If FALSE is passed in, ambient color is calculated.
//***************************************************************************
BOOL calcMixedVertexColors(INode* node, TimeValue t, int lightModel, ColorTab& vxColTab, EvalColProgressCallback* fn)
{
	ObjectState ostate;
	BOOL deleteTri;
	Mesh* mesh;
	SContext sc;
	DefaultLight dl1, dl2;
	MtlBaseLib mtls;
	Matrix3 tm;

	sc.SetNodeAndTime(node, t);
	tm = sc.tmAfterWSM;

	TriObject* tri = GetTriObjectFromNode(node, t, deleteTri);

	// We will only work on GeomObjects
	if (!tri) {
		return FALSE;
	}

	// Get the mesh from the object
	mesh = &tri->GetMesh();
	if (!mesh) {
		return FALSE;
	}

	// If the node doesn't have a material attached,
	// we create a dummy material.
	Mtl* mtl = node->GetMtl();
	if (!mtl) {
		mtl = new DumMtl(Color(node->GetWireColor()));
	}

	mesh->buildRenderNormals();

	vxColTab.ZeroCount();
	vxColTab.Shrink();

	sc.SetMesh(mesh);
	sc.CalcBoundObj();

	// Add the material to the list
	mtls.AddMtl(mtl);

	// Setup ambient light
	if (lightModel == LIGHT_AMBIENT) {
		sc.SetAmbientLight(Color(1.0f, 1.0f, 1.0f));
	}
	else {
		sc.SetAmbientLight(Color(0.0f, 0.0f, 0.0f));
	}

	// If we're using the real lights, we need to find them first
	if (lightModel == LIGHT_SCENELIGHT) {
		AddSceneLights(&sc, &mtls);

		// Add default lights if there are no lights in the scene
		if (sc.lightTab.Count() == 0) {
			dl1.ls.intens = 1.0f;
			dl1.ls.color = Color(0.8f, 0.8f, 0.8f);
			dl1.ls.type = OMNI_LGT;
			dl1.tm = TransMatrix(1000.0f * Point3(-900.0f, -1000.0f, 1500.0f));

			dl2.ls.intens = 1.0f;
			dl2.ls.color = Color(0.8f, 0.8f, 0.8f);
			dl2.ls.type = OMNI_LGT;
			dl2.tm = TransMatrix(-1000.0f * Point3(-900.0f, -1000.0f, 1500.0f));

			sc.AddLight(new LightInfo(&dl1));
			sc.AddLight(new LightInfo(&dl2));
		}

		sc.SetAmbientLight(GetCOREInterface()->GetAmbient(t, FOREVER));
	}

	sc.UpdateLights();
	// Update material
	mtl->Update(t, FOREVER);
	
	int numVerts = mesh->numVerts;
	for (unsigned int v = 0; v < (unsigned)numVerts; v++) {

		if (fn) {
			if (fn->progress(float(v)/float(numVerts))) {
				if (deleteTri) {
					delete tri;
				}

				mtls.Empty();

				if (mtl->ClassID() == DUMMTL_CLASS_ID) {
					delete mtl;
				}

				// What to return here is up for discussion.
				// 1) We are aborting so FALSE might be in order.
				// 2) We have calculated some colors. Let's use what we've got so far.
				return TRUE;
			}
		}

		// Create a new entry
		Color* vxCol = new Color;
		Point3 tmpCol(0.0f, 0.0f, 0.0f);

		int numShades = 0;
		BitArray faceList;
		faceList.SetSize(mesh->numFaces, 0);

		// Get vertex normal
		// We also pass in a BitArray that will be filled in with
		// to inform us to which faces this vertex belongs.
		// We could do this manually, but we need to do it to get
		// the vertex normal anyway so this is done to speed things
		// up a bit.
		Point3 vxNormal = interpVertexNormal(mesh, tm, v, faceList);
		Point3 viewDir = -vxNormal;
		Point3 viewPoint = tm*mesh->verts[v] + 5.0f*vxNormal;
		Point3 lightPos = viewPoint;
		Point3 viewTarget = tm*mesh->verts[v];

		// We now have a viewpoint and a view target.
		// Now we just have to shade this point on the mesh in order
		// to get it's color.
		// Note: 
		// Since materials are assigned on Face basis we need to render each
		// vertex as many times as it has connecting faces.
		// the colors collected are mixed to get the resulting
		// color at each vertex.
		
		for (int nf = 0; nf < faceList.GetSize(); nf++) {
			if (faceList[nf]) {
				// render vertex for this face.
				sc.SetViewPoint(viewPoint);
				sc.SetTargetPoint(viewTarget);
				sc.SetViewDir(viewDir);
				sc.SetFaceNum(nf);
				Face* f = &mesh->faces[nf];
				sc.SetMtlNum(f->getMatID());
				sc.CalcNormals();

				// Setup the barycentric coordinate
				if (mesh->faces[nf].v[0] == v)
					sc.SetBaryCoord(Point3(1.0f, 0.0f, 0.0f));
				else if (mesh->faces[nf].v[1] == v)
					sc.SetBaryCoord(Point3(0.0f, 1.0f, 0.0f));
				else if (mesh->faces[nf].v[2] == v)
					sc.SetBaryCoord(Point3(0.0f, 0.0f, 1.0f));

				// Use diffuse color instead of ambient
				// The only difference is that we create a special light
				// located at the viewpoint and we set the ambient light to black.
				if (lightModel == LIGHT_DIFFUSE) {
					dl1.ls.intens = 1.0f;
					dl1.ls.color = Color(0.8f, 0.8f, 0.8f);
					dl1.ls.type = OMNI_LGT;
					dl1.tm = TransMatrix(lightPos);

					sc.ClearLights();
					sc.AddLight(new LightInfo(&dl1));
					sc.UpdateLights();
				}


				// Shade the vertex
				mtl->Shade(sc);

				tmpCol.x += sc.out.c.r;
				tmpCol.y += sc.out.c.g;
				tmpCol.z += sc.out.c.b;
				numShades++;
			}
		}

		// The color mixes. We just add the colors together and 
		// then divide with as many colors as we added.
		if (numShades > 0) {
			tmpCol = tmpCol / (float)numShades;
		}

		
		vxCol->r = tmpCol.x;
		vxCol->g = tmpCol.y;
		vxCol->b = tmpCol.z;

		
		vxCol->ClampMinMax();

		
		// Append the Color to the table. If the array needs
		// to be realloc'ed, allocate extra space for 100 points.
		vxColTab.Append(1, &vxCol, 100);
	}

	// Some objects gives us a temporary mesh that we need to delete afterwards.
	if (deleteTri) {
		delete tri;
	}


	mtls.Empty();

	if (mtl->ClassID() == DUMMTL_CLASS_ID) {
		delete mtl;
	}

	return TRUE;
}
コード例 #9
0
// --[  Method  ]---------------------------------------------------------------
//
//  - Class     : CStravaganzaMaxTools
//
//  - prototype : bool BuildShaders()
//
//  - Purpose   : Builds the shader list from MAX's materials.
//                Preview mode requires texture files to be stored with full
//                path in order to load them. When we export, we only store the
//                filename. Another thing is that in the export mode, we copy
//                all textures into the path specified by the user if that
//                option is checked.
//
// -----------------------------------------------------------------------------
bool CStravaganzaMaxTools::BuildShaders()
{
	std::vector<Mtl*>::iterator it;

	assert(m_vecShaders.empty());

	if(!m_bPreview && m_bCopyTextures && m_strTexturePath == "")
	{
		CLogger::NotifyWindow("Textures won't be copied\nSpecify a valid output texture path first");
	}

	LOG.Write("\n\n-Building shaders: ");

	for(it = m_vecMaterials.begin(); it != m_vecMaterials.end(); ++it)
	{
		Mtl* pMaxMaterial = *it;
		assert(pMaxMaterial);

		LOG.Write("\n    %s", pMaxMaterial->GetName().data());
		CShaderStandard* pShaderStd = new CShaderStandard;
		pShaderStd->SetName(pMaxMaterial->GetName().data());

		// Properties

		StdMat2 *pMaxStandardMtl = NULL;
		StdMat2 *pMaxBakedMtl    = NULL;

		float fAlpha;

		if(pMaxMaterial->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
		{
			pMaxStandardMtl = (StdMat2 *)pMaxMaterial;
		}
		else if(pMaxMaterial->ClassID() == Class_ID(BAKE_SHELL_CLASS_ID, 0))
		{
			pMaxStandardMtl = (StdMat2 *)pMaxMaterial->GetSubMtl(0);
			pMaxBakedMtl    = (StdMat2 *)pMaxMaterial->GetSubMtl(1);
		}

		if(pMaxStandardMtl)
		{
			// Standard material

			fAlpha = pMaxStandardMtl->GetOpacity(0);

			Shader* pMaxShader = pMaxStandardMtl->GetShader();

			CVector4 v4Specular = ColorToVector4(pMaxStandardMtl->GetSpecular(0), 0.0f) * pMaxShader->GetSpecularLevel(0, 0);

			pShaderStd->SetAmbient  (ColorToVector4(pMaxStandardMtl->GetAmbient(0),  0.0f));
			pShaderStd->SetDiffuse  (ColorToVector4(pMaxStandardMtl->GetDiffuse(0),  fAlpha));
			pShaderStd->SetSpecular (v4Specular);
			pShaderStd->SetShininess(pMaxShader->GetGlossiness(0, 0) * 128.0f);

			if(pMaxStandardMtl->GetTwoSided() == TRUE)
			{
				pShaderStd->SetTwoSided(true);
			}

			// Need to cast to StdMat2 in order to get access to IsFaceted().
			// ¿Is StdMat2 always the interface for standard materials?
			if(((StdMat2*)pMaxStandardMtl)->IsFaceted())
			{
				pShaderStd->SetFaceted(true);
			}

			if(pMaxStandardMtl->GetWire() == TRUE)
			{
				pShaderStd->SetPostWire(true);
				pShaderStd->SetWireLineThickness(pMaxStandardMtl->GetWireSize(0));
			}
		}
		else
		{
			// Material != Standard

			fAlpha = 1.0f; // pMaxMaterial->GetXParency();

			pShaderStd->SetAmbient  (ColorToVector4(pMaxMaterial->GetAmbient(),  0.0f));
			pShaderStd->SetDiffuse  (ColorToVector4(pMaxMaterial->GetDiffuse(),  fAlpha));
			pShaderStd->SetSpecular (CVector4(0.0f, 0.0f, 0.0f, 0.0f));
			pShaderStd->SetShininess(0.0f);
		}

		// Layers

		if(!pMaxStandardMtl)
		{
			m_vecShaders.push_back(pShaderStd);
			continue;
		}

		bool bDiffuseMap32Bits = false;
		StdMat2 *pStandardMtl;

		for(int i = 0; i < 3; i++)
		{
			int nMap;

			pStandardMtl = pMaxStandardMtl;

			// 0 = diffuse, 1 == bump, 2 = lightmap (self illumination slot) or envmap (reflection slot)

			if(i == 0)
			{
				nMap = ID_DI;
			}
			else if(i == 1)
			{
				nMap = ID_BU;

				// If its a baked material, get the bump map from there

				if(pMaxBakedMtl)
				{
					pStandardMtl = pMaxBakedMtl;
				}
			}
			else if(i == 2)
			{
				bool bBaked = false;

				// If its a baked material, get the map2 (lightmap) from there

				if(pMaxBakedMtl)
				{
					if(pMaxBakedMtl->GetMapState(ID_SI) == MAXMAPSTATE_ENABLED)
					{
						bBaked       = true;
						nMap         = ID_SI;
						pStandardMtl = pMaxBakedMtl;
					}
				}

				if(!bBaked)
				{
					if(pStandardMtl->GetMapState(ID_SI) == MAXMAPSTATE_ENABLED)
					{
						nMap = ID_SI;
					}
					else
					{
						nMap = ID_RL;
					}
				}
			}

			// Check validity

			if(pStandardMtl->GetMapState(nMap) != MAXMAPSTATE_ENABLED)
			{
				if(i == 0)
				{
					LOG.Write("\n        No diffuse. Skipping.");
					break;
				}

				continue;
			}

			Texmap* pMaxTexmap = pStandardMtl->GetSubTexmap(nMap);

			if(!pMaxTexmap)
			{
				if(i == 0)
				{
					LOG.Write("\n        No diffuse. Skipping.");
					break;
				}

				continue;
			}

			// Get texmaps

			std::vector<std::string> vecTextures, vecPaths;

			CShaderStandard::SLayerInfo  layerInfo;
			CShaderStandard::SBitmapInfo bitmapInfo;

			if(pMaxTexmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0))
			{
				BitmapTex* pMaxBitmapTex = (BitmapTex*)pMaxTexmap;
				Bitmap*    pMaxBitmap    = pMaxBitmapTex->GetBitmap(SECONDS_TO_TICKS(m_fStartTime));
				StdUVGen*  pMaxUVGen     = pMaxBitmapTex->GetUVGen();

				if(!pMaxBitmap)
				{
					if(i == 0)
					{
						LOG.Write("\n        Invalid diffuse. Skipping.");
						break;
					}
					continue;
				}

				assert(pMaxUVGen);

				BitmapInfo bi = pMaxBitmap->Storage()->bi;

				// bi.Name() returns the full path
				// bi.Filename() returns just the filename

				vecTextures.push_back(bi.Filename());
				vecPaths.   push_back(bi.Name());

				LOG.Write("\n        Bitmap %s", vecTextures[0].data());

				// Check if diffuse texture has alpha channel

				if(i == 0)
				{
					CBitmap    bitmap;
					CInputFile bitmapFile;

					if(!bitmapFile.Open(bi.Name(), false))
					{
						CLogger::NotifyWindow("WARNING - CStravaganzaMaxTools::BuildShaders():\nUnable to load file %s", bi.Name());
					}
					else
					{
						if(!bitmap.Load(&bitmapFile, GetFileExt(bi.Name())))
						{
							CLogger::NotifyWindow("WARNING - CStravaganzaMaxTools::BuildShaders():\nUnable to load bitmap %s", bi.Name());
						}
						else
						{
							if(bitmap.GetBpp() == 32)
							{
								bDiffuseMap32Bits = true;
								LOG.Write(" (with alpha channel)");
							}
							bitmap.Free();
						}
						bitmapFile.Close();
					}
				}

				// Ok, copy properties

				layerInfo.texInfo.bLoop        = false;
				layerInfo.texInfo.eTextureType = UtilGL::Texturing::CTexture::TEXTURE2D;

				bitmapInfo.strFile         = m_bPreview ? bi.Name() : bi.Filename();
				bitmapInfo.bTile           = ((pMaxUVGen->GetTextureTiling() & (U_WRAP | V_WRAP)) == (U_WRAP | V_WRAP)) ? true : false;
				bitmapInfo.fSeconds        = 0.0f;
				bitmapInfo.bForceFiltering = false;
				bitmapInfo.eFilter         = UtilGL::Texturing::FILTER_TRILINEAR; // won't be used (forcefiltering = false)
				
				layerInfo.texInfo.m_vecBitmaps.push_back(bitmapInfo);

				layerInfo.eTexEnv          = nMap == ID_RL ? CShaderStandard::TEXENV_ADD : CShaderStandard::TEXENV_MODULATE;
				layerInfo.eUVGen           = pMaxUVGen->GetCoordMapping(0) == UVMAP_SPHERE_ENV ? CShaderStandard::UVGEN_ENVMAPPING : CShaderStandard::UVGEN_EXPLICITMAPPING;
				layerInfo.uMapChannel      = pMaxUVGen->GetMapChannel();
				layerInfo.v3ScrollSpeed    = CVector3(0.0f, 0.0f, 0.0f);
				layerInfo.v3RotationSpeed  = CVector3(0.0f, 0.0f, 0.0f);
				layerInfo.v3ScrollOffset   = CVector3(pMaxUVGen->GetUOffs(0), pMaxUVGen->GetVOffs(0), 0.0f);
				layerInfo.v3RotationOffset = CVector3(pMaxUVGen->GetUAng(0),  pMaxUVGen->GetVAng(0),  pMaxUVGen->GetWAng(0));
			}
			else if(pMaxTexmap->ClassID() == Class_ID(ACUBIC_CLASS_ID, 0))
			{
				ACubic*       pMaxCubic  = (ACubic*)pMaxTexmap;
				IParamBlock2* pBlock     = pMaxCubic->pblock;
				Interval      validRange = m_pMaxInterface->GetAnimRange();

				for(int nFace = 0; nFace < 6; nFace++)
				{
					int nMaxFace;

					switch(nFace)
					{
					case 0: nMaxFace = 3; break;
					case 1: nMaxFace = 2; break;
					case 2: nMaxFace = 1; break;
					case 3: nMaxFace = 0; break;
					case 4: nMaxFace = 5; break;
					case 5: nMaxFace = 4; break;
					}

					TCHAR *name;
					pBlock->GetValue(acubic_bitmap_names, TICKS_TO_SECONDS(m_fStartTime), name, validRange, nMaxFace);

					vecPaths.push_back(name);

					CStr path, file, ext;
					SplitFilename(CStr(name), &path, &file, &ext);

					std::string strFile = std::string(file.data()) + ext.data();

					vecTextures.push_back(strFile);

					bitmapInfo.strFile         = m_bPreview ? name : strFile;
					bitmapInfo.bTile           = false;
					bitmapInfo.fSeconds        = 0.0f;
					bitmapInfo.bForceFiltering = false;
					bitmapInfo.eFilter         = UtilGL::Texturing::FILTER_TRILINEAR;
					
					layerInfo.texInfo.m_vecBitmaps.push_back(bitmapInfo);
				}

				layerInfo.texInfo.bLoop        = false;
				layerInfo.texInfo.eTextureType = UtilGL::Texturing::CTexture::TEXTURECUBEMAP;

				layerInfo.eTexEnv          = nMap == ID_RL ? CShaderStandard::TEXENV_ADD : CShaderStandard::TEXENV_MODULATE;
				layerInfo.eUVGen           = CShaderStandard::UVGEN_ENVMAPPING;
				layerInfo.uMapChannel      = 0;
				layerInfo.v3ScrollSpeed    = CVector3(0.0f, 0.0f, 0.0f);
				layerInfo.v3RotationSpeed  = CVector3(0.0f, 0.0f, 0.0f);
				layerInfo.v3ScrollOffset   = CVector3(0.0f, 0.0f, 0.0f);
				layerInfo.v3RotationOffset = CVector3(0.0f, 0.0f, 0.0f);
			}
			else
			{
				if(i == 0)
				{
					LOG.Write("\n        No diffuse. Skipping.");
					break;
				}
				continue;
			}

			if(!m_bPreview && m_bCopyTextures && m_strTexturePath != "")
			{
				for(int nTex = 0; nTex != vecTextures.size(); nTex++)
				{
					// Copy textures into the specified folder

					std::string strDestPath = m_strTexturePath;

					if(strDestPath[strDestPath.length() - 1] != '\\')
					{
						strDestPath.append("\\", 1);
					}

					strDestPath.append(vecTextures[nTex]);

					if(!CopyFile(vecPaths[nTex].data(), strDestPath.data(), FALSE))
					{
						CLogger::NotifyWindow("Unable to copy %s to\n%s", vecPaths[i], strDestPath.data());
					}
				}
			}

			if(layerInfo.eUVGen == CShaderStandard::UVGEN_ENVMAPPING && i == 1)
			{
				CLogger::NotifyWindow("%s : Bump with spheremapping not supported", pShaderStd->GetName().data());
			}
			else
			{
				// Add layer

				switch(i)
				{
				case 0: pShaderStd->SetLayer(CShaderStandard::LAYER_DIFF, layerInfo); break;
				case 1: pShaderStd->SetLayer(CShaderStandard::LAYER_BUMP, layerInfo); break;
				case 2: pShaderStd->SetLayer(CShaderStandard::LAYER_MAP2, layerInfo); break;
				}
			}
		}

		// ¿Do we need blending?

		if(ARE_EQUAL(fAlpha, 1.0f) && !bDiffuseMap32Bits)
		{
			pShaderStd->SetBlendSrcFactor(UtilGL::States::BLEND_ONE);
			pShaderStd->SetBlendDstFactor(UtilGL::States::BLEND_ZERO);
		}
		else
		{
			pShaderStd->SetBlendSrcFactor(UtilGL::States::BLEND_SRCALPHA);
			pShaderStd->SetBlendDstFactor(UtilGL::States::BLEND_INVSRCALPHA);
		}

		// Add shader

		m_vecShaders.push_back(pShaderStd);
	}

	return true;
}
コード例 #10
0
//----------------------------------------------------------------------------
void SceneBuilder::ConvertMaterial (Mtl &mtl, MtlTree &mtlTree)
{
	// 光照属性
	PX2::Shine *shine = new0 PX2::Shine;
	Color color = mtl.GetAmbient();
	float alpha = 1.0f - mtl.GetXParency();
	shine->Ambient = PX2::Float4(color.r, color.g, color.b, 1.0f);
	color = mtl.GetDiffuse();
	shine->Diffuse = PX2::Float4(color.r, color.g, color.b, alpha);
	color = mtl.GetSpecular();
	float shininess = mtl.GetShininess()*2.0f;
	shine->Specular = PX2::Float4(color.r, color.g, color.b, shininess);

	const char *name = (const char*)mtl.GetName();
	shine->SetName(name);

	mtlTree.SetShine(shine);

	bool IsDirect9Shader = false;

	if (mtl.ClassID() == Class_ID(CMTL_CLASS_ID, 0)
		|| mtl.ClassID() == Class_ID(DMTL_CLASS_ID, 0))
	{
		StdMat2 *stdMat2 = (StdMat2*)(&mtl);
		Interval valid = FOREVER;
		stdMat2->Update(mTimeStart, valid);

		std::string strName(stdMat2->GetName());
		bool doubleSide = (stdMat2->GetTwoSided()==1);

		char strBitMapName[256];
		memset(strBitMapName, 0, 256*sizeof(char));
		std::string resourcePath;

		PX2::Shader::SamplerFilter filter = PX2::Shader::SF_LINEAR_LINEAR;
		PX2::Shader::SamplerCoordinate uvCoord = PX2::Shader::SC_REPEAT;
		PX2_UNUSED(uvCoord);

		if (stdMat2->MapEnabled(ID_DI))
		{
			BitmapTex *tex = (BitmapTex*)stdMat2->GetSubTexmap(ID_DI);

			BitmapInfo bI;
			const char *mapName = tex->GetMapName();
			TheManager->GetImageInfo(&bI, mapName);
			strcpy(strBitMapName, bI.Name());

			std::string fullName = std::string(strBitMapName);
			std::string::size_type sizeT = fullName.find_first_not_of(mSettings->SrcRootDir);
			resourcePath = std::string(strBitMapName).substr(sizeT);

			StdUVGen* uvGen = tex->GetUVGen();
			PX2_UNUSED(uvGen);
			int filType = tex->GetFilterType();
			switch (filType)
			{
				case FILTER_PYR:
					filter = PX2::Shader::SF_LINEAR_LINEAR;
					break;
				case FILTER_SAT:
					filter = PX2::Shader::SF_NEAREST;
					break;
				default:
					break;
			}
		}
		else
		{
			sprintf(strBitMapName, "%s/%s", mSettings->SrcRootDir, PX2_DEFAULT_TEXTURE);
			resourcePath = PX2_DEFAULT_TEXTURE;
		}

		PX2::Texture2D *tex2d = PX2::DynamicCast<PX2::Texture2D>(
			PX2::ResourceManager::GetSingleton().BlockLoad(strBitMapName));
		tex2d->SetResourcePath(resourcePath);

		if (tex2d)
		{
			PX2::Texture2DMaterial *tex2dMtl = new0 PX2::Texture2DMaterial(filter, 
				uvCoord, uvCoord);
			if (doubleSide)
			{
				tex2dMtl->GetCullProperty(0, 0)->Enabled = false;
			}

			PX2::MaterialInstance *instance = tex2dMtl->CreateInstance(tex2d);

			mtlTree.SetMaterialInstance(instance);
		}
		else
		{
			PX2::VertexColor4Material *vcMtl = new0 PX2::VertexColor4Material();
			PX2::MaterialInstance *instance = vcMtl->CreateInstance();
			mtlTree.SetMaterialInstance(instance);
		}
	}
	else if (mtl.ClassID() == Class_ID(MULTI_CLASS_ID, 0))
	{
	}
	else if (mtl.ClassID() == DIRECTX_9_SHADER_CLASS_ID)
	{
		IsDirect9Shader = true;

		IDxMaterial* dxMtl = (IDxMaterial*)mtl.GetInterface(IDXMATERIAL_INTERFACE);
		char *effectName = dxMtl->GetEffectFilename();
		IParamBlock2 *paramBlock = mtl.GetParamBlock(0);

		std::string outPath;
		std::string outBaseName;
		std::string outExtention;
		PX2::StringHelp::SplitFullFilename(effectName, outPath, outBaseName,
			outExtention);

		PX2::ShinePtr shineStandard = new0 PX2::Shine();
		bool alphaVertex = false;
		PX2::Texture2DPtr diffTex;
		bool normalEnable = false;
		PX2::Texture2DPtr normalTex;
		float normalScale = 0.0f;
		bool specEnable = false;
		PX2::Texture2DPtr specTex;
		float specPower = 0.0f;
		bool reflectEnable = false;
		PX2::TextureCubePtr reflectTex;
		float reflectPower = 0.0f;
		bool doubleSide = false;
		int blendMode = 2;

		ParamBlockDesc2 *paramDesc = 0;
		int numParam = 0;
		if (paramBlock)
		{
			paramDesc = paramBlock->GetDesc();
			numParam = paramBlock->NumParams();

			ParamType2 paramType;
			for (int i=0; i<numParam; i++)
			{
				std::string parmName;
				PX2::Float4 color4 = PX2::Float4(0.0f, 0.0f, 0.0f, 0.0f);
				PX2::Float3 color3 = PX2::Float3(0.0f, 0.0f, 0.0f);
				float floatValue = 0.0f;
				bool boolValue = false;
				float *floatTable = 0;
				int intValue = 0;
				std::string str;
				PX2::Texture2D *tex2d = 0;

				paramType = paramBlock->GetParameterType((ParamID)i);

				if (TYPE_STRING == paramType)
					ConvertStringAttrib(paramBlock, i, parmName, str);
				else if (TYPE_FLOAT == paramType)
					ConvertFloatAttrib(paramBlock, i, parmName, floatValue);
				else if (TYPE_INT == paramType)
					ConvertIntAttrib(paramBlock, i, parmName, intValue);
				else if (TYPE_RGBA == paramType)
					ConvertColorAttrib(paramBlock, i, parmName, color4, i);
				else if (TYPE_POINT3 == paramType)
					ConvertPoint3Attrib(paramBlock, i, parmName, color3);
				else if (TYPE_POINT4 == paramType)
					ConvertPoint4Attrib(paramBlock, i, parmName, color4);
				else if (TYPE_BOOL == paramType)
					ConvertBoolAttrib(paramBlock, i, parmName, boolValue);
				else if (TYPE_FLOAT_TAB == paramType)
					ConvertFloatTabAttrib(paramBlock, i, parmName, floatTable);
				else if (TYPE_BITMAP == paramType)
					ConvertBitMapAttrib(paramBlock, i, parmName, tex2d);
				else if (TYPE_FRGBA ==paramType)
					ConvertFRGBAAttrib(paramBlock, i, parmName, color4);

				// shine
				if (parmName == "gBlendMode")
				{
					blendMode = intValue;
				}
				else if (parmName == "gShineEmissive")
				{
					shineStandard->Emissive = color4;
				}
				else if (parmName == "gShineAmbient")
				{
					shineStandard->Ambient = color4;
				}
				else if (parmName == "gShineDiffuse")
				{
					shineStandard->Diffuse = color4;
				}
				// alpha vertex
				else if (parmName == "gAlphaVertex")
				{
					alphaVertex = boolValue;
				}
				// diffuse
				else if (parmName == "gDiffuseTexture")
				{
					diffTex = tex2d;
				}
				// normal
				else if (parmName == "gNormalEnable")
				{
					normalEnable = boolValue;
				}
				else if (parmName == "gNormalTexture")
				{
					normalTex = tex2d;
				}
				else if (parmName == "gNormalScale")
				{
					normalScale = floatValue;
				}
				// specular
				else if (parmName == "gSpecularEnable")
				{
					specEnable = boolValue;
				}
				else if (parmName == "gSpecularTexture")
				{
					specTex = tex2d;
				}
				else if (parmName == "gSpecularPower")
				{
					specPower = floatValue;
				}
				// reflect
				else if (parmName == "gReflectionEnable")
				{
					reflectEnable = boolValue;
				}
				else if (parmName == "gReflectTexture")
				{
					//reflectTex = tex2d;
				}
				else if (parmName == "gReflectPower")
				{
					reflectPower = floatValue;
				}
				// other
				else if (parmName == "gDoubleSide")
				{
					doubleSide = boolValue;
				}
			}
		}

		PX2::MaterialInstance *inst = 0;
		PX2::StandardMaterial *standardMtl = 0;
		PX2::StandardESMaterial_Default *standardESMtl_D = 0;
		PX2::StandardESMaterial_Specular *standardESMtl_S = 0;
		if (outBaseName == "Standard")
		{
			char mtlName[256];
			memset(mtlName, 0, 256*sizeof(char));
			sprintf(mtlName, "%s/%s", mSettings->DstRootDir, 
				"Data/mtls/Standard.pxfx");
			standardMtl = new0 PX2::StandardMaterial(mtlName);
		}
		else if (outBaseName == "StandardES")
		{
			if (false == specEnable)
			{
				standardESMtl_D = new0 PX2::StandardESMaterial_Default();

				if (0 == blendMode)
				{
					standardESMtl_D->GetAlphaProperty(0, 0)->BlendEnabled = false;
					standardESMtl_D->GetAlphaProperty(0, 0)->CompareEnabled = false;
				}
				else if (1 == blendMode)
				{
					standardESMtl_D->GetAlphaProperty(0, 0)->BlendEnabled = true;
				}
				else if (2 == blendMode)
				{
					standardESMtl_D->GetAlphaProperty(0, 0)->BlendEnabled = false;
					standardESMtl_D->GetAlphaProperty(0, 0)->CompareEnabled = true;
					standardESMtl_D->GetAlphaProperty(0, 0)->Compare = PX2::AlphaProperty::CM_GEQUAL;
					standardESMtl_D->GetAlphaProperty(0, 0)->Reference = 0.2f;
				}
			}
			else
			{
				char mtlName[256];
				memset(mtlName, 0, 256*sizeof(char));
				sprintf(mtlName, "%s/%s", mSettings->DstRootDir, 
					"Data/mtls/StandardES_Specular.pxfx");
				standardESMtl_S = new0 PX2::StandardESMaterial_Specular(mtlName);
			}
		}

		if (standardMtl && diffTex)
		{
			if (doubleSide)
			{
				standardMtl->GetCullProperty(0, 0)->Enabled = false;
			}

			inst = standardMtl->CreateInstance(diffTex, alphaVertex, 
				normalEnable, normalTex, normalScale, specEnable, specTex,
				specPower, 0, shineStandard);
		}
		else if (standardESMtl_D && diffTex)
		{
			if (doubleSide)
			{
				standardESMtl_D->GetCullProperty(0, 0)->Enabled = false;
			}

			inst = standardESMtl_D->CreateInstance(diffTex, 0, shineStandard);
		}
		else if (standardESMtl_S && diffTex && specTex)
		{
			if (doubleSide)
			{
				standardESMtl_S->GetCullProperty(0, 0)->Enabled = false;
			}

			inst = standardESMtl_S->CreateInstance(diffTex, specTex, specPower,
				0, shineStandard);
		}

		if (inst)
		{
			mtlTree.SetMaterialInstance(inst);
		}
		else
		{
			PX2::MaterialInstance *instance = 
				PX2::VertexColor4Material::CreateUniqueInstance();
			mtlTree.SetMaterialInstance(instance);
		}
	}
	else
	{
		PX2::VertexColor4Material *vcMtl = new0 PX2::VertexColor4Material();
		PX2::MaterialInstance *instance = vcMtl->CreateInstance();
		mtlTree.SetMaterialInstance(instance);
	}

	// 对子材质进行处理
	if (IsDirect9Shader)
		return;

	int mQuantity = mtl.NumSubMtls(); // Class_ID(MULTI_CLASS_ID, 0)
	if (mQuantity > 0)
	{
		mtlTree.SetMChildQuantity(mQuantity);
		for (int i=0; i<mQuantity; i++)
		{
			Mtl *subMtl = 0;
			subMtl = mtl.GetSubMtl(i);
			if (subMtl)
			{
				ConvertMaterial(*subMtl, mtlTree.GetMChild(i));
			}
		}
	}
}
コード例 #11
0
ファイル: G3DSExport.cpp プロジェクト: sundoom/glow
/*
====================
GatherSkin
====================
*/
void G3DSExport::GatherSkin(INode* i_node)
{
	SKIN skin;

	// get the name of the node
	skin.name = i_node->GetName();

	// get the skin interface
	Modifier *modifier = GetModifier(i_node,SKIN_CLASSID);
	ISkin* i_skin = (ISkin*)modifier->GetInterface(I_SKIN);
	MAX_CHECK(i_skin);

	// convert to the triangle type
	Mesh* i_mesh = NULL;
	Object* obj = i_node->EvalWorldState(mTime).obj;
	if(obj && ( obj->SuperClassID() == GEOMOBJECT_CLASS_ID ))
	{
		if(obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) 
		{ 
			TriObject *tri_obj = (TriObject*)obj->ConvertToType(mTime, Class_ID(TRIOBJ_CLASS_ID, 0)); MAX_CHECK(tri_obj);
			i_mesh = &tri_obj->mesh;
		}
	}
	MAX_CHECK(i_mesh&&i_mesh->getNumFaces()&&i_mesh->getNumVerts());

	// get the material
	skin.texture = "textures/default.tga";
	Mtl* mtl = i_node->GetMtl();
	if(mtl && (mtl->ClassID()==Class_ID(DMTL_CLASS_ID, 0)) && ((StdMat*)mtl)->MapEnabled(ID_DI)) 
	{
		Texmap *texmap = mtl->GetSubTexmap(ID_DI);
		if(texmap && texmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0x00))
		{
			skin.texture = UnifySlashes(((BitmapTex *)texmap)->GetMapName());
			if( !strstr( skin.texture.c_str(), mPath.c_str() ) )
			{
				G3DAssert("The material(%s) is error : the texture path(%s) is illegal!",mtl->GetName(), skin.texture.c_str());
			}
			else
			{
				skin.texture = strstr(skin.texture.c_str(),mPath.c_str()) + strlen(mPath.c_str());
			}
		}
	}

	// if it has uvs
	int map_count = i_mesh->getNumMaps();
	bool has_uvs = i_mesh->getNumTVerts() && i_mesh->tvFace;
	if(!(has_uvs&&map_count)) { G3DAssert("The skin(%s) has not the uv coordinates.",skin.name.c_str()); return; }

	// get the transform
	Matrix3 mesh_matrix = i_node->GetObjectTM(mTime);
	Matrix3 node_matrix = i_node->GetNodeTM(mTime);
	Matrix3 transform = mesh_matrix * Inverse(node_matrix);

	// get the points
	skin.points.assign(i_mesh->verts, i_mesh->verts+i_mesh->getNumVerts());

	// get the triangles
	for(int i = 0; i < i_mesh->getNumFaces(); i++)
	{
		Face& face = i_mesh->faces[i];

		TRIANGLE tri;		
		tri.smoothing = face.smGroup;
		for(int j = 0; j < 3; j++)
		{
			VPTNIS v;
			v.pos = transform * i_mesh->verts[face.v[j]];

			// get the uv
			UVVert * map_verts = i_mesh->mapVerts(1);
			TVFace * map_faces = i_mesh->mapFaces(1);
			v.uv = reinterpret_cast<Point2&>(map_verts[map_faces[i].t[j]]);
			v.uv.y = 1 - v.uv.y;

			// initialize the normal
			v.normal = Point3::Origin;

			// get the vertex index
			v.index = face.v[j];

			// get the smoothing group
			v.smoothing = face.smGroup;			

			// set the index for the triangle
			tri.index0[j] = v.index;

			// reassemble the vertex list
			tri.index1[j] = AddVertex(skin, v);
		}

		// add the triangle to the table
		skin.triangles.push_back(tri);
	}

	// build the index map
	for( int i = 0; i < skin.vertexes.size(); i++ )
	{
		skin.vertex_index_map[skin.vertexes[i].index].push_back(i);
	}

	// get the skin context data
	ISkinContextData* i_skin_context_data = i_skin->GetContextInterface(i_node);
	if(i_skin_context_data == NULL) { G3DAssert("The skin(%s) has not the weight.",skin.name.c_str()); return; }

	// gets the initial matrix of the skinned object 
	Matrix3 initial_object_transform;
	i_skin->GetSkinInitTM(i_node, initial_object_transform, true);

	// process the points
	int num_points = i_skin_context_data->GetNumPoints();
	for(int i = 0; i < num_points; i++)
	{
		MAX_CHECK(i < skin.points.size());

		VPIW viw;

		// get the initial point				
		viw.pos = initial_object_transform * skin.points[i];

		// process the weights		
		std::multimap< float, int > weights;

		// get the number of bones that control this vertex
		int num_bones = i_skin_context_data->GetNumAssignedBones(i);
		if(num_bones>0)
		{
			for (int j = 0; j < num_bones; j++)
			{
				Matrix3 transform;

				// get the assigned bone of the point 
				INode* i_bone_node = i_skin->GetBone(i_skin_context_data->GetAssignedBone(i, j));
				MAX_CHECK(i_bone_node != NULL);

				// get the weight of the bone
				float weight = i_skin_context_data->GetBoneWeight(i, j);

				// add the weight to the table
				weights.insert(std::make_pair(weight, AddBone(skin,i_bone_node)));
			}
		}
		else
		{
			// add the weight to the table
			weights.insert(std::make_pair(1.f, AddBone(skin,i_node)));
		}

		// recalculate the weights
		float weight0 = 0.f, weight1 = 0.f, weight2 = 0.f;
		int index0 = 0, index1 = 0, index2 = 0;
		std::multimap< float, int >::iterator it = weights.end();
		it--;
		weight0 = it->first;
		index0 = it->second;
		if(it != weights.begin())
		{
			it--;
			weight1 = it->first;
			index1 = it->second;
			if(it != weights.begin())
			{
				it--;
				weight2 = it->first;
				index2 = it->second;
			}
		}		
		float sum_weights = weight0 + weight1 + weight2;

		// store the skin weights	
		viw.weight[0]	= weight0/sum_weights;
		viw.index[0]	= index0;
		viw.weight[1]	= weight1/sum_weights;
		viw.index[1]	= index1;
		viw.weight[2]	= weight2/sum_weights;
		viw.index[2]	= index2;
		skin.weights.push_back(viw);
	}

	// get the initial transforms
	skin.transforms.resize(skin.bones.size());
	for(int i = 0; i < skin.bones.size(); i++)
	{
		INode* node = skin.bones[i];
		Matrix3 mat;
		if (SKIN_INVALID_NODE_PTR == i_skin->GetBoneInitTM( node, mat ))
		{
			if (SKIN_INVALID_NODE_PTR == i_skin->GetSkinInitTM( node, mat ))
			{
				mat.IdentityMatrix();
			}
		}
		skin.transforms[i] = Inverse(mat);
	}

	// there is a 75 bone limit for each skinned object.
	if(skin.bones.size()>75)
	{
		G3DAssert("There are more %d bones in the skin(%s).",skin.bones.size(), i_node->GetName());
		return;
	}

	// reset the skin vertex position
	for(int i = 0; i < skin.vertexes.size(); i++)
	{
		VPTNIS& v0 = skin.vertexes[i];
		VPIW& v1 = skin.weights[v0.index];
		v0.pos = v1.pos;
	}

	// build the normal space
	BuildNormal(skin);

	// calculate the bounding box	
	skin.box.Init();
	for(int i = 0; i < skin.vertexes.size(); i++)
	{
		Point3 pt = node_matrix * skin.vertexes[i].pos;
		skin.box += pt;
	}

	// add the skin to the table
	mSkins.push_back(skin);
}
コード例 #12
0
//----------------------------------------------------------------------------------
void DumpMaterial(IGameMaterial *pGMaxMat)
{
    m_material *pMat = NULL;

	if (!pGMaxMat->IsMultiType()) // check not a mix material
	{
        pMat = new m_material;

		// set the name of the material...
	    pMat->name = pGMaxMat->GetMaterialName();

		// add the new material to the TOC(Table Of Contants) and set its id...
		pMat->id = ExporterMAX::GetExporter()->AddMaterial(pGMaxMat, pMat);

		Mtl *pMaxMaterial = pGMaxMat->GetMaxMaterial();
				
		if (pMaxMaterial->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
		{
			StdMat *pStandardMaterial = (StdMat*)pMaxMaterial;
			
			Color col;

			// diffuse color...
			col = pStandardMaterial->GetDiffuse(ExporterMAX::GetExporter()->GetStaticFrame());
			pMat->diffuse = Vector4f(col.r, col.g, col.b, 1.f);

			// ambient color...
			col = pStandardMaterial->GetAmbient(ExporterMAX::GetExporter()->GetStaticFrame());
			pMat->ambient = Vector4f(col.r, col.g, col.b, 1.f);

			// specular color...
			col = pStandardMaterial->GetSpecular(ExporterMAX::GetExporter()->GetStaticFrame());
			pMat->specular = Vector4f(col.r, col.g, col.b, 1.f);

			// emissive color...
			pMat->emission = Vector4f(0.f, 0.f, 0.f, 1.f);

			// level of transparency
			pMat->transparent = pStandardMaterial->GetOpacity(ExporterMAX::GetExporter()->GetStaticFrame());

			// specular exponent...
			pMat->shininess = pStandardMaterial->GetShininess(ExporterMAX::GetExporter()->GetStaticFrame());
	
			// transparency
			if (pMat->transparent < 1.f){
				pMat->diffuse.z = pMat->transparent;
			}
		
		}// 3dsmax6 HLSL Material support. (IDxMaterial)
		else if (IsDynamicDxMaterial((MtlBase*)pMaxMaterial))
		{
			IDxMaterial *idxm = (IDxMaterial*)pMaxMaterial->GetInterface(IDXMATERIAL_INTERFACE);
			
			int lightParams = idxm->GetNumberOfLightParams();

			for (int i = 0; i < lightParams; ++i)
			{
                INode *pNode = idxm->GetLightNode(i);

				if (pNode){
                    TCHAR *paramName = idxm->GetLightParameterName(i);
				}
			}

			// Other attributes are located in paramblk 0...
			IParamBlock2 *pParamBlk2 = (IParamBlock2*)(pMaxMaterial->GetParamBlock(0));
			TimeValue t0 = ExporterMAX::GetExporter()->GetIGame()->GetSceneStartTime();
			TimeValue t1 = ExporterMAX::GetExporter()->GetIGame()->GetSceneEndTime();
			TimeValue DeltaTime = ExporterMAX::GetExporter()->GetIGame()->GetSceneTicks();

			const int SamplingRate = 1;

			int numkeys = (t1 - t0) / (DeltaTime * SamplingRate) + 1; 

			for (int i = 0; i < pParamBlk2->NumParams(); ++i)
			{
				ParamID id = pParamBlk2->IndextoID(i);
				ParamDef paramDef = pParamBlk2->GetParamDef(id);

				// we want the variable name not the UI Name...
				OutputDebugString(paramDef.int_name);
			}
		}
		//do the textures if they are there
		DumpTexture(pMat, pGMaxMat);
	}
}