a48
2.0.2
|
This is an example of how to use the ContainerBasedAP derived classes together with how to draw a simple mesh using OpenGL 2.x and GLUT.
#include <cstdio> #include <cmath> #include <iostream> #include <GL/gl.h> #include <GL/glut.h> #include <mesh.hh> #include <adaptivepolicies.hh> #define MAX_LEVEL 12 typedef struct { char* title; int w, h, id; unsigned int mode; } glut_window; template< class Traits > class PosVertex : public a48::AdaptiveVertexT< Traits > { public: float pos[3]; unsigned int id; float f(float u, float v) { float d = sqrt(u*u + v*v); return .1*sin(10*d); } }; class GeoTraits { public: typedef PosVertex< GeoTraits > vertex_type; typedef a48::AdaptiveFaceT< GeoTraits > face_type; typedef a48::AdaptiveHalfedgeT< GeoTraits > halfedge_type; }; template< class Traits > class ItemsPolicy : public virtual a48::BaseItemsPolicy< Traits > { typedef typename Traits::vertex_type vertex_type; typedef typename Traits::halfedge_type halfedge_type; typedef typename Traits::face_type face_type; public: float *coords; unsigned int *faces; unsigned int nv, nf; ItemsPolicy() { const float c[] = { -1.0,-1.0, 1.0,-1.0, 1.0,1.0, -1.0,1.0 }; const size_t cs = sizeof(c)/sizeof(float); coords = new float[ cs ]; std::copy(c, c+cs, coords); const unsigned int f[] = { 1,3,0, 3,1,2 }; const size_t fs = sizeof(f)/sizeof(unsigned int); faces = new unsigned int[ fs ]; std::copy(f, f+fs, faces); nv = cs/2; nf = fs/3; } ~ItemsPolicy() { delete [] coords; delete [] faces; } void set_vertex_attributes(const unsigned int& i, vertex_type *v) { float *c = coords + 2*i; v->pos[0] = c[0]; v->pos[1] = c[1]; v->pos[2] = v->f( c[0], c[1] ); v->id = i; } void set_vertex_attributes(vertex_type *v1, const vertex_type *v0) { } void set_halfedge_attributes(halfedge_type *h1, const halfedge_type *h0) { } void set_halfedge_attributes(halfedge_type *h, halfedge_type *o) { } void set_halfedge_attributes(const unsigned int& i, const unsigned int& j, const unsigned int& hi, halfedge_type *h) { } void set_face_attributes(face_type *f1, const face_type *f0) { } void set_face_attributes(const unsigned int& i, face_type *f) { } }; template< class Traits > class StellarPolicy : public virtual a48::BaseStellarPolicy< Traits > { typedef typename Traits::vertex_type vertex_type; typedef typename Traits::halfedge_type halfedge_type; typedef typename Traits::face_type face_type; public: ItemsPolicy< Traits > ip; void sample_vertex(const halfedge_type *h, vertex_type *v) { const vertex_type* org = h->vertex(); const vertex_type* dst = h->from_vertex(); float x0, y0, x1, y1; x0 = org->pos[0]; y0 = org->pos[1]; x1 = dst->pos[0]; y1 = dst->pos[1]; v->pos[0] = 0.5*(x0 + x1); v->pos[1] = 0.5*(y0 + y1); v->pos[2] = v->f( v->pos[0], v->pos[1] ); v->id = ip.nv; ++ip.nv; } void sample_vertex(const face_type *f, vertex_type *v) { } void remove_vertex(const halfedge_type *h, const vertex_type *v) { } void remove_vertex(const face_type *f, const vertex_type *v) { } void flip_halfedge(const halfedge_type *h) { } }; typedef a48::AdaptiveMeshT< GeoTraits > Mesh; static glut_window win = { (char*)"a48 GL Example", 1024, 1024, 0, GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH }; Mesh* mesh; a48::UniformLevelAP< GeoTraits > *uap; a48::RangeLevelAP< GeoTraits > *rap; unsigned char srange = 0; std::vector<float> verts; std::vector<unsigned int> faces; void init() { glEnable(GL_DEPTH_TEST); glEnable(GL_ALPHA_TEST); glDepthFunc(GL_LESS); glShadeModel(GL_SMOOTH); glEnable(GL_LINE_SMOOTH); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE); glEnable(GL_MULTISAMPLE); glClearColor(1.0, 1.0, 1.0, 1.0); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(2.0,2.0,3.0, 0.0,0.0,0.0, 0.0,0.0,1.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( 40.0, 1.0, 0.125, 128.0 ); } void get_data() { verts.clear(); verts.reserve( mesh->size_of_vertices()*3 ); unsigned int i = 0; for(Mesh::vertex_iterator vit = mesh->vertices_begin(); vit != mesh->vertices_end(); ++vit, ++i){ Mesh::vertex_type *v = *vit; verts.push_back(v->pos[0]); verts.push_back(v->pos[1]); verts.push_back(v->pos[2]); v->id = i; } faces.clear(); faces.reserve( mesh->size_of_faces()*3 ); for(Mesh::face_iterator fit = mesh->faces_begin(); fit != mesh->faces_end(); ++fit){ Mesh::halfedge_type *h = (*fit)->halfedge(); faces.push_back(h->vertex()->id); h = h->next(); faces.push_back(h->vertex()->id); h = h->next(); faces.push_back(h->vertex()->id); } } void glWrite(GLdouble _x, GLdouble _y, const char *_str) { glRasterPos2d( _x, _y ); for (char *s = (char*)_str; *s; s++) glutBitmapCharacter( GLUT_BITMAP_HELVETICA_12, *s ); } void reshape(int _w, int _h) { glViewport( 0, 0, win.w = _w, win.h = _h ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 40.0, win.w/(GLdouble)win.h, 0.125, 128.0 ); } void display(void) { char str[256]; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glColor3d(0.2, 0.1, 0.8); sprintf( str, "Choose adaptive policy (u|r): %s", (mesh->get_adaptive_policy() == uap?"UniformLevel":"RangeLevel") ); glWrite( -0.9, 0.9, str ); glWrite( -0.9, 0.85, "Choose adaptation level (UP|DOWN)" ); glWrite( -0.9, 0.8, "Choose min/max range level (LEFT|RIGHT)" ); if( mesh->get_adaptive_policy() == uap ) sprintf( str, "Current level: %d", uap->get_target_level() ); else sprintf( str, "Current range: [%s%d, %d%s]", ((srange==0)?"*":" "), rap->get_min_level(), rap->get_max_level(), ((srange==1)?"*":" ") ); glWrite( -0.9, -0.9, str ); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glColor3d(0.0, 0.0, 0.0); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, &verts[0]); glDrawElements(GL_TRIANGLES, faces.size(), GL_UNSIGNED_INT, &faces[0]); glDisableClientState(GL_VERTEX_ARRAY); glutSwapBuffers(); } void update_mesh(void) { mesh->adapt_refine(); mesh->adapt_simplify(); get_data(); } void special(int key, int x, int y) { switch(key) { case GLUT_KEY_UP: if( mesh->get_adaptive_policy() == uap ) uap->inc_target_level( MAX_LEVEL ); else { if( srange == 0 ) rap->inc_min_level( MAX_LEVEL ); else rap->inc_max_level( MAX_LEVEL ); } update_mesh(); break; case GLUT_KEY_DOWN: if( mesh->get_adaptive_policy() == uap ) uap->dec_target_level(); else { if( srange == 0 ) rap->dec_min_level(); else rap->dec_max_level(); } update_mesh(); break; case GLUT_KEY_LEFT: srange = 0; break; case GLUT_KEY_RIGHT: srange = 1; break; } glutPostRedisplay(); } void keyboard(unsigned char key, int x, int y) { switch(key) { case 'u': case 'U': mesh->set_adaptive_policy( uap ); update_mesh(); break; case 'r': case 'R': mesh->set_adaptive_policy( rap ); update_mesh(); break; case 'q': case 'Q': case 27: glutDestroyWindow( win.id ); return; } glutPostRedisplay(); } float select_range_level(PosVertex< GeoTraits > *v) { return (v->pos[2] + .1f) / .2f; } int main(int argc, char** argv) { StellarPolicy< GeoTraits > sp; mesh = new Mesh(&sp.ip, &sp); uap = new a48::UniformLevelAP< GeoTraits >( mesh, 4 ); rap = new a48::RangeLevelAP< GeoTraits >( mesh, select_range_level, 5, 12 ); mesh->set_base( sp.ip.nv, sp.ip.nf, sp.ip.faces ); mesh->set_adaptive_policy( uap ); update_mesh(); glutInit( &argc, argv ); glutInitWindowPosition( 0, 0 ); glutInitWindowSize( win.w, win.h ); glutInitDisplayMode( win.mode ); win.id = glutCreateWindow( win.title ); init(); glutReshapeFunc(reshape); glutDisplayFunc(display); glutSpecialFunc(special); glutKeyboardFunc(keyboard); glutMainLoop (); delete [] mesh; delete [] uap; delete [] rap; return 0; }