// 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 ; iname, 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>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 (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); }