|
|
#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); }
|