529 lines
14 KiB
C++
529 lines
14 KiB
C++
#include "viewer.h"
|
|
#include "FileIO.h" // StreamSetFMode()
|
|
#include "gmesh.h"
|
|
#include "a3dstream.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
#define GL_COLOR4(c) glColor4ub(((c)>>24)&0xff,((c)>>16)&0xff,((c)>>8)&0xff,((c)>>0)&0xff)
|
|
/************************************************************************/
|
|
/******************* Constants ******************************************/
|
|
/************************************************************************/
|
|
const int MAXOBJECT=250; // should be >= GLuint::MAXNUM
|
|
const DWORD colorinvalid=0xffffff00;
|
|
|
|
/************************************************************************/
|
|
/******************* Globals ********************************************/
|
|
/************************************************************************/
|
|
static BOOL c_mat_set;
|
|
BOOL pm_ready = FALSE;
|
|
|
|
static int thickboundary = 2;
|
|
static int thicksharp = 2;
|
|
static int thicknormal = 1;
|
|
static int thicka3d = 1;
|
|
|
|
static BOOL perspec = TRUE;
|
|
static int cullbackedges=1;
|
|
|
|
static GLfloat ambient;
|
|
static GLfloat backfacec[4];
|
|
|
|
static float fdisplacepolygon = 1.0;
|
|
static float sphereradius=.005;
|
|
static float zoom = 1.0;
|
|
static Frame tcam;
|
|
static int nxpix,nypix; // window dimensions
|
|
static float tzp1, tzp2;
|
|
static float edgeoffset;
|
|
static Frame tcami;
|
|
static Point eyeinobframe;
|
|
static int cob;
|
|
|
|
static BOOL lcullface = FALSE;
|
|
|
|
static BOOL haveconcave = FALSE;
|
|
|
|
static DWORD edgecolor = 0x000000FF; // black
|
|
static DWORD sharpedgecolor = 0xFF40FFFF; // bright yellow
|
|
static float xpointerold, ypointerold;
|
|
|
|
static DWORD curcol; // current color (for lines and points)
|
|
static MatColor matcol; // material color (for polygons)
|
|
static MatColor cuspcolor;
|
|
static MatColor meshcolor;
|
|
|
|
// default color for polygons
|
|
const A3dVertexColor DEFAULTCOL(A3dColor(0.9, 0.6, 0.4),
|
|
A3dColor(0.5, 0.5, 0.5),
|
|
A3dColor(5, 0, 0));
|
|
|
|
// default color for polylines and points
|
|
const A3dVertexColor WHITECOL(A3dColor(1, 1, 1),
|
|
A3dColor(0, 0, 0),
|
|
A3dColor(1, 0, 0));
|
|
|
|
static Array<DWORD> pm_ar_colors;
|
|
|
|
PMesh *pmesh; // Global pointer to the (one and only) PM object
|
|
PMeshRStream* pmrs=0;
|
|
PMeshIter* pmi=0;
|
|
float pm_lod_level = 0.0;
|
|
float old_lod = 0.0;
|
|
|
|
float curquat[4], lastquat[4];
|
|
/************************************************************************/
|
|
/******************* Function Prototypes ********************************/
|
|
/************************************************************************/
|
|
BOOL InitPMDrawState(void);
|
|
BOOL read_pm (char *);
|
|
void draw_pm (void);
|
|
static void glinit(void);
|
|
static int setupob(void);
|
|
void pm_update_lod (void);
|
|
|
|
/************************************************************************/
|
|
/******************* Code ***********************************************/
|
|
/************************************************************************/
|
|
|
|
static DWORD packcolor(const A3dColor& col)
|
|
{
|
|
return (DWORD(col[0]*255.99)<<24)+(DWORD(col[1]*255.99)<<16)+
|
|
(DWORD(col[2]*255.99)<<8)+(DWORD(255)<<0);
|
|
}
|
|
|
|
static void creatematcolor(const A3dVertexColor& vc, MatColor& col)
|
|
{
|
|
col.diffuse = packcolor(vc.d);
|
|
col.specular = packcolor(vc.s);
|
|
col.shininess = vc.g[0];
|
|
}
|
|
|
|
BOOL InitPMDrawState(char *fname)
|
|
{
|
|
perspec = TRUE;
|
|
backfacec[0] = 0.15, backfacec[1]= 0.5, backfacec[2]= 0.15;
|
|
backfacec[3] = 1.0;
|
|
|
|
nxpix = g_wi.wSize.cx;
|
|
nypix = g_wi.wSize.cy;
|
|
float cuspcol[3]= {1.0, 0.2, 0.2};
|
|
float meshcd[3]={0.8, 0.5, 0.4};
|
|
float meshcs[3]={0.5, 0.5, 0.5};
|
|
float meshcp[3]={5, 0, 0};
|
|
|
|
int cuspbright = (cuspcol[0] + cuspcol[1] + cuspcol[2]>2.);
|
|
A3dVertexColor CUSPCOL(A3dColor(cuspcol[0],cuspcol[1],cuspcol[2]),
|
|
A3dColor(cuspcol[0],cuspcol[1],cuspcol[2]),
|
|
A3dColor(cuspbright?1:7,0,0));
|
|
|
|
creatematcolor(CUSPCOL, cuspcolor);
|
|
creatematcolor(A3dVertexColor(A3dColor(meshcd[0],meshcd[1],meshcd[2]),
|
|
A3dColor(meshcs[0],meshcs[1],meshcs[2]),
|
|
A3dColor(meshcp[0],meshcp[1],meshcp[2])),
|
|
meshcolor);
|
|
if (fname)
|
|
if (read_pm( fname ))
|
|
{
|
|
glinit();
|
|
setupob ();
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static int pthick;
|
|
|
|
static void resetthickness()
|
|
{
|
|
pthick=-1;
|
|
}
|
|
|
|
|
|
static void setthickness2(int vthick)
|
|
{
|
|
pthick=vthick;
|
|
if (vthick > 1)
|
|
glLineWidth((GLfloat)(vthick));
|
|
}
|
|
|
|
inline void InitViewing (void)
|
|
{
|
|
float a = 1.0f / min(nxpix, nypix);
|
|
tzp1 = 0.5f / (zoom*nxpix*a);
|
|
tzp2 = 0.5f / (zoom*nypix*a);
|
|
|
|
//if (g_s.yon <= g_s.hither*1.0001) g_s.yon = g_s.hither*1.0001;
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
//Reshape (nxpix, nypix);
|
|
#if 1
|
|
if (perspec)
|
|
{
|
|
glFrustum (-nxpix*a*zoom*g_s.hither, nxpix*a*zoom*g_s.hither,
|
|
-nypix*a*zoom*g_s.hither, nypix*a*zoom*g_s.hither,
|
|
g_s.hither, g_s.yon);
|
|
}
|
|
else
|
|
{
|
|
glOrtho(-nxpix*a*zoom, nxpix*a*zoom,
|
|
-nypix*a*zoom, nypix*a*zoom,
|
|
g_s.hither, g_s.yon);
|
|
}
|
|
#endif
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
trackball(curquat, 0.0, 0.0, 0.0, 0.0);
|
|
}
|
|
|
|
inline void setthickness(int vthick)
|
|
{
|
|
if (vthick!=pthick) setthickness2(vthick);
|
|
}
|
|
|
|
|
|
// must be followed by setupob()!
|
|
static void glinit(void)
|
|
{
|
|
|
|
const float cedgeoffset=4.2e-3f;
|
|
edgeoffset = cedgeoffset*zoom*fdisplacepolygon;
|
|
|
|
InitViewing ();
|
|
|
|
NEST
|
|
{ // front material
|
|
float material[] = {0.0, 0.0, 0.0, 1.0};
|
|
glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, material);
|
|
}
|
|
NEST
|
|
{ // back material
|
|
float amb[] = {0.0, 0.0, 0.0, 1.0};
|
|
float diff[] = {0.15, 0.15, 0.15, 1.0};
|
|
glMaterialfv(GL_BACK, GL_AMBIENT, amb);
|
|
glMaterialfv(GL_BACK, GL_DIFFUSE, diff);
|
|
glMaterialfv(GL_BACK, GL_EMISSION, backfacec);
|
|
}
|
|
NEST
|
|
{ // lighting model
|
|
GLfloat ambient[] = { 0.2, 0.2, 0.2, 1.0 };
|
|
GLfloat diffuse[] = { 0.7, 0.7, 0.7, 1.0 };
|
|
GLfloat position[] = { 0.0, 0.0, 2.0, 0.0 };
|
|
|
|
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, ambient);
|
|
glLightfv(GL_LIGHT0, GL_POSITION, position);
|
|
}
|
|
|
|
resetthickness();
|
|
setthickness(thicka3d);
|
|
glDepthRange(0x0, 0x7FFFFF);
|
|
c_mat_set = FALSE;
|
|
glDisable (GL_COLOR_MATERIAL);
|
|
|
|
curcol = colorinvalid;
|
|
matcol.diffuse = colorinvalid;
|
|
matcol.specular = colorinvalid;
|
|
matcol.shininess = -1;
|
|
}
|
|
|
|
|
|
static int setupob(void)
|
|
{
|
|
char buf[200];
|
|
|
|
NEST
|
|
{
|
|
GLfloat ambient[] = {0.25, 0.25, 0.25, 1.0};
|
|
|
|
glLightModelfv (GL_LIGHT_MODEL_AMBIENT, ambient);
|
|
glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
|
|
glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, 0);
|
|
}
|
|
glFrontFace (front_face);
|
|
|
|
glCullFace(cull_face);
|
|
if (cull_enable)
|
|
glEnable(GL_CULL_FACE);
|
|
else
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, filled_mode?GL_FILL:GL_LINE);
|
|
//if (edge_mode) displacepolygon(fdisplacepolygon);
|
|
|
|
// Compute the model bounding box
|
|
g_s.max_vert[0] = g_s.max_vert[1] = g_s.max_vert[2] = -1e30f;
|
|
g_s.min_vert[0] = g_s.min_vert[1] = g_s.min_vert[2] = 1e30f;
|
|
int nv0=pmesh->_base_mesh._vertices.num();
|
|
//int nvsplits=pmesh->_vsplits.num();
|
|
//int nv=nv0+int((nvsplits+1)*0.999999f); //max LOD
|
|
pmi->goto_nvertices(nv0);
|
|
|
|
const AWMesh& wmesh=*pmi;
|
|
int num_v = wmesh._vertices.num();
|
|
//S_Vertex* svp = wmesh._vertices;
|
|
|
|
for (int i=0; i<num_v; i++)
|
|
{
|
|
#if 0
|
|
const float* p1 = &wmesh._vertices[i].attrib.point[0];
|
|
for (int j=0; j<3; j)
|
|
{
|
|
if (p1[j] > g_s.max_vert[j]) g_s.max_vert[j] = p1[j];
|
|
if (p1[j] < g_s.min_vert[j]) g_s.min_vert[j] = p1[j];
|
|
}
|
|
#endif
|
|
}
|
|
sprintf (buf, "NumVert = %d\r\n", num_v);
|
|
|
|
MessageBox (NULL, buf, "Info", MB_OK);
|
|
//pmi->goto_nvertices(nv0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static void updatecurcolor2(DWORD col)
|
|
{
|
|
if (c_mat_set) c_mat_set = 0, glDisable(GL_COLOR_MATERIAL);
|
|
curcol = col;
|
|
glColor4ub ( (col>>24) & 0xff,
|
|
(col>>16) & 0xff,
|
|
(col>>8) & 0xff,
|
|
(col>>0) & 0xff);
|
|
matcol.diffuse = colorinvalid;
|
|
matcol.specular = colorinvalid;
|
|
matcol.shininess = -1;
|
|
}
|
|
|
|
inline void updatecurcolor (DWORD col)
|
|
{
|
|
if (col != curcol) updatecurcolor2 (col);
|
|
}
|
|
|
|
static void updatematcolor2(const MatColor& col)
|
|
{
|
|
if (!c_mat_set)
|
|
{
|
|
c_mat_set = TRUE;
|
|
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
|
}
|
|
glEnable(GL_COLOR_MATERIAL);
|
|
|
|
if (col.shininess != matcol.shininess)
|
|
{
|
|
matcol.shininess = col.shininess;
|
|
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matcol.shininess);
|
|
}
|
|
|
|
if (col.specular != matcol.specular)
|
|
{
|
|
matcol.specular = col.specular;
|
|
glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
|
|
GL_COLOR4(matcol.specular);
|
|
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
|
}
|
|
|
|
if (col.diffuse != matcol.diffuse)
|
|
{
|
|
matcol.diffuse = col.diffuse;
|
|
GL_COLOR4(col.diffuse);
|
|
}
|
|
curcol=colorinvalid;
|
|
}
|
|
|
|
|
|
inline void updatematcolor(const MatColor& col)
|
|
{
|
|
if (col.diffuse != matcol.diffuse ||
|
|
col.specular != matcol.specular ||
|
|
col.shininess != matcol.shininess)
|
|
updatematcolor2(col);
|
|
}
|
|
|
|
inline void updatematdiffuse(DWORD cd)
|
|
{
|
|
if (cd != matcol.diffuse)
|
|
{
|
|
if (!c_mat_set)
|
|
{
|
|
c_mat_set = TRUE;
|
|
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
|
}
|
|
glEnable(GL_COLOR_MATERIAL);
|
|
matcol.diffuse = cd;
|
|
GL_COLOR4(cd);
|
|
curcol=colorinvalid;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline void pm_draw_segment(int fn, int v0, int v1,
|
|
const Point& p0, const Point& p1)
|
|
{
|
|
if (fn >= 0 && v0 > v1) return;
|
|
glBegin(GL_LINES);
|
|
glVertex3fv(&p0[0]);
|
|
glVertex3fv(&p1[0]);
|
|
glEnd();
|
|
}
|
|
|
|
void draw_pm (void)
|
|
{
|
|
updatematcolor(meshcolor);
|
|
const AWMesh& wmesh=*pmi;
|
|
if (!edge_mode || filled_mode)
|
|
{
|
|
const S_Vertex* svp = wmesh._vertices;
|
|
const S_Wedge* swp = wmesh._wedges;
|
|
const S_Face* sfp = wmesh._faces;
|
|
const DWORD * matp = pm_ar_colors;
|
|
ForIndex(f, wmesh._faces.num())
|
|
{
|
|
int matid = sfp[f].attrib.matid;
|
|
updatematdiffuse(matp[matid]);
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
const int* wp = sfp[f].wedges;
|
|
int w0 = wp[0];
|
|
int w1 = wp[1];
|
|
int w2 = wp[2];
|
|
|
|
int v0 = swp[w0].vertex;
|
|
int v1 = swp[w1].vertex;
|
|
int v2 = swp[w2].vertex;
|
|
|
|
const float* n0 = &swp[w0].attrib.normal[0];
|
|
const float* p0 = &svp[v0].attrib.point[0];
|
|
|
|
const float* n1 = &swp[w1].attrib.normal[0];
|
|
const float* p1 = &svp[v1].attrib.point[0];
|
|
|
|
const float* n2=&swp[w2].attrib.normal[0];
|
|
const float* p2=&svp[v2].attrib.point[0];
|
|
|
|
glNormal3fv(n0); glVertex3fv(p0);
|
|
glNormal3fv(n1); glVertex3fv(p1);
|
|
glNormal3fv(n2); glVertex3fv(p2);
|
|
glEnd();
|
|
} EndFor;
|
|
}
|
|
if (edge_mode)
|
|
{
|
|
// Options cullbackedges, lquickmode not handled.
|
|
setthickness (thicknormal);
|
|
updatecurcolor (edgecolor);
|
|
const S_Vertex* svp = wmesh._vertices;
|
|
const S_Wedge* swp = wmesh._wedges;
|
|
const S_Face* sfp = wmesh._faces;
|
|
const S_FaceNeighbors* snp = wmesh._fnei;
|
|
ForIndex(f, wmesh._faces.num())
|
|
{
|
|
const int* wp = sfp[f].wedges;
|
|
const int* np = snp[f].faces;
|
|
|
|
int w0 = wp[0];
|
|
int w1 = wp[1];
|
|
|
|
int v0 = swp[w0].vertex;
|
|
int v1 = swp[w1].vertex;
|
|
|
|
const Point& p0 = svp[v0].attrib.point;
|
|
const Point& p1 = svp[v1].attrib.point;
|
|
|
|
int fn2 = np[2];
|
|
int fn0 = np[0];
|
|
|
|
pm_draw_segment (fn2, v0, v1, p0, p1);
|
|
|
|
int w2 = wp[2];
|
|
int v2 = swp[w2].vertex;
|
|
|
|
const Point& p2 = svp[v2].attrib.point;
|
|
int fn1 = np[1];
|
|
|
|
pm_draw_segment (fn0, v1, v2, p1, p2);
|
|
pm_draw_segment (fn1, v2, v0, p2, p0);
|
|
} EndFor;
|
|
setthickness (thicka3d);
|
|
}
|
|
}
|
|
|
|
|
|
#define ForStringKeyValue(S,KS,KL,VS,VL) \
|
|
{ StringKeyIter zz(S); \
|
|
const char* KS; const char* VS; \
|
|
int KL; int VL; \
|
|
while (zz.next(KS,KL,VS,VL)) {
|
|
|
|
const char* string_key(const char* str, const char* key)
|
|
{
|
|
int keyl=strlen(key);
|
|
ForStringKeyValue(str,kb,kl,vb,vl) {
|
|
int found=!strncmp(kb,key,kl) && kl==keyl;
|
|
if (!found) continue;
|
|
char* sret=(char*)hform(""); // un-const
|
|
strncat(sret,vb,vl);
|
|
return sret;
|
|
} EndFor;
|
|
return 0;
|
|
}
|
|
|
|
BOOL read_pm (char *fname)
|
|
{
|
|
BOOL retVal = TRUE;
|
|
|
|
if (pmesh)
|
|
delete pmesh;
|
|
pmesh=new PMesh;
|
|
{
|
|
ifstream fi(fname);
|
|
StreamSetFMode((fstream&)fi,1);
|
|
pmesh->read(fi);
|
|
}
|
|
pmrs=new PMeshRStream(*pmesh);
|
|
pmi=new PMeshIter(*pmrs);
|
|
// When pmrs is created, it automatically reads in pmesh._base_mesh
|
|
const AWMesh& base_mesh=pmesh->_base_mesh;
|
|
const Materials& materials=base_mesh._materials;
|
|
|
|
ForIndex(matid,materials.num()) {
|
|
DWORD pcolor;
|
|
const char* str=materials.get(matid);
|
|
const char* s=string_key(str,"rgb");
|
|
if (s)
|
|
{
|
|
A3dColor co;
|
|
if (sscanf(s,"( %g %g %g )",&co[0],&co[1],&co[2])!=3)
|
|
MessageBox (NULL, "viewer.cxx", "Error", MB_OK);
|
|
//assertx(sscanf(s,"( %g %g %g )",&co[0],&co[1],&co[2])==3);
|
|
pcolor=packcolor(co);
|
|
}
|
|
else
|
|
{
|
|
pcolor = meshcolor.diffuse;
|
|
}
|
|
pm_ar_colors+=pcolor;
|
|
} EndFor;
|
|
pm_lod_level = 0.0f;
|
|
auxSetScrollPos (AUX_HSCROLL, auxGetScrollMin(AUX_HSCROLL));
|
|
pm_ready = TRUE;
|
|
return retVal;
|
|
}
|
|
|
|
|
|
void pm_update_lod (void)
|
|
{
|
|
//float flevel=min(pm_lod_level,1.f);
|
|
int nv0=pmesh->_base_mesh._vertices.num();
|
|
int nvsplits=pmesh->_vsplits.num();
|
|
int nv=nv0+int((nvsplits+1)*pm_lod_level*.999999f);
|
|
pmi->goto_nvertices(nv);
|
|
}
|
|
|