コード例 #1
0
void CompositeMat::PreShade(ShadeContext& sc, IReshadeFragment* pFrag)
{
	int i(0);
	Mtl *submtl = NULL;
//	BOOL enabled(FALSE);

	char texLengths[12];

	int lengthChan = pFrag->NTextures();
	pFrag->AddIntChannel(0);
	pFrag->AddIntChannel(0);
	pFrag->AddIntChannel(0);

	int nPrevTex = 3 + lengthChan;

	// preshade any submaterials
	for (i=0; i<MAX_NUM_MTLS; i++)
	{
		pblock2->GetValue(compmat_mtls, sc.CurTime(), submtl, FOREVER, i);
		if (submtl){
			IReshading* pReshading = (IReshading*)(submtl->GetInterface(IID_IReshading));
			if( pReshading ){
				pReshading->PreShade(sc, pFrag);
				int nTex = pFrag->NTextures();
				texLengths[i] = char( nTex - nPrevTex);
				nPrevTex = nTex;
			}
		}
	}
	int* pI = (int*)&texLengths[0];
	pFrag->SetIntChannel( lengthChan++, pI[0] );
	pFrag->SetIntChannel( lengthChan++, pI[1] );
	pFrag->SetIntChannel( lengthChan, pI[2] );

}
コード例 #2
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;
	}
}
コード例 #3
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;
}
コード例 #4
0
ファイル: refenum.cpp プロジェクト: DimondTheCat/xray
int EnumMtlTree(MtlBase *mb, int subMtl, MtlEnum &tenum)
{
	for (int i=0; i<mb->NumSubTexmaps(); i++) {
		Texmap *st = mb->GetSubTexmap(i);
		if (st) {
			if (!EnumMtlTree(st,subMtl, tenum)) {
				return 0;
			}
		}
	}
	if (IsTex(mb)) {
		if (!tenum.proc(mb,subMtl)) {
			return 0;
		}
	}
	if (IsMtl(mb)) {
		Mtl *m = (Mtl *)mb;
		for (i=0; i<m->NumSubMtls(); i++) {
			Mtl *sm = m->GetSubMtl(i);
			int subm = (mb->IsMultiMtl()&&subMtl<0)?i:subMtl;
			if (sm) {
				if (!EnumMtlTree(sm,subm,tenum)) {
					return 0;
				}
			}
		}
		if (!tenum.proc(mb,subMtl)) {
			return 0;
		}
	}
	return 1;
}
コード例 #5
0
void plMultipassMtlDlg::UpdateLayerDisplay() 
{
    int numlayers = fPBlock->GetInt(kMultCount);

    fNumTexSpin->SetValue(numlayers, FALSE);

    int i;
    for (i = 0; i < numlayers && i < NSUBMTLS; i++)
    {
        Mtl *m = fPBlock->GetMtl(kMultPasses, curTime, i);
        TSTR nm;
        if (m) 
            nm = m->GetName();
        else 
            nm = "None";
        fLayerBtns[i]->SetText(nm.data());
        
        ShowWindow(GetDlgItem(fhRollup, kLayerID[i].layerID), SW_SHOW);
        ShowWindow(GetDlgItem(fhRollup, kLayerID[i].activeID), SW_SHOW);
        SetCheckBox(fhRollup, kLayerID[i].activeID, fPBlock->GetInt(kMultOn, curTime, i));  
    }

    for (i = numlayers; i < NSUBMTLS; i++)
    {
        ShowWindow(GetDlgItem(fhRollup, kLayerID[i].layerID), SW_HIDE);
        ShowWindow(GetDlgItem(fhRollup, kLayerID[i].activeID), SW_HIDE);
    }
}
コード例 #6
0
ファイル: IfcMax.cpp プロジェクト: 15921050052/IfcOpenShell
Mtl* FindOrCreateMaterial(MtlBaseLib* library, Interface* max_interface, int& slot, const IfcGeom::Material& material) {
	Mtl* m = FindMaterialByName(library, material.name());
	if (m == 0) {
		StdMat2* stdm = NewDefaultStdMat();
		const TimeValue t = -1;
		if (material.hasDiffuse()) {
			const double* diffuse = material.diffuse();
			stdm->SetDiffuse(Color(diffuse[0], diffuse[1], diffuse[2]),t);
		}
		if (material.hasSpecular()) {
			const double* specular = material.specular();
			stdm->SetSpecular(Color(specular[0], specular[1], specular[2]),t);
		}
		if (material.hasSpecularity()) {
			stdm->SetShininess(material.specularity(), t);
		}
		if (material.hasTransparency()) {
			stdm->SetOpacity(1.0 - material.transparency(), t);
		}
		m = stdm;
		m->SetName(S(material.name()));
		library->Add(m);
		if (slot < NUM_MATERIAL_SLOTS) {
			max_interface->PutMtlToMtlEditor(m,slot++);
		}
	}
	return m;
}
コード例 #7
0
    void IInit(HWND hWnd, IParamBlock2* pb)
    {
        Mtl* mtl = pb->GetMtl(kMarkerMtl);

        if (mtl)
        {
            SetDlgItemText(hWnd, IDC_MTL_BUTTON, mtl->GetName());

            plNotetrackAnim anim(mtl, nil);
            ILoadCombo(hWnd, IDC_ANIM_RED_COMBO, kMarkerRedAnim, pb, anim);
            ILoadCombo(hWnd, IDC_ANIM_GREEN_COMBO, kMarkerGreenAnim, pb, anim);
            ILoadCombo(hWnd, IDC_ANIM_OPEN_COMBO, kMarkerOpenAnim, pb, anim);
        }

        if (pb->GetINode(kMarkerMtlNode))
            SetDlgItemText(hWnd, IDC_MTL_NODE_BUTTON, pb->GetINode(kMarkerMtlNode)->GetName());
        else
            SetDlgItemText(hWnd, IDC_MTL_NODE_BUTTON, "(none)");

        if (pb->GetINode(kMarkerBounceNode))
            SetDlgItemText(hWnd, IDC_BOUNCE_BUTTON, pb->GetINode(kMarkerBounceNode)->GetName());
        else
            SetDlgItemText(hWnd, IDC_BOUNCE_BUTTON, "(none)");

        if (pb->GetINode(kMarkerSndPlace))
            SetDlgItemText(hWnd, IDC_PLACE_BUTTON, pb->GetINode(kMarkerSndPlace)->GetName());
        else
            SetDlgItemText(hWnd, IDC_PLACE_BUTTON, "(none)");

        if (pb->GetINode(kMarkerSndHit))
            SetDlgItemText(hWnd, IDC_HIT_BUTTON, pb->GetINode(kMarkerSndHit)->GetName());
        else
            SetDlgItemText(hWnd, IDC_HIT_BUTTON, "(none)");
    }
コード例 #8
0
ファイル: SceneExportUtil.cpp プロジェクト: TheRyaz/c_reading
void SceneExportUtil::getUsedMaterials( INode* node, Vector<Mtl*>& materials )
{
	require( node );

	Mtl* mat = node->GetMtl();
	if ( mat )
	{
		materials.add( mat );

		// get sub-materials (Multi/Sub-Object material)
		for ( int k = 0 ; k < mat->NumSubMtls() ; ++k )
		{
			Mtl* submat = mat->GetSubMtl(k);
			if ( submat )
				materials.add( submat );
		}
	}

	// remove duplicates
	std::sort( materials.begin(), materials.end() );
	std::unique( materials.begin(), materials.end() );

	// sort to abc order
	std::sort( materials.begin(), materials.end(), MtlNameLess() );
}
コード例 #9
0
//????????????????????????????????????????????????????????????????????????
// The submat with a higher index "cover" the ones "below".
// If the first submat taken from the end of the array has amount == 100,
// that's al it matters. Otherwise all until the second consecutive submat
// with amount == 100 matter
//
bool CompositeMat::IsOutputConst
( 
	ShadeContext& sc, // describes context of evaluation
	int stdID				// must be ID_AM, ect
)
{
	Mtl *sm = NULL;
	int numSubMatOn = 0;
	int numConsec = 0;
	bool bIsConst = true;
	Interval iv;

	// Iterate through the submats in reverse order because that is
	// the order of their significance
	for (int i = MAX_NUM_MTLS-1; i >= 0; i--)
	{
		BOOL enabled;
		float amount;
		
		// The first one is always enabled
		if ( i == 0 ) 
			enabled = 1;
		else 
			pblock2->GetValue( compmat_map_on, sc.CurTime(), enabled, iv, i-1 );
		
		if ( enabled )
		{
			pblock2->GetValue( compmat_mtls, sc.CurTime(), sm, iv, i );
			if ( sm != NULL ) 
			{
				numSubMatOn++;

				// All of the first on is always composited
				if ( i == 0 ) 
					amount = 100.f;
				else 
					pblock2->GetValue( compmat_amount, sc.CurTime(), amount, iv, i-1 );
				
				if ( numSubMatOn == 1 && amount == 100.0f )
					return sm->IsOutputConst( sc, stdID );
				else
				{
					if ( amount == 100.0f )
						numConsec++;
					else
						numConsec = 0;
					bool b = sm->IsOutputConst( sc, stdID );
					bIsConst = (bIsConst && b );
					if ( !bIsConst )
						return bIsConst;
					else if ( numConsec == 2 )
						return bIsConst;
				}
			}
		}
	}
	return bIsConst;
}
コード例 #10
0
//+--------------------------------------------------------------------------+
//|							From IPViewItem									 |
//+--------------------------------------------------------------------------+
bool PFOperatorMaterialStatic::HasDynamicName(TSTR& nameSuffix)
{
	bool assign = (pblock()->GetInt(kMaterialStatic_assignMaterial, 0) != 0);
	if (!assign) return false;
	Mtl* mtl = GetMaterial();
	if (mtl == NULL) {
		nameSuffix = GetString(IDS_NONE);
	} else {
		nameSuffix = mtl->GetName();
	}
	return true;
}
コード例 #11
0
void CompositeMat::Reset()
	{
	compositematCD.Reset(this, TRUE);	// reset all pb2's
	Init();
	CompMatDlgProc *parmDlg = (CompMatDlgProc *) compmat_param_blk.GetUserDlgProc();
	if (parmDlg) parmDlg->ReloadDialog();
//watje 3-22-99 set the name of the first material
	Mtl *m = NULL;;
	Interval iv;
	pblock2->GetValue(compmat_mtls,0,m,iv,0);
	if (m) m->SetName(GetString(IDS_PW_BASE));

	}
