⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 export.cpp

📁 3dmax导出3d模型二次开发插件
💻 CPP
📖 第 1 页 / 共 4 页
字号:
{
	deleteIt = FALSE;
	Object *obj = node->EvalWorldState(t).obj;
	if (obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) { 
		TriObject *tri = (TriObject *) obj->ConvertToType(t, 
			Class_ID(TRIOBJ_CLASS_ID, 0));

		if (obj != tri) deleteIt = TRUE;
		return tri;
	}
	else {
		return NULL;
	}
}

// Return a pointer to a PatchObject given an INode or return NULL
// if the node cannot be converted to a PatchObject
PatchObject* Max2Nmo::GetPatchObjectFromNode(INode *node,TimeValue t,int &deleteIt)
{
	deleteIt = FALSE;
	Object *obj = node->EvalWorldState(t).obj;
	if (obj->SuperClassID()==GEOMOBJECT_CLASS_ID)
	if (obj->ClassID()==Class_ID(PATCHOBJ_CLASS_ID, 0))
	if (obj->CanConvertToType(Class_ID(PATCHOBJ_CLASS_ID, 0))) 
	{ 
		PatchObject *patch = (PatchObject *) obj->ConvertToType(	t
														 ,	Class_ID(PATCHOBJ_CLASS_ID, 0) );
		if (obj != patch) deleteIt = TRUE;
		return patch;
	}
	else return NULL;
	return NULL;
}


// Try to find if a skin modifier is in the modifier stack of a node
Modifier* Max2Nmo::FindSkinModifier (INode* node)
{
#ifndef MAX42
	if (g_CharacterStudio312) {
		return FindSkinModifierCS312(node);
	} else 
#endif	
	{
		return FindSkinModifierCS300(node);
	}
}

// Try to find if a physique modifier is in the modifier stack of a node
Modifier* Max2Nmo::FindPhysiqueModifier (INode* node)
{
#ifndef MAX42
	if (g_CharacterStudio312) {
		return FindPhysiqueModifierCS312(node);
	} else 
#endif
	{
		return FindPhysiqueModifierCS300(node);
	}
}


SplineShape* Max2Nmo::GetSplineShapeFromNode(INode *node,TimeValue t,int &deleteIt)
{
	deleteIt = FALSE;
	Object *obj = node->EvalWorldState(t).obj;
	
	if (obj->SuperClassID()==SHAPE_CLASS_ID) {
		SplineShape *pSplineShape= (SplineShape *) obj->ConvertToType(0,splineShapeClassID );
		if (obj != pSplineShape) deleteIt = TRUE;
		return pSplineShape;
	}
	return NULL;
}


// From the Max SDK
// How to calculate UV's for face mapped materials.
static Point3 basic_tva[3] = { 
	Point3(0.0,0.0,0.0),Point3(1.0,1.0,0.0),Point3(1.0,0.0,0.0)
};
static Point3 basic_tvb[3] = { 
	Point3(0.0,1.0,0.0),Point3(1.0,1.0,0.0),Point3(0.0,0.0,0.0)
};
static int nextpt[3] = {1,2,0};
static int prevpt[3] = {2,0,1};

static int nhidCase[8] = {-1,-1,-1,-1,0,1,-1,2};
static int forceInvertTab[8] = {0,0,0,0,0,0,0,0};
static int shiftifA[8] = {2,0,2,0,2,1,2,0};
static int shiftifB[8] = {0,0,0,1,0,2,0,1};
// To check that all case have been tested
static int check[8]   = {0,0,0,0,0,0,0,0};


void Max2Nmo::make_face_uv(Face *f, VxUV *tv)
{
	int na,nhid,i;
	Point3 *basetv;
	/* make the invisible edge be 2->0 */
	nhid = 1;
	if (!(f->flags&EDGE_A))  nhid=0;
	else if (!(f->flags&EDGE_B)) nhid = 1;
	else if (!(f->flags&EDGE_C)) nhid = 2;

	int fFlags = f->flags & 0x7;
	if (nhidCase[fFlags] >=0) {
		nhid = nhidCase[fFlags];
	}
	na = 2-nhid;
	basetv = (f->v[prevpt[nhid]]<f->v[nhid]) ? basic_tva : basic_tvb; 
	if (forceInvertTab[fFlags]) {
		basetv = (basetv == basic_tvb) ? basic_tva : basic_tvb; 
	}
	if ( (basetv == basic_tva) && shiftifA[fFlags] ) {
		na = nextpt[na];
		if (shiftifA[fFlags] > 1)
			na = nextpt[na];
	}
	if ( (basetv == basic_tvb) && shiftifB[fFlags] ) {
		na = nextpt[na];
		if (shiftifB[fFlags] > 1)
			na = nextpt[na];
	}
	if (basetv == basic_tvb)
		check[fFlags] |= 2;
	if (basetv == basic_tva)
		check[fFlags] |= 1;
	for (i=0; i<3; i++) {  
		tv[i].u = basetv[na].x;
		tv[i].v = basetv[na].y;
		na = nextpt[na];
	}
}


/*************************************************************
Since Virtools and Max referential have switched Y and Z axis 
we need to swap the 2 axis in the matrix
***************************************************************/
void   Max2Nmo::ConvertMaxMatrix2Virtools(Matrix3 &m, VxMatrix &WM)
{
 	MRow* pMRow=m.GetAddr();
// Row & Colummn 1 & 2 must be swapped
	WM[0][0]=(*pMRow)[0];	  WM[0][1]=(*pMRow)[2];		WM[0][2]=(*pMRow)[1];	  WM[0][3]=0.0f;
	WM[1][0]=(*(pMRow+2))[0]; WM[1][1]=(*(pMRow+2))[2]; WM[1][2]=(*(pMRow+2))[1]; WM[1][3]=0.0f;
	WM[2][0]=(*(pMRow+1))[0]; WM[2][1]=(*(pMRow+1))[2]; WM[2][2]=(*(pMRow+1))[1]; WM[2][3]=0.0f;
	WM[3][0]=(*(pMRow+3))[0]; WM[3][1]=(*(pMRow+3))[2]; WM[3][2]=(*(pMRow+3))[1]; WM[3][3]=1.0f;
}

/*************************************************************
Max Camera and Light matrix don't act like object matrix, we 
need a specific conversion method
***************************************************************/
void   Max2Nmo::ConvertMaxLightMatrix2Virtools(Matrix3 &m, VxMatrix &WM)
{
	MRow* pMRow=m.GetAddr();
	
	WM[0][0]=(*pMRow)[0];	  WM[0][1]=(*pMRow)[2];		WM[0][2]=(*pMRow)[1];	  WM[0][3]=0.0f;
	WM[1][0]=(*(pMRow+1))[0]; WM[1][1]=(*(pMRow+1))[2]; WM[1][2]=(*(pMRow+1))[1]; WM[1][3]=0.0f;
	WM[2][0]=(*(pMRow+2))[0]; WM[2][1]=(*(pMRow+2))[2]; WM[2][2]=(*(pMRow+2))[1]; WM[2][3]=0.0f;
	WM[3][0]=(*(pMRow+3))[0]; WM[3][1]=(*(pMRow+3))[2]; WM[3][2]=(*(pMRow+3))[1]; WM[3][3]=1.0f;

	WM[2][0] = -WM[2][0];	WM[2][1] = -WM[2][1];	WM[2][2] = -WM[2][2];
//--- Camera and Light Matrices should not have any scale...
	WM[0].Normalize();
	WM[1].Normalize();
	WM[2].Normalize();

}


/********************************************************
// Max Vertices are given in the ObjectTM referential and we need them in NodeTM referential
// use  this method to get the OffsetTM
*********************************************************/
Matrix3   Max2Nmo::GetNodeOffsetTM(INode* node)
{
	Matrix3 tOffsetTM(1);
	Point3 pos = node->GetObjOffsetPos();
	tOffsetTM.PreTranslate(pos);
	Quat quat = node->GetObjOffsetRot();
	PreRotateMatrix(tOffsetTM, quat);
	ScaleValue scaleValue = node->GetObjOffsetScale();
	ApplyScaling(tOffsetTM, scaleValue);
	return tOffsetTM;
}



/*****************************************************************************************/	
// GetMaterialByIndex 
//
// This function is used to retrieve the 3dsmax material applied to a face of an object.
// of a face. 
// - pMtl: root material of the object
// - MatId: Id given to the face in order to know wich sub-material 
// is to be used from the root.
// - MapChannel: channel in which to look for the material (note: 0 means no channels)
// - returnedKey: key to retrieve the matching CKMaterial later 
// (note: ~ little trick for lightmap material)
/*****************************************************************************************/	
Mtl* Max2Nmo::GetMaterialByIndex(Mtl *pMtl,DWORD MatId,int MapChannel, void*& returnedKey )
{
	returnedKey = NULL;
	if (!pMtl) return NULL;
	Mtl *pSubMtl=NULL;

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

#ifdef MAX51
		//--- Araya: If for this channel there's a lightmap texture enabled
		///// then returnedKey is not the pMtl, but some trick to retrieve it from pMtl
		if( LM::ShaderEnabled(pMtl) ){
			
			if( MapChannel ){

				if( LM::LightmapTextureEnabled(pMtl) && 
					LM::LightmapTextureMapping(pMtl)==MapChannel ){
					returnedKey = (void*)~(DWORD)pMtl;
					return pMtl;
				} 
			} else {
				if( LM::BaseTextureEnabled(pMtl) ){
					
					const char* baseTextureFilename = LM::BaseTextureFilename(pMtl);
					if( baseTextureFilename ){
						Mtl** matchingBaseMaterialPtr = m_lightmapBaseMaterials.FindPtr( baseTextureFilename );
						if( matchingBaseMaterialPtr ){
							returnedKey = *matchingBaseMaterialPtr;
							return *matchingBaseMaterialPtr;
						}
					}
				}
			}

			return NULL;
		}
#endif
		
		if (MapChannel) {
			
			Texmap* pTexmap=pMtl->GetSubTexmap(ID_DI);
			if (pTexmap && pTexmap->GetUVWSource()==UVWSRC_EXPLICIT
				&& pTexmap->GetMapChannel()==MapChannel) {
				returnedKey = pMtl;
				return pMtl;
			}
			else return NULL;
		} else {
			returnedKey = pMtl;
			return pMtl;
		}
	}
	else
#ifdef MAX51
	if(pMtl->ClassID()==Class_ID(BAKE_SHELL_CLASS_ID, 0)) {

		//--- Baked Shell Material
		int selectedViewPortMaterialIndex = 1;

		enum { bakeShell_params };
		enum { bakeShell_vp_n_mtl };

		IParamBlock2* pblock = pMtl->GetParamBlockByID( bakeShell_params );
		if( pblock ){
			pblock->GetValue( bakeShell_vp_n_mtl, 0, 
				selectedViewPortMaterialIndex, FOREVER );
		}
			
		pSubMtl=pMtl->GetSubMtl( selectedViewPortMaterialIndex );
		return GetMaterialByIndex(pSubMtl,MatId,MapChannel, returnedKey);
	}
	else
#endif
		if(pMtl->ClassID()==Class_ID(MULTI_CLASS_ID, 0)) {
			//Multi Material
			pSubMtl=pMtl->GetSubMtl(MatId % pMtl->NumSubMtls());
			return GetMaterialByIndex(pSubMtl,MatId,MapChannel, returnedKey);
		}
	else
	if(pMtl->ClassID()==Class_ID(MIXMAT_CLASS_ID, 0))
	{
		// In case we are looking for a material assigned to a specific channel
		if (MapChannel) {
			for (int i=0;i<pMtl->NumSubMtls();i++)
				if (pSubMtl=pMtl->GetSubMtl(i))
					if(pSubMtl->ClassID()==Class_ID(DMTL_CLASS_ID, 0)) {
						Texmap* pTexmap=pSubMtl->GetSubTexmap(ID_DI);
						if (pTexmap->GetUVWSource()==UVWSRC_EXPLICIT)
						if (pTexmap->GetMapChannel()==MapChannel) break;
			}
			if (i>=pMtl->NumSubMtls()) pSubMtl=NULL;
		} else pSubMtl=pMtl->GetSubMtl(0);
		return GetMaterialByIndex(pSubMtl,MatId,MapChannel, returnedKey);
	}
	return NULL;  // ????
}

// from bmTex.cpp 
#define PB_CLIPU		0
#define PB_CLIPV		1
#define PB_CLIPW		2
#define PB_CLIPH		3
#define PB_APPLYCROP	6


BOOL Max2Nmo::GetTextureUvGen(Mtl* pMtl,TextureUVGen& uvgen)
{
	if (!pMtl) return FALSE;
	if (pMtl->ClassID()!=Class_ID(DMTL_CLASS_ID, 0)) return FALSE;

	StdMat* stdmat = (StdMat*)pMtl;
	if( !stdmat->MapEnabled(ID_DI) ) return FALSE;

	Texmap *ptexmap = stdmat->GetSubTexmap(ID_DI);
	if( !ptexmap ) return FALSE;
	if( ptexmap->ClassID()!=Class_ID(BMTEX_CLASS_ID,0) ) return FALSE;
	
	BitmapTex *pbitmaptex = (BitmapTex*)ptexmap;

	//--- Tiling & mirroring 
	StdUVGen* uvs	= pbitmaptex->GetUVGen();
	int adrMode		= uvs->GetTextureTiling();

	uvgen.UOffset	= uvs->GetUOffs(0);
	uvgen.UScale	= uvs->GetUScl(0);
	uvgen.VOffset	= uvs->GetVOffs(0);
	uvgen.VScale	= uvs->GetVScl(0);

	uvgen.TileU		= adrMode&U_WRAP;
	uvgen.MirrorU	= adrMode&U_MIRROR;
	uvgen.TileV		= adrMode&V_WRAP;
	uvgen.MirrorV	= adrMode&V_MIRROR;

	uvgen.AngleMap		= uvs->GetAng(0); 
	uvgen.Cropping		= FALSE;
	uvgen.UCropOffset	= 0;
	uvgen.VCropOffset	= 0;
	uvgen.UCropScale	= 1.0f;
	uvgen.VCropScale	= 1.0f;

	// There is no api to access cropping values : 
	// use param blocks
	IParamBlock2* block=(IParamBlock2*)pbitmaptex->GetReference(1);
	if (block) 	{
		uvgen.Cropping = block->GetInt( PB_APPLYCROP, 0);
		uvgen.UCropOffset = block->GetFloat( PB_CLIPU, 0);
		uvgen.VCropOffset = block->GetFloat( PB_CLIPV, 0);
		uvgen.UCropScale = block->GetFloat( PB_CLIPW, 0);
		uvgen.VCropScale = block->GetFloat( PB_CLIPH, 0);
	}
	return TRUE;
}


void	Max2Nmo::ApplyUvGen(VxUV& uv,TextureUVGen& uvgen,BOOL useUVGen)
{
	//--- Virtools and Max texture coordinates are upside down
	uv.v = 1.0f - uv.v; 
	if( !useUVGen ) return;
		
	float u = uv.u;
	float v = uv.v; 

	//-- Apply cropping and test because uCropOfs sometimes is -NAND				
	if(uvgen.Cropping) 	{	
		if (!(_isnan(uvgen.UCropOffset) || _isnan(uvgen.UCropScale)))
			u = uvgen.UCropOffset + ( u * uvgen.UCropScale);

		if (!(_isnan(uvgen.VCropOffset) || _isnan(uvgen.VCropScale)))
			v = uvgen.VCropOffset + ( v * uvgen.VCropScale);
	}
	//-- Apply tiling
	u=-uvgen.UOffset + 0.5f + ((u-0.5f)*uvgen.UScale);
	v=uvgen.VOffset + 0.5f + ((v-0.5f)*uvgen.VScale);
	
	uv.u = u;
	uv.v = v;
}


CKMesh* Max2Nmo::IsMeshInstance(void* mesh,Mtl* mtl)
{
	for (int i=0;i<MeshTable.Size();++i) {
		if ((MeshTable[i].mesh==mesh) && (MeshTable[i].mtl==mtl)) 
			return MeshTable[i].CKMesh;
	}
	return NULL;
}

void    Max2Nmo::InsertNewMeshInstance(void* mesh,Mtl* mtl,CKMesh* ckmesh)
{
	NodeMeshMtl tmp;
	tmp.mesh = mesh;
	tmp.CKMesh = ckmesh;
	tmp.mtl = mtl;
	MeshTable.PushBack(tmp);
}



void Max2Nmo::Report(int InfoLevel,char *format, ...)
{
	if (InfoLevel>nReportLevel) return;
	va_list	marker;
	va_start(marker, format);
	
	// Always ensure at least 16384 characters are to be written 
	ReportBuffer.Resize(ReportBufferPos + 16384);

	DWORD nbC = vsprintf((char*)&ReportBuffer[ReportBufferPos],format,marker);
	ReportBufferPos+=nbC;
}


/*--------------------------------------------------*/
/* macro */
#pragma warning (disable:4035)

_inline unsigned long	GetMSB(unsigned long data)

	{
	_asm
		{
		mov		eax,data
		bsr		eax,eax
		}
	}

#pragma warning (default:4035)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -