2295 lines
60 KiB
C++
2295 lines
60 KiB
C++
// FlexModel.cpp
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "vector.h"
|
|
#include "resource.h"
|
|
#include "DDUtil.h"
|
|
#include "Matrix.h"
|
|
#include "Model.h"
|
|
#include "FrameManager2.h"
|
|
#include "FlexModel.h"
|
|
|
|
|
|
//
|
|
// CNode
|
|
//
|
|
|
|
void CNode::Init()
|
|
{
|
|
m_group = 0;
|
|
m_treeitem = NULL;
|
|
m_mesh = NULL;
|
|
m_visible = true;
|
|
m_numTris = 0;
|
|
m_numVerts = 0;
|
|
m_vertPath = NULL;
|
|
m_tris = NULL;
|
|
m_verts = NULL;
|
|
m_start_glcmds = NULL;
|
|
m_num_glcmds = 0;
|
|
m_defaultSkin = 0;
|
|
m_curSkin = NULL;
|
|
}
|
|
|
|
void CNode::Delete()
|
|
{
|
|
DeleteMesh();
|
|
if (m_tris != NULL)
|
|
{
|
|
free(m_tris);
|
|
m_tris = NULL;
|
|
}
|
|
if (m_verts != NULL)
|
|
{
|
|
free(m_verts);
|
|
m_verts = NULL;
|
|
}
|
|
if (m_vertPath != NULL)
|
|
{
|
|
delete m_vertPath;
|
|
m_vertPath = NULL;
|
|
}
|
|
}
|
|
|
|
void CNode::DeleteMesh()
|
|
{
|
|
if (m_mesh != NULL)
|
|
{
|
|
m_mesh->Release();
|
|
m_mesh = NULL;
|
|
}
|
|
}
|
|
|
|
LPDIRECT3DRMMESH CNode::GetMesh()
|
|
{
|
|
return m_mesh;
|
|
}
|
|
|
|
CBitmap* CNode::GetBitmap(LPDIRECT3DRM2 d3drm, CDC* pDC, int& width, int& height)
|
|
{
|
|
width = m_curSkin->GetWidth(d3drm, pDC);
|
|
height = m_curSkin->GetHeight(d3drm, pDC);
|
|
return m_curSkin->GetBitmap(d3drm, pDC);
|
|
}
|
|
|
|
void CNode::ChangeSkin(LPDIRECT3DRM2 d3drm, CDC* pDC, CSkin* skin)
|
|
{
|
|
if (m_curSkin == skin)
|
|
{
|
|
return;
|
|
}
|
|
// if (m_curSkin != NULL)
|
|
// {
|
|
// m_curSkin->GetTexture(d3drm, pDC)->Release();
|
|
// }
|
|
m_mesh->SetGroupTexture(m_group, skin->GetTexture(d3drm, pDC));
|
|
m_mesh->SetGroupMapping(m_group, D3DRMMAP_PERSPCORRECT);
|
|
m_mesh->SetGroupQuality(m_group, D3DRMRENDER_FLAT);
|
|
m_curSkin = skin;
|
|
}
|
|
|
|
void CNode::LoadSkin(LPDIRECT3DRM2 d3drm, CDC* pDC, CSkin* skin, int skinnum)
|
|
{
|
|
// if (m_defaultSkin == skinnum)
|
|
{
|
|
if (m_curSkin != skin)
|
|
{
|
|
ChangeSkin(d3drm, pDC, skin);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CNode::IsVisible()
|
|
{
|
|
return m_visible;
|
|
}
|
|
|
|
void CNode::SetVisible(bool visible)
|
|
{
|
|
m_visible = visible;
|
|
}
|
|
|
|
int CNode::GetNumTris()
|
|
{
|
|
return m_numTris;
|
|
}
|
|
|
|
void CNode::SetTris(byte* buf, int numTris)
|
|
{
|
|
m_numTris = numTris;
|
|
m_tris = (byte*)malloc(numTris);
|
|
memcpy(m_tris, buf, numTris);
|
|
}
|
|
|
|
void CNode::SetVerts(byte* buf, int numVerts)
|
|
{
|
|
m_numVerts = numVerts;
|
|
m_verts = (byte*)malloc(numVerts);
|
|
memcpy(m_verts, buf, numVerts);
|
|
}
|
|
|
|
void CNode::SetGlcmds(long* glcmds, int num)
|
|
{
|
|
m_start_glcmds = glcmds;
|
|
m_num_glcmds = num;
|
|
}
|
|
|
|
void CNode::RenderTexture(LPDIRECT3DRM2 d3drm, CDC* pDC, bool useTexture)
|
|
{
|
|
if (useTexture)
|
|
{
|
|
m_mesh->SetGroupTexture(m_group, m_curSkin->GetTexture(d3drm, pDC));
|
|
}
|
|
else
|
|
{
|
|
m_mesh->SetGroupTexture(m_group, NULL);
|
|
}
|
|
}
|
|
|
|
void CNode::SetTransparency(LPDIRECT3DRM2 d3drm, CDC* pDC, bool trans)
|
|
{
|
|
m_curSkin->GetTexture(d3drm, pDC)->SetDecalTransparency(trans);
|
|
}
|
|
|
|
HRESULT CNode::SetQuality(D3DRMRENDERQUALITY value)
|
|
{
|
|
return m_mesh->SetGroupQuality(m_group, value);
|
|
}
|
|
|
|
HRESULT CNode::SetColorRGB(D3DVALUE red, D3DVALUE green, D3DVALUE blue)
|
|
{
|
|
return m_mesh->SetGroupColorRGB(m_group, red, green, blue);
|
|
}
|
|
|
|
void CNode::BuildMesh(LPDIRECT3DRM2 d3drm, frameinfo2_t* frameinfo1, int skinwidth, int skinheight)
|
|
{
|
|
D3DRMVERTEX* vertexlist = new D3DRMVERTEX[m_numTris * 3 + 1];
|
|
if (vertexlist == NULL)
|
|
{
|
|
AfxMessageBox("Cannot make vertexlist");
|
|
return;
|
|
}
|
|
|
|
int curvert=0;
|
|
|
|
d3drm->CreateMesh(&m_mesh);
|
|
|
|
vec5_t* vertlist = (vec5_t*)malloc(sizeof(vec5_t) * m_numTris * 3);
|
|
m_vertPath = new int[m_numTris * 3];
|
|
|
|
long* command = m_start_glcmds;
|
|
int cur_glcmnd = m_num_glcmds;
|
|
|
|
//do the gl commands
|
|
int realvert = 0;
|
|
int realTris = 0;
|
|
while (*command && cur_glcmnd)
|
|
{
|
|
cur_glcmnd--;
|
|
|
|
int num_verts;
|
|
int command_type;
|
|
bool odd = true;
|
|
|
|
if (*command>0)
|
|
{
|
|
//triangle strip
|
|
num_verts = *command;
|
|
command_type = 0;
|
|
}
|
|
else
|
|
{
|
|
//triangle fan
|
|
num_verts = -(*command);
|
|
command_type = 1;
|
|
}
|
|
|
|
command++;
|
|
|
|
for (int i = 0; i < num_verts; i++)
|
|
{
|
|
vec5_t p1;
|
|
//grab the floating point s and t
|
|
p1.s = (*((float *)command)) * skinwidth; command++;
|
|
p1.t = (*((float *)command)) * skinheight; command++;
|
|
|
|
//grab the vertex index
|
|
int vert_index = *command; command++;
|
|
|
|
p1.z = -((frameinfo1->verts[vert_index].x * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
p1.y = ((frameinfo1->verts[vert_index].y * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
p1.x = -((frameinfo1->verts[vert_index].z * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertlist[i] = p1;
|
|
}
|
|
|
|
D3DVECTOR p[3];
|
|
switch (command_type)
|
|
{
|
|
case 0:
|
|
//tristrip
|
|
for (i = 0;i < num_verts - 2; i++)
|
|
{
|
|
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
p[j].x = vertlist[i+j].x;
|
|
p[j].y = vertlist[i+j].y;
|
|
p[j].z = vertlist[i+j].z;
|
|
}
|
|
|
|
if (odd)
|
|
{
|
|
for (j = 2; j > -1; j--)
|
|
{
|
|
vertexlist[curvert].position.x = vertlist[i+j].x;
|
|
vertexlist[curvert].position.y = vertlist[i+j].y;
|
|
vertexlist[curvert].position.z = vertlist[i+j].z;
|
|
vertexlist[curvert].tu = D3DVALUE(vertlist[i+j].s) / skinwidth;
|
|
vertexlist[curvert].tv = D3DVALUE(vertlist[i+j].t) / skinheight;
|
|
m_vertPath[curvert] = realvert+i+j;
|
|
curvert++;
|
|
}
|
|
realTris++;
|
|
}
|
|
else
|
|
{
|
|
for (j = 0; j < 3; j++)
|
|
{
|
|
vertexlist[curvert].position.x = vertlist[i+j].x;
|
|
vertexlist[curvert].position.y = vertlist[i+j].y;
|
|
vertexlist[curvert].position.z = vertlist[i+j].z;
|
|
vertexlist[curvert].tu = D3DVALUE(vertlist[i+j].s) / skinwidth;
|
|
vertexlist[curvert].tv = D3DVALUE(vertlist[i+j].t) / skinheight;
|
|
m_vertPath[curvert] = realvert+i+j;
|
|
curvert++;
|
|
}
|
|
realTris++;
|
|
}
|
|
odd = !odd;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
//trifan
|
|
for (i = 0; i < num_verts - 2; i++)
|
|
{
|
|
for (int j = 2; j > -1; j--)
|
|
{
|
|
int x;
|
|
if (j == 0)
|
|
x = 0;
|
|
else
|
|
x = i;
|
|
|
|
p[j].x = vertlist[x+j].x;
|
|
p[j].y = vertlist[x+j].y;
|
|
p[j].z = vertlist[x+j].z;
|
|
}
|
|
|
|
for (j = 2; j > -1; j--)
|
|
{
|
|
int x;
|
|
if (j == 0)
|
|
x = 0;
|
|
else
|
|
x = i;
|
|
|
|
vertexlist[curvert].position.x = vertlist[x+j].x;
|
|
vertexlist[curvert].position.y = vertlist[x+j].y;
|
|
vertexlist[curvert].position.z = vertlist[x+j].z;
|
|
vertexlist[curvert].tu = D3DVALUE(vertlist[x+j].s) / skinwidth;
|
|
vertexlist[curvert].tv = D3DVALUE(vertlist[x+j].t) / skinheight;
|
|
m_vertPath[curvert] = realvert + x + j;
|
|
curvert++;
|
|
}
|
|
realTris++;
|
|
}
|
|
break;
|
|
}
|
|
|
|
realvert += num_verts;
|
|
}
|
|
|
|
int tempvert = curvert;
|
|
|
|
unsigned* vertorder = new unsigned[curvert + 1];
|
|
if (vertorder == NULL)
|
|
{
|
|
AfxMessageBox("Cannot make vertorder");
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < (curvert); i++)
|
|
{
|
|
tempvert--;
|
|
vertorder[i] = tempvert;
|
|
}
|
|
|
|
m_numTris = realTris;
|
|
m_numVerts = curvert;
|
|
|
|
m_mesh->AddGroup(curvert, realTris, 3, vertorder, &m_group);
|
|
m_mesh->SetVertices(m_group, 0, curvert, vertexlist );
|
|
|
|
if (vertexlist) delete vertexlist;
|
|
if (vertorder) delete vertorder;
|
|
if (vertlist) free(vertlist);
|
|
|
|
return;
|
|
}
|
|
|
|
void CNode::SetSkin(LPDIRECT3DRM2 d3drm, CDC* pDC, CSkin* skin, int skinnum)
|
|
{
|
|
m_defaultSkin = skinnum;
|
|
ChangeSkin(d3drm, pDC, skin);
|
|
}
|
|
|
|
void CNode::AddVisual(LPDIRECT3DRMFRAME frame)
|
|
{
|
|
HRESULT ddrval = frame->AddVisual(m_mesh);
|
|
if (ddrval != D3DRM_OK)
|
|
{
|
|
AfxMessageBox(CDDHelper::TraceError(ddrval));
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool CNode::ShowFrame(LPDIRECT3DRM2 d3drm, CDC* pDC, vec3a_t* rotVerts, frameinfo2_t* frameinfo1)
|
|
{
|
|
|
|
D3DRMVERTEX* vertexlist = new D3DRMVERTEX[m_numTris * 3 + 1];
|
|
if (vertexlist == NULL)
|
|
{
|
|
AfxMessageBox("Cannot make vertexlist");
|
|
return false;
|
|
}
|
|
|
|
vec5_t* vertlist = (vec5_t*)malloc(sizeof(vec5_t) * m_numTris * 3);
|
|
|
|
long* command = m_start_glcmds;
|
|
int cur_glcmnd = m_num_glcmds;
|
|
|
|
int realvert = 0;
|
|
int skinwidth = m_curSkin->GetWidth(d3drm, pDC);
|
|
int skinheight = m_curSkin->GetHeight(d3drm, pDC);
|
|
|
|
//do the gl commands <?>
|
|
while (*command && cur_glcmnd)
|
|
{
|
|
cur_glcmnd--;
|
|
|
|
int num_verts;
|
|
if (*command>0)
|
|
{
|
|
//triangle strip
|
|
num_verts = *command;
|
|
}
|
|
else
|
|
{
|
|
//triangle fan
|
|
num_verts = -(*command);
|
|
}
|
|
command++;
|
|
|
|
vec5_t p1;
|
|
for (int i=0; i < num_verts; i++)
|
|
{
|
|
//grab the floating point s and t
|
|
p1.s = (*((float *)command)) * skinwidth; command++;
|
|
p1.t = (*((float *)command)) * skinheight; command++;
|
|
|
|
//grab the vertex index
|
|
int vert_index = *command; command++;
|
|
|
|
p1.z = -((rotVerts[vert_index][0] * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
p1.y = ((rotVerts[vert_index][1] * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
p1.x = -((rotVerts[vert_index][2] * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertlist[realvert] = p1;
|
|
realvert++;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < m_numVerts; i++)
|
|
{
|
|
vertexlist[i].position.x = vertlist[m_vertPath[i]].x;
|
|
vertexlist[i].position.y = vertlist[m_vertPath[i]].y;
|
|
vertexlist[i].position.z = vertlist[m_vertPath[i]].z;
|
|
vertexlist[i].tu = D3DVALUE(vertlist[m_vertPath[i]].s) / skinwidth;
|
|
vertexlist[i].tv = D3DVALUE(vertlist[m_vertPath[i]].t) / skinheight;
|
|
}
|
|
|
|
m_mesh->SetVertices(m_group, 0, m_numVerts, vertexlist);
|
|
|
|
free(vertlist);
|
|
delete (vertexlist);
|
|
|
|
return true;
|
|
}
|
|
|
|
void CNode::ShowInterFrame(LPDIRECT3DRM2 d3drm, CDC* pDC, frameinfo2_t* frameinfo1, frameinfo2_t* frameinfo2, int step, int numsteps)
|
|
{
|
|
D3DRMVERTEX* vertexlist = new D3DRMVERTEX[m_numTris * 3 + 1];
|
|
if (vertexlist == NULL)
|
|
{
|
|
AfxMessageBox("Cannot make vertexlist");
|
|
return;
|
|
}
|
|
|
|
vec5_t* vertlist = (vec5_t*)malloc(sizeof(vec5_t) * m_numTris * 3);
|
|
|
|
long* command = m_start_glcmds;
|
|
int cur_glcmnd = m_num_glcmds;
|
|
int realvert = 0;
|
|
int skinwidth = m_curSkin->GetWidth(d3drm, pDC);
|
|
int skinheight = m_curSkin->GetHeight(d3drm, pDC);
|
|
|
|
//do the gl commands <?>
|
|
while (*command && cur_glcmnd)
|
|
{
|
|
cur_glcmnd--;
|
|
|
|
int num_verts;
|
|
if (*command>0)
|
|
{
|
|
//triangle strip
|
|
num_verts = *command;
|
|
}
|
|
else
|
|
{
|
|
//triangle fan
|
|
num_verts = -(*command);
|
|
}
|
|
|
|
command++;
|
|
|
|
for (int i = 0; i < num_verts; i++)
|
|
{
|
|
vec5_t p1;
|
|
vec5_t p2;
|
|
//grab the floating point s and t
|
|
p1.s = (*((float *)command)) * skinwidth; command++;
|
|
p1.t = (*((float *)command)) * skinheight; command++;
|
|
|
|
//grab the vertex index
|
|
long vert_index = *command; command++;
|
|
|
|
p1.z = -((frameinfo1->verts[vert_index].x * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
p1.y = ((frameinfo1->verts[vert_index].y * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
p1.x = -((frameinfo1->verts[vert_index].z * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
p2.z = -((frameinfo2->verts[vert_index].x * frameinfo2->scale.x) + frameinfo2->origin.x);
|
|
p2.y = ((frameinfo2->verts[vert_index].y * frameinfo2->scale.y) + frameinfo2->origin.y);
|
|
p2.x = -((frameinfo2->verts[vert_index].z * frameinfo2->scale.z) + frameinfo2->origin.z);
|
|
|
|
D3DVECTOR delta;
|
|
delta.x = (p2.x - p1.x) / numsteps;
|
|
delta.y = (p2.y - p1.y) / numsteps;
|
|
delta.z = (p2.z - p1.z) / numsteps;
|
|
|
|
p1.x += delta.x * step;
|
|
p1.y += delta.y * step;
|
|
p1.z += delta.z * step;
|
|
|
|
vertlist[realvert] = p1;
|
|
realvert++;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < m_numVerts; i++)
|
|
{
|
|
vertexlist[i].position.x = vertlist[m_vertPath[i]].x;
|
|
vertexlist[i].position.y = vertlist[m_vertPath[i]].y;
|
|
vertexlist[i].position.z = vertlist[m_vertPath[i]].z;
|
|
vertexlist[i].tu = D3DVALUE(vertlist[m_vertPath[i]].s) / skinwidth;
|
|
vertexlist[i].tv = D3DVALUE(vertlist[m_vertPath[i]].t) / skinheight;
|
|
}
|
|
|
|
m_mesh->SetVertices(m_group, 0, m_numVerts, vertexlist);
|
|
|
|
free(vertlist);
|
|
delete (vertexlist);
|
|
}
|
|
|
|
//
|
|
// CFlexModel
|
|
//
|
|
bool CFlexModel::LoadSkin(LPDIRECT3DRM2 d3drm, LPDIRECT3DRMFRAME frame, int skinnum, CDC* pDC)
|
|
{
|
|
CSkin* skin = GetSkin(skinnum);
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
m_nodes[i].LoadSkin(d3drm, pDC, skin, skinnum);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CFlexModel::CreateJointVisuals(LPDIRECT3DRM2 d3drm, LPDIRECT3DRMFRAME frame)
|
|
{
|
|
if (m_numClusters)
|
|
{
|
|
for (int i = 0; i < m_numClusters; i++)
|
|
{
|
|
CreateJointVisual(d3drm, m_skeletons[0].rootJoint[i].model, i, frame);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CFlexModel::CreateJointVisual(LPDIRECT3DRM2 d3drm, Placement_t model, int jointNum, LPDIRECT3DRMFRAME frame)
|
|
{
|
|
D3DRMVERTEX vertexlist[12];
|
|
unsigned vertorder[24];
|
|
|
|
frameinfo2_t *frameinfo1 = (frameinfo2_t *)m_frames;
|
|
|
|
vertexlist[0].position.z = -(((model.origin[0] - 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[0].position.y = (((model.origin[1]) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[0].position.x = -(((model.origin[2]) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[2].position.z = -(((model.origin[0] + 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[2].position.y = (((model.origin[1]) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[2].position.x = -(((model.origin[2]) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[1].position.z = -(((model.origin[0]) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[1].position.y = (((model.origin[1]) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[1].position.x = -(((model.origin[2] + 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[3].position.z = -(((model.origin[0]) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[3].position.y = (((model.origin[1]) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[3].position.x = -(((model.origin[2] - 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[4].position.z = -(((model.origin[0]) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[4].position.y = (((model.origin[1] + 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[4].position.x = -(((model.origin[2]) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[5].position.z = -(((model.origin[0]) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[5].position.y = (((model.origin[1] - 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[5].position.x = -(((model.origin[2]) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertorder[0] = 1;
|
|
vertorder[1] = 4;
|
|
vertorder[2] = 0;
|
|
|
|
vertorder[3] = 4;
|
|
vertorder[4] = 3;
|
|
vertorder[5] = 0;
|
|
|
|
vertorder[6] = 1;
|
|
vertorder[7] = 2;
|
|
vertorder[8] = 4;
|
|
|
|
vertorder[9] = 2;
|
|
vertorder[10] = 3;
|
|
vertorder[11] = 4;
|
|
|
|
//////////////////
|
|
|
|
vertorder[12] = 3;
|
|
vertorder[13] = 5;
|
|
vertorder[14] = 0;
|
|
|
|
vertorder[15] = 5;
|
|
vertorder[16] = 1;
|
|
vertorder[17] = 0;
|
|
|
|
vertorder[18] = 3;
|
|
vertorder[19] = 2;
|
|
vertorder[20] = 5;
|
|
|
|
vertorder[21] = 2;
|
|
vertorder[22] = 1;
|
|
vertorder[23] = 5;
|
|
|
|
d3drm->CreateMesh(&m_joint_visuals[jointNum].origin);
|
|
|
|
m_joint_visuals[jointNum].origin->AddGroup( 24, 8, 3, vertorder, &m_group );
|
|
m_joint_visuals[jointNum].origin->SetVertices(m_group, 0, 23, vertexlist );
|
|
|
|
m_joint_visuals[jointNum].origin->SetGroupQuality(m_group, D3DRMRENDER_FLAT );
|
|
m_joint_visuals[jointNum].origin->SetGroupColorRGB(m_group, D3DVALUE( 255 ), D3DVALUE( 0 ), D3DVALUE( 0 ));
|
|
|
|
HRESULT ddrval = frame->AddVisual(m_joint_visuals[jointNum].origin);
|
|
if (ddrval != D3DRM_OK)
|
|
AfxMessageBox(CDDHelper::TraceError(ddrval));
|
|
|
|
/**************************************************************************/
|
|
|
|
D3DVECTOR dir, up, org;
|
|
|
|
dir.x = model.direction[0];
|
|
dir.y = model.direction[1];
|
|
dir.z = model.direction[2];
|
|
|
|
up.x = model.up[0];
|
|
up.y = model.up[1];
|
|
up.z = model.up[2];
|
|
|
|
org.x = model.origin[0];
|
|
org.y = model.origin[1];
|
|
org.z = model.origin[2];
|
|
|
|
D3DRMVectorSubtract(&dir, &dir, &org);
|
|
D3DRMVectorNormalize(&dir);
|
|
|
|
dir.x *= 5;
|
|
dir.y *= 5;
|
|
dir.z *= 5;
|
|
|
|
dir.x += org.x;
|
|
dir.y += org.y;
|
|
dir.z += org.z;
|
|
|
|
D3DRMVectorSubtract(&up, &up, &org);
|
|
D3DRMVectorNormalize(&up);
|
|
|
|
up.x *= 5;
|
|
up.y *= 5;
|
|
up.z *= 5;
|
|
|
|
up.x += org.x;
|
|
up.y += org.y;
|
|
up.z += org.z;
|
|
|
|
vertexlist[0].position.z = -(((dir.x - 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[0].position.y = (((dir.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[0].position.x = -(((dir.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[2].position.z = -(((dir.x + 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[2].position.y = (((dir.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[2].position.x = -(((dir.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[1].position.z = -(((dir.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[1].position.y = (((dir.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[1].position.x = -(((dir.z + 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[3].position.z = -(((dir.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[3].position.y = (((dir.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[3].position.x = -(((dir.z - 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[4].position.z = -(((dir.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[4].position.y = (((dir.y + 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[4].position.x = -(((dir.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[5].position.z = -(((dir.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[5].position.y = (((dir.y - 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[5].position.x = -(((dir.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
d3drm->CreateMesh(&m_joint_visuals[jointNum].dir);
|
|
|
|
m_joint_visuals[jointNum].dir->AddGroup( 24, 8, 3, vertorder, &m_group );
|
|
m_joint_visuals[jointNum].dir->SetVertices(m_group, 0, 23, vertexlist );
|
|
|
|
m_joint_visuals[jointNum].dir->SetGroupQuality(m_group, D3DRMRENDER_FLAT );
|
|
m_joint_visuals[jointNum].dir->SetGroupColorRGB(m_group, D3DVALUE( 0 ), D3DVALUE( 255 ), D3DVALUE( 0 ));
|
|
|
|
ddrval = frame->AddVisual(m_joint_visuals[jointNum].dir );
|
|
if (ddrval != D3DRM_OK)
|
|
AfxMessageBox(CDDHelper::TraceError(ddrval));
|
|
|
|
/**************************************************************************/
|
|
|
|
vertexlist[0].position.z = -(((up.x - 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[0].position.y = (((up.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[0].position.x = -(((up.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[2].position.z = -(((up.x + 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[2].position.y = (((up.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[2].position.x = -(((up.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[1].position.z = -(((up.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[1].position.y = (((up.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[1].position.x = -(((up.z + 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[3].position.z = -(((up.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[3].position.y = (((up.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[3].position.x = -(((up.z - 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[4].position.z = -(((up.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[4].position.y = (((up.y + 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[4].position.x = -(((up.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[5].position.z = -(((up.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[5].position.y = (((up.y - 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[5].position.x = -(((up.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
d3drm->CreateMesh(&m_joint_visuals[jointNum].up);
|
|
|
|
m_joint_visuals[jointNum].up->AddGroup( 24, 8, 3, vertorder, &m_group );
|
|
m_joint_visuals[jointNum].up->SetVertices(m_group, 0, 23, vertexlist );
|
|
|
|
m_joint_visuals[jointNum].up->SetGroupQuality(m_group, D3DRMRENDER_FLAT );
|
|
m_joint_visuals[jointNum].up->SetGroupColorRGB(m_group, D3DVALUE( 0 ), D3DVALUE( 0 ), D3DVALUE( 255 ));
|
|
|
|
ddrval = frame->AddVisual(m_joint_visuals[jointNum].up );
|
|
if (ddrval != D3DRM_OK)
|
|
AfxMessageBox(CDDHelper::TraceError(ddrval));
|
|
}
|
|
|
|
CFlexModel::CFlexModel()
|
|
{
|
|
}
|
|
|
|
CFlexModel::~CFlexModel()
|
|
{
|
|
}
|
|
|
|
void CFlexModel::Init()
|
|
{
|
|
m_compdata.start_frame =0;
|
|
m_compdata.num_frames = 0;
|
|
m_compdata.degrees = 0;
|
|
m_compdata.mat = NULL;
|
|
m_compdata.ccomp = NULL;
|
|
m_compdata.cbase = NULL;
|
|
m_compdata.cscale = NULL;
|
|
m_compdata.coffset = NULL;
|
|
m_compdata.complerp = NULL;
|
|
m_compdata.trans[0] = 0;
|
|
m_compdata.scale[0] = 0;
|
|
m_compdata.bmin[0] = 0;
|
|
m_compdata.bmax[0] = 0;
|
|
m_compdata.trans[1] = 0;
|
|
m_compdata.scale[1] = 0;
|
|
m_compdata.bmin[1] = 0;
|
|
m_compdata.bmax[1] = 0;
|
|
m_compdata.trans[2] = 0;
|
|
m_compdata.scale[2] = 0;
|
|
m_compdata.bmin[2] = 0;
|
|
m_compdata.bmax[2] = 0;
|
|
|
|
m_curFrame = 0;
|
|
m_framenames = NULL;
|
|
|
|
m_lightnormalindex = NULL;
|
|
m_skeletalType = 0;
|
|
m_skeletons = NULL;
|
|
m_referenceType = -1;
|
|
for (int i = 0; i < JOINT_VISUALS; i++)
|
|
{
|
|
m_joint_visuals[i].origin = NULL;
|
|
m_joint_visuals[i].dir = NULL;
|
|
m_joint_visuals[i].up = NULL;
|
|
}
|
|
|
|
m_num_mesh_nodes = 0;
|
|
m_curNode = -1;
|
|
m_nodes = NULL;
|
|
|
|
m_skin_names = NULL;
|
|
CModel::Init();
|
|
// joint support
|
|
m_jointsOn = false;
|
|
m_curJoint = -1;
|
|
m_jointConstraintAngles = NULL;
|
|
m_modelJointAngles = NULL;
|
|
m_skeletalClusters = NULL;
|
|
m_numClusters = 0;
|
|
}
|
|
|
|
void CFlexModel::DeleteMeshs(LPDIRECT3DRMFRAME frame)
|
|
{
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
m_nodes[i].DeleteMesh();
|
|
}
|
|
m_curNode = -1;
|
|
}
|
|
|
|
void CFlexModel::DeleteVisuals(LPDIRECT3DRMFRAME frame)
|
|
{
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
LPDIRECT3DRMMESH mesh = m_nodes[i].GetMesh();
|
|
if (mesh != NULL)
|
|
{
|
|
frame->DeleteVisual(mesh);
|
|
}
|
|
}
|
|
for (i = 0; i < m_numClusters; i++)
|
|
{
|
|
if (m_joint_visuals[i].origin != NULL)
|
|
{
|
|
frame->DeleteVisual(m_joint_visuals[i].origin);
|
|
m_joint_visuals[i].origin->Release();
|
|
m_joint_visuals[i].origin = NULL;
|
|
}
|
|
if (m_joint_visuals[i].dir != NULL)
|
|
{
|
|
frame->DeleteVisual(m_joint_visuals[i].dir);
|
|
m_joint_visuals[i].dir->Release();
|
|
m_joint_visuals[i].dir = NULL;
|
|
}
|
|
if (m_joint_visuals[i].up != NULL)
|
|
{
|
|
frame->DeleteVisual(m_joint_visuals[i].up);
|
|
m_joint_visuals[i].up->Release();
|
|
m_joint_visuals[i].up = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CFlexModel::Delete()
|
|
{
|
|
if (m_skin_names)
|
|
{
|
|
for (int i = 0; i < m_num_skins; i++)
|
|
{
|
|
free(m_skin_names[i]);
|
|
m_skin_names[i] = NULL;
|
|
}
|
|
free (m_skin_names);
|
|
m_skin_names = NULL;
|
|
}
|
|
|
|
if (m_nodes != NULL)
|
|
{
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
m_nodes[i].Delete();
|
|
}
|
|
delete m_nodes;
|
|
m_nodes = NULL;
|
|
}
|
|
if (m_compdata.mat)
|
|
{
|
|
free (m_compdata.mat);
|
|
m_compdata.mat = NULL;
|
|
}
|
|
|
|
if (m_compdata.ccomp)
|
|
{
|
|
free (m_compdata.ccomp);
|
|
m_compdata.ccomp = NULL;
|
|
}
|
|
|
|
if (m_compdata.cbase)
|
|
{
|
|
free (m_compdata.cbase);
|
|
m_compdata.cbase = NULL;
|
|
}
|
|
|
|
if (m_compdata.cscale)
|
|
{
|
|
free (m_compdata.cscale);
|
|
m_compdata.cscale = NULL;
|
|
}
|
|
|
|
if (m_compdata.coffset)
|
|
{
|
|
free (m_compdata.coffset);
|
|
m_compdata.coffset = NULL;
|
|
}
|
|
|
|
if (m_compdata.complerp)
|
|
{
|
|
free (m_compdata.complerp);
|
|
m_compdata.complerp = NULL;
|
|
}
|
|
|
|
if (m_framenames != NULL)
|
|
{
|
|
free(m_framenames);
|
|
m_framenames = NULL;
|
|
}
|
|
|
|
if (m_lightnormalindex)
|
|
{
|
|
free (m_lightnormalindex);
|
|
m_lightnormalindex = NULL;
|
|
}
|
|
|
|
if (m_skeletons)
|
|
{
|
|
free (m_skeletons);
|
|
m_skeletons = NULL;
|
|
}
|
|
|
|
for (int i = 0; i < m_numClusters; i++)
|
|
{
|
|
delete (m_skeletalClusters[i].verticies);
|
|
m_skeletalClusters[i].verticies = NULL;
|
|
}
|
|
if (m_skeletalClusters != NULL)
|
|
{
|
|
delete m_skeletalClusters;
|
|
m_skeletalClusters = NULL;
|
|
m_numClusters = 0;
|
|
}
|
|
if (m_jointConstraintAngles != NULL)
|
|
{
|
|
delete m_jointConstraintAngles;
|
|
m_jointConstraintAngles = NULL;
|
|
}
|
|
if (m_modelJointAngles != NULL)
|
|
{
|
|
delete m_modelJointAngles;
|
|
m_modelJointAngles = NULL;
|
|
}
|
|
m_num_mesh_nodes = -1;
|
|
CModel::Delete();
|
|
}
|
|
|
|
HRESULT CFlexModel::SetGroupQuality(D3DRMRENDERQUALITY value)
|
|
{
|
|
HRESULT retval;
|
|
if (m_num_mesh_nodes > 0)
|
|
{
|
|
if (m_curNode < 0)
|
|
{
|
|
for (int i = 0; i < m_num_mesh_nodes;i++)
|
|
{
|
|
retval = m_nodes[i].SetQuality(value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retval = m_nodes[m_curNode].SetQuality(value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retval = CModel::SetGroupQuality(value);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
LPDIRECT3DRMMESH CFlexModel::GetMesh(int i)
|
|
{
|
|
if (i < 0)
|
|
{
|
|
if (m_curNode < 0)
|
|
{
|
|
return m_nodes[0].GetMesh();
|
|
}
|
|
return m_nodes[m_curNode].GetMesh();
|
|
}
|
|
return m_nodes[i].GetMesh();
|
|
}
|
|
|
|
void CFlexModel::Drag(double delta_x, double delta_y)
|
|
{
|
|
if (GetKeyState(VK_SHIFT)&0x8000)
|
|
{
|
|
m_modelJointAngles[m_curJoint].y += (float) delta_x / 100;
|
|
|
|
if (m_modelJointAngles[m_curJoint].y > PI*2)
|
|
m_modelJointAngles[m_curJoint].y = (float) PI*2 - m_modelJointAngles[m_curJoint].y;
|
|
else if (m_modelJointAngles[m_curJoint].y < 0)
|
|
m_modelJointAngles[m_curJoint].y = (float) PI*2 + m_modelJointAngles[m_curJoint].y;
|
|
}
|
|
else
|
|
{
|
|
m_modelJointAngles[m_curJoint].x += (float) delta_x / 100;
|
|
|
|
m_modelJointAngles[m_curJoint].z += (float) delta_y / 100;
|
|
|
|
if (m_modelJointAngles[m_curJoint].x > PI*2)
|
|
m_modelJointAngles[m_curJoint].x = (float) PI*2 - m_modelJointAngles[m_curJoint].x;
|
|
else if (m_modelJointAngles[m_curJoint].x < 0)
|
|
m_modelJointAngles[m_curJoint].x = (float) PI*2 + m_modelJointAngles[m_curJoint].x;
|
|
|
|
if (m_modelJointAngles[m_curJoint].z > PI*2)
|
|
m_modelJointAngles[m_curJoint].z = (float) PI*2 - m_modelJointAngles[m_curJoint].z;
|
|
else if (m_modelJointAngles[m_curJoint].z < 0)
|
|
m_modelJointAngles[m_curJoint].z = (float) PI*2 + m_modelJointAngles[m_curJoint].z;
|
|
}
|
|
// ShowFrame();
|
|
// ConstrainJoint();
|
|
}
|
|
|
|
void CFlexModel::DeSelectAll()
|
|
{
|
|
m_curNode = -1;
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
GetMesh(i)->SetGroupColorRGB( 0, D3DVALUE(255),
|
|
D3DVALUE(255),
|
|
D3DVALUE(255) );
|
|
}
|
|
}
|
|
|
|
void CFlexModel::ChangeVisual(LPDIRECT3DRMFRAME frame, int nodeNum)
|
|
{
|
|
if (nodeNum != m_curNode)
|
|
{
|
|
if (m_curNode != -1 && !m_nodes[m_curNode].IsVisible())
|
|
{
|
|
frame->DeleteVisual(m_nodes[m_curNode].GetMesh());
|
|
}
|
|
|
|
if (nodeNum != -1 && !m_nodes[nodeNum].IsVisible())
|
|
{
|
|
frame->AddVisual(m_nodes[nodeNum].GetMesh());
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
int CFlexModel::SelectNode(int nodeNum)
|
|
{
|
|
int retval = m_curNode;
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
m_nodes[i].SetColorRGB(D3DVALUE(255), D3DVALUE(255), D3DVALUE(255));
|
|
}
|
|
|
|
m_nodes[nodeNum].SetColorRGB(D3DVALUE(255), D3DVALUE(0), D3DVALUE(0));
|
|
m_curNode = nodeNum;
|
|
return retval;
|
|
}
|
|
|
|
HTREEITEM CFlexModel::SelectMesh(LPDIRECT3DRMVISUAL selection)
|
|
{
|
|
HTREEITEM retval = NULL;
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
if (m_nodes[i].GetMesh() == selection)
|
|
{
|
|
m_curNode = i;
|
|
m_nodes[i].SetColorRGB(255, 0, 0);
|
|
retval = m_nodes[i].m_treeitem;
|
|
}
|
|
else
|
|
{
|
|
m_nodes[i].SetColorRGB(255, 255, 255);
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
bool CFlexModel::ToggleNodeVisibility(int node)
|
|
{
|
|
m_nodes[node].SetVisible(!m_nodes[node].IsVisible());
|
|
return m_nodes[node].IsVisible ();
|
|
}
|
|
|
|
void CFlexModel::MakeAllNodesVisible(LPDIRECT3DRMFRAME frame)
|
|
{
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
if (!m_nodes[i].IsVisible())
|
|
{
|
|
m_nodes[i].SetVisible(true);
|
|
frame->AddVisual(m_nodes[i].GetMesh());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CFlexModel::SetCurJoint(long joint)
|
|
{
|
|
m_curJoint = joint;
|
|
}
|
|
|
|
bool CFlexModel::ValidNode()
|
|
{
|
|
return m_curNode >= 0;
|
|
}
|
|
|
|
long CFlexModel::GetNumNodes()
|
|
{
|
|
return m_num_mesh_nodes;
|
|
}
|
|
|
|
long CFlexModel::GetNumTris()
|
|
{
|
|
return m_nodes[m_curNode].GetNumTris();
|
|
}
|
|
|
|
long CFlexModel::GetCurJoint()
|
|
{
|
|
return m_curJoint;
|
|
}
|
|
|
|
CBitmap* CFlexModel::GetBitmap(LPDIRECT3DRM2 d3drm, CDC* pDC, int skinnum, int& width, int& height)
|
|
{
|
|
if (skinnum >= 0)
|
|
{
|
|
CSkin* skin = GetSkin(skinnum);
|
|
width = skin->GetWidth(d3drm, pDC);
|
|
height = skin->GetHeight(d3drm, pDC);
|
|
return skin->GetBitmap(d3drm, pDC);
|
|
}
|
|
if (m_curNode > -1)
|
|
{
|
|
return m_nodes[m_curNode].GetBitmap(d3drm, pDC, width, height);
|
|
}
|
|
width = 0;
|
|
height = 0;
|
|
return NULL;
|
|
}
|
|
|
|
void CFlexModel::Snap()
|
|
{
|
|
if (m_curJoint < 0)
|
|
{
|
|
return;
|
|
}
|
|
m_modelJointAngles[m_curJoint].x = 0;
|
|
m_modelJointAngles[m_curJoint].y = 0;
|
|
m_modelJointAngles[m_curJoint].z = 0;
|
|
}
|
|
|
|
void CFlexModel::LoadSkinInfo(CTreeCtrl* pCTree, HTREEITEM rootSkin)
|
|
{
|
|
for (int i = 0; i < m_num_skins; i++)
|
|
{
|
|
HTREEITEM point = pCTree->InsertItem(m_skin_names[i], rootSkin, TVI_LAST);
|
|
pCTree->SetItemImage(point, 0, 0);
|
|
pCTree->SetItemData(point, i);
|
|
}
|
|
}
|
|
|
|
void CFlexModel::UpdateJointVisuals(int jointNum)
|
|
{
|
|
D3DRMVERTEX vertexlist[12];
|
|
|
|
Placement_t model = m_skeletons[m_curFrame].rootJoint[jointNum].model;
|
|
|
|
frameinfo2_t *frameinfo1 = (frameinfo2_t *)((char *)m_frames + m_framesize * m_curFrame);
|
|
|
|
vertexlist[0].position.z = -(((model.origin[0] - 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[0].position.y = (((model.origin[1]) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[0].position.x = -(((model.origin[2]) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[2].position.z = -(((model.origin[0] + 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[2].position.y = (((model.origin[1]) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[2].position.x = -(((model.origin[2]) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[1].position.z = -(((model.origin[0]) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[1].position.y = (((model.origin[1]) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[1].position.x = -(((model.origin[2] + 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[3].position.z = -(((model.origin[0]) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[3].position.y = (((model.origin[1]) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[3].position.x = -(((model.origin[2] - 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[4].position.z = -(((model.origin[0]) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[4].position.y = (((model.origin[1] + 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[4].position.x = -(((model.origin[2]) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[5].position.z = -(((model.origin[0]) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[5].position.y = (((model.origin[1] - 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[5].position.x = -(((model.origin[2]) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
m_joint_visuals[jointNum].origin->SetVertices( 0, 0, 23, vertexlist );
|
|
|
|
/**************************************************************************/
|
|
|
|
D3DVECTOR dir, up, org;
|
|
|
|
dir.x = model.direction[0];
|
|
dir.y = model.direction[1];
|
|
dir.z = model.direction[2];
|
|
|
|
up.x = model.up[0];
|
|
up.y = model.up[1];
|
|
up.z = model.up[2];
|
|
|
|
org.x = model.origin[0];
|
|
org.y = model.origin[1];
|
|
org.z = model.origin[2];
|
|
|
|
D3DRMVectorSubtract(&dir, &dir, &org);
|
|
D3DRMVectorNormalize(&dir);
|
|
|
|
dir.x *= 8;
|
|
dir.y *= 8;
|
|
dir.z *= 8;
|
|
|
|
dir.x += org.x;
|
|
dir.y += org.y;
|
|
dir.z += org.z;
|
|
|
|
D3DRMVectorSubtract(&up, &up, &org);
|
|
D3DRMVectorNormalize(&up);
|
|
|
|
up.x *= 8;
|
|
up.y *= 8;
|
|
up.z *= 8;
|
|
|
|
up.x += org.x;
|
|
up.y += org.y;
|
|
up.z += org.z;
|
|
|
|
vertexlist[0].position.z = -(((dir.x - 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[0].position.y = (((dir.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[0].position.x = -(((dir.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[2].position.z = -(((dir.x + 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[2].position.y = (((dir.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[2].position.x = -(((dir.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[1].position.z = -(((dir.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[1].position.y = (((dir.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[1].position.x = -(((dir.z + 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[3].position.z = -(((dir.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[3].position.y = (((dir.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[3].position.x = -(((dir.z - 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[4].position.z = -(((dir.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[4].position.y = (((dir.y + 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[4].position.x = -(((dir.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[5].position.z = -(((dir.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[5].position.y = (((dir.y - 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[5].position.x = -(((dir.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
m_joint_visuals[jointNum].dir->SetVertices( 0, 0, 23, vertexlist );
|
|
|
|
/**************************************************************************/
|
|
|
|
vertexlist[0].position.z = -(((up.x - 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[0].position.y = (((up.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[0].position.x = -(((up.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[2].position.z = -(((up.x + 1) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[2].position.y = (((up.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[2].position.x = -(((up.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[1].position.z = -(((up.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[1].position.y = (((up.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[1].position.x = -(((up.z + 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[3].position.z = -(((up.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[3].position.y = (((up.y) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[3].position.x = -(((up.z - 1) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[4].position.z = -(((up.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[4].position.y = (((up.y + 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[4].position.x = -(((up.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
vertexlist[5].position.z = -(((up.x) * frameinfo1->scale.x) + frameinfo1->origin.x);
|
|
vertexlist[5].position.y = (((up.y - 1) * frameinfo1->scale.y) + frameinfo1->origin.y);
|
|
vertexlist[5].position.x = -(((up.z) * frameinfo1->scale.z) + frameinfo1->origin.z);
|
|
|
|
m_joint_visuals[jointNum].up->SetVertices( 0, 0, 23, vertexlist );
|
|
}
|
|
|
|
void CFlexModel::FillRawVerts(vec3a_t *foo)
|
|
{
|
|
frameinfo2_t *frameinfo1 = (frameinfo2_t *)((char *)m_frames + m_framesize * m_curFrame);
|
|
|
|
for (int i = 0; i < m_num_xyz; i++)
|
|
{
|
|
foo[i][0] = frameinfo1->verts[i].x;
|
|
foo[i][1] = frameinfo1->verts[i].y;
|
|
foo[i][2] = frameinfo1->verts[i].z;
|
|
}
|
|
}
|
|
|
|
BOOL CFlexModel::ShowFrame(LPDIRECT3DRM2 d3drm, CDC* pDC)
|
|
{
|
|
for (int i = 0; i < m_numClusters; i++)
|
|
UpdateJointVisuals(i);
|
|
|
|
if (m_num_mesh_nodes > 0)
|
|
{
|
|
vec3a_t angles;
|
|
|
|
if (m_curJoint > -1)
|
|
{
|
|
angles[0] = m_modelJointAngles[m_curJoint].x;
|
|
angles[1] = m_modelJointAngles[m_curJoint].y;
|
|
angles[2] = m_modelJointAngles[m_curJoint].z;
|
|
}
|
|
else
|
|
{
|
|
angles[0] = 0;
|
|
angles[1] = 0;
|
|
angles[2] = 0;
|
|
}
|
|
|
|
vec3a_t* rotVerts = (vec3a_t *) malloc(sizeof(vec3a_t)*m_num_tris*3);
|
|
|
|
FillRawVerts(rotVerts);
|
|
|
|
if (m_skeletons && m_jointsOn)
|
|
RotateModelSegment((M_SkeletalJoint_s *) &m_skeletons[m_curFrame].rootJoint[m_curJoint], rotVerts, angles, &m_skeletalClusters[m_curJoint]);
|
|
|
|
frameinfo2_t* frameinfo1 = (frameinfo2_t*)((char *)m_frames + m_framesize * GetCurFrame());
|
|
for (i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
m_nodes[i].ShowFrame(d3drm, pDC, rotVerts, frameinfo1);
|
|
}
|
|
|
|
free (rotVerts);
|
|
return true;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CFlexModel::CalcInterpolate(LPDIRECT3DRM2 d3drm, CDC* pDC, int step, int numsteps, int intertype, int direction)
|
|
{
|
|
int curvert = 0;
|
|
int lastframe, i;
|
|
|
|
if (direction == ANIM_FORWARD)
|
|
{
|
|
if (m_curGroup == -1)
|
|
{
|
|
if (m_curFrame + 1 > m_num_frames-1)
|
|
lastframe = 0;
|
|
else
|
|
lastframe = m_curFrame + 1;
|
|
}
|
|
else
|
|
{
|
|
if (m_curFrame + 1 > m_treeInfo[m_curGroup].eFrame)
|
|
{
|
|
lastframe = m_treeInfo[m_curGroup].bFrame;
|
|
}
|
|
else
|
|
{
|
|
lastframe = m_curFrame + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
frameinfo2_t* frameinfo1 = (frameinfo2_t*)((char*)m_frames + m_framesize * m_curFrame);
|
|
frameinfo2_t* frameinfo2 = (frameinfo2_t*)((char*)m_frames + m_framesize * lastframe);
|
|
if (m_num_mesh_nodes > 0)
|
|
{
|
|
for (i=0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
m_nodes[i].ShowInterFrame(d3drm, pDC, frameinfo1, frameinfo2, step, numsteps);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_nodes[0].ShowInterFrame(d3drm, pDC, frameinfo1, frameinfo2, step, numsteps);
|
|
}
|
|
|
|
if (step + 1 > numsteps) m_curstep = 0;
|
|
else m_curstep++;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Node Tree Ctrl Support
|
|
void CFlexModel::AddNode (CTreeCtrl*pCTree, HTREEITEM rootNode, int nodeNum)
|
|
{
|
|
CString foo;
|
|
foo.Format("Node %d", nodeNum);
|
|
HTREEITEM point = pCTree->InsertItem(foo, rootNode, TVI_LAST);
|
|
m_nodes[nodeNum].m_treeitem = point;
|
|
pCTree->SetItemData(point, nodeNum);
|
|
pCTree->SetItemImage(point, 1, 1);
|
|
pCTree->Expand(rootNode, TVE_EXPAND);
|
|
}
|
|
|
|
void CFlexModel::AddNodes(CTreeCtrl* pCTreeCtrl, HTREEITEM rootNode)
|
|
{
|
|
if (m_num_mesh_nodes > 0)
|
|
{
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
m_nodes[i].SetVisible(true);
|
|
AddNode(pCTreeCtrl, rootNode, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CFlexModel::FillMenuWithSkins(CMenu* menu)
|
|
{
|
|
int curID = IDR_SKIN_SELECT_START;
|
|
for (int i = 0; i < m_num_skins; i++)
|
|
{
|
|
menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, curID++, m_skin_names[i]);
|
|
}
|
|
}
|
|
|
|
void CFlexModel::ChangeSkin(LPDIRECT3DRM2 d3drm, CDC* pDC, int nodenum, int skinnum)
|
|
{
|
|
CSkin* skin = CModel::GetSkin(m_skin_names[skinnum]);
|
|
m_nodes[nodenum].ChangeSkin(d3drm, pDC, skin);
|
|
}
|
|
|
|
void CFlexModel::AddSkin(LPCTSTR skinname)
|
|
{
|
|
char** holdSkins = m_skin_names;
|
|
m_skin_names = (char**)malloc(sizeof(char*) * (m_num_skins + 1));
|
|
for (int i = 0; i < m_num_skins; i++)
|
|
{
|
|
m_skin_names[i] = holdSkins[i];
|
|
}
|
|
free(holdSkins);
|
|
CString result = skinname;
|
|
|
|
while(true)
|
|
{
|
|
int destChar = result.Find("/");
|
|
if (destChar < 0)
|
|
{
|
|
break;
|
|
}
|
|
result.SetAt(destChar, '\\');
|
|
}
|
|
|
|
m_skin_names[m_num_skins] = (char*)malloc(result.GetLength() + 1);
|
|
strcpy(m_skin_names[m_num_skins], result);
|
|
m_num_skins++;
|
|
}
|
|
|
|
void CFlexModel::ReplaceSkin(int i, LPCTSTR skinname)
|
|
{
|
|
if (m_skin_names[i] != NULL)
|
|
{
|
|
free(m_skin_names[i]);
|
|
m_skin_names[i] = NULL;
|
|
}
|
|
m_skin_names[i] = (char*)malloc(strlen(skinname) + 1);
|
|
strcpy(m_skin_names[i], skinname);
|
|
}
|
|
|
|
CSkin* CFlexModel::GetSkin(int i)
|
|
{
|
|
return CModel::GetSkin(m_skin_names[i]);
|
|
}
|
|
|
|
void CFlexModel::BuildMesh(LPDIRECT3DRM2 d3drm, LPDIRECT3DRMFRAME frame, LPDIRECT3DRMFRAME scene, CDC* pDC)
|
|
{
|
|
CSkin* skin = GetSkin(0);
|
|
|
|
if (m_num_mesh_nodes > 0)
|
|
{
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
m_curNode = i;
|
|
m_nodes[i].BuildMesh(d3drm, (frameinfo2_t*)m_frames, skin->GetWidth(d3drm, pDC), skin->GetHeight(d3drm, pDC));
|
|
m_nodes[i].SetSkin(d3drm, pDC, skin, 0);
|
|
m_nodes[i].AddVisual(frame);
|
|
}
|
|
frame->SetOrientation(scene,
|
|
D3DVALUE(0), D3DVALUE(0), D3DVALUE(1),
|
|
D3DVALUE(1), D3DVALUE(0), D3DVALUE(0));
|
|
}
|
|
}
|
|
|
|
void CFlexModel::RotateModelSegment(M_SkeletalJoint_t *joint, vec3a_t *modelVerticies, vec3a_t angles, M_SkeletalCluster_t *modelCluster)
|
|
{
|
|
int i;
|
|
matrix3_t rotation, rotation2, toWorld, partialBackToLocal;
|
|
vec3a_t localAngles;
|
|
|
|
localAngles[0] = 0;//angles[0];
|
|
localAngles[1] = 0;//angles[1];
|
|
localAngles[2] = 0;//angles[2];
|
|
|
|
memset(rotation, 0, sizeof(rotation));
|
|
|
|
CMatrix::Matrix3FromAngles(angles, rotation);
|
|
|
|
//D3DVECTOR dir, up;
|
|
vec3a_t fdir, fup;
|
|
|
|
fdir[0] = joint->model.direction[0];
|
|
fdir[1] = joint->model.direction[1];
|
|
fdir[2] = joint->model.direction[2];
|
|
|
|
Vec3Normalize(fdir);
|
|
|
|
fup[0] = joint->model.up[0];
|
|
fup[1] = joint->model.up[1];
|
|
fup[2] = joint->model.up[2];
|
|
|
|
Vec3Normalize(fup);
|
|
|
|
localAngles[ROLL] += (float) CMatrix::Matricies3FromDirAndUp(fdir, fup, toWorld, partialBackToLocal);
|
|
|
|
CMatrix::Matrix3MultByMartrix3(rotation, toWorld, rotation2);
|
|
CMatrix::Matrix3MultByMartrix3(partialBackToLocal, rotation2, rotation);
|
|
|
|
for(i = 0; i < modelCluster->numVerticies; ++i)
|
|
{
|
|
CMatrix::RotatePointAboutLocalOrigin_d(rotation, joint->model.origin, modelVerticies[modelCluster->verticies[i]]);
|
|
}
|
|
}
|
|
|
|
// frame tree ctrl support
|
|
|
|
void CFlexModel::LoadFrameInfo(CTreeCtrl* treeDlg, HTREEITEM rootFrame)
|
|
{
|
|
if (m_num_frames > 0)
|
|
{
|
|
m_numGroups = 0;
|
|
|
|
m_treeInfo = new CTreeHead[m_num_frames];
|
|
if (m_treeInfo == NULL) AfxMessageBox("Null tree");
|
|
|
|
CTreeGroup* groupList = new CTreeGroup[m_num_frames];
|
|
if (groupList == NULL) AfxMessageBox("Null groupList");
|
|
|
|
for (int i = 0; i < m_num_frames; i++)
|
|
{
|
|
frameinfo2_t* frameinfo1 = (frameinfo2_t *)((char *)m_frames + m_framesize * i);
|
|
char name[18];
|
|
memcpy(name , frameinfo1->name, 16);
|
|
name[16] = '\0';
|
|
char* newname = name;
|
|
StripGroupName(newname);
|
|
int thisgroup = InGroupList(newname, groupList, m_numGroups);
|
|
if (thisgroup == -1)
|
|
{
|
|
thisgroup = m_numGroups;
|
|
groupList[thisgroup].head = treeDlg->InsertItem(newname, rootFrame, TVI_LAST);
|
|
treeDlg->SetItemData(groupList[thisgroup].head, thisgroup);
|
|
m_treeInfo[m_numGroups].bFrame = i;
|
|
m_numGroups++;
|
|
}
|
|
m_treeInfo[thisgroup].eFrame = i;
|
|
HTREEITEM item = treeDlg->InsertItem(frameinfo1->name, groupList[thisgroup].head);
|
|
treeDlg->SetItemData(item, i);
|
|
treeDlg->SetItemImage(item, 1, 1);
|
|
}
|
|
treeDlg->Expand(rootFrame, TVE_EXPAND);
|
|
if (groupList)
|
|
{
|
|
delete groupList;
|
|
groupList = NULL;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// file serialization support
|
|
|
|
#define FM_HEADER_NAME "header"
|
|
#define FM_HEADER_VER 2
|
|
#define FM_SKIN_NAME "skin"
|
|
#define FM_SKIN_VER 1
|
|
#define FM_ST_NAME "st coord"
|
|
#define FM_ST_VER 1
|
|
#define FM_TRI_NAME "tris"
|
|
#define FM_TRI_VER 1
|
|
#define FM_FRAME_NAME "frames"
|
|
#define FM_FRAME_VER 1
|
|
#define FM_SHORT_FRAME_NAME "short frames"
|
|
#define FM_SHORT_FRAME_VER 1
|
|
#define FM_NORMAL_NAME "normals"
|
|
#define FM_NORMAL_VER 1
|
|
#define FM_COMP_NAME "comp data"
|
|
#define FM_COMP_VER 1
|
|
#define FM_GLCMDS_NAME "glcmds"
|
|
#define FM_GLCMDS_VER 1
|
|
#define FM_MESH_NAME "mesh nodes"
|
|
#define FM_MESH_VER 3
|
|
#define FM_SKELETON_NAME "skeleton"
|
|
#define FM_SKELETON_VER 1
|
|
#define FM_REFERENCES_NAME "references"
|
|
#define FM_REFERENCES_VER 1
|
|
#define FRAME_NAME_LEN (16)
|
|
|
|
enum
|
|
{
|
|
FM_BLOCK_HEADER,
|
|
FM_BLOCK_SKIN,
|
|
FM_BLOCK_ST,
|
|
FM_BLOCK_TRIS,
|
|
FM_BLOCK_FRAMES,
|
|
FM_BLOCK_GLCMDS,
|
|
FM_BLOCK_MESHNODES,
|
|
FM_BLOCK_SHORTFRAMES,
|
|
FM_BLOCK_NORMAL,
|
|
FM_BLOCK_COMP,
|
|
FM_BLOCK_SKELETON,
|
|
FM_BLOCK_REFERENCES,
|
|
};
|
|
|
|
fmblock_t CFlexModel::m_fmblocks[] =
|
|
{
|
|
{FM_HEADER_NAME, FM_BLOCK_HEADER},
|
|
{FM_SKIN_NAME, FM_BLOCK_SKIN},
|
|
{FM_ST_NAME, FM_BLOCK_ST},
|
|
{FM_TRI_NAME, FM_BLOCK_TRIS},
|
|
{FM_FRAME_NAME , FM_BLOCK_FRAMES},
|
|
{FM_GLCMDS_NAME, FM_BLOCK_GLCMDS},
|
|
{FM_MESH_NAME, FM_BLOCK_MESHNODES},
|
|
{FM_SHORT_FRAME_NAME, FM_BLOCK_SHORTFRAMES},
|
|
{FM_NORMAL_NAME, FM_BLOCK_NORMAL},
|
|
{FM_COMP_NAME, FM_BLOCK_COMP},
|
|
{FM_SKELETON_NAME, FM_BLOCK_SKELETON},
|
|
{FM_REFERENCES_NAME, FM_BLOCK_REFERENCES},
|
|
{"", -1}
|
|
};
|
|
|
|
void CFlexModel::Serialize(CArchive& ar)
|
|
{
|
|
DWORD filesize = ar.GetFile()->GetLength();
|
|
char* buffer = new char[filesize];
|
|
ar.Read(buffer, filesize);
|
|
|
|
char* back = buffer;
|
|
|
|
while(filesize > 0)
|
|
{
|
|
int version;
|
|
int size;
|
|
|
|
char* blockname = buffer;
|
|
|
|
int i = 0;
|
|
while (m_fmblocks[i].blocktype >= 0)
|
|
{
|
|
if (strcmpi(buffer, m_fmblocks[i].blockid)==0)
|
|
{
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
buffer += sizeof(m_fmblocks[0].blockid);
|
|
version = *(int*)buffer;
|
|
buffer += sizeof(version);
|
|
size = *(int*)buffer;
|
|
buffer += sizeof(size);
|
|
filesize = filesize - sizeof(m_fmblocks[0].blockid) - sizeof(version) - sizeof(size);
|
|
|
|
|
|
CString foo;
|
|
switch (m_fmblocks[i].blocktype)
|
|
{
|
|
case FM_BLOCK_HEADER:
|
|
SerializeHeader(version, size, buffer);
|
|
break;
|
|
case FM_BLOCK_SKIN:
|
|
SerializeSkin(version, size, buffer);
|
|
break;
|
|
case FM_BLOCK_ST:
|
|
SerializeSt(version, size, buffer);
|
|
break;
|
|
case FM_BLOCK_TRIS:
|
|
SerializeTris(version, size, buffer);
|
|
break;
|
|
case FM_BLOCK_FRAMES:
|
|
SerializeFrames(version, size, buffer);
|
|
break;
|
|
case FM_BLOCK_GLCMDS:
|
|
SerializeGLCmds(version, size, buffer);
|
|
break;
|
|
case FM_BLOCK_MESHNODES:
|
|
SerializeMeshNodes(version, size, buffer);
|
|
break;
|
|
case FM_BLOCK_SHORTFRAMES:
|
|
SerializeShortFrames(version, size, buffer);
|
|
break;
|
|
case FM_BLOCK_NORMAL:
|
|
SerializeNormal(version, size, buffer);
|
|
break;
|
|
case FM_BLOCK_COMP:
|
|
SerializeComp(version, size, buffer);
|
|
break;
|
|
case FM_BLOCK_SKELETON:
|
|
SerializeSkeleton(version, size, buffer);
|
|
break;
|
|
case FM_BLOCK_REFERENCES:
|
|
SerializeReferences(version, size, buffer);
|
|
break;
|
|
default:
|
|
foo.Format("Unknown block %s\n", blockname);
|
|
AfxMessageBox(foo);
|
|
}
|
|
filesize -= size;
|
|
buffer += size;
|
|
}
|
|
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
m_nodes[i].SetVisible(true);
|
|
}
|
|
|
|
m_curNode = -1;
|
|
if (back)
|
|
{
|
|
delete(back);
|
|
back = buffer = NULL;
|
|
}
|
|
}
|
|
|
|
void CFlexModel::SerializeHeader(int version, int length, char *buffer)
|
|
{
|
|
if (version != FM_HEADER_VER)
|
|
{
|
|
AfxMessageBox("Invalid header version for block\n");
|
|
return;
|
|
}
|
|
|
|
int* offset = (int*)buffer;
|
|
m_skinwidth = *offset++;
|
|
m_skinheight = *offset++;
|
|
m_framesize = *offset++;
|
|
m_num_skins = *offset++;
|
|
m_num_xyz = *offset++;
|
|
m_num_st = *offset++;
|
|
m_num_tris = *offset++;
|
|
m_num_glcmds = *offset++;
|
|
m_num_frames = *offset++;
|
|
m_num_mesh_nodes = *offset++;
|
|
|
|
if ((char*)offset != (buffer + length))
|
|
{
|
|
AfxMessageBox("Invalid header read");
|
|
return;
|
|
}
|
|
|
|
if (m_skinheight > MAX_LBM_HEIGHT)
|
|
{
|
|
AfxMessageBox("Model has a skin taller than max LBM height\n");
|
|
return;
|
|
}
|
|
|
|
if (m_num_xyz <= 0)
|
|
{
|
|
AfxMessageBox("Model has no verts\n");
|
|
return;
|
|
}
|
|
|
|
if (m_num_xyz > MAX_FM_VERTS)
|
|
{
|
|
AfxMessageBox("Model has too many vertices\n");
|
|
return;
|
|
}
|
|
|
|
if (m_num_st <= 0)
|
|
{
|
|
AfxMessageBox("Model has no st verts\n");
|
|
return;
|
|
}
|
|
|
|
if (m_num_tris <= 0)
|
|
{
|
|
AfxMessageBox("Model has no tris\n");
|
|
return;
|
|
}
|
|
|
|
if (m_num_frames <= 0)
|
|
{
|
|
AfxMessageBox("Model has no frames\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
void CFlexModel::SerializeSkin(int version, int length, char *buffer)
|
|
{
|
|
if (m_skin_names != NULL)
|
|
{
|
|
AfxMessageBox("Duplicate skin block!\n");
|
|
return;
|
|
}
|
|
if (version != FM_SKIN_VER)
|
|
{
|
|
AfxMessageBox("Invalid skin version!\n");
|
|
return;
|
|
}
|
|
|
|
CString filePath = m_filename;
|
|
int destChar = filePath.ReverseFind('\\');
|
|
if (destChar > -1)
|
|
{
|
|
filePath = filePath.Left(destChar);
|
|
}
|
|
|
|
m_skin_names = (char**)malloc(sizeof(char*) * m_num_skins);
|
|
char* strname = buffer;
|
|
|
|
for (int i = 0; i < m_num_skins; i++)
|
|
{
|
|
CString result = strname;
|
|
strname += 64;
|
|
|
|
while(true)
|
|
{
|
|
destChar = result.Find("/");
|
|
if (destChar < 0)
|
|
{
|
|
break;
|
|
}
|
|
result.SetAt(destChar, '\\');
|
|
}
|
|
|
|
CString namePart;
|
|
CString partialPath = result;
|
|
destChar = partialPath.ReverseFind('\\');
|
|
if (destChar > -1)
|
|
{
|
|
namePart = partialPath.Right(partialPath.GetLength() - destChar);
|
|
partialPath = partialPath.Left(destChar);
|
|
}
|
|
|
|
if (partialPath.CompareNoCase(filePath.Right(partialPath.GetLength())) == 0)
|
|
{
|
|
partialPath = filePath;
|
|
}
|
|
partialPath = partialPath + namePart;
|
|
|
|
m_skin_names[i] = (char*)malloc(partialPath.GetLength() + 1);
|
|
strcpy(m_skin_names[i], partialPath);
|
|
}
|
|
}
|
|
|
|
|
|
void CFlexModel::SerializeSt(int version, int length, char *buffer)
|
|
{
|
|
// ignoring data
|
|
}
|
|
|
|
void CFlexModel::SerializeTris(int version, int length, char *buffer)
|
|
{
|
|
// ignoring data
|
|
}
|
|
|
|
void CFlexModel::SerializeFrames(int version, int length, char *buffer)
|
|
{
|
|
int i,j;
|
|
fmaliasframe_t *pinframe, *poutframe;
|
|
|
|
if (m_frames != NULL)
|
|
{
|
|
AfxMessageBox("Duplicate frames block!\n");
|
|
return;
|
|
}
|
|
if (version != FM_FRAME_VER)
|
|
{
|
|
AfxMessageBox("Invalid frames version\n");
|
|
false;
|
|
}
|
|
|
|
m_frames = (void*) malloc(m_num_frames * m_framesize);
|
|
|
|
for (i=0 ; i<m_num_frames ; i++)
|
|
{
|
|
pinframe = (fmaliasframe_t *) ((byte *)buffer + i * m_framesize);
|
|
poutframe = (fmaliasframe_t *) ((byte *)m_frames + i * m_framesize);
|
|
|
|
memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name));
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
poutframe->scale[j] = pinframe->scale[j];
|
|
poutframe->translate[j] = pinframe->translate[j];
|
|
}
|
|
|
|
// verts are all 8 bit, so no swapping needed
|
|
memcpy (poutframe->verts, pinframe->verts, m_num_xyz*sizeof(fmtrivertx_t));
|
|
}
|
|
}
|
|
|
|
void CFlexModel::SerializeGLCmds(int version, int length, char *buffer)
|
|
{
|
|
if (m_glcmds != NULL)
|
|
{
|
|
AfxMessageBox("Duplicate glCmds block!\n");
|
|
return;
|
|
}
|
|
if (version != FM_GLCMDS_VER)
|
|
{
|
|
AfxMessageBox("Invalid glcmds version\n");
|
|
return;
|
|
}
|
|
|
|
int* poutcmd = (int *) malloc(sizeof(int) * m_num_glcmds);
|
|
m_glcmds = (long*)poutcmd;
|
|
int* pincmd = (int *) ((byte *)buffer);
|
|
for (int i=0 ; i<m_num_glcmds ; i++)
|
|
poutcmd[i] = (pincmd[i]);
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
byte tris[MAX_FM_TRIANGLES>>3];
|
|
byte verts[MAX_FM_VERTS>>3];
|
|
short start_glcmds, num_glcmds;
|
|
} fmmeshnode_t;
|
|
|
|
void CFlexModel::SerializeMeshNodes(int version, int length, char *buffer)
|
|
{
|
|
int i;
|
|
fmmeshnode_t *node;
|
|
|
|
if (m_nodes != NULL)
|
|
{
|
|
AfxMessageBox("Duplicate mesh node block!\n");
|
|
return;
|
|
}
|
|
if (version != FM_MESH_VER)
|
|
{
|
|
AfxMessageBox("Invalid mesh version\n");
|
|
return;
|
|
}
|
|
|
|
if (m_num_mesh_nodes)
|
|
{
|
|
m_nodes = new CNode[m_num_mesh_nodes];
|
|
for(i=0,node = (fmmeshnode_t *)buffer;i<m_num_mesh_nodes;i++,node++)
|
|
{
|
|
m_nodes[i].Init();
|
|
|
|
int numtris = m_num_tris;
|
|
// if (numtris > (MAX_FM_TRIANGLES>>3))
|
|
// {
|
|
// numtris = MAX_FM_TRIANGLES>>3;
|
|
// }
|
|
m_nodes[i].SetTris(node->tris, numtris);
|
|
|
|
int numverts = m_num_xyz;
|
|
// if (numverts > (MAX_FM_VERTS>>3))
|
|
// {
|
|
// numverts = MAX_FM_VERTS>>3;
|
|
// }
|
|
m_nodes[i].SetVerts(node->verts, numverts);
|
|
m_nodes[i].SetGlcmds((long*)((long*)m_glcmds + node->start_glcmds), node->num_glcmds);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CFlexModel::SerializeShortFrames(int version, int length, char *buffer)
|
|
{
|
|
if (m_framenames != NULL)
|
|
{
|
|
AfxMessageBox("Duplicate short frames block!\n");
|
|
return;
|
|
}
|
|
AfxMessageBox("This is short frames\n");
|
|
if (version != FM_SHORT_FRAME_VER)
|
|
{
|
|
AfxMessageBox("Invalid shortframes version\n");
|
|
return;
|
|
}
|
|
|
|
//?? m_frames=NULL;
|
|
m_framenames=(char *) (m_num_frames*FRAME_NAME_LEN);
|
|
memcpy(m_framenames,buffer,m_num_frames*FRAME_NAME_LEN);
|
|
}
|
|
|
|
void CFlexModel::SerializeNormal(int version, int length, char *buffer)
|
|
{
|
|
if (m_lightnormalindex != NULL)
|
|
{
|
|
AfxMessageBox("Duplicate light normal block!\n");
|
|
return;
|
|
}
|
|
if (version != FM_NORMAL_VER)
|
|
{
|
|
AfxMessageBox("Invalid normal version\n");
|
|
return;
|
|
}
|
|
m_lightnormalindex=(byte *)malloc(m_num_xyz*sizeof(byte));
|
|
memcpy(m_lightnormalindex,buffer,m_num_xyz*sizeof(byte));
|
|
}
|
|
|
|
void CFlexModel::SerializeComp(int version, int length, char *buff)
|
|
{
|
|
fmgroup_t *g;
|
|
char *buffer;
|
|
|
|
AfxMessageBox("This is compressed\n");
|
|
|
|
buffer= (char *)buff;
|
|
g=&m_compdata;
|
|
|
|
if (version != FM_COMP_VER)
|
|
{
|
|
AfxMessageBox("Invalid comp version\n");
|
|
return;
|
|
}
|
|
|
|
g->start_frame=*(int *)buffer;
|
|
buffer+=sizeof(int);
|
|
g->num_frames= *(int *)buffer;
|
|
buffer+=sizeof(int);
|
|
g->degrees=*(int *)buffer;
|
|
buffer+=sizeof(int);
|
|
|
|
g->mat= (char *)malloc(m_num_xyz*3*g->degrees*sizeof(char));
|
|
g->ccomp= (char *)malloc(g->num_frames*g->degrees*sizeof(char));
|
|
g->cbase= (unsigned char*)malloc(m_num_xyz*3*sizeof(unsigned char));
|
|
g->cscale= (float *)malloc(g->degrees*sizeof(float));
|
|
g->coffset= (float *)malloc(g->degrees*sizeof(float));
|
|
g->complerp=(float *)malloc(g->degrees*sizeof(float));
|
|
|
|
memcpy(g->mat,buffer,m_num_xyz*3*g->degrees*sizeof(char));
|
|
buffer+=m_num_xyz*3*g->degrees*sizeof(char);
|
|
memcpy(g->ccomp,buffer,g->num_frames*g->degrees*sizeof(char));
|
|
buffer+=g->num_frames*g->degrees*sizeof(char);
|
|
memcpy(g->cbase,buffer,m_num_xyz*3*sizeof(unsigned char));
|
|
buffer+=m_num_xyz*3*sizeof(unsigned char);
|
|
memcpy(g->cscale,buffer,g->degrees*sizeof(float));
|
|
buffer+=g->degrees*sizeof(float);
|
|
memcpy(g->coffset,buffer,g->degrees*sizeof(float));
|
|
buffer+=g->degrees*sizeof(float);
|
|
memcpy(g->trans,buffer,3*sizeof(float));
|
|
buffer+=3*sizeof(float);
|
|
memcpy(g->scale,buffer,3*sizeof(float));
|
|
buffer+=3*sizeof(float);
|
|
memcpy(g->bmin,buffer,3*sizeof(float));
|
|
buffer+=3*sizeof(float);
|
|
memcpy(g->bmax,buffer,3*sizeof(float));
|
|
buffer+=3*sizeof(float);
|
|
}
|
|
|
|
void CFlexModel::SerializeSkeleton(int version, int length, char *buffer)
|
|
{
|
|
int i, j, k;
|
|
int *basei;
|
|
int runningTotalVertices = 0;
|
|
int indexBase = 0;
|
|
float *basef;
|
|
|
|
if (m_skeletons != NULL)
|
|
{
|
|
AfxMessageBox("Duplicate skeleton block!\n");
|
|
return;
|
|
}
|
|
if (version != FM_SKELETON_VER)
|
|
{
|
|
AfxMessageBox("Invalid skeleton version\n");
|
|
return;
|
|
}
|
|
|
|
basei = (int *)buffer;
|
|
|
|
m_skeletalType = *basei;
|
|
|
|
m_numClusters = *(++basei);
|
|
|
|
m_jointConstraintAngles = new rangeVector_t[m_numClusters];
|
|
m_modelJointAngles = new D3DVECTOR[m_numClusters];
|
|
m_skeletalClusters = new M_SkeletalCluster_t[m_numClusters];
|
|
|
|
for(i = m_numClusters - 1; i >= 0; --i)
|
|
{
|
|
m_jointConstraintAngles[i].min.x = 0;
|
|
m_jointConstraintAngles[i].min.y = 0;
|
|
m_jointConstraintAngles[i].min.z = 0;
|
|
m_jointConstraintAngles[i].max.x = 0;
|
|
m_jointConstraintAngles[i].max.y = 0;
|
|
m_jointConstraintAngles[i].max.z = 0;
|
|
m_modelJointAngles[i].x = 0;
|
|
m_modelJointAngles[i].y = 0;
|
|
m_modelJointAngles[i].z = 0;
|
|
|
|
runningTotalVertices += *(++basei);
|
|
m_skeletalClusters[i].numVerticies = runningTotalVertices;
|
|
m_skeletalClusters[i].verticies = (int*)malloc(m_skeletalClusters[i].numVerticies*sizeof(int));
|
|
}
|
|
|
|
for(j = m_numClusters - 1; j >= 0; --j)
|
|
{
|
|
for(i = indexBase; i < m_skeletalClusters[j].numVerticies; ++i)
|
|
{
|
|
++basei;
|
|
|
|
for(k = 0; k <= j; ++ k)
|
|
{
|
|
m_skeletalClusters[k].verticies[i] = *basei;
|
|
}
|
|
}
|
|
|
|
indexBase = m_skeletalClusters[j].numVerticies;
|
|
}
|
|
|
|
if(*(++basei))
|
|
{
|
|
basef = (float *)++basei;
|
|
|
|
m_skeletons = (ModelSkeleton_t*) malloc(m_num_frames*sizeof(ModelSkeleton_t));
|
|
|
|
for (i = 0; i < m_num_frames; ++i)
|
|
{
|
|
for(j = 0; j < m_numClusters; ++j)
|
|
{
|
|
m_skeletons[i].rootJoint[j].model.origin[0] = *(basef++);
|
|
m_skeletons[i].rootJoint[j].model.origin[1] = *(basef++);
|
|
m_skeletons[i].rootJoint[j].model.origin[2] = *(basef++);
|
|
|
|
m_skeletons[i].rootJoint[j].model.direction[0] = *(basef++);
|
|
m_skeletons[i].rootJoint[j].model.direction[1] = *(basef++);
|
|
m_skeletons[i].rootJoint[j].model.direction[2] = *(basef++);
|
|
|
|
m_skeletons[i].rootJoint[j].model.up[0] = *(basef++);
|
|
m_skeletons[i].rootJoint[j].model.up[1] = *(basef++);
|
|
m_skeletons[i].rootJoint[j].model.up[2] = *(basef++);
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
m_num_xyz -= m_numClusters*3;
|
|
}
|
|
}
|
|
|
|
void CFlexModel::SerializeReferences(int version, int length, char *buffer)
|
|
{
|
|
if (version != FM_REFERENCES_VER)
|
|
{
|
|
AfxMessageBox("Invalid reference version\n");
|
|
return;
|
|
}
|
|
|
|
int* basei = (int*)buffer;
|
|
m_referenceType = *basei++;
|
|
/* remainder of this data structure is hard coded logic for specific models -- just ignore */
|
|
}
|
|
|
|
// skin texture support
|
|
|
|
void CFlexModel::SetTransparency(LPDIRECT3DRM2 d3drm, CDC* pDC, bool trans)
|
|
{
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
m_nodes[i].SetTransparency(d3drm, pDC, trans);
|
|
}
|
|
}
|
|
|
|
// joint support
|
|
|
|
void CFlexModel::ToggleJointOn()
|
|
{
|
|
m_jointsOn = !m_jointsOn;
|
|
}
|
|
|
|
bool CFlexModel::IsJointOn()
|
|
{
|
|
return m_jointsOn;
|
|
}
|
|
|
|
void CFlexModel::ConstrainJoint()
|
|
{
|
|
if (m_jointConstraintAngles[m_curJoint].max.x || m_jointConstraintAngles[m_curJoint].min.x)
|
|
{
|
|
if (m_modelJointAngles[m_curJoint].x > m_jointConstraintAngles[m_curJoint].max.x)
|
|
m_modelJointAngles[m_curJoint].x = m_jointConstraintAngles[m_curJoint].max.x;
|
|
|
|
if (m_modelJointAngles[m_curJoint].x < m_jointConstraintAngles[m_curJoint].min.x)
|
|
m_modelJointAngles[m_curJoint].x = m_jointConstraintAngles[m_curJoint].min.x;
|
|
}
|
|
|
|
if (m_jointConstraintAngles[m_curJoint].max.y || m_jointConstraintAngles[m_curJoint].min.y)
|
|
{
|
|
if (m_modelJointAngles[m_curJoint].y > m_jointConstraintAngles[m_curJoint].max.y)
|
|
m_modelJointAngles[m_curJoint].y = m_jointConstraintAngles[m_curJoint].max.y;
|
|
|
|
if (m_modelJointAngles[m_curJoint].y < m_jointConstraintAngles[m_curJoint].min.y)
|
|
m_modelJointAngles[m_curJoint].y = m_jointConstraintAngles[m_curJoint].min.y;
|
|
}
|
|
|
|
if (m_jointConstraintAngles[m_curJoint].max.z || m_jointConstraintAngles[m_curJoint].min.z)
|
|
{
|
|
if (m_modelJointAngles[m_curJoint].z > m_jointConstraintAngles[m_curJoint].max.z)
|
|
m_modelJointAngles[m_curJoint].z = m_jointConstraintAngles[m_curJoint].max.z;
|
|
|
|
if (m_modelJointAngles[m_curJoint].z < m_jointConstraintAngles[m_curJoint].min.z)
|
|
m_modelJointAngles[m_curJoint].z = m_jointConstraintAngles[m_curJoint].min.z;
|
|
}
|
|
|
|
// ShowFrame();
|
|
}
|
|
|
|
void CFlexModel::GetModelAngles(float* x, float* y, float* z)
|
|
{
|
|
*x = m_modelJointAngles[m_curJoint].x;
|
|
*y = m_modelJointAngles[m_curJoint].y;
|
|
*z = m_modelJointAngles[m_curJoint].z;
|
|
}
|
|
|
|
void CFlexModel::SetModelAngles(float x, float y, float z)
|
|
{
|
|
m_modelJointAngles[m_curJoint].x = x;
|
|
m_modelJointAngles[m_curJoint].y = y;
|
|
m_modelJointAngles[m_curJoint].z = z;
|
|
|
|
if (m_modelJointAngles[m_curJoint].y > PI*2)
|
|
m_modelJointAngles[m_curJoint].y = (float) PI*2 - m_modelJointAngles[m_curJoint].y;
|
|
else if (m_modelJointAngles[m_curJoint].y < 0)
|
|
m_modelJointAngles[m_curJoint].y = (float) PI*2 + m_modelJointAngles[m_curJoint].y;
|
|
|
|
if (m_modelJointAngles[m_curJoint].x > PI*2)
|
|
m_modelJointAngles[m_curJoint].x = (float) PI*2 - m_modelJointAngles[m_curJoint].x;
|
|
else if (m_modelJointAngles[m_curJoint].x < 0)
|
|
m_modelJointAngles[m_curJoint].x = (float) PI*2 + m_modelJointAngles[m_curJoint].x;
|
|
|
|
if (m_modelJointAngles[m_curJoint].z > PI*2)
|
|
m_modelJointAngles[m_curJoint].z = (float) PI*2 - m_modelJointAngles[m_curJoint].z;
|
|
else if (m_modelJointAngles[m_curJoint].z < 0)
|
|
m_modelJointAngles[m_curJoint].z = (float) PI*2 + m_modelJointAngles[m_curJoint].z;
|
|
}
|
|
|
|
void CFlexModel::RenderTexture(LPDIRECT3DRM2 d3drm, CDC* pDC, bool useTexture)
|
|
{
|
|
for (int i = 0; i < m_num_mesh_nodes; i++)
|
|
{
|
|
m_nodes[i].RenderTexture(d3drm, pDC, useTexture);
|
|
}
|
|
}
|
|
|
|
void CFlexModel::GetConstraintAngleMaxs(float* x, float* y, float* z)
|
|
{
|
|
*x = m_jointConstraintAngles[m_curJoint].max.x;
|
|
*y = m_jointConstraintAngles[m_curJoint].max.y;
|
|
*z = m_jointConstraintAngles[m_curJoint].max.z;
|
|
}
|
|
|
|
void CFlexModel::GetConstraintAngleMins(float* x, float* y, float* z)
|
|
{
|
|
*x = m_jointConstraintAngles[m_curJoint].min.x;
|
|
*y = m_jointConstraintAngles[m_curJoint].min.y;
|
|
*z = m_jointConstraintAngles[m_curJoint].min.z;
|
|
}
|
|
|
|
void CFlexModel::SetConstraintAngleMaxs(float x, float y, float z)
|
|
{
|
|
m_jointConstraintAngles[m_curJoint].max.x = x;
|
|
m_jointConstraintAngles[m_curJoint].max.y = y;
|
|
m_jointConstraintAngles[m_curJoint].max.z = z;
|
|
ConstrainJoint();
|
|
}
|
|
|
|
void CFlexModel::SetConstraintAngleMins(float x, float y, float z)
|
|
{
|
|
m_jointConstraintAngles[m_curJoint].min.x = x;
|
|
m_jointConstraintAngles[m_curJoint].min.y = y;
|
|
m_jointConstraintAngles[m_curJoint].min.z = z;
|
|
ConstrainJoint();
|
|
}
|
|
|
|
// joint tree control support
|
|
|
|
void CFlexModel::AddJoints(CTreeCtrl* pCTree, HTREEITEM rootJoint)
|
|
{
|
|
if (m_skeletons != NULL)
|
|
{
|
|
CString name;
|
|
for (int i = 0; i < m_numClusters; i++)
|
|
{
|
|
name.Format("Joint %d", i);
|
|
HTREEITEM item = pCTree->InsertItem(name, rootJoint, TVI_LAST);
|
|
pCTree->SetItemData(item, i);
|
|
pCTree->SetItemImage(item, 1, 1);
|
|
}
|
|
pCTree->Expand(rootJoint, TVE_EXPAND);
|
|
}
|
|
}
|
|
|
|
// property page support
|
|
|
|
void CFlexModel::AddPropPages(CPropertySheet* propSheet)
|
|
{
|
|
CModel::AddPropPages(propSheet);
|
|
// add private pages
|
|
}
|
|
|
|
void CFlexModel::UpdateFromPropPages(CPropertySheet* propSheet)
|
|
{
|
|
// update data from private pages (some could be after)
|
|
CModel::UpdateFromPropPages(propSheet);
|
|
// update data from private pages (some could be before)
|
|
}
|
|
|
|
void CFlexModel::RemovePropPages(CPropertySheet* propSheet)
|
|
{
|
|
// remove private pages
|
|
CModel::RemovePropPages(propSheet);
|
|
}
|
|
|