コード例 #12
0
ファイル: wm3_material.cpp プロジェクト: 2asoft/xray
void M3Mat::PreShade(ShadeContext& sc, IReshadeFragment* pFrag)
{
	int i; 
	IReshading* pReshading;

	TimeValue t = sc.CurTime();
	Interval valid = FOREVER;

	// get the base material value into i
	pblockMat->GetValue(100, t, i, valid );

	Mtl *sm1 = mTex[100];

	// handle no base mat
	if(sm1 == NULL) 
	{
		return;
	}

	if(i==0||(i==1&&inRender))
	{
		for( i=0;i<100;i++)
		{
			float u;
			pblockMat->GetValue(i,t,u,valid);

			if(mTex[i]!=NULL && u!=0 && mapOn[i])
			{
				Mtl *comb = mTex[i];
				pReshading = (IReshading*)(comb->GetInterface(IID_IReshading));
				if( pReshading ) 
					pReshading->PreShade(sc, pFrag);
			}
		}

		pReshading = (IReshading*)(sm1->GetInterface(IID_IReshading));
		if( pReshading ) 
			pReshading->PreShade(sc, pFrag);
	}
	else {
		// i == 1 && not inRender
		pReshading = (IReshading*)(sm1->GetInterface(IID_IReshading));
		if( pReshading ) 
			pReshading->PreShade(sc, pFrag);
	}
}
コード例 #13
0
void CompositeMat::Update(TimeValue t, Interval& valid)
	{	
	ivalid = FOREVER;
	curTime = t;
	for (int i = 0; i < MAX_NUM_MTLS; i++)
		{
		Mtl* sub = NULL;
		float u;
		pblock2->GetValue(compmat_mtls,t,sub,valid,i);
		if (sub != NULL)
			{
			sub->Update(t,valid);
			if (i != MAX_NUM_MTLS-1)
				pblock2->GetValue(compmat_amount,t,u,valid,i);
			}
		}
	valid &= ivalid;
	}
コード例 #14
0
void plMtlAnimProc::IUpdateMtlButton(HWND hWnd, IParamBlock2* pb)
{
    HWND hMtl = GetDlgItem(hWnd, fMtlButtonID);

    // Get the saved material
    Mtl *savedMtl = IGetMtl(pb);

    if (savedMtl)
        SetWindowText(hMtl, savedMtl->GetName());
    else
        SetWindowText(hMtl, "(none)");

    // Enable the node button if a material is selected
    EnableWindow(GetDlgItem(hWnd, fNodeButtonID), (savedMtl != nil));

    // Update the dependencies of this
    IUpdateNodeButton(hWnd, pb);
}
コード例 #15
0
ファイル: gmodelexp.cpp プロジェクト: chenbk85/3dlearn
void GmodelExp::ExportMaterial(void)
{
	PrintSpace(); fprintf(m_pFile, "Begin Material\n");
	PrintSpace(); fprintf(m_pFile, "{\n");
	PushSpace();

	m_iNumMaterials = m_MaterialTable.size();

	PrintSpace(); fprintf(m_pFile, "Materials %d\n", m_iNumMaterials);

	for ( int i=0; i<m_iNumMaterials; i++ )
	{
		PrintSpace(); fprintf(m_pFile, "{	// material %d\n", i);
		PushSpace();

		Mtl *mtl = m_MaterialTable[i];
		sMaterial dxMaterial;
		dxMaterial.ConvertMTL(mtl);

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

		PrintSpace(); fprintf(m_pFile, "name = \"%s\"\n", name ? name : "unknown");

		PrintSpace(); fprintf(m_pFile, "emissive = %f,%f,%f\n", dxMaterial.m_EmissiveColor.r, dxMaterial.m_EmissiveColor.g, dxMaterial.m_EmissiveColor.b);
		PrintSpace(); fprintf(m_pFile, "ambient = %f,%f,%f\n", dxMaterial.m_AmbientColor.r, dxMaterial.m_AmbientColor.g, dxMaterial.m_AmbientColor.b);
		PrintSpace(); fprintf(m_pFile, "diffuse = %f,%f,%f\n", dxMaterial.m_DiffuseColor.r, dxMaterial.m_DiffuseColor.g, dxMaterial.m_DiffuseColor.b);
		PrintSpace(); fprintf(m_pFile, "specular = %f,%f,%f\n", dxMaterial.m_SpecularColor.r, dxMaterial.m_SpecularColor.g, dxMaterial.m_SpecularColor.b);
		PrintSpace(); fprintf(m_pFile, "shininess = %f\n", dxMaterial.m_fShininess);

		PrintSpace(); fprintf(m_pFile, "blendmode = %s\n", dxMaterial.m_BlendMode.c_str());
		PrintSpace(); fprintf(m_pFile, "CullFace = %s\n", dxMaterial.m_bCullFace ? "on" : "off");

		PrintSpace(); fprintf(m_pFile, "diffuseMap = \"%s\" MapChannel = %d\n", dxMaterial.m_Textures[0].length() ? dxMaterial.m_Textures[0].c_str() : "None", dxMaterial.m_MapChannel[0]);
		PrintSpace(); fprintf(m_pFile, "lightMap = \"%s\" MapChannel = %d\n", dxMaterial.m_Textures[1].length() ? dxMaterial.m_Textures[1].c_str() : "None", dxMaterial.m_MapChannel[1]);
		PrintSpace(); fprintf(m_pFile, "environmentMap = \"%s\"\n", dxMaterial.m_Textures[2].length() ? dxMaterial.m_Textures[2].c_str() : "None");

		PopSpace();
		PrintSpace(); fprintf(m_pFile, "}\n");
	}

	PopSpace();
	PrintSpace(); fprintf(m_pFile, "}\n");
	PrintSpace(); fprintf(m_pFile, "End Material\n");
}
コード例 #16
0
Interval CompositeMat::Validity(TimeValue t)
	{
	Interval valid = FOREVER;		
	for (int i = 0; i < MAX_NUM_MTLS; i++)
		{
		Mtl* sub = NULL;
		float u;
		pblock2->GetValue(compmat_mtls,t,sub,valid,i);
		if (sub != NULL)
			{
			valid &= sub->Validity(t);
			if (i != MAX_NUM_MTLS-1)
				pblock2->GetValue(compmat_amount,t,u,valid,i);
			}
		}
//	pblock2->GetValue(compmat_type,t,currentType,ivalid);

	return valid;
	}
