361 lines
8.5 KiB
C++
361 lines
8.5 KiB
C++
/**
|
|
** File : glmesh.cxx
|
|
** Description: Implementations of CGlMesh class
|
|
**/
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
#include "glmesh.h"
|
|
#include "pmerrors.h"
|
|
|
|
|
|
/**************************************************************************/
|
|
|
|
/*
|
|
* CGlMesh: Constructor
|
|
*/
|
|
CGlMesh::CGlMesh()
|
|
{
|
|
//Dynamically allocated arrays
|
|
m_matArray = NULL;
|
|
m_varray = NULL;
|
|
m_narray = NULL;
|
|
m_tarray = NULL;
|
|
m_wedgelist = NULL;
|
|
m_fnei = NULL;
|
|
m_facemap = NULL;
|
|
|
|
m_numFaces =
|
|
m_numWedges =
|
|
m_numVerts =
|
|
m_numMaterials =
|
|
m_numTextures = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* CGlMesh: Destructor
|
|
*/
|
|
CGlMesh::~CGlMesh()
|
|
{
|
|
delete [] m_matArray;
|
|
delete [] m_varray;
|
|
delete [] m_narray;
|
|
delete [] m_tarray;
|
|
delete [] m_wedgelist;
|
|
delete [] m_fnei;
|
|
delete [] m_facemap;
|
|
}
|
|
|
|
/*
|
|
* CGlMesh: Print
|
|
*/
|
|
STDMETHODIMP CGlMesh::Print(ostream& os)
|
|
{
|
|
|
|
os << "\n\nMaterials:";
|
|
for (int i=0; i<m_numMaterials; ++i)
|
|
{
|
|
LPGLmaterial lpglm = &m_matArray[i];
|
|
|
|
os << "\n\nMaterial [" << i << "] :";
|
|
os << "\nShininess : " << lpglm->shininess;
|
|
os << "\nDiffuse : (" << lpglm->diffuse.r << ", "
|
|
<< lpglm->diffuse.g << ", "
|
|
<< lpglm->diffuse.b << ", "
|
|
<< lpglm->diffuse.a << ")";
|
|
os << "\nSpecular : (" << lpglm->specular.r << ", "
|
|
<< lpglm->specular.g << ", "
|
|
<< lpglm->specular.b << ", "
|
|
<< lpglm->specular.a << ")";
|
|
os << "\nEmissive : (" << lpglm->emissive.r << ", "
|
|
<< lpglm->emissive.g << ", "
|
|
<< lpglm->emissive.b << ", "
|
|
<< lpglm->emissive.a << ")";
|
|
os << "\nNumber of faces: " << m_matcnt[i];
|
|
for (int j=0; j< m_matcnt[i]; j++)
|
|
{
|
|
#ifdef __MATPOS_IS_A_PTR
|
|
os << "\n(" << m_matpos[i][j].w[0] << ","
|
|
<< (m_matpos[i][j]).w[1] << ","
|
|
<< (m_matpos[i][j]).w[2] << ")";
|
|
#else
|
|
os << "\n(" << (m_farray[m_matpos[i] + j]).w[0] << ","
|
|
<< (m_farray[m_matpos[i] + j]).w[0] << ","
|
|
<< (m_farray[m_matpos[i] + j]).w[0] << ")";
|
|
#endif
|
|
}
|
|
}
|
|
|
|
os << "\n\nWedge connectivity:";
|
|
for (i=0; i<m_numWedges; ++i)
|
|
{
|
|
os << "\n" << m_wedgelist[i];
|
|
}
|
|
|
|
os << "\n\nWedge data:";
|
|
for (i=0; i<m_numWedges; ++i)
|
|
{
|
|
os << "\n(" << m_varray[i].x << ", "
|
|
<< m_varray[i].y << ", "
|
|
<< m_varray[i].z << ") "
|
|
<< " (" << m_narray[i].x << ", "
|
|
<< m_narray[i].y << ", "
|
|
<< m_narray[i].z << ") "
|
|
<< " (" << m_tarray[i].s << ", "
|
|
<< m_tarray[i].t << ") ";
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* CGlMesh: Render
|
|
*/
|
|
STDMETHODIMP CGlMesh::Render(RenderType rt)
|
|
{
|
|
if (rt == GLPM_SOLID)
|
|
{
|
|
glVertexPointer(3, GL_FLOAT, 0, (void *)&(m_varray[0].x));
|
|
glNormalPointer (GL_FLOAT, 0, (void *)&(m_narray[0].x));
|
|
glTexCoordPointer (2, GL_FLOAT, 0, (void *)&(m_tarray[0].s));
|
|
|
|
glEnableClientState (GL_VERTEX_ARRAY);
|
|
glEnableClientState (GL_NORMAL_ARRAY);
|
|
|
|
for (int i=0; i<m_numMaterials; i++)
|
|
{
|
|
LPGLmaterial lpglm = &(m_matArray[i]);
|
|
|
|
if (m_matcnt[i] == (WORD) 0) continue;
|
|
|
|
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, lpglm->shininess);
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,
|
|
(GLfloat *) &(lpglm->specular));
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
|
|
(GLfloat *) &(lpglm->diffuse));
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION,
|
|
(GLfloat *) &(lpglm->emissive));
|
|
glDrawElements (GL_TRIANGLES, (GLuint) m_matcnt[i]*3,
|
|
GL_UNSIGNED_SHORT,
|
|
#ifdef __MATPOS_IS_A_PTR
|
|
(void *) m_matpos[i]);
|
|
#else
|
|
(void *) &(m_farray[m_matpos[i]]));
|
|
#endif
|
|
}
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
}
|
|
|
|
PHASHENTRY* hashtable;
|
|
PHASHENTRY hashentries;
|
|
int freeptr, maxptr;
|
|
|
|
void CGlMesh::HashAdd(WORD va, WORD vb, WORD f)
|
|
{
|
|
#ifdef _DEBUG
|
|
if (va > m_numWedges || va < 0)
|
|
throw CHashOvrflw();
|
|
#endif
|
|
for (PHASHENTRY* t = &(hashtable[va]); *t; t = &((*t)->next));
|
|
PHASHENTRY p = &(hashentries[freeptr++]);
|
|
p->f = f;
|
|
p->v2 = vb;
|
|
p->next = NULL;
|
|
*t=p;
|
|
}
|
|
|
|
WORD CGlMesh::HashFind(WORD va, WORD vb)
|
|
{
|
|
#ifdef _DEBUG
|
|
if (va > m_baseWedges || va < 0)
|
|
throw CHashOvrflw();
|
|
#endif
|
|
for (PHASHENTRY* t = &(hashtable[va]); *t; t = &((*t)->next))
|
|
{
|
|
if ((*t)->v2 == vb)
|
|
{
|
|
return (*t)->f;
|
|
}
|
|
}
|
|
return USHRT_MAX;
|
|
}
|
|
|
|
|
|
void CGlMesh::ComputeAdjacency(void)
|
|
{
|
|
freeptr = 0;
|
|
maxptr = m_numFaces*3;
|
|
hashtable = new PHASHENTRY[m_numWedges];
|
|
|
|
// An entry for each 3 edges of each face in base mesh
|
|
hashentries = new hashentry[maxptr];
|
|
if (!hashtable)
|
|
throw CExNewFailed();
|
|
memset(hashtable, 0, sizeof(PHASHENTRY)*m_numWedges);
|
|
|
|
/*
|
|
* For each group of faces
|
|
*/
|
|
for(int i=0; i<m_numMaterials; ++i)
|
|
{
|
|
/*
|
|
* For each face in the group
|
|
*/
|
|
#ifdef __MATPOS_IS_A_PTR
|
|
for (int k=0; k<m_matcnt[i]; ++k)
|
|
{
|
|
int v1 = FindVertexIndex((m_matpos[i][k]).w[0]);
|
|
int v2 = FindVertexIndex((m_matpos[i][k]).w[1]);
|
|
int v3 = FindVertexIndex((m_matpos[i][k]).w[2]);
|
|
|
|
int fi = GetFaceIndex(i,k);
|
|
HashAdd(v1,v2,fi);
|
|
HashAdd(v2,v3,fi);
|
|
HashAdd(v3,v1,fi);
|
|
}
|
|
#else
|
|
for (int k=m_matpos[i]; k<(m_matpos[i]+m_matcnt[i]); ++k)
|
|
{
|
|
int v1 = FindVertexIndex((m_farray[k]).w[0]);
|
|
int v2 = FindVertexIndex((m_farray[k]).w[1]);
|
|
int v3 = FindVertexIndex((m_farray[k]).w[2]);
|
|
|
|
HashAdd(v1,v2,k);
|
|
HashAdd(v2,v3,k);
|
|
HashAdd(v3,v1,k);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
if (freeptr > maxptr)
|
|
throw CHashOvrflw();
|
|
#endif
|
|
/*
|
|
* For each group of faces
|
|
*/
|
|
for(i=0; i<m_numMaterials; ++i)
|
|
{
|
|
/*
|
|
* For each face in the group
|
|
*/
|
|
#ifdef __MATPOS_IS_A_PTR
|
|
for (int k=0; k<m_matcnt[i]; ++k)
|
|
{
|
|
int v1 = FindVertexIndex((m_matpos[i][k]).w[0]);
|
|
int v2 = FindVertexIndex((m_matpos[i][k]).w[1]);
|
|
int v3 = FindVertexIndex((m_matpos[i][k]).w[2]);
|
|
|
|
int fi = GetFaceIndex(i,k);
|
|
m_fnei[fi][0] = HashFind(v3,v2);
|
|
m_fnei[fi][1] = HashFind(v1,v3);
|
|
m_fnei[fi][2] = HashFind(v2,v1);
|
|
}
|
|
#else
|
|
for (int k=m_matpos[i]; k<(m_matpos[i]+m_matcnt[i]); ++k)
|
|
{
|
|
int v1 = FindVertexIndex((m_farray[k]).w[0]);
|
|
int v2 = FindVertexIndex((m_farray[k]).w[1]);
|
|
int v3 = FindVertexIndex((m_farray[k]).w[2]);
|
|
|
|
m_fnei[k][0] = HashFind(v3,v2);
|
|
m_fnei[k][1] = HashFind(v1,v3);
|
|
m_fnei[k][2] = HashFind(v2,v1);
|
|
}
|
|
#endif
|
|
}
|
|
delete [] hashtable;
|
|
delete [] hashentries;
|
|
}
|
|
|
|
#if 0
|
|
STDMETHODIMP AddWedge (WORD vertex_id, GLnormal& n,
|
|
GLtexCoord& t, DWORD* const wedge_id)
|
|
{
|
|
WORD w;
|
|
|
|
w = m_numWedges++;
|
|
m_wedgelist[w] = m_wedgelist[vertex_id];
|
|
m_wedgelist[vertex_id] = w;
|
|
|
|
m_varray[w] = m_varray[vertex_id];
|
|
m_narray[w] = n;
|
|
m_tarray[w] = t;
|
|
|
|
*wedge_id = w;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP AddWedge (Glvertex &v, GLnormal& n, GLtexCoord& t,
|
|
DWORD* const wedge_id)
|
|
{
|
|
WORD w;
|
|
|
|
w = m_numWedges++;
|
|
m_wedgelist[w] = w;
|
|
|
|
m_varray[w] = v;
|
|
m_narray[w] = n;
|
|
m_tarray[w] = t;
|
|
|
|
*wedge_id = w;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP AddWedge (Glvertex &v)
|
|
{
|
|
WORD w;
|
|
|
|
w = m_numWedges++;
|
|
m_wedgelist[w] = w;
|
|
|
|
m_varray[w] = v;
|
|
//m_narray[w] = n;
|
|
//m_tarray[w] = t;
|
|
|
|
*wedge_id = w;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP AddWedge (WORD vertex_id, WORD old_wedge_id,
|
|
DWORD* const wedge_id)
|
|
{
|
|
WORD w;
|
|
|
|
w = m_numWedges++;
|
|
|
|
/*
|
|
* Add wnl to the list of wedges sharing vertex_id
|
|
*/
|
|
m_wedgelist[w] = m_wedgelist[vertex_id];
|
|
m_wedgelist[vertex_id] = w;
|
|
|
|
/*
|
|
* Copy wedge attributes
|
|
*/
|
|
m_varray[w] = m_varray[vertex_id];
|
|
m_narray[w] = m_narray[old_wedge_id];
|
|
m_tarray[w] = m_tarray[old_wedge_id];
|
|
|
|
*wedge_id = w;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP AddFace (WORD matid, GLface& f)
|
|
{
|
|
return S_OK;
|
|
}
|
|
#endif
|