heretic2-sdk/Toolkit/Programming/Tools/qMView/Quake2Model.cpp
1998-11-24 00:00:00 +00:00

594 lines
14 KiB
C++

// Quake2Model
//
#include "stdafx.h"
#include "resource.h"
#include "DDUtil.h"
#include "Matrix.h"
#include "Model.h"
#include "FrameManager2.h"
#include "Quake2Model.h"
//
// CQuake2Model
//
CQuake2Model::CQuake2Model()
{
}
CQuake2Model::~CQuake2Model()
{
}
void CQuake2Model::Init()
{
m_mesh = NULL;
m_skinname = NULL;
CModel::Init();
}
void CQuake2Model::DeleteMeshs(LPDIRECT3DRMFRAME frame)
{
if (m_mesh != NULL)
{
frame->DeleteVisual(m_mesh);
m_mesh->Release();
m_mesh = NULL;
}
}
void CQuake2Model::Delete()
{
if (m_skinname != NULL)
{
free (m_skinname);
m_skinname = NULL;
}
CModel::Delete();
}
void CQuake2Model::Serialize(CArchive& ar)
{
long ofs_skins; // each skin is a MAX_SKINNAME string
long ofs_st; // byte offset from start for stverts
long ofs_tris; // offset for dtriangles
long ofs_frames; // offset for first frame
long ofs_glcmds;
long ofs_end; // end of file
m_curFrame = 0;
m_curscale = -150;
m_playing = FALSE;
ar >> m_ident >> m_version >> m_skinwidth >> m_skinheight >>
m_framesize >> m_num_skins >> m_num_xyz >> m_num_st >>
m_num_tris >> m_num_glcmds >> m_num_frames >> ofs_skins >>
ofs_st >> ofs_tris >> ofs_frames >> ofs_glcmds >>
ofs_end;
if (m_glcmds)
{
free(m_glcmds);
m_glcmds = NULL;
}
CFile* file = ar.GetFile();
file->Seek(ofs_glcmds, CFile::begin);
m_glcmds = (long*)malloc(m_num_glcmds * sizeof(long));
file->Read(m_glcmds, m_num_glcmds * sizeof(long));
if (m_frames != NULL)
{
free(m_frames);
m_frames = NULL;
}
file->Seek(ofs_frames, CFile::begin);
m_frames = (void*)malloc(m_framesize * m_num_frames);
file->Read(m_frames, m_framesize * m_num_frames);
file->Seek(ofs_skins, CFile::begin);
char tempskinname[64];
file->Read(tempskinname, 64);
CString skinname = tempskinname;
int pos = skinname.ReverseFind('.');
if (pos > -1)
{
skinname = skinname.Left(pos);
}
skinname += ".pcx";
CString filePath = m_filename;
int destChar = filePath.ReverseFind('\\');
if (destChar > -1)
{
filePath = filePath.Left(destChar);
}
while(true)
{
destChar = skinname.Find("/");
if (destChar < 0)
{
break;
}
skinname.SetAt(destChar, '\\');
}
CString namePart;
CString partialPath = skinname;
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_skinname = (char*)malloc(partialPath.GetLength() + 1);
strcpy(m_skinname, partialPath);
}
void CQuake2Model::BuildMesh(LPDIRECT3DRM2 d3drm, LPDIRECT3DRMFRAME frame, LPDIRECT3DRMFRAME scene, CDC* pDC)
{
int realvert = 0;
D3DRMVERTEX* vertexlist = new D3DRMVERTEX[m_num_tris*3+1];
if (vertexlist == NULL)
{
AfxMessageBox("Cannot make vertexlist");
return;
}
if (m_vertPath != NULL)
{
delete m_vertPath;
}
m_vertPath = new long[m_num_tris*3+1];
int curvert = m_num_tris * 3;
unsigned* vertorder = new unsigned[m_num_tris*3+1];
if (vertorder == NULL)
{
AfxMessageBox("Cannot make vertorder");
return;
}
for (int i = 0; i < (m_num_tris * 3); i++)
{
curvert--;
vertorder[i] = curvert;
}
curvert=0;
d3drm->CreateMesh(&m_mesh);
vec5_t* vertlist = (vec5_t*)malloc(sizeof(vec5_t)*m_num_tris*3);
frameinfo2_t* frameinfo1 = (frameinfo2_t*)m_frames;
long* command = m_glcmds;
BOOL ODD = FALSE;
int num_verts;
int command_type;
//do the gl commands <?>
while (*command)
{
ODD = TRUE;
if (*command>0)
{
//triangle strip
num_verts = *command;
command_type = 0;
}
else
{
//triangle fan
num_verts = -(*command);
command_type = 1;
}
command++;
for (i=0; i < num_verts; i++)
{
vec5_t p1;
//grab the floating point s and t
p1.s = (*((float *)command)) * m_skinwidth; command++;
p1.t = (*((float *)command)) * m_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], n1, n2, n3;
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;
}
D3DRMVectorSubtract(&n1, &p[1], &p[0]);
D3DRMVectorSubtract(&n2, &p[2], &p[1]);
D3DRMVectorCrossProduct(&n3, &n1, &n2);
D3DRMVectorNormalize(&n3);
if (ODD == TRUE)
{
for (int 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) / m_skinwidth;
vertexlist[curvert].tv = D3DVALUE(vertlist[i+j].t) / m_skinheight;
vertexlist[curvert].color = D3DCOLOR(2);
m_vertPath[curvert] = realvert+i+j;
curvert++;
}
ODD = FALSE;
}
else
{
for (int 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) / m_skinwidth;
vertexlist[curvert].tv = D3DVALUE(vertlist[i+j].t) / m_skinheight;
vertexlist[curvert].color = D3DCOLOR(2);
m_vertPath[curvert] = realvert+i+j;
curvert++;
}
ODD = TRUE;
}
}
break;
case 1:
//trifan
for (i=0;i<num_verts-2;i++)
{
int x;
for (int j = 2; j > -1; j--)
{
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;
}
D3DRMVectorSubtract(&n1, &p[1], &p[0]);
D3DRMVectorSubtract(&n2, &p[2], &p[1]);
D3DRMVectorCrossProduct(&n3, &n1, &n2);
D3DRMVectorNormalize(&n3);
for (j = 2; j > -1; j--)
{
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) / m_skinwidth;
vertexlist[curvert].tv = D3DVALUE(vertlist[x+j].t) / m_skinheight;
vertexlist[curvert].color = D3DCOLOR(2);
m_vertPath[curvert] = realvert+x+j;
curvert++;
}
}
break;
}
realvert += num_verts;
}
m_mesh->AddGroup( m_num_tris * 3, m_num_tris, 3, vertorder, &m_group );
m_mesh->SetVertices(m_group, 0, m_num_tris * 3, vertexlist );
frame->SetOrientation( scene,
D3DVALUE(0), D3DVALUE(0), D3DVALUE(1),
D3DVALUE(1), D3DVALUE(0), D3DVALUE(0) );
if (vertexlist) delete vertexlist;
if (vertorder) delete vertorder;
if (vertlist) free(vertlist);
}
BOOL CQuake2Model::ShowFrame(LPDIRECT3DRM2 d3drm, CDC* pDC)
{
int curvert = 0;
D3DRMVERTEX *vertexlist;
vec5_t *vertlist;
int i;
vec5_t p1;
frameinfo2_t *frameinfo1;
long *command;
int num_verts,vert_index;
int command_type;
vertexlist = new D3DRMVERTEX[m_num_tris*3+1];
if (vertexlist == NULL)
return AfxMessageBox("Cannot make vertexlist");
vertlist = (vec5_t *)malloc(sizeof(vec5_t)*m_num_tris*3);
frameinfo1 = (frameinfo2_t*)((char*)m_frames + m_curFrame * m_framesize);
command = m_glcmds;
curvert = 0;
//do the gl commands <?>
while (*command)
{
if (*command>0)
{
//triangle strip
num_verts = *command;
command_type = 0;
}
else
{
//triangle fan
num_verts = -(*command);
command_type = 1;
}
command++;
for (i=0; i < num_verts; i++)
{
//grab the floating point s and t
p1.s = (*((float *)command)) * m_skinwidth; command++;
p1.t = (*((float *)command)) * m_skinheight; command++;
//grab the vertex index
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[curvert] = p1;
curvert++;
}
}
for (i = 0; i < m_num_tris*3; 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) / m_skinwidth;
vertexlist[i].tv = D3DVALUE(vertlist[m_vertPath[i]].t) / m_skinheight;
}
m_mesh->SetVertices(m_group, 0, m_num_tris*3, vertexlist );
free(vertlist);
delete (vertexlist);
return TRUE;
}
BOOL CQuake2Model::CalcInterpolate(LPDIRECT3DRM2 d3drm, CDC* pDC, int step, int numsteps, int intertype, int direction)
{
D3DVECTOR delta;
int curvert = 0;
D3DRMVERTEX *vertexlist;
int lastframe, i;
vec5_t p1,p2;
frameinfo2_t *frameinfo1, *frameinfo2;
long *command;
int num_verts,vert_index;
int command_type;
vec5_t *vertlist;
BOOL ODD;
vertexlist = new D3DRMVERTEX[m_num_tris*3+1];
if (vertexlist == NULL)
return AfxMessageBox("Cannot make vertexlist");
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;
}
}
curvert = 0;
vertlist = (vec5_t *)malloc(sizeof(vec5_t)*m_num_tris*3);
frameinfo1 = (frameinfo2_t*)((char*)m_frames + m_curFrame * m_framesize);
frameinfo2 = (frameinfo2_t*)((char*)m_frames + lastframe * m_framesize);
command = m_glcmds;
//do the gl commands <?>
while (*command)
{
ODD = TRUE;
if (*command>0)
{
//triangle strip
num_verts = *command;
command_type = 0;
}
else
{
//triangle fan
num_verts = -(*command);
command_type = 1;
}
command++;
for (i=0; i < num_verts; i++)
{
//grab the floating point s and t
p1.s = (*((float *)command)) * m_skinwidth; command++;
p1.t = (*((float *)command)) * m_skinheight; command++;
//grab the vertex index
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);
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[curvert] = p1;
curvert++;
}
}
for (i = 0; i < m_num_tris*3; 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) / m_skinwidth;
vertexlist[i].tv = D3DVALUE(vertlist[m_vertPath[i]].t) / m_skinheight;
}
m_mesh->SetVertices(m_group, 0, m_num_tris*3, vertexlist );
free(vertlist);
delete (vertexlist);
if (step + 1 > numsteps) m_curstep = 0;
else m_curstep++;
return TRUE;
}
LPDIRECT3DRMMESH CQuake2Model::GetMesh(int i)
{
return m_mesh;
}
CSkin* CQuake2Model::GetSkin(int i)
{
return CModel::GetSkin(m_skinname);
}
void CQuake2Model::FillMenuWithSkins(CMenu* menu)
{
if (m_skinname != NULL)
{
menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, IDR_SKIN_SELECT_START, m_skinname);
}
}
void CQuake2Model::AddSkin(LPCTSTR skinname)
{
}
void CQuake2Model::ReplaceSkin(int i, LPCTSTR skinname)
{
if (m_skinname != NULL)
{
free(m_skinname);
m_skinname = NULL;
}
m_skinname = (char*)malloc(strlen(skinname) + 1);
strcpy(m_skinname, skinname);
}
// frame tree ctrl support
void CQuake2Model::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 + i * m_framesize);
char name[16];
strcpy(name , frameinfo1->name);
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);
}
if (groupList)
{
delete groupList;
groupList = NULL;
}
treeDlg->Expand(rootFrame, TVE_EXPAND);
}
}