コード例 #17
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;
}
コード例 #18
0
ファイル: scp_read.cpp プロジェクト: 2asoft/xray
static INT_PTR CALLBACK DefaultDlgProc(
		HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) {
		case WM_INITDIALOG:
			theSCPUtil.Init(hWnd);
			break;

		case WM_DESTROY:
			theSCPUtil.Destroy(hWnd);
			break;

		case WM_COMMAND:
			switch (LOWORD(wParam)) {
				case IDC_CLOSE:
					theSCPUtil.iu->CloseUtility();
					break;

				case IDC_BTN1:
					{
					// Open a material browser to find the material to inspect
					Interface *ip = theSCPUtil.ip;

					BOOL newMat,cancel;
					MtlBase *mtlb = ip->DoMaterialBrowseDlg(hWnd,BROWSE_MATSONLY|BROWSE_INSTANCEONLY,newMat,cancel);


					if(!cancel&&mtlb)
					{
						// Check to see if this is one of ours
						if(mtlb->ClassID() == GAMEMTL_CLASSID)
						{

						Mtl *scp = (Mtl*)mtlb;

						// Get the number of pblock2s and references on the mtl
						int num_pblock2 = scp->NumParamBlocks();
						int num_refs = scp->NumRefs();

							// Get the custom parameters
							// We defined two custom parameters in our scripted plugin
							// called GM_Custom1 and GM_Custom2
							// When we walk through the retrieved paramblock2, we can
							// get access to the hardwired internal name and check that
							// against our own names, to see if its the parameter we want
							// This way, its position-independant : it doesn't matter
							// where the parameters ARE in the pblock2, we will find them.
							if(num_pblock2>0)
							{
								// Get the first paramblock2 (the only one in our scripted plugin)
								IParamBlock2 *pb2 = scp->GetParamBlock(0);
								// The the descriptor to 'decode'
								ParamBlockDesc2 *pdc = pb2->GetDesc();

								// Loop through all the defined parameters therein
								for(int i=0;i<pdc->count;i++)
								{
									// Get a ParamDef structure for the parameter
									ParamDef pD = pdc->paramdefs[i];
									

									// Now compare against our names
									// When we match against one we want, we get the 
									// ParamID from the ParamDef and pass it to GetValue of ParamBlock2
									// which will retrieve us the value
									if(stricmp(pD.int_name,"GM_Custom1")==0)
									{
										int itmp = pb2->GetInt(pD.ID,theSCPUtil.ip->GetTime());

										char s[255];
										sprintf(s,"%i",itmp);
										SetWindowText(GetDlgItem(hWnd,IDC_GM1),s);
									}

									if(stricmp(pD.int_name,"GM_Custom2")==0)
									{
										float ftmp = pb2->GetFloat(pD.ID,theSCPUtil.ip->GetTime());

										char s[255];
										sprintf(s,"%.1f%%",ftmp);
										SetWindowText(GetDlgItem(hWnd,IDC_GM2),s);
									}

								}

								// Mustn't forget to...
								pb2->ReleaseDesc();
							}


							// With a scripted plugin that overrides/extends an existing plugin,
							// the original "delegate" is kept as Reference 0.
							// If the scripted plugin is a brand new one, Ref 0 will be the first
							// paramblock2, and ref n will be paramblock2 n, if applicable.
							//
							// In this case, we get a poitner back to the original Standard Material
							// that we override, and get its Diffuse color
							Mtl *delegate = (Mtl*)scp->GetReference(0);
							theSCPUtil.cs->SetColor(delegate->GetDiffuse());

						}
						else
						{
							// The user chose something that wasn't a GameMtl class
							MessageBox(hWnd,"Chosen Material Is NOT a GAMEMTL!","Error",MB_OK);
						}
					}

					}
					break;
			}
			break;


		default:
			return FALSE;
	}
	return TRUE;
}
コード例 #19
0
ファイル: Mesh.cpp プロジェクト: ElliotWood/max_nif_plugin
bool Exporter::splitMesh(INode *node, Mesh& mesh, FaceGroups &grps, TimeValue t, vector<Color4>& vertColors, bool noSplit)
{
	Mtl* nodeMtl = node->GetMtl();
	Matrix3 tm = node->GetObjTMAfterWSM(t);

	// Order of the vertices. Get 'em counter clockwise if the objects is
	// negatively scaled.
	int vi[3];
	if (TMNegParity(tm)) {
		vi[0] = 2; vi[1] = 1; vi[2] = 0;
	} else {
		vi[0] = 0; vi[1] = 1; vi[2] = 2;
	}

	Matrix3 flip;
	flip.IdentityMatrix();
	flip.Scale(Point3(1, -1, 1));

   int nv = mesh.getNumVerts();
   int nf = mesh.getNumFaces();

	if (noSplit)
	{
		int nv = mesh.getNumVerts();
		int nf = mesh.getNumFaces();
		// Dont split the mesh at all.  For debugging purposes.
		FaceGroup& grp = grps[0];
		grp.vidx.resize(nv, -1);
		grp.verts.resize(nv);
		grp.faces.resize(nf);
		grp.uvs.resize(nv);
		grp.vnorms.resize(nv);
      grp.fidx.resize(nf);

		Matrix3 texm;
		getTextureMatrix(texm, getMaterial(node, 0));
		texm *= flip;

		for (int face=0; face<nf; ++face) {
         grp.fidx[face] = face;
			for (int vi=0; vi<3; ++vi) {
				int idx = mesh.faces[face].getVert(vi);
				grp.faces[face][vi] = idx;

				// Calculate normal
				Point3 norm;
#if VERSION_3DSMAX <= ((5000<<16)+(15<<8)+0) // Version 5
				norm = getVertexNormal(&mesh, face, mesh.getRVertPtr(idx));
#else
				MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals ();
				if (NULL != specNorms && specNorms->GetNumNormals() != 0)
					norm = specNorms->GetNormal(face, vi);
				else
					norm = getVertexNormal(&mesh, face, mesh.getRVertPtr(idx));
#endif
				Point3 uv;
				if (mesh.tVerts && mesh.tvFace) {
					uv = mesh.tVerts[ mesh.tvFace[ face ].t[ vi ]] * texm;
					uv.y += 1.0f;
				}

				if (grp.vidx[idx] == idx){
					ASSERT(grp.verts[idx] == TOVECTOR3(mesh.getVert(idx)));
					//ASSERT(vg.norm == norm);
					//Point3 uv = mesh.getTVert(idx);
					//if (mesh.getNumTVerts() > 0)
					//{
					//	ASSERT(grp.uvs[idx].u == uv.x && grp.uvs[idx].v == uv.y);
					//}
				} else {
					grp.vidx[idx] = idx;
					grp.verts[idx] = TOVECTOR3(mesh.getVert(idx));
					//grp.uvs[idx].u = uv.x;
					//grp.uvs[idx].v = uv.y;
					grp.vnorms[idx] = TOVECTOR3(norm);
				}
			}
		}
		for (int i=0; i<nv; ++i) {
			ASSERT(grp.vidx[i] != -1);
		}
	}
	else
	{
		int face, numSubMtls = nodeMtl?nodeMtl->NumSubMtls():0;
		for (face=0; face<mesh.getNumFaces(); face++) 
		{
			int mtlID = (numSubMtls!=0) ? (mesh.faces[face].getMatID() % numSubMtls) : 0;
         Mtl *mtl = getMaterial(node, mtlID);
			Matrix3 texm;
			getTextureMatrix(texm, mtl);
			texm *= flip;

         FaceGroup& grp = grps[mtlID];

		 if (grp.uvMapping.size() == 0) // Only needs to be done once per face group
		 {
			 int nmaps = 0;
			 int nmapsStart = max(1, mesh.getNumMaps() - (mesh.mapSupport(0) ? 1 : 0)); // Omit vertex color map.
			 for (int ii = 1; ii <= nmapsStart; ii++) // Winnow out the unsupported maps.
			 {
				 if (!mesh.mapSupport(ii)) continue;
				 grp.uvMapping[ii] = nmaps++;
			 }
			 grp.uvs.resize(nmaps == 0 ? 1 : nmaps);
		 }
         if (nv > int(grp.verts.capacity()))
         {
            grp.vgrp.reserve(nv);
            grp.verts.reserve(nv);
            grp.vnorms.reserve(nv);
            for (int i=0; i<grp.uvs.size(); ++i)
               grp.uvs[i].reserve(nv);
            grp.vcolors.reserve(nv);
            grp.vidx.reserve(nv);
         }
         if (nf > int(grp.faces.capacity()))
         {
            grp.faces.reserve(nf);
            grp.fidx.reserve(nf);
         }

         Triangle tri;
         for (int i=0; i<3; i++)
            tri[i] = addVertex(grp, face, vi[i], &mesh, texm, vertColors);
         grp.faces.push_back(tri);

         if (grp.fidx.size() < nf)
            grp.fidx.resize(nf,-1);
         grp.fidx[face] = grp.faces.size() - 1;
		}
	}

	return true;
}
コード例 #20
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;
}
コード例 #21
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;
}
コード例 #22
0
ファイル: export.cpp プロジェクト: grasmanek94/darkreign2
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;
	}
}
コード例 #23
0
void CompositeMat::PostShade(ShadeContext& sc, IReshadeFragment* pFrag, int& nextTexIndex, IllumParams* )
{
	int i(0), type(2);
	Mtl* submtl = NULL;
	BOOL enabled(TRUE);
	ShadeOutput out1, out2;
	float amount(100.0f); // , gamount(0.0f);

	char texLengths[12];

	int* pI = (int*)&texLengths[0];
	pI[0] = pFrag->GetIntChannel(nextTexIndex++);
	pI[1] = pFrag->GetIntChannel(nextTexIndex++);
	pI[2] = pFrag->GetIntChannel(nextTexIndex++);



	// postshade any submaterials
	for ( i=0; i<MAX_NUM_MTLS; i++)
	{
		if( i>0 )
			pblock2->GetValue(compmat_map_on, sc.CurTime(), enabled, FOREVER, i-1);
		else 
			enabled = TRUE;

		pblock2->GetValue(compmat_mtls, sc.CurTime(), submtl, FOREVER, i);
		if ( enabled && submtl ){
			if( i > 0 ){
				pblock2->GetValue(compmat_amount, sc.CurTime(), amount, FOREVER, i-1);
				pblock2->GetValue(compmat_type, sc.CurTime(), type, FOREVER, i-1);
			}
			amount = amount * 0.01f;
			sc.ResetOutput();
			IReshading* pReshading = (IReshading*)(submtl->GetInterface(IID_IReshading));
			if( pReshading ) 
				pReshading->PostShade(sc, pFrag, nextTexIndex);
			
			// first check for base material
			if( i > 0 ) {
				// not base material, composite the next material
				out2 = sc.out;
					
				if (type == 0) // additive
				{
					out2.t.r += 1.0f-amount;
					out2.t.g += 1.0f-amount;
					out2.t.b += 1.0f-amount;
					out2.c *= amount;
					out2.t.ClampMinMax();
					out2.ior *= amount;

					float f1 = 1.0f - (out1.t.r + out1.t.g + out1.t.b) / 3.0f; 
					float f2 = 1.0f - (out2.t.r + out2.t.g + out2.t.b) / 3.0f; 
					out1.c = out1.c * (1.0f-f2) + out2.c * f1;
					out1.t = out1.t - (1.0f-out2.t);
					out1.ior = out1.ior + out2.ior;
					out1.t.ClampMinMax();
				}
				else if (type == 1) // subtractive
				{
					out2.t.r += 1.0f-amount;
					out2.t.g += 1.0f-amount;
					out2.t.b += 1.0f-amount;
					out2.c *= amount;
					out2.t.ClampMinMax();
					out2.ior *= amount;

					float f1 = 1.0f - (out1.t.r + out1.t.g + out1.t.b) / 3.0f;
					float f2 = 1.0f - (out2.t.r + out2.t.g + out2.t.b) / 3.0f;

					out1.c = out1.c * (1.0f-f2) - out2.c * f1;
					out1.t = out1.t - (1.0f-out2.t);
					out1.ior = out1.ior + out2.ior;

					out1.t.ClampMinMax();
				}
				else //mix
				{
					out1.MixIn(out2, 1.0f-amount);
				}
			}// end, not base mtl
			else {
				// base material.
				out1 = sc.out;
				out1.ior *= amount;
			}

		}// end, if has submtl & enabled
		else {
			nextTexIndex += texLengths[i];
		}

	}// end, for each mtl

	sc.out = out1;
}
コード例 #24
0
bool CEditableMesh::Convert( INode *node )
{
	// prepares & checks
	BOOL bDeleteObj;
	bool bResult = true;
	TriObject *obj = ExtractTriObject( node, bDeleteObj );

	if( !obj ){
		ELog.Msg(mtError,"%s -> Can't convert to TriObject", node->GetName() );
		return false; }

	if( obj->mesh.getNumFaces() <=0 ){
		ELog.Msg(mtError,"%s -> There are no faces ?", node->GetName() );
		if (bDeleteObj) delete (obj);
		return false; }

	Mtl *pMtlMain = node->GetMtl();
	DWORD cSubMaterials=0;

	if (pMtlMain){
		// There is at least one material. We're in case 1) or 2)
		cSubMaterials = pMtlMain->NumSubMtls();
		if (cSubMaterials < 1){
			// Count the material itself as a submaterial.
			cSubMaterials = 1;
		}
	}

	// build normals
	obj->mesh.buildRenderNormals();

	// vertices
	m_VertCount = obj->mesh.getNumVerts();
	m_Vertices = xr_alloc<Fvector>(m_VertCount);
	for (int v_i=0; v_i<m_VertCount; v_i++){
		Point3* p = obj->mesh.verts+v_i;
		m_Vertices[v_i].set(p->x,p->y,p->z);
	}

	// set smooth group MAX type
	m_Flags.set(flSGMask,TRUE);

	// faces
	m_FaceCount		= obj->mesh.getNumFaces();
	m_Faces			= xr_alloc<st_Face>	(m_FaceCount);
	m_SmoothGroups	= xr_alloc<u32>		(m_FaceCount);

	m_VMRefs.reserve(m_FaceCount*3);
	if (0==obj->mesh.mapFaces(1))
	{
		bResult = false;
		ELog.Msg(mtError,"'%s' hasn't UV mapping!", node->GetName());
	}
	if (bResult)
	{
		CSurface* surf=0;
		for (int f_i=0; f_i<m_FaceCount; ++f_i)
		{
			Face*	vf = obj->mesh.faces+f_i;
			TVFace* tf = obj->mesh.mapFaces(1) + f_i;
			if (!tf)
			{
				bResult = false;
				ELog.Msg(mtError,"'%s' hasn't UV mapping!", node->GetName());
				break;
			}
			m_SmoothGroups[f_i]					= vf->getSmGroup();
			for (int k=0; k<3; ++k)
			{
				m_Faces[f_i].pv[k].pindex = vf->v[k];
				m_VMRefs.push_back(st_VMapPtLst());
				st_VMapPtLst&	vm_lst = m_VMRefs.back();
				vm_lst.count	= 1;
				vm_lst.pts		= xr_alloc<st_VMapPt>(vm_lst.count);
				for (DWORD vm_i=0; vm_i<vm_lst.count; ++vm_i)
				{
					vm_lst.pts[vm_i].vmap_index	= 0;
					vm_lst.pts[vm_i].index 		= tf->t[k];
				}
				m_Faces[f_i].pv[k].vmref	= m_VMRefs.size()-1;
				if (!bResult) break;
			}
			if (pMtlMain)
			{
				int m_id = obj->mesh.getFaceMtlIndex(f_i);
				if (cSubMaterials == 1)
				{
					m_id = 0;
				}else
				{
					// SDK recommends mod'ing the material ID by the valid # of materials, 
					// as sometimes a material number that's too high is returned.
					m_id %= cSubMaterials;
				}
				surf = m_Parent->CreateSurface(pMtlMain,m_id);
				if (!surf) bResult = false;
			}
			if (!bResult) break;
			m_SurfFaces[surf].push_back(f_i);
		}
	}

	// vmaps
	if( bResult ){
		int vm_cnt = obj->mesh.getNumTVerts();
		m_VMaps.resize(1);
		st_VMap*& VM = m_VMaps.back();
		VM = xr_new<st_VMap>("Texture",vmtUV,false);
		for (int tx_i=0; tx_i<vm_cnt; tx_i++){
			UVVert* tv = obj->mesh.tVerts + tx_i;
			VM->appendUV(tv->x,1-tv->y);
		}
	}

	if ((GetVertexCount()<4)||(GetFaceCount()<2))
	{
		ELog.Msg(mtError,"Invalid mesh: '%s'. Faces<2 or Verts<4");
		bResult = false;
	}

	if (bResult ){
		ELog.Msg(mtInformation,"Model '%s' contains: %d points, %d faces",
			node->GetName(), m_VertCount, m_FaceCount);
	}

	if (bResult)
	{
		RecomputeBBox	();
		OptimizeMesh	(false);
		RebuildVMaps	();
		ELog.Msg(mtInformation,"Model '%s' converted: %d points, %d faces",
			node->GetName(), GetVertexCount(), GetFaceCount());
	}

	if (bDeleteObj) delete (obj);
	return bResult;
}
コード例 #25
0
int ExportQuake3Model(const TCHAR *filename, ExpInterface *ei, Interface *gi, int start_time, std::list<ExportNode> lTags, std::list<ExportNode> lMeshes)
{
	FILE *file;
	int i, j, totalTags, totalMeshes, current_time = 0;
	long pos_current, totalTris = 0, totalVerts = 0;
	std::list<FrameRange>::iterator range_i;
	std::vector<Point3> lFrameBBoxMin;
	std::vector<Point3> lFrameBBoxMax;
	long pos_tagstart;
	long pos_tagend;
	long pos_filesize;
	long pos_framestart;
	int lazynamesfixed = 0;
	const Point3 x_axis(1, 0, 0);
	const Point3 z_axis(0, 0, 1);

	SceneEnumProc checkScene(ei->theScene, start_time, gi);
	totalTags = (int)lTags.size();
	if (g_tag_for_pivot)
		totalTags++;
	totalMeshes = (int)lMeshes.size();

	// open file
	file = _tfopen(filename, _T("wb"));
	if (!file)
	{
		ExportError("Cannot open file '%s'.", filename);
		return FALSE;
	}
	ExportDebug("%s:", filename);

	// sync pattern and version
	putChars("IDP3", 4, file);
	put32(15, file);
	putChars("Darkplaces MD3 Exporter", 64, file);
	put32(0, file);   // flags
	
	// MD3 header
	ExportState("Writing MD3 header");
	put32(g_total_frames, file);      // how many frames
	put32(totalTags, file);	  // tagsnum
	put32(totalMeshes, file); // meshnum
	put32(1, file);   // maxskinnum
	put32(108, file); // headersize
	pos_tagstart = ftell(file); put32(0, file);   // tagstart
	pos_tagend	= ftell(file);  put32(256, file); // tagend
	pos_filesize = ftell(file); put32(512, file); // filesize
	ExportDebug("    %i frames, %i tags, %i meshes", g_total_frames, totalTags, totalMeshes);

	// frame info
	// bbox arrays get filled while exported mesh and written back then
	ExportState("Writing frame info");
	pos_framestart = ftell(file);
	lFrameBBoxMin.resize(g_total_frames);
	lFrameBBoxMax.resize(g_total_frames);
	for (i = 0; i < g_total_frames; i++)
	{
		// init frame data
		lFrameBBoxMin[i].Set(0, 0, 0);
		lFrameBBoxMax[i].Set(0, 0, 0);
		// put data
		putFloat(-1.0f, file); // bbox min vector
		putFloat(-1.0f, file);
		putFloat(-1.0f, file);	
		putFloat( 1.0f, file); // bbox max vector
		putFloat(1.0f, file);
		putFloat(1.0f, file);
		putFloat(0.0f, file);  // local origin (usually 0 0 0)
		putFloat(0.0f, file);
		putFloat(0.0f, file);
		putFloat(1.0f, file);  // radius of bounding sphere
		putChars("", 16, file);
	}

	// tags
	pos_current = ftell(file);
	fseek(file, pos_tagstart, SEEK_SET);
	put32(pos_current, file);
	fseek(file, pos_current, SEEK_SET);
	
	// for each frame range cycle all frames and write out each tag
	long pos_tags = pos_current;
	if (totalTags)
	{
		long current_frame = 0;
		ExportState("Writing %i tags", totalTags);
		for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
		{
			for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
			{
				SceneEnumProc current_scene(ei->theScene, i * g_ticks_per_frame, gi);
				current_time = current_scene.time;

				// write out tags
				if (lTags.size())
				{
					for (std::list<ExportNode>::iterator tag_i = lTags.begin(); tag_i != lTags.end(); tag_i++)
					{
						INode *node	= current_scene[tag_i->i]->node;
						Matrix3	tm = node->GetObjTMAfterWSM(current_time);

						ExportState("Writing '%s' frame %i of %i", tag_i->name, i, g_total_frames);

						// tagname
						putChars(tag_i->name, 64, file);
						// origin, rotation matrix
						Point3 row = tm.GetRow(3);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
						row = tm.GetRow(0);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
						row = tm.GetRow(1);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
						row = tm.GetRow(2);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
					}
				}

				// write the center of mass tag_pivot which is avg of all objects's pivots
				if (g_tag_for_pivot)
				{
					ExportState("Writing 'tag_pivot' frame %i of %i", i, g_total_frames);

					// write the null data as tag_pivot need to be written after actual geometry
					// (it needs information on frame bound boxes to get proper blendings)
					putChars("tag_pivot", 64, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(1, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(1, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(1, file);
				}
			}
		}
	}

	// write the tag object offsets
	pos_current = ftell(file);
	fseek(file, pos_tagend, SEEK_SET);
	put32(pos_current, file);
	fseek(file, pos_current, SEEK_SET);

	// allocate the structs used to calculate tag_pivot
	std::vector<Point3> tag_pivot_origin;
	std::vector<double> tag_pivot_volume;
	if (g_tag_for_pivot)
	{
		tag_pivot_origin.resize(g_total_frames);
		tag_pivot_volume.resize(g_total_frames);
	}

	// mesh objects
	// for each mesh object write uv and frames
	SceneEnumProc scratch(ei->theScene, start_time, gi);
	ExportState("Writing %i meshes", (int)lMeshes.size());
	for (std::list<ExportNode>::iterator mesh_i = lMeshes.begin(); mesh_i != lMeshes.end(); mesh_i++)
	{
		bool needsDel;

		ExportState("Start mesh #%i", mesh_i);
		INode *node = checkScene[mesh_i->i]->node;
		Matrix3 tm	= node->GetObjTMAfterWSM(start_time);
		TriObject *tri = GetTriObjectFromNode(node, start_time, needsDel);
		if (!tri)
			continue;

		// get mesh, compute normals
		Mesh &mesh = tri->GetMesh();
		MeshNormalSpec *meshNormalSpec = mesh.GetSpecifiedNormals();
		if (meshNormalSpec)
		{
			if (!meshNormalSpec->GetNumFaces())
				meshNormalSpec = NULL;
			else
			{
				meshNormalSpec->SetParent(&mesh);
				meshNormalSpec->CheckNormals();
			}
		}
		mesh.checkNormals(TRUE);

		// fix lazy object names
		ExportState("Attempt to fix mesh name '%s'", mesh_i->name);
		char  meshname[64];
		size_t meshnamelen = min(63, strlen(mesh_i->name));
		memset(meshname, 0, 64);
		strncpy(meshname, mesh_i->name, meshnamelen);
		meshname[meshnamelen] = 0;
		if (!strncmp("Box", meshname, 3)    || !strncmp("Sphere", meshname, 6)  || !strncmp("Cylinder", meshname, 8) ||
            !strncmp("Torus", meshname, 5)  || !strncmp("Cone", meshname, 4)    || !strncmp("GeoSphere", meshname, 9) ||
			!strncmp("Tube", meshname, 4)   || !strncmp("Pyramid", meshname, 7) || !strncmp("Plane", meshname, 5) ||
			!strncmp("Teapot", meshname, 6) || !strncmp("Object", meshname, 6))
		{
name_conflict:
			lazynamesfixed++;
			if (lazynamesfixed == 1)
				strcpy(meshname, "base");
			else
				sprintf(meshname, "base%i", lazynamesfixed);

			// check if it's not used by another mesh
			for (std::list<ExportNode>::iterator m_i = lMeshes.begin(); m_i != lMeshes.end(); m_i++)
				if (!strncmp(m_i->name, meshname, strlen(meshname)))
					goto name_conflict;
			// approve name
			ExportWarning("Lazy object name '%s' (mesh renamed to '%s').", node->GetName(), meshname);
		}

		// special mesh check
		bool shadow_or_collision = false;
		if (g_mesh_special)
			  if (!strncmp("collision", meshname, 9) || !strncmp("shadow", meshname, 6))
				shadow_or_collision = true;

		// get material
		const char *shadername = NULL;
		Texmap *tex = 0;
		Mtl *mtl = 0;
		if (!shadow_or_collision)
		{
			mtl = node->GetMtl();
			if (mtl)
			{
				// check for multi-material
				if (mtl->IsMultiMtl())
				{
					// check if it's truly multi material
					// we do support multi-material with only one texture (some importers set it)
					bool multi_material = false;
					MtlID matId = mesh.faces[0].getMatID();
					for (i = 1; i < mesh.getNumFaces(); i++)
						if (mesh.faces[i].getMatID() != matId)
							multi_material = true;

					if (multi_material)
						if (g_mesh_multimaterials == MULTIMATERIALS_NONE)
							ExportWarning("Object '%s' is multimaterial and using multiple materials on its faces, that case is not yet supported (truncating to first submaterial).", node->GetName());
					
					// switch to submaterial
					mtl = mtl->GetSubMtl(matId);
				}

				// get shader from material if supplied
				char *materialname = GetChar(mtl->GetName());
				if (g_mesh_materialasshader && (strstr(materialname, "/") != NULL || strstr(materialname, "\\") != NULL))
					shadername = GetChar(mtl->GetName());
				else
				{
					// get texture
					tex = mtl->GetSubTexmap(ID_DI);
					if (tex)
					{
						if (tex->ClassID() == Class_ID(BMTEX_CLASS_ID, 0x00))
						{
							shadername = GetChar(((BitmapTex *)tex)->GetMapName());
							if (shadername == NULL || !shadername[0])
								ExportWarning("Object '%s' material '%s' has no bitmap.", tex->GetName(), node->GetName());
						}
						else
						{
							tex = NULL;
							ExportWarning("Object '%s' has material with wrong texture type (only Bitmap are supported).", node->GetName());
						}
					}
					else
						ExportWarning("Object '%s' has material but no texture.", node->GetName());
				}
			}
			else
				ExportWarning("Object '%s' has no material.", node->GetName());
		}

		long pos_meshstart = ftell(file);

		// surface object
		ExportState("Writing mesh '%s' header", meshname);
		putChars("IDP3", 4, file);
		putChars(meshname, 64, file);
		put32(0, file); // flags
		put32(g_total_frames, file);                          // framecount
		put32(1, file);                                       // skincount
		long pos_vertexnum = ftell(file); put32(0, file);     // vertexcount
		put32(mesh.getNumFaces(), file);                      // trianglecount
		long pos_trianglestart = ftell(file); put32(0, file); // start triangles
		put32(108, file);                                     // header size
		long pos_texvecstart = ftell(file); put32(0, file);   // texvecstart
		long pos_vertexstart = ftell(file); put32(16, file);  // vertexstart
		long pos_meshsize = ftell(file); put32(32, file);	  // meshsize

		// write out a single 'skin'
		ExportState("Writing mesh %s texture", meshname);
		if (shadow_or_collision)
			putChars(meshname, 64, file);
		else if (shadername) 
			putMaterial(shadername, mtl, tex, file);
		else
			putChars("noshader", 64, file);
		put32(0, file); // flags

		// build geometry
		ExportState("Building vertexes/triangles");
		std::vector<ExportVertex>vVertexes;
		std::vector<ExportTriangle>vTriangles;
		vVertexes.resize(mesh.getNumVerts());
		int vExtraVerts = mesh.getNumVerts();
		for (i = 0; i < mesh.getNumVerts(); i++)
		{
			vVertexes[i].vert = i;
			vVertexes[i].normalfilled = false;
			// todo: check for coincident verts
		}
		int vNumExtraVerts = 0;

		// check normals
		if (!mesh.normalsBuilt && !shadow_or_collision)
			ExportWarning("Object '%s' does not have normals contructed.", node->GetName());

		// get info for triangles
		const float normal_epsilon = 0.01f;
		vTriangles.resize(mesh.getNumFaces());
		for (i = 0; i < mesh.getNumFaces(); i++)
		{
			DWORD smGroup = mesh.faces[i].getSmGroup();
			ExportState("Mesh %s: checking normals for face %i of %i", meshname, i, mesh.getNumFaces());
			for (j = 0; j < 3; j++)
			{
				int vert = mesh.faces[i].getVert(j);
				vTriangles[i].e[j] = vert;
				// find a right normal for this vertex and save its 'address'
				int vni;
				Point3 vn;
				if (!mesh.normalsBuilt || shadow_or_collision)
				{
					vn.Set(0, 0, 0);
					vni = 0;
				}
				else
				{
					int numNormals;
					RVertex *rv = mesh.getRVertPtr(vert);
					if (meshNormalSpec)
					{  
						ExportState("face %i vert %i have normal specified", i, j);
						// mesh have explicit normals (i.e. Edit Normals modifier)
						vn = meshNormalSpec->GetNormal(i, j);
						vni = meshNormalSpec->GetNormalIndex(i, j);
					}
					else if (rv && rv->rFlags & SPECIFIED_NORMAL)
					{
						ExportState("face %i vert %i have SPECIFIED_NORMAL flag", i, j);
						// SPECIFIED_NORMAL flag
						vn = rv->rn.getNormal();
						vni = 0;
					}
					else if (rv && (numNormals = rv->rFlags & NORCT_MASK) && smGroup)
					{
						// If there is only one vertex is found in the rn member.
						if (numNormals == 1)
						{
							ExportState("face %i vert %i have solid smooth group", i, j);
							vn = rv->rn.getNormal();
							vni = 0;
							
						}
						else
						{
							ExportState("face %i vert %i have mixed smoothing groups", i, j);
							// If two or more vertices are there you need to step through them
							// and find the vertex with the same smoothing group as the current face.
							// You will find multiple normals in the ern member.
							for (int k = 0; k < numNormals; k++)
							{
								if (rv->ern[k].getSmGroup() & smGroup)
								{
									vn = rv->ern[k].getNormal();
									vni = 1 + k;
								}
							}
						}
					}
					else
					{
						ExportState("face %i vert %i flat shaded", i, j);
						// Get the normal from the Face if no smoothing groups are there
						vn = mesh.getFaceNormal(i);
						vni = 0 - (i + 1);
					}
				}

				// subdivide to get all normals right
				if (!vVertexes[vert].normalfilled)
				{
					vVertexes[vert].normal = vn;
					vVertexes[vert].normalindex = vni;
					vVertexes[vert].normalfilled = true;
				}
				else if ((vVertexes[vert].normal - vn).Length() >= normal_epsilon)
				{
					// current vertex not matching normal - it was already filled by different smoothing group
					// find a vert in extra verts in case it was already created
					bool vert_found = false;
					for (int ev = vExtraVerts; ev < (int)vVertexes.size(); ev++)
					{
						if (vVertexes[ev].vert == vert && (vVertexes[ev].normal - vn).Length() < normal_epsilon)
						{
							vert_found = true;
							vTriangles[i].e[j] = ev;
							break;
						}
					}
					// we havent found a vertex, create new
					if (!vert_found)
					{
						ExportVertex NewVert;
						NewVert.vert = vVertexes[vert].vert;
						NewVert.normal = vn;
						NewVert.normalindex = vni;
						NewVert.normalfilled = true;
						vTriangles[i].e[j] = (int)vVertexes.size();
						vVertexes.push_back(NewVert);
						vNumExtraVerts++;
					}
				}
			}
		}
		int vNumExtraVertsForSmoothGroups = vNumExtraVerts;

		// generate UV map
		// VorteX: use direct maps reading since getNumTVerts()/getTVert is deprecated
		//  max sets two default mesh maps: 0 - vertex color, 1 : UVW, 2 & up are custom ones
		ExportState("Building UV map");
		std::vector<ExportUV>vUVMap;
		vUVMap.resize(vVertexes.size());
		int meshMap = 1;
		if (!mesh.mapSupport(meshMap) || !mesh.getNumMapVerts(meshMap) || shadow_or_collision)
		{
			for (i = 0; i < mesh.getNumVerts(); i++)
			{
				vUVMap[i].u = 0.5;
				vUVMap[i].v = 0.5;
			}
			if (!shadow_or_collision)
				ExportWarning("No UV mapping was found on object '%s'.", node->GetName());
		}
		else
		{
			UVVert *meshUV = mesh.mapVerts(meshMap);
			for (i = 0; i < (int)vTriangles.size(); i++)
			{
				ExportState("Mesh %s: converting tvert for face %i of %i", meshname, i, (int)vTriangles.size());
				// for 3 face vertexes
				for (j = 0; j < 3; j++)
				{
					int vert = vTriangles[i].e[j];
					int tv = mesh.tvFace[i].t[j];
					UVVert &UV = meshUV[tv];

					if (!vUVMap[vert].filled)
					{
						// fill uvMap vertex
						vUVMap[vert].u = UV.x;
						vUVMap[vert].v = UV.y;
						vUVMap[vert].filled = true;
						vUVMap[vert].tvert = tv;
					}
					else if (tv != vUVMap[vert].tvert)
					{
						// uvMap slot for this vertex has been filled
						// we should arrange triangle to other vertex, which not filled and having same shading and uv
						// check if any of the extra vertices can fit
						bool vert_found = false;
						for (int ev = vExtraVerts; ev < (int)vVertexes.size(); ev++)
						{
							if (vVertexes[ev].vert == vert && vUVMap[vert].u == UV.x &&vUVMap[vert].v == UV.y  && (vVertexes[ev].normal - vVertexes[vert].normal).Length() < normal_epsilon)
							{
								vert_found = true;
								vTriangles[i].e[j] = vVertexes[ev].vert;
								break;
							}
						}
						if (!vert_found)
						{
							// create new vert
							ExportVertex NewVert;
							NewVert.vert = vVertexes[vert].vert;
							NewVert.normal = vVertexes[vert].normal;
							NewVert.normalindex = vVertexes[vert].normalindex;
							NewVert.normalfilled = vVertexes[vert].normalfilled;
							vTriangles[i].e[j] = (int)vVertexes.size();
							vVertexes.push_back(NewVert);
							vNumExtraVerts++;
							// create new TVert
							ExportUV newUV;
							newUV.filled = true;
							newUV.u = UV.x;
							newUV.v = UV.y;
							newUV.tvert = tv;
							vUVMap.push_back(newUV);
						}
					}
				}
			}
		}
		int vNumExtraVertsForUV = (vNumExtraVerts - vNumExtraVertsForSmoothGroups);

		// print some debug stats
		ExportDebug("    mesh %s: %i vertexes +%i %s +%i UV, %i triangles", meshname, ((int)vVertexes.size() - vNumExtraVerts), vNumExtraVertsForSmoothGroups, meshNormalSpec ? "EditNormals" : "SmoothGroups", vNumExtraVertsForUV, (int)vTriangles.size());

		// fill in triangle start
		pos_current = ftell(file);
		fseek(file, pos_trianglestart, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);

		// detect if object have negative scale (mirrored)
		// in this canse we should rearrange triangles counterclockwise
		// so stuff will not be inverted
		ExportState("Mesh %s: writing %i triangles", meshname, (int)vTriangles.size());
		if (DotProd(CrossProd(tm.GetRow(0), tm.GetRow(1)), tm.GetRow(2)) < 0.0)
		{
			ExportWarning("Object '%s' is mirrored (having negative scale on it's transformation)", node->GetName());
			for (i = 0; i < (int)vTriangles.size(); i++)
			{
				put32(vTriangles[i].b, file);	// vertex index
				put32(vTriangles[i].c, file);	// for 3 vertices
				put32(vTriangles[i].a, file);	// of triangle
			}
		}
		else
		{
			for (i = 0; i < (int)vTriangles.size(); i++)
			{
				put32(vTriangles[i].a, file);	// vertex index
				put32(vTriangles[i].c, file);	// for 3 vertices
				put32(vTriangles[i].b, file);	// of triangle
			}
		}

		// fill in texvecstart
		// write out UV mapping coords.
		ExportState("Mesh %s: writing %i UV vertexes", meshname, (int)vUVMap.size());
		pos_current = ftell(file);
		fseek(file, pos_texvecstart, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);
		for (i = 0; i < (int)vUVMap.size(); i++)
		{
			putFloat(vUVMap[i].u, file); // texture coord u,v
			putFloat(1.0f - vUVMap[i].v, file);	// for vertex
		}
		vUVMap.clear();

		// fill in vertexstart
		pos_current = ftell(file);
		fseek(file, pos_vertexstart, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);

		// fill in vertexnum
		pos_current = ftell(file);
		fseek(file, pos_vertexnum, SEEK_SET);
		put32((int)vVertexes.size(), file);
		fseek(file, pos_current, SEEK_SET);

		// write out for each frame the position of each vertex
		long current_frame = 0;
		ExportState("Mesh %s: writing %i frames", meshname, g_total_frames);
		for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
		{
			for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
			{
				bool _needsDel;

				// get triobject for current frame
				SceneEnumProc current_scene(ei->theScene, i * g_ticks_per_frame, gi);
				current_time = current_scene.time;
				INode *_node = current_scene[mesh_i->i]->node;
				TriObject *_tri	= GetTriObjectFromNode(_node, current_time, _needsDel);
				if (!_tri)
					continue;

				// get mesh, compute normals
				Mesh &_mesh	= _tri->GetMesh();
				MeshNormalSpec *_meshNormalSpec = _mesh.GetSpecifiedNormals();
				if (_meshNormalSpec)
				{
					if (!_meshNormalSpec->GetNumFaces())
						_meshNormalSpec = NULL;
					else
					{
						_meshNormalSpec->SetParent(&_mesh);
						_meshNormalSpec->CheckNormals();
					}
				}
				_mesh.checkNormals(TRUE);

				// get transformations for current frame
				Matrix3 _tm	= _node->GetObjTMAfterWSM(current_time);

				ExportState("Mesh %s: writing frame %i of %i", meshname, current_frame, g_total_frames);

				Point3 BoxMin(0, 0, 0);
				Point3 BoxMax(0, 0, 0);
				for (j = 0; j < (int)vVertexes.size(); j++) // number of vertices
				{
					ExportState("Mesh %s: transform vertex %i of %i", meshname, j, (int)vVertexes.size());

					int vert = vVertexes[j].vert;
					Point3 &v = _tm.PointTransform(_mesh.getVert(vert));
					
					// populate bbox data
					if (!shadow_or_collision)
					{
						BoxMin.x = min(BoxMin.x, v.x);
						BoxMin.y = min(BoxMin.y, v.y);
						BoxMin.z = min(BoxMin.z, v.z);
						BoxMax.x = max(BoxMax.x, v.x);
						BoxMax.y = max(BoxMax.y, v.y);
						BoxMax.z = max(BoxMax.z, v.z);
					}

					// write vertex
					double f;
					f = v.x * 64.0f; if (f < -32768.0) f = -32768.0; if (f > 32767.0) f = 32767.0; put16((short)f, file);
					f = v.y * 64.0f; if (f < -32768.0) f = -32768.0; if (f > 32767.0) f = 32767.0; put16((short)f, file);
					f = v.z * 64.0f; if (f < -32768.0) f = -32768.0; if (f > 32767.0) f = 32767.0; put16((short)f, file);

					// get normal
					ExportState("Mesh %s: transform vertex normal %i of %i", meshname, j, (int)vVertexes.size());
					Point3 n;
					if (_meshNormalSpec) // mesh have explicit normals (i.e. Edit Normals modifier)
						n = _meshNormalSpec->Normal(vVertexes[j].normalindex);
					else if (!vVertexes[j].normalfilled || !_mesh.normalsBuilt)
						n = _mesh.getNormal(vert);
					else
					{
						RVertex *rv = _mesh.getRVertPtr(vert);
						if (vVertexes[j].normalindex < 0)
							n = _mesh.getFaceNormal((0 - vVertexes[j].normalindex) - 1);
						else if (vVertexes[j].normalindex == 0)
							n = rv->rn.getNormal();
						else 
							n = rv->ern[vVertexes[j].normalindex - 1].getNormal();
					}

					// transform normal
					Point3 &nt = _tm.VectorTransform(n).Normalize();

					// encode a normal vector into a 16-bit latitude-longitude value
					double lng = acos(nt.z) * 255 / (2 * pi);
					double lat = atan2(nt.y, nt.x) * 255 / (2 * pi);
					put16((((int)lat & 0xFF) << 8) | ((int)lng & 0xFF), file);
				}

				// blend the pivot positions for tag_pivot using mesh's volumes for blending power
				if (g_tag_for_pivot && !shadow_or_collision)
				{
					ExportState("Mesh %s: writing tag_pivot", meshname);

					Point3 Size = BoxMax - BoxMin;
					double BoxVolume = pow(Size.x * Size.y * Size.z, 0.333f);

					// blend matrices
					float blend = (float)(BoxVolume / (BoxVolume + tag_pivot_volume[current_frame]));
					float iblend = 1 - blend;
					tag_pivot_volume[current_frame]   = tag_pivot_volume[current_frame] + BoxVolume;
					Point3 row = _tm.GetRow(3) - _node->GetObjOffsetPos();
					tag_pivot_origin[current_frame].x = tag_pivot_origin[current_frame].x * iblend + row.x * blend;
					tag_pivot_origin[current_frame].y = tag_pivot_origin[current_frame].y * iblend + row.y * blend;
					tag_pivot_origin[current_frame].z = tag_pivot_origin[current_frame].z * iblend + row.z * blend;
				}

				// populate bbox data for frames
				lFrameBBoxMin[current_frame].x = min(lFrameBBoxMin[current_frame].x, BoxMin.x);
				lFrameBBoxMin[current_frame].y = min(lFrameBBoxMin[current_frame].y, BoxMin.y);
				lFrameBBoxMin[current_frame].z = min(lFrameBBoxMin[current_frame].z, BoxMin.z);
				lFrameBBoxMax[current_frame].x = max(lFrameBBoxMax[current_frame].x, BoxMax.x);
				lFrameBBoxMax[current_frame].y = max(lFrameBBoxMax[current_frame].y, BoxMax.y);
				lFrameBBoxMax[current_frame].z = max(lFrameBBoxMax[current_frame].z, BoxMax.z);

				// delete the working object, if necessary.
				if (_needsDel)
					delete _tri;
			}
		}

		// delete if necessary
		if (needsDel)
			delete tri;

		// fill in meshsize
		pos_current = ftell(file);
		fseek(file, pos_meshsize, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);  

		// reset back to first frame
		SceneEnumProc scratch(ei->theScene, start_time, gi);
		totalTris += (long)vTriangles.size();
		totalVerts += (long)vVertexes.size();
		vTriangles.clear();
		vVertexes.clear();
	}

	// write tag_pivot
	ExportState("Writing tag_pivot positions");
	if (g_tag_for_pivot)
	{
		pos_current = ftell(file);
		long current_frame = 0;
		for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
		{
			for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
			{
				fseek(file, pos_tags + totalTags*112*current_frame + (int)lTags.size()*112 + 64, SEEK_SET);
				// origin
				putFloat(tag_pivot_origin[current_frame].x, file);
				putFloat(tag_pivot_origin[current_frame].y, file);
				putFloat(tag_pivot_origin[current_frame].z, file);
			}
		}
		fseek(file, pos_current, SEEK_SET);
	}
	tag_pivot_volume.clear();
	tag_pivot_origin.clear();

	// write frame data
	ExportState("Writing culling info");
	long current_frame = 0;
	pos_current = ftell(file);
	for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
	{
		for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
		{
			fseek(file, pos_framestart + current_frame*56, SEEK_SET);
			putFloat(lFrameBBoxMin[current_frame].x, file);	// bbox min vector
			putFloat(lFrameBBoxMin[current_frame].y, file);
			putFloat(lFrameBBoxMin[current_frame].z, file);	
			putFloat(lFrameBBoxMax[current_frame].x, file); // bbox max vector
			putFloat(lFrameBBoxMax[current_frame].y, file);
			putFloat(lFrameBBoxMax[current_frame].z, file);
			putFloat(0, file); // local origin (usually 0 0 0)
			putFloat(0, file);
			putFloat(0, file);
			putFloat(max(lFrameBBoxMin[current_frame].Length(), lFrameBBoxMax[current_frame].Length()) , file); // radius of bounding sphere
		}
	}
	fseek(file, pos_current, SEEK_SET);
	lFrameBBoxMin.clear();
	lFrameBBoxMax.clear();

	// fill in filesize
	pos_current = ftell(file);
	fseek(file, pos_filesize, SEEK_SET);
	put32(pos_current, file);
	fseek(file, pos_current, SEEK_SET);

	fclose(file);

	ExportDebug("    total: %i vertexes, %i triangles", totalVerts, totalTris);

	return TRUE;
}
コード例 #26
0
ファイル: GmUtil.cpp プロジェクト: TheRyaz/c_reading
static void extractTriangleGeometry( GmModel* gm, INode* node, Mesh* mesh, Mtl* material )
{
#ifdef SGEXPORT_PHYSIQUE
	Modifier*			phyMod		= 0;
	IPhysiqueExport*	phyExport	= 0;
	IPhyContextExport*	mcExport	= 0;
#endif
	Modifier*			skinMod		= 0;
	ISkin*				skin		= 0;
	String				nodeName	( node->GetName() );

	try
	{
		// vertex transform to left-handed system
		Matrix3 pivot = TmUtil::getPivotTransform( node );
		Matrix3 vertexTM = pivot * s_convtm;
		bool insideOut = TmUtil::hasNegativeParity( pivot );

		/*Matrix4x4 pm = TmUtil::toLH( vertexTM );
		Debug::println( "Object {0} vertex local TM is", nodeName );
		Debug::println( "  {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(0,0), pm(0,1), pm(0,2), pm(0,3) );
		Debug::println( "  {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(1,0), pm(1,1), pm(1,2), pm(1,3) );
		Debug::println( "  {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(2,0), pm(2,1), pm(2,2), pm(2,3) );
		Debug::println( "  {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(3,0), pm(3,1), pm(3,2), pm(3,3) );*/

		// add vertex positions
		int vertices = mesh->getNumVerts();
		for ( int vi = 0 ; vi < vertices ; ++vi )
		{
			Point3 v = vertexTM * mesh->verts[vi];
			mb::Vertex* vert = gm->addVertex();
			vert->setPosition( v.x, v.y, v.z );
		}

		// add vertex weights (from Physique modifier)
#ifdef SGEXPORT_PHYSIQUE
		phyMod = PhyExportUtil::findPhysiqueModifier( node );
		if ( phyMod )
		{
			Debug::println( "  Found Physique modifier: {0}", gm->name );

			// get (possibly shared) Physique export interface
			phyExport = (IPhysiqueExport*)phyMod->GetInterface( I_PHYINTERFACE );
			if( !phyExport )
				throw Exception( Format("No Physique modifier export interface") );

			// export from initial pose?
			phyExport->SetInitialPose( false );
			
			// get (unique) context dependent export inteface
			mcExport = (IPhyContextExport*)phyExport->GetContextInterface( node );
			if( !mcExport )
				throw Exception( Format("No Physique modifier context export interface") );

			// convert to rigid for time independent vertex assignment
			mcExport->ConvertToRigid( true );

			// allow blending to export multi-link assignments
			mcExport->AllowBlending( true );

			// list bones
			Vector<INode*> bones( Allocator<INode*>(__FILE__,__LINE__) );
			PhyExportUtil::listBones( mcExport, bones );

			// add vertex weight maps
			for ( int i = 0 ; i < bones.size() ; ++i )
			{
				INode* bone = bones[i];
				String name = bone->GetName();
				mb::VertexMap* vmap = gm->addVertexMap( 1, name, mb::VertexMapFormat::VERTEXMAP_WEIGHT );
				PhyExportUtil::addWeights( vmap, bone, mcExport );
			}
		}
#endif // SGEXPORT_PHYSIQUE

		// add vertex weights (from Skin modifier)
		skinMod = SkinExportUtil::findSkinModifier( node );
		if ( skinMod )
		{
			skin = (ISkin*)skinMod->GetInterface(I_SKIN);
			require( skin );
			ISkinContextData* skincx = skin->GetContextInterface( node );
			require( skincx );
			Debug::println( "  Found Skin modifier: {0} ({1} bones, {2} points)", gm->name, skin->GetNumBones(), skincx->GetNumPoints() );
			
			if ( skincx->GetNumPoints() != gm->vertices() )
				throw Exception( Format("Only some vertices ({0}/{1}) of {2} are skinned", skincx->GetNumPoints(), gm->vertices(), gm->name) );

			// list bones
			Vector<INode*> bones( Allocator<INode*>(__FILE__,__LINE__) );
			SkinExportUtil::listBones( skin, bones );

			// add vertex weight maps
			for ( int i = 0 ; i < bones.size() ; ++i )
			{
				INode* bone = bones[i];
				String name = bone->GetName();
				mb::VertexMap* vmap = gm->addVertexMap( 1, name, mb::VertexMapFormat::VERTEXMAP_WEIGHT );
				SkinExportUtil::addWeights( vmap, bone, skin, skincx );
				//Debug::println( "    Bone {0} is affecting {1} vertices", name, vmap->size() );
			}

			// DEBUG: print skin node tm and initial object tm
			/*Matrix3 tm;
			int ok = skin->GetSkinInitTM( node, tm );
			require( ok == SKIN_OK );
			Debug::println( "  NodeInitTM of {0}", nodeName );
			TmUtil::println( tm, 4 );
			ok = skin->GetSkinInitTM( node, tm, true );
			require( ok == SKIN_OK );
			Debug::println( "  NodeObjectTM of {0}", nodeName );
			TmUtil::println( tm, 4 );*/

			// DEBUG: print bones
			/*Debug::println( "  bones of {0}:", nodeName );
			for ( int i = 0 ; i < bones.size() ; ++i )
			{
				Debug::println( "    bone ({0}): {1}", i, String(bones[i]->GetName()) );
				skin->GetBoneInitTM( bones[i], tm );
				Debug::println( "      InitNodeTM:" );
				TmUtil::println( tm, 6 );
				skin->GetBoneInitTM( bones[i], tm, true );
				Debug::println( "      InitObjectTM:" );
				TmUtil::println( tm, 6 );
			}*/

			// DEBUG: print bones used by the points
			/*for ( int i = 0 ; i < skincx->GetNumPoints() ; ++i )
			{
				int bonec = skincx->GetNumAssignedBones(i);
				Debug::println( "    point {0} has {1} bones", i, bonec );
				for ( int k = 0 ; k < bonec ; ++k )
				{
					int boneidx = skincx->GetAssignedBone( i, k );
					float w = skincx->GetBoneWeight( i, k );
					Debug::println( "    point {0} boneidx ({1}): {2}, weight {3}", i, k, boneidx, w );
				}
			}*/
		}

		// ensure clockwise polygon vertex order
		int vx[3] = {2,1,0};
		if ( insideOut )
		{
			int tmp = vx[0];
			vx[0] = vx[2];
			vx[2] = tmp;
		}
	
		// list unique materials used by the triangles
		Vector<ShellMaterial> usedMaterials( Allocator<ShellMaterial>(__FILE__,__LINE__) );
		if ( material )
		{
			for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi )
			{
				Face& face = mesh->faces[fi];
				
				int mergesubmaterial = -1;
				int originalsubmaterial = -1;

				for ( int j = 0; j < material->NumSubMtls(); ++j)
				{
					// Get Sub Material Slot name 
					TSTR name = material->GetSubMtlSlotName(j);

					// Light maps are stored in sub material slot named "Baked Material"
					if ( strcmp( name, "Baked Material" ) == 0 ) 
						mergesubmaterial = j;
					else 
						originalsubmaterial = j;				
				}

				if ( mergesubmaterial != -1 ) // A baked material was found, shell materials will be created
				{
					Mtl* mat = material->GetSubMtl( originalsubmaterial );
					Mtl* bakedmtl = material->GetSubMtl( mergesubmaterial );
				
					if ( mat->NumSubMtls() > 0 ) // Check for nested multi-material
					{
						for ( int j = 0; j < mat->NumSubMtls(); ++j)
							usedMaterials.add( ShellMaterial( mat->GetSubMtl( face.getMatID() % mat->NumSubMtls() ), bakedmtl ) );
					} else
						usedMaterials.add( ShellMaterial( mat, bakedmtl ) );
				}
				else if ( material->NumSubMtls() > 0 ) // Multi-material without baked material 
				{  
					usedMaterials.add( ShellMaterial( material->GetSubMtl( face.getMatID() % material->NumSubMtls() ), 0 ) ); 
				}
				else	// Single material without baked material
				{
					usedMaterials.add( ShellMaterial( material, 0 ) );
				}				
			}
			std::sort( usedMaterials.begin(), usedMaterials.end() );
			usedMaterials.setSize( std::unique( usedMaterials.begin(), usedMaterials.end() ) - usedMaterials.begin() );
		}

		// create used materials
		for ( int mi = 0 ; mi < usedMaterials.size() ; ++mi )
		{
			ShellMaterial shellmtl = usedMaterials[mi];
			gm->materials.add( GmUtil::createGmMaterial( shellmtl.original, shellmtl.baked ) );
		}

		// add triangles
		for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi )
		{
			mb::Polygon* poly = gm->addPolygon();

			// triangle indices
			Face& face = mesh->faces[fi];
			for ( int vxi = 0 ; vxi < 3 ; ++vxi )
			{
				int vi = face.v[ vx[vxi] ];
				require( vi >= 0 && vi < gm->vertices() );
				mb::Vertex* vert = gm->getVertex( vi );
				poly->addVertex( vert );
			}

			// triangle material
			int polyMaterialIndex = 0;
			if ( material )
			{
				ShellMaterial mat( material, 0 );
				
				int numsubmaterials = material->NumSubMtls();  

				if ( numsubmaterials > 0 )
				{
					mat.original = material->GetSubMtl( face.getMatID() % material->NumSubMtls() );
		
					for ( int j = 0; j < numsubmaterials; ++j) // Is baked material present?
					{
						TSTR name = material->GetSubMtlSlotName(j);
						if ( strcmp( name, "Baked Material" ) == 0 )
							mat.baked = material->GetSubMtl( j );
						if ( strcmp( name, "Original Material" ) == 0 )
							mat.original = material->GetSubMtl( j );
					}
					if ( mat.original->NumSubMtls() > 0 )  // Is there a nested multi-material?
					{
						mat.original = mat.original->GetSubMtl( face.getMatID() % mat.original->NumSubMtls() );
					}
				}

				for ( int mi = 0 ; mi < usedMaterials.size() ; ++mi )
				{
					if ( usedMaterials[mi] == mat )
					{
						polyMaterialIndex = mi;
						break;
					}
				}
			}
			poly->setMaterial( polyMaterialIndex );
		}

		// add vertex colors
		int mp = 0;
		if ( mesh->mapSupport(mp) && mesh->getNumMapVerts(mp) > 0 )
		{
			mb::DiscontinuousVertexMap* vmad = gm->addDiscontinuousVertexMap( 3, "rgb", mb::VertexMapFormat::VERTEXMAP_RGB );

			int tverts = mesh->getNumMapVerts( mp );
			UVVert* tvert = mesh->mapVerts( mp );
			TVFace* tface = mesh->mapFaces( mp );

			//Debug::println( "Vertex colors:" );
			for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi )
			{
				Face& face = mesh->faces[fi];
				mb::Polygon* poly = gm->getPolygon( fi );

				for ( int vxi = 0 ; vxi < 3 ; ++vxi )
				{
					int vi = face.v[ vx[vxi] ];
					mb::Vertex* vert = gm->getVertex( vi );
					Point3 tc = tvert[ tface[fi].t[ vx[vxi] ] % tverts ];
					float rgb[3] = {tc.x, tc.y, tc.z};
					vmad->addValue( vert->index(), poly->index(), rgb, 3 );
					//Debug::println( "  vertex[{0}].rgb: {1} {2} {3}", vert->index(), rgb[0], rgb[1], rgb[2] );
				}
			}
		}

		// add texcoord layers
		int lastCoords = MAX_MESHMAPS-2;
		while ( lastCoords > 0 && (!mesh->mapSupport(lastCoords) || 0 == mesh->getNumMapVerts(lastCoords)) )
			--lastCoords;
		if ( lastCoords > 8 )
			throw IOException( Format("Too many texture coordinate sets ({1}) in {0}", gm->name, lastCoords) );

		for ( mp = 1 ; mp <= lastCoords ; ++mp )
		{
			mb::DiscontinuousVertexMap* vmad = gm->addDiscontinuousVertexMap( 2, "uv", mb::VertexMapFormat::VERTEXMAP_TEXCOORD );

			if ( mesh->mapSupport(mp) && mesh->getNumMapVerts(mp) > 0 )
			{
				int tverts = mesh->getNumMapVerts( mp );
				UVVert* tvert = mesh->mapVerts( mp );
				TVFace* tface = mesh->mapFaces( mp );
				
				for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi )
				{
					Face& face = mesh->faces[fi];
					mb::Polygon* poly = gm->getPolygon( fi );

					for ( int vxi = 0 ; vxi < 3 ; ++vxi )
					{
						int vi = face.v[ vx[vxi] ];
						mb::Vertex* vert = gm->getVertex( vi );
						Point3 tc = tvert[ tface[fi].t[ vx[vxi] ] % tverts ];
						float uv[2] = {tc.x, 1.f-tc.y};
						vmad->addValue( vert->index(), poly->index(), uv, 2 );
					}
				}
			}
		}

		// compute face vertex normals from smoothing groups
		require( mesh->getNumFaces() == gm->polygons() );
		mb::DiscontinuousVertexMap* vmad = gm->addDiscontinuousVertexMap( 3, "vnormals", mb::VertexMapFormat::VERTEXMAP_NORMALS );
		for ( int fi = 0 ; fi < gm->polygons() ; ++fi )
		{
			mb::Polygon* poly = gm->getPolygon( fi );
			require( poly );
			require( poly->index() >= 0 && poly->index() < mesh->getNumFaces() );
			Face& face = mesh->faces[ poly->index() ];

			require( poly->vertices() == 3 );
			for ( int j = 0 ; j < poly->vertices() ; ++j )
			{
				Vector3 vn(0,0,0);
				mb::Vertex* vert = poly->getVertex( j );

				// sum influencing normals
				for ( int k = 0 ; k < vert->polygons() ; ++k )
				{
					mb::Polygon* vpoly = vert->getPolygon( k );
					require( vpoly );
					require( vpoly->index() >= 0 && vpoly->index() < mesh->getNumFaces() );
					Face& vface = mesh->faces[ vpoly->index() ];

					if ( 0 != (face.smGroup & vface.smGroup) || poly == vpoly )
					{
						Vector3 vpolyn;
						vpoly->getNormal( &vpolyn.x, &vpolyn.y, &vpolyn.z );
						vn += vpolyn;
					}
				}

				// normalize
				float lensqr = vn.lengthSquared();
				if ( lensqr > Float::MIN_VALUE )
					vn *= 1.f / Math::sqrt(lensqr);
				else
					vn = Vector3(0,0,0);

				vmad->addValue( vert->index(), poly->index(), vn.begin(), 3 );
			}
		}

		// re-export mesh points in non-deformed pose if Skin modifier present
		// NOTE: 3ds Mesh must not be used after this, because collapsing can invalidate it
		if ( skin )
		{
			// evaluate derived object before Skin modifier
			TimeValue time = 0;
			bool evalNext = false;
			bool evalDone = false;
			::ObjectState os;
			::Object* obj = node->GetObjectRef();
			while ( obj->SuperClassID() == GEN_DERIVOB_CLASS_ID && !evalDone )
			{
				IDerivedObject* derivedObj = static_cast<IDerivedObject*>(obj);
				for ( int modStack = 0 ; modStack < derivedObj->NumModifiers() ; ++modStack )
				{
					if ( evalNext )
					{
						os = derivedObj->Eval( time, modStack );
						evalDone = true;
						break;
					}

					Modifier* mod = derivedObj->GetModifier(modStack);
					if ( mod->ClassID() == SKIN_CLASSID )
						evalNext = true;
				}
				obj = derivedObj->GetObjRef();
			}

			// evaluate possible non-derived object
			if ( evalNext && !evalDone )
			{
				os = obj->Eval( time );
				evalDone = true;
			}

			// convert to TriObject and get points
			if ( evalDone && os.obj->CanConvertToType( Class_ID(TRIOBJ_CLASS_ID,0) ) )
			{
				Debug::println( "  Evaluating object {0} before Skin modifier", nodeName );

				// get TriObject
				std::auto_ptr<TriObject> triAutoDel(0);
				TriObject* tri = static_cast<TriObject*>( os.obj->ConvertToType( time, Class_ID(TRIOBJ_CLASS_ID,0) ) );
				if ( tri != os.obj )
					triAutoDel = std::auto_ptr<TriObject>( tri );

				// get mesh points before Skin is applied
				//Debug::println( "  Original collapsed mesh has {0} points, before Skin modifier {1} points", mesh->getNumVerts(), tri->mesh.getNumVerts() );
				require( gm->vertices() == tri->mesh.getNumVerts() );
				Mesh* mesh = &tri->mesh;
				int vertices = mesh->getNumVerts();
				for ( int vi = 0 ; vi < vertices ; ++vi )
				{
					Point3 v = vertexTM * mesh->verts[vi];
					mb::Vertex* vert = gm->getVertex( vi );
					vert->setPosition( v.x, v.y, v.z );
				}
			}
		}

		// split vertices with discontinuous vertex map values
		for ( int vmi = 0 ; vmi < gm->discontinuousVertexMaps() ; ++vmi )
		{
			mb::DiscontinuousVertexMap* vmad = gm->getDiscontinuousVertexMap( vmi );
			gm->splitVertexDiscontinuities( vmad );
		}

		// find base texcoord layer
		mb::DiscontinuousVertexMap* texcoords = 0;
		for ( int i = 0 ; i < gm->discontinuousVertexMaps() ; ++i )
		{
			mb::DiscontinuousVertexMap* vmad = gm->getDiscontinuousVertexMap(i);
			if ( vmad->dimensions() == 2 && vmad->format() == mb::VertexMapFormat::VERTEXMAP_TEXCOORD )
			{
				texcoords = vmad;
				break;
			}
		}
		if ( !texcoords )
			Debug::printlnError( "Object {0} must have texture coordinates", gm->name );
			// requires identification of footsteps in MySceneExport::isExportableGeometry
			//throw IOException( Format("Object {0} must have texture coordinates", gm->name) );

		// optimize
		gm->removeUnusedVertices();

		// cleanup export interfaces
#ifdef SGEXPORT_PHYSIQUE
		if ( mcExport )
		{
			require( phyExport );
			phyExport->ReleaseContextInterface( mcExport );
			mcExport = 0;
		}
		if ( phyExport )
		{
			require( phyMod );
			phyMod->ReleaseInterface( I_PHYINTERFACE, phyExport );
			phyExport = 0;
		}
#endif // SGEXPORT_PHYSIQUE
		if ( skin )
		{
			skinMod->ReleaseInterface( I_SKIN, skin );
			skin = 0;
			skinMod = 0;
		}
	}
	catch ( ... )
	{
		// cleanup export interfaces
#ifdef SGEXPORT_PHYSIQUE
		if ( mcExport )
		{
			require( phyExport );
			phyExport->ReleaseContextInterface( mcExport );
			mcExport = 0;
		}
		if ( phyExport )
		{
			require( phyMod );
			phyMod->ReleaseInterface( I_PHYINTERFACE, phyExport );
			phyExport = 0;
		}
#endif // SGEXPORT_PHYSIQUE
		if ( skin )
		{
			skinMod->ReleaseInterface( I_SKIN, skin );
			skin = 0;
			skinMod = 0;
		}
		throw;
	}
}
コード例 #27
0
void plTextureSearch::IUpdateTextures(plTextureSearch::Update update)
{
    MtlSet mtls;
    plMtlCollector::GetMtls(&mtls, nil, plMtlCollector::kPlasmaOnly | plMtlCollector::kNoMultiMtl);

    char searchStr[256];
    GetDlgItemText(fDlg, IDC_FIND_EDIT, searchStr, sizeof(searchStr));
    strlwr(searchStr);

    HWND hList = GetDlgItem(fDlg, IDC_TEXTURE_LIST);
    ListView_DeleteAllItems(hList);

    int sizeX = -1, sizeY = -1;

    HWND hCombo = GetDlgItem(fDlg, IDC_SIZE_COMBO);

    // If we're updating the size, get whatever the user selected
    if (update == kUpdateSetSize)
    {
        int sel = ComboBox_GetCurSel(hCombo);
        uint32_t data = ComboBox_GetItemData(hCombo, sel);
        sizeX = LOWORD(data);
        sizeY = HIWORD(data);
    }

    MtlSet::iterator it = mtls.begin();
    for (; it != mtls.end(); it++)
    {
        Mtl *mtl = (*it);

        LayerSet layers;
        plMtlCollector::GetMtlLayers(mtl, layers);

        LayerSet::iterator layerIt = layers.begin();
        for (; layerIt != layers.end(); layerIt++)
        {
            plPlasmaMAXLayer *layer = (*layerIt);

            int numBitmaps = layer->GetNumBitmaps();

            for (int i = 0; i < numBitmaps; i++)
            {
                PBBitmap *pbbm = layer->GetPBBitmap(i);
                if (pbbm)
                {
                    const char *name = pbbm->bi.Filename();
                    if (name && *name != '\0')
                    {
                        char buf[256];
                        strncpy(buf, name, sizeof(buf));
                        strlwr(buf);

                        // If we don't have a search string, or we do and it was
                        // found in the texture name, add the texture to the list.
                        if (searchStr[0] == '\0' || strstr(buf, searchStr))
                        {
                            if (update == kUpdateLoadList)
                            {
                                LVITEM item = {0};
                                item.mask = LVIF_TEXT | LVIF_PARAM;
                                item.pszText = mtl->GetName();
                                item.lParam = (LPARAM)mtl;  // A little dangerous, since the user could delete this
                                int idx = ListView_InsertItem(hList, &item);

                                ListView_SetItemText(hList, idx, 1, layer->GetName());
                                ListView_SetItemText(hList, idx, 2, (char*)name);

                                // If size is uninitialized or the same as the last, keep size
                                if ((sizeX == -1 && sizeY == -1) || (sizeX == pbbm->bi.Width() && sizeY == pbbm->bi.Height()))
                                {
                                    sizeX = pbbm->bi.Width();
                                    sizeY = pbbm->bi.Height();
                                }
                                // Otherwise clear it
                                else
                                {
                                    sizeX = sizeY = 0;
                                }
                            }
                            else if (update == kUpdateReplace)
                            {
#ifdef MAXASS_AVAILABLE
                                layer->SetBitmapAssetId(gAssetID, i);
#endif

                                BitmapInfo info;
                                info.SetName(fFileName);
                                layer->SetBitmap(&info, i);
                            }
                            else if (update == kUpdateSetSize)
                            {
                                layer->SetExportSize(sizeX, sizeY);
                            }
                        }
                    }
                }
            }
        }
    }

    if (update == kUpdateLoadList)
    {
        HWND hButton = GetDlgItem(fDlg, IDC_SET_ALL_BUTTON);
        ComboBox_ResetContent(hCombo);

        // If all bitmaps are the same size, enable resizing
        if (sizeX != -1 && sizeX != 0)
        {
            sizeX = FloorPow2(sizeX);
            sizeY = FloorPow2(sizeY);

            char buf[256];

            while (sizeX >= 4 && sizeY >= 4)
            {
                sprintf(buf, "%d x %d", sizeX, sizeY);
                int idx = ComboBox_AddString(hCombo, buf);
                ComboBox_SetItemData(hCombo, idx, MAKELPARAM(sizeX, sizeY));

                sizeX >>= 1;
                sizeY >>= 1;
            }

            ComboBox_SetCurSel(hCombo, 0);

            EnableWindow(hCombo, TRUE);
            EnableWindow(hButton, TRUE);
        }
コード例 #28
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;
			}
		}
	}
}
コード例 #29
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);
}
コード例 #30
0
ファイル: DxStdMtl2.cpp プロジェクト: whztt07/OgreGameProject
int DxStdMtl2::GetMatIndex(Mtl * m_Mtl)
{
	int				i;
	Mtl			*Std;
	StdMat2  * Shader;
	//	MaxShader   *Shader, *s;


	if(m_Mtl->IsMultiMtl())
	{
		Shader = (StdMat2 *)GetRefTarg();

		// I use the SubAnims here, as I do not want any NULL material introduced that are not visible to the user
		// this can happen when you have N materials and you select N+1 mat ID - the material will add a NULL material 
		// to the list to compensate - this screws with the index into the paramblock
		for(i=0; i < m_Mtl->NumSubs(); i++)
		{	
			Std = (Mtl*)m_Mtl->SubAnim(i);

			if(Std!=NULL)
			{
				if(Std->NumSubMtls()>0)
				{

					for(int j=0; j< Std->NumSubMtls();j++)
					{
						Mtl * subMtl = Std->GetSubMtl(j);
						if(subMtl == Shader)
							Std = subMtl;

					}
				}
				MSPlugin* plugin = (MSPlugin*)((ReferenceTarget*)Std)->GetInterface(I_MAXSCRIPTPLUGIN);
				ReferenceTarget * targ = NULL;
				if(plugin){
					targ = plugin->get_delegate();
					Std = (Mtl*)targ;
				}
				if(Std == Shader)
				{
					int id=0;
					// this gets interesting - the MatID are editable !! must get them from the PAramblock
					IParamBlock2 * pblock = m_Mtl->GetParamBlock(0);	// there is only one
					if(pblock)
					{
						ParamBlockDesc2 * pd = pblock->GetDesc();

						for(int j=0;j<pd->count;j++)
						{
							if(_tcsicmp(_T("materialIDList"),pd->paramdefs[j].int_name)==0)	//not localised
							{
								//int id;
								pblock->GetValue(j,0,id,FOREVER,i); 
								id = id+1;	//for some reason this is stored as a zero index, when a 1's based index is used
							}	

						}
						pblock->ReleaseDesc();

					}
					return(id);
				}
			}
		}
	}
	return(0);
}