📄 m2character.cpp
字号:
//--------------------------------------------------
// Desc: M2 Character Control
// From: WOW Model Viewer
// I just coding in my own ways!
//--------------------------------------------------
#include "M2Character.h"
#include "M2CharTexture.h"
#include "Common.h"
#include "CSVFile.h"
int SlotOrder[] =
{
ES_SHIRT,
ES_HEAD,
ES_NECK,
ES_SHOULDER,
//-----------------------------
ES_PANTS, // 裤子
ES_BOOTS, // 鞋在裤子外
ES_CHEST,
ES_TABARD,
ES_BELT, // 皮带
ES_BRACERS, // 护手
ES_GLOVES, // 手套在护手外
//-----------------------------
ES_HAND_RIGHT,
ES_HAND_LEFT,
ES_CAPE, // 披风
ES_QUIVER // 箭袋
};
// 长袍
int SlotOrderWithRobe[] =
{
ES_SHIRT,
ES_HEAD,
ES_NECK,
ES_SHOULDER,
//-----------------------------
ES_BOOTS,
ES_PANTS, // 裙子在鞋子外
ES_BRACERS, // 护手在衣服内
ES_CHEST,
ES_GLOVES,
ES_TABARD,
ES_BELT,
//-----------------------------
ES_HAND_RIGHT,
ES_HAND_LEFT,
ES_CAPE,
ES_QUIVER
};
M2Character::M2Character()
{
m_hChar = INVALID_HANDLE;
m_hHair = INVALID_HANDLE;
m_hCape = INVALID_HANDLE;
for(int i=0; i<32; i++)
{
m_EquipmentIndex[i] = 0;
m_EquipmentMax[i] = 0;
m_EquipTexture[i] = INVALID_HANDLE;
m_EquipmentBase[i] = -1;
}
CSVFile csv("Picture\\Item.csv");
for(int i=ES_EQUITBASE; i<ES_EQUITBASE+NUM_CHAR_SLOTS; i++)
{
m_EquipmentBase[i] = csv.GetRecordIndex(0, CSV_SLOT, i, 0);
m_EquipmentMax[i] = csv.GetRecordNumber(CSV_SLOT, i);
}
// 左右与右手使用相同的物品
m_EquipmentBase[ES_HAND_LEFT] = m_EquipmentBase[ES_HAND_RIGHT];
m_EquipmentMax[ES_HAND_LEFT] = m_EquipmentMax[ES_HAND_RIGHT];
m_EquipmentIndex[ES_SKINCOLOR] = 0;
m_EquipmentMax[ES_SKINCOLOR] = 0;
m_EquipmentIndex[ES_HAIRCOLOR] = 0;
m_EquipmentMax[ES_HAIRCOLOR] = 0;
m_EquipmentIndex[ES_HAIRSTYLE] = 0;
m_EquipmentMax[ES_HAIRSTYLE] = 19;
m_EquipmentIndex[ES_FACESTYLE] = 0;
m_EquipmentMax[ES_FACESTYLE] = 0;
m_EquipmentIndex[ES_FACIALSTYLE] = 0;
m_EquipmentMax[ES_FACIALSTYLE] = 7; // (有一个为不显示)
CAniFile anifile;
AMFHeader header;
if(anifile.ReadHeader("Picture\\BaseSkin.amf", &header))
{
m_EquipmentMax[ES_SKINCOLOR] = header.m_FrameCount;
}
if(anifile.ReadHeader("Picture\\Hair.amf", &header))
{
m_EquipmentMax[ES_HAIRCOLOR] = header.m_FrameCount;
}
if(anifile.ReadHeader("Picture\\FaceLower.amf", &header))
{
m_EquipmentMax[ES_FACESTYLE] = header.m_FrameCount/m_EquipmentMax[ES_SKINCOLOR];
}
m_pCurModel = NULL;
m_pCharacter = NULL;
for(int i=0; i<5; i++)
{
m_Geoset[i] = 0;
}
}
M2Character::~M2Character()
{
ReleaseTexture(m_hChar);
ReleaseTexture(m_hHair);
ReleaseTexture(m_hCape);
for(int i=0; i<32; i++)
{
ReleaseTexture(m_EquipTexture[i]);
}
}
void M2Character::OnMount(int mountID)
{
if(mountID<0 || mountID>2)
return;
if(m_Root.m_pModel != NULL)
{
delete m_Root.m_pModel;
m_Root.m_pModel = NULL;
}
if(mountID==0)
{
m_pCharacter->SetAnimationByIndex(0, 0, 0);
m_pCurModel = (m_Root.m_Children[0])->m_pModel;
m_Root.SetScale(1.0f);
(m_Root.m_Children[0])->SetScale(1.0f);
}
else
{
CM2Loader *pHorse = new CM2Loader;
if(pHorse==NULL) return;
m_Root.m_pModel = pHorse;
if(mountID==1)
{
pHorse->Load("Model\\Nightmare.m2");
pHorse->m_ReplaceTexture[11] = 1006;
m_Root.SetScale(1.0f);
(m_Root.m_Children[0])->SetScale(1.0f);
}
else if(mountID==2)
{
pHorse->Load("Model\\Drake.m2");
pHorse->m_ReplaceTexture[11] = 1009;
pHorse->m_ReplaceTexture[12] = 1010;
pHorse->m_ReplaceTexture[13] = 1011;
m_Root.SetScale(0.3f);
(m_Root.m_Children[0])->SetScale(2.5f);
}
m_pCharacter->SetAnimationByID(0, 0, 91);
m_pCurModel = m_Root.m_pModel;
}
}
bool M2Character::Load(void)
{
m_Root.Load(NULL, NULL, -1, -1);
Attachment *pAttach = m_Root.AddChild("Model\\HumanFemale.m2", 0, -1);
m_pCharAttach = pAttach;
m_pCharacter = pAttach->m_pModel;
m_pCharacter->SetChar(true);
LoadEquipment();
return true;
//-------------------------------------------------------------------
// -----------------------------SUB MESH-----------------------------
// mesh index---descripe--------mesh id---------------------Base Part
//-------------------------------------------------------------------
// 0 基本身形 基本部位(ID: 0) Base
// 1-10 头发 (2-20之间)
// 11-12 耳朵 (701, 702) Ears
// 13 光头 (ID: 1) Bald Head
// 14-25 头发或夹子(15,24,25) (2-20之间)
// 26 小手臂 基本部位(ID: 401) Low arm
// 27-28 手套Mesh (402, 403)
// 29-30 袖子mesh (802, 803)
// 31-32 手套Mesh (404, 403)
// 33-42 披风 (1502, 1503, 1503, 1502, 1504, 1504, 1505, 1505, 1506, 1506)
// 43 后背 基本部位(ID: 1501) Back
// 44-45 裙子 (长裙1302, 短裙1102)
// 46 公会Mesh(tabard)(ID为1202)
// 47大腿 基本部位 (ID: 1301) Up Leg
// 48-49 长靴子 (长靴ID: 504, 短靴ID: 502)
// 50小腿 基本部位 (ID: 501) Low Leg
// 51-53 小腿部 (503, 503, 902)
// 54-55 大腿部 (903, 1002)
// 56 眼睛 基本部位(ID: 0) Eye
// 57-59 耳环 (302, 303, 305)
// 60-61 鼻环 (306, 307)
// 62 耳环 (304)
//-------------------------------------------------------------------
//--------------------------------------------------
// ---SUB MESH ID 指示该MESH的用处------------------
// ID值 作用
// 0 基本身形(index0 & index56)
// 1 光头模型
// 2-20 为头发模型,某个ID可能对应两个MESH INDEX
// 如(19对应23,25)(9对应7,15)(10对应16,24)
// 302-307 耳环
// 802-803 袖子MESH(29, 30)
// 100-300 Facial ID
//--------------------------------------------------
}
void M2Character::Update(void)
{
GNode::Update();
m_Root.Update();
m_Root.UpdateParticle();
if(g_stInputInfo.KeyValue==DIK_F6)
{
SaveEquipment();
}
}
void M2Character::Render(void)
{
D3DXMATRIX matWorld;
GetWorldTransform(&matWorld);
g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
m_Root.Render();
g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
matWorld = GetDerivedOrientation();
m_Root.RenderParticle(matWorld);
}
//--------------------------------------------------
// 加载或去除有模型的部分
//--------------------------------------------------
void M2Character::LoadItem(int slot)
{
m_pCharAttach->ReleaseSlot(slot);
ReleaseTexture(m_EquipTexture[slot]);
int index = m_EquipmentIndex[slot];
if(index)
{
int id1 = -1;
int id2 = -1;
if(slot==ES_HEAD) { id1 = 11; }
else if(slot==ES_SHOULDER) { id1 = 6; id2 = 5; }
else if(slot==ES_HAND_LEFT) { id1 = 2; } // when is shield id=0;
else if(slot==ES_HAND_RIGHT){ id1 = 1; }
else if(slot==ES_QUIVER) { id1 = 26; }
else return;
CSVFile csv("Picture\\Item.csv");
if(id1>=0)
{
char szModelA[64];
csv.ReadString(index, CSV_MODEL_A, szModelA);
int picIndex = csv.ReadInt32(index, CSV_MODEL_TEXTURE, 0);
Attachment *pAttach = m_pCharAttach->AddChild(szModelA, id1, slot);
m_EquipTexture[slot] = g_pTextureManager->LoadAMFTexture("Picture\\ModelItem.amf",
picIndex, MM_KEEPINMEMORY, 0);
pAttach->m_pModel->m_ReplaceTexture[2] = m_EquipTexture[slot];
pAttach->m_pModel->SetParticle(false);
}
if(id2>=0)
{
char szModelB[64];
csv.ReadString(index, CSV_MODEL_B, szModelB);
Attachment *pAttach = m_pCharAttach->AddChild(szModelB, id2, slot);
pAttach->m_pModel->m_ReplaceTexture[2] = m_EquipTexture[slot];
pAttach->m_pModel->SetParticle(false);
}
}
}
//--------------------------------------------------
// Load Special Hair Color
//--------------------------------------------------
void M2Character::ChangeHairColor(void)
{
ReleaseTexture(m_hHair);
m_hHair = g_pTextureManager->LoadAMFTexture("Picture\\Hair.amf", m_EquipmentIndex[ES_HAIRCOLOR],
MM_KEEPINMEMORY, 0);
m_pCharacter->m_ReplaceTexture[6] = m_hHair;
}
//--------------------------------------------------
// Load Special Hair Style
//--------------------------------------------------
void M2Character::ChangeHairStyle(void)
{
for(int style=0; style<m_EquipmentMax[ES_HAIRSTYLE]; style++)
{
unsigned int id = style + 2;
for(size_t i=0; i<m_pCharacter->m_RenderPass.size(); i++)
{
if(m_pCharacter->m_SubMesh[i].id == id)
{
m_pCharacter->m_bShowSubMesh[i] = (m_EquipmentIndex[ES_HAIRSTYLE]==style);
}
}
}
}
//--------------------------------------------------
// Load Special Facial Style
//--------------------------------------------------
void M2Character::ChangeFacialStyle(void)
{
for(int i=57; i<63; i++)
{
m_pCharacter->m_bShowSubMesh[i] = false;
}
m_pCharacter->m_bShowSubMesh[56+m_EquipmentIndex[ES_FACIALSTYLE]] = true;
}
//--------------------------------------------------
// Add or remove an equipment(no model)
//--------------------------------------------------
void M2Character::AddEquipment(int slot, TextureGroup *pTexGroup, int layer)
{
if(slot<ES_EQUITBASE || slot>=ES_EQUITBASE+NUM_CHAR_SLOTS || pTexGroup==NULL)
return;
if(slot==ES_PANTS && m_Geoset[1]!=0)
return;
int index = m_EquipmentIndex[slot];
if(index)
{
int texIndex = -1;
CSVFile texFile("Picture\\Item.csv");
texIndex = texFile.ReadInt32(index, CSV_ARM_UPPER, -1);
if(texIndex != -1)
pTexGroup->AddTexture("Picture\\ArmUpper.amf", texIndex, CR_ARM_UPPER, layer);
texIndex = texFile.ReadInt32(index, CSV_ARM_LOWER, -1);
if(texIndex != -1)
pTexGroup->AddTexture("Picture\\ArmLower.amf", texIndex, CR_ARM_LOWER, layer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -