📄 export.cpp
字号:
//**************************************************************************
//* Export.cpp - Virtools File Exporter
//*
//* Romain Sididris - Copyright (c) Virtools 2000
//*
//* (Based on Ascii File Exporter source code
//* By Christer Janson
//* Kinetix Development
//* Copyright (c) Kinetix 1997, All Rights Reserved. )
//*
//* This module contains the main export functions
//*
//***************************************************************************
#include "Precomp.h"
#include "Max2Nmo.h"
#include "bitmap.h"
#include "icustattribcontainer.h"
#ifdef MAX51
#include "PBBitmap.h"
#include "d3dx8.h"
#include "IViewportManager.h"
#endif
extern BOOL g_CharacterStudio312;
_inline unsigned long GetMSB(unsigned long data);
/****************************************************************************
Convenient Functions For Lightmap Manipulation
****************************************************************************/
#ifdef MAX51
class LM {
protected:
enum { lightmap_params };
enum {
pb_light_texture,
pb_diffuse_texture,
pb_diffuse_mapping,
pb_lightmap_filename,
pb_diffuse_filename,
pb_lightmap_on,
pb_diffuse_on,
pb_lightmap_mapping,
};
static IParamBlock2* GetLightMapParameters( Mtl* mtl ){
//--- Find Effects
IDXShaderManagerInterface* shaderManager = GetDXShaderManager();
if( !shaderManager ) return NULL;
CustAttrib *cust = shaderManager->FindViewportShaderManager(mtl);
if( !cust ) return NULL;
IViewportShaderManager* viewShader = (IViewportShaderManager *)(cust->GetInterface(VIEWPORT_SHADER_MANAGER_INTERFACE));
if( !viewShader ) return NULL;
ReferenceTarget* rt = viewShader->GetActiveEffect();
if( !rt ) return NULL;
//--- if it's a lightmap material
#define LIGHTMAP_CLASS_ID Class_ID(0x727d33be, 0x3255c000)
if( rt->ClassID() == LIGHTMAP_CLASS_ID ){
//--- Get Parameter Block Info
IDXDataBridge* db = (IDXDataBridge*)(rt->GetInterface( VIEWPORT_SHADER_CLIENT_INTERFACE ));
if( !db ) return NULL;
return rt->GetParamBlockByID( lightmap_params );
}
return NULL;
}
public:
static BOOL ShaderEnabled( Mtl* mtl ){
return ( GetLightMapParameters( mtl ) != NULL );
}
//--- Read Base Texture Parameters
static BOOL BaseTextureEnabled( Mtl* mtl ){
IParamBlock2* pblock = GetLightMapParameters(mtl);
BOOL diffuseOn = FALSE;
pblock->GetValue( pb_diffuse_on, 0, diffuseOn, FOREVER);
return diffuseOn;
}
static const char* BaseTextureFilename( Mtl* mtl ){
IParamBlock2* pblock = GetLightMapParameters(mtl);
TCHAR* diffuseFilename;
pblock->GetValue( pb_diffuse_filename, 0, (TCHAR*&)diffuseFilename, FOREVER );
return diffuseFilename;
}
static int BaseTextureMapping( Mtl* mtl ){
IParamBlock2* pblock = GetLightMapParameters(mtl);
int diffuseMapping = 1;
pblock->GetValue( pb_diffuse_mapping, 0, diffuseMapping, FOREVER);
return diffuseMapping;
}
//--- Read Lightmap Texture Parameters
static BOOL LightmapTextureEnabled( Mtl* mtl ){
IParamBlock2* pblock = GetLightMapParameters(mtl);
BOOL lightOn = FALSE;
pblock->GetValue( pb_lightmap_on, 0, lightOn, FOREVER);
return lightOn;
}
static const char* LightmapTextureFilename( Mtl* mtl ){
IParamBlock2* pblock = GetLightMapParameters(mtl);
TCHAR* lightFilename;
pblock->GetValue( pb_lightmap_filename, 0, (TCHAR*&)lightFilename, FOREVER );
return lightFilename;
}
static int LightmapTextureMapping( Mtl* mtl ){
IParamBlock2* pblock = GetLightMapParameters(mtl);
int lightMapping = 3;
pblock->GetValue( pb_lightmap_mapping, 0, lightMapping, FOREVER);
return lightMapping;
}
};
#endif // MAX51
/****************************************************************************
GeomObject output (Geom objects are tri or patch based meshes)
****************************************************************************/
void Max2Nmo::ExportGeomObject(INode* node)
{
ObjectState os = node->EvalWorldState(GetStaticFrame());
if (!os.obj)
return;
// Targets are actually geomobjects, but we will export them
// from the camera and light objects, so we skip them here.
if (os.obj->ClassID() == Class_ID(TARGET_CLASS_ID, 0))
return;
BOOL Biped = FALSE;
BOOL SaveMesh = TRUE;
Control* tmC = node->GetTMController();
if ((tmC->ClassID()== FOOTPRINT_CLASS_ID) || (tmC->ClassID()== BIPSLAVE_CONTROL_CLASS_ID) || (tmC->ClassID()== BIPBODY_CONTROL_CLASS_ID)) {
Biped = TRUE;
}
CK3dEntity* Entity = NULL;
if (GetExportAsCharacter())
Entity = (CK3dEntity*)VirtoolsExporter->AddCharacterBodyPart(node->GetName(),node);
else
Entity = (CK3dEntity*)VirtoolsExporter->Add3dObject(node->GetName(),node);
ExportNodeBase(node, Entity);
if (!Biped || GetSaveBipedGeom()) {
if (os.obj->ClassID() == Class_ID(PATCHOBJ_CLASS_ID, 0))
ExportPatchMesh(node,Entity);
else
ExportMesh(node,Entity);
} else {
Report(REPORT_HLEVEL,"%sBiped Object: %s.....",StrGroupIndent().Str(),node->GetName());
}
if (Biped && !GetSaveBipedGeom() ) Entity->Show(CKHIDE);
// Rename the floor reference object
if (tmC->ClassID() == FOOTPRINT_CLASS_ID) {
Entity->SetName("FloorRef");
}
ExportAnimKeys(node,Entity);
Report(REPORT_HLEVEL,"...Done\r\n");
}
/****************************************************************************
Shape (Curve) output
****************************************************************************/
void Max2Nmo::ExportShapeObject(INode* node)
{
TimeValue t = GetStaticFrame();
ObjectState os = node->EvalWorldState(t);
if (!os.obj || os.obj->SuperClassID()!=SHAPE_CLASS_ID) {
return;
}
Report(REPORT_HLEVEL,"%sCurve : %s.....",StrGroupIndent().Str(),node->GetName());
int deleteIt;
SplineShape *pSplineShape = GetSplineShapeFromNode(node,t,deleteIt);
Matrix3 ObjectTM = node->GetObjectTM(t);
if(pSplineShape && pSplineShape->shape.SplineCount()==1) {
// We only convert if the shape contains only one spline
Spline3D* spline3D = pSplineShape->shape.GetSpline(0);
if(spline3D) {
CKCurve* VirtoolsCurve = VirtoolsExporter->AddCurve(node->GetName(),node);
int KnotCount = spline3D->KnotCount();
for (int i=0; i<KnotCount;++i) {
CKCurvePoint* pt = VirtoolsExporter->AddCurvePoint(VirtoolsCurve,NULL,NULL);
SplineKnot SKnot = spline3D->GetKnot(i);
Point3 WorldKnot = ObjectTM.PointTransform(SKnot.Knot());
int KnotType = SKnot.Ktype();
int SegType = SKnot.Ltype();
// Max and Virtools tangents conversion =>
// scale by a factor of 3 ?????
Point3 WorldInTan = -spline3D->GetRelInVec(i)*3.0f;
Point3 WorldOutTan = spline3D->GetRelOutVec(i)*3.0f;
if (KnotType != KTYPE_AUTO) {
pt->UseTCB(FALSE);
pt->SetTangents(&VxVector(WorldInTan.x,WorldInTan.z,WorldInTan.y),
&VxVector(WorldOutTan.x,WorldOutTan.z,WorldOutTan.y));
}
if (SegType == LTYPE_LINE) pt->SetLinear(TRUE);
// Swap Y & Z to reflect referential changes between Max and Virtools
pt->SetPosition(&VxVector( WorldKnot.x,WorldKnot.z,WorldKnot.y),NULL,TRUE );
}
if (spline3D->Closed()) VirtoolsCurve->Close();
ExportNodeBase(node,VirtoolsCurve);
ExportAnimKeys(node,VirtoolsCurve);
}
// Deletes created shape
if (deleteIt) pSplineShape->DeleteMe();
}
Report(REPORT_HLEVEL,"Done\r\n");
}
/****************************************************************************
Light output
****************************************************************************/
void Max2Nmo::ExportLightObject(INode* node)
{
TimeValue t = GetStaticFrame();
ObjectState os = node->EvalWorldState(t);
if (!os.obj) return;
Report(REPORT_HLEVEL,"%sLight : %s.....",StrGroupIndent().Str(),node->GetName());
GenLight* light = (GenLight*)os.obj;
struct LightState ls;
Interval valid = FOREVER;
Interval animRange = ip->GetAnimRange();
light->EvalLightState(t, valid, &ls);
INode* target = node->GetTarget();
VXLIGHT_TYPE LightType = VX_LIGHTPOINT;
switch(ls.type) {
case OMNI_LIGHT: LightType = VX_LIGHTPOINT; break;
case TDIR_LIGHT:
case DIR_LIGHT: LightType = VX_LIGHTDIREC; break;
case TSPOT_LIGHT:
case FSPOT_LIGHT: LightType = VX_LIGHTSPOT; break;
}
CKLight* VirtoolsLight = NULL;
CK3dEntity* VirtoolsLightTarget = NULL;
// Virtools Objects creation
VirtoolsLight = (CKLight*)VirtoolsExporter->AddLight(target? TRUE:FALSE,LightType,node->GetName(),node);
ExportNodeBase(node, VirtoolsLight);
if (target && (LightType == VX_LIGHTSPOT)) {
VirtoolsLightTarget = ((CKTargetLight* )VirtoolsLight)->GetTarget();
ExportNodeBase(target, VirtoolsLightTarget);
}
VirtoolsLight->SetColor(VxColor(ls.color.r,ls.color.g,ls.color.b));
VirtoolsLight->SetRange(ls.attenEnd);
VirtoolsLight->SetSpecularFlag(ls.affectSpecular);
VirtoolsLight->Active(ls.on);
VirtoolsLight->SetHotSpot(DegToRad(ls.hotsize));
VirtoolsLight->SetFallOff(DegToRad(ls.fallsize));
// Export animation keys for the light node
ExportAnimKeys(node,VirtoolsLight);
// If we have a target, export animation keys for the target too.
if (target && VirtoolsLightTarget) {
ExportAnimKeys(target,VirtoolsLightTarget);
}
Report(REPORT_HLEVEL,"Done\r\n");
}
/****************************************************************************
Camera output
****************************************************************************/
void Max2Nmo::ExportCameraObject(INode* node)
{
TimeValue t = GetStaticFrame();
ObjectState os = node->EvalWorldState(t);
if (!os.obj) return;
Report(REPORT_HLEVEL,"%sCamera : %s.....",StrGroupIndent().Str(),node->GetName());
CameraObject *cam = (CameraObject *)os.obj;
CameraState cs;
Interval valid = FOREVER;
Interval animRange = ip->GetAnimRange();
cam->EvalCameraState(t,valid,&cs);
INode* target = node->GetTarget();
CKCamera* VirtoolsCamera = NULL;
CK3dEntity* VirtoolsCameraTarget = NULL;
// Virtools Objects creation
VirtoolsCamera = VirtoolsExporter->AddCamera(target? TRUE:FALSE,node->GetName(),node);
ExportNodeBase(node, VirtoolsCamera);
if (target) {
VirtoolsCameraTarget = ((CKTargetCamera* )VirtoolsCamera)->GetTarget();
ExportNodeBase(target, VirtoolsCameraTarget);
}
if (cs.manualClip) {
VirtoolsCamera->SetFrontPlane(cs.hither<1.0f ? 1.0f : cs.hither);
VirtoolsCamera->SetBackPlane(cs.yon);
} else {
VirtoolsCamera->SetFrontPlane(cs.nearRange<1.0f ? 1.0f : cs.nearRange);
VirtoolsCamera->SetBackPlane(cs.farRange);
}
VirtoolsCamera->SetFov(cs.fov);
// Export animation keys for the light node
ExportAnimKeys(node,VirtoolsCamera);
// If we have a target, export animation keys for the target too.
if (target && VirtoolsCameraTarget) {
ExportAnimKeys(target,VirtoolsCameraTarget);
}
Report(REPORT_HLEVEL,"Done\r\n");
}
/****************************************************************************
Helper object output
****************************************************************************/
void Max2Nmo::ExportHelperObject(INode* node)
{
// We don't really know what kind of helper this is, but by exporting
// the Classname of the helper object, the importer has a chance to
// identify it.
Object* helperObj = node->EvalWorldState(GetStaticFrame()).obj;
TSTR className="Dummy";
if (helperObj) {
helperObj->GetClassName(className);
}
if (node->IsGroupHead() && !GetGroupAsPlace()) className = "Group";
CK3dEntity* dummy = NULL;
if (node->IsGroupHead() && GetGroupAsPlace()) {
dummy = (CK3dEntity *)VirtoolsExporter->AddPlace(node->GetName(),node);
className = "Place";
} else {
if(GetExportAsCharacter())
dummy = (CK3dEntity*)VirtoolsExporter->AddCharacterBodyPart(node->GetName(),node);
else
dummy = VirtoolsExporter->AddDummyObject(node->GetName(),node);
}
Report(REPORT_HLEVEL,"%s%s : %s.....",StrGroupIndent().Str(),className,node->GetName());
ExportNodeBase(node,dummy);
ExportAnimKeys(node,dummy);
if (node->IsGroupHead()) GroupIndent+=2;
Report(REPORT_HLEVEL,"Done\r\n");
}
/****************************************************************************
Node Base (Hierarchy + position )
****************************************************************************/
void Max2Nmo::ExportNodeBase(INode* node,CK3dEntity* entity)
{
VxMatrix VirtoolsMat;
Matrix3 MaxMat = node->GetNodeTM(GetStaticFrame());
// Special Matrix conversion for lights
if (CKIsChildClassOf(entity,CKCID_CAMERA) || CKIsChildClassOf(entity,CKCID_LIGHT))
ConvertMaxLightMatrix2Virtools(MaxMat,VirtoolsMat);
else
ConvertMaxMatrix2Virtools(MaxMat,VirtoolsMat);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -