Subversion Repositories gelsvn

Rev

Rev 333 | Blame | Last modification | View Log | RSS feed

// ----------------------------------------
// A simple Range Scan Viewer
//
// Controls:
// - left mouse down + mouse motion : rotate
// - Scroll button and +- buttons   : zoom
// - right mouse click              : centre trackball
// - esc                            : exits
// - x,y,z buttons                  : switch trackball up axis
// ----------------------------------------

#if (_MSC_VER >= 1200)
#pragma warning (disable: 4786)
#endif

#include <list>
#include <vector>

#include <assert.h>
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#include <io.h>
#endif
#include <string.h>
#include <stdlib.h>

#include <iostream>
#include <CGLA/Vec2i.h>
#include <CGLA/Vec2f.h>

#include <CGLA/Vec3f.h>
#include <CGLA/Mat4x4f.h>
#include "GLGraphics/gel_glut.h"
#include "GLGraphics/QuatTrackBall.h"
#include "Geometry/KDTree.h"


#include "ply.h"

#include <CGLA/statistics.h>
#include <CGLA/eigensolution.h>

using namespace std;
using namespace CGLA;
using namespace Geometry;
using namespace GLGraphics;

namespace
{
        int win_size_x = 800;
        int win_size_y = 800;

        QuatTrackBall* ball;
        int spin_timer = 20;
        void spin(int x);

        int main_window;

        Vec3f cen;
        Vec3f pmin;
        Vec3f bbsize;
        std::vector<CGLA::Vec3f> verts;
        std::vector<CGLA::Vec3f> norms;
        float rad;

        void verts_from_conf(std::string filename, float dist=0.002)
        {
                verts.clear();
                norms.clear();

                CGLA::Quatf qrot;
                CGLA::Vec3f tr;
                CGLA::Mat4x4f transform;
                CGLA::Mat4x4f Ntransform;

                char plyfile[50];
                char elemtag[50];
                FILE * pFile;
                //filename = "data/" + filename;
                pFile = fopen (filename.c_str(),"r");
                if (pFile==NULL)
                {
                        cout << "file error " << filename << endl;
                        return;
                }

                bool end=false;

                cen=Vec3f(0,0,0);
                pmin=Vec3f(1000,10000,1000);
                bbsize=Vec3f(-100,-100,-100);

                cout << "using file " << filename << endl;

                while(!end)
                {
                        //bmesh bun045.ply -0.0520211 -0.000383981 -0.0109223 0.00548449 -0.294635 -0.0038555 0.955586

                        //int params = fscanf (pFile, "%s %s %f %f %f %f %f %f %f", &elemtag, &plyfile, &tr[0], &tr[1], &tr[2], &qrot.qw ,&qrot.qv[0], &qrot.qv[1], &qrot.qv[2]);
                        int params = fscanf (pFile, "%s %s %f %f %f %f %f %f %f", &elemtag, &plyfile, &tr[0], &tr[1], &tr[2],&qrot.qv[0], &qrot.qv[1], &qrot.qv[2], &qrot.qw );
                        //int params = fscanf (pFile, "%s ", &elemtag);
                        if (params>0)
                        {
                                if ( strcmp(elemtag, "bmesh")==0 )
                                {
                                        //  fscanf (pFile, "%s %f %f %f %f %f %f %f\n", &plyfile, &tr[0], &tr[1], &tr[2],&qrot.qv[0], &qrot.qv[1], &qrot.qv[2], &qrot.qw );
                                        string splyfile = string(plyfile);
                                        cout << "found plyfile " << splyfile << endl;

                                        qrot = qrot.inverse();
                                        transform = CGLA::translation_Mat4x4f(tr) * qrot.get_Mat4x4f();
                                        Ntransform = transform;
                                        Ntransform = invert(Ntransform);
                                        Ntransform = transpose(Ntransform);

                                        PlyFile *ply;
                                        int nelems;
                                        int nprops;
                                        char **elist;
                                        int file_type;
                                        float version;
                                        int num_elems;
                                        //PlyProperty **plist;
                                        char *elem_name;


                                        ply = ply_open_for_reading(splyfile.c_str(), &nelems, &elist, &file_type, &version);

                                        /* print what we found out about the file */
                                        printf ("version %f\n", version);
                                        printf ("type %d\n", file_type);

                                        /* go through each kind of element that we learned is in the file */
                                        /* and read them */

                                        for (int i = 0; i < nelems; i++) 
                                        {

                                                /* get the description of the first element */
                                                elem_name = elist[i];
                                                //plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);
                                                ply_get_element_description (ply, elem_name, &num_elems, &nprops);

                                                /* print the name of the element, for debugging */
                                                printf ("element %s %d\n", elem_name, num_elems);

                                                /* if we're on vertex elements, read them in */
                                                if (equal_strings ("vertex", elem_name)) 
                                                {
                                                        typedef struct PlyVertex {
                                                                float x,y,z;             /* the usual 3-space position of a vertex */
                                                        } PlyVertex;

                                                        PlyProperty vert_props[] = { /* list of property information for a vertex */
                                                                {"x", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,x), 0, 0, 0, 0},
                                                                {"y", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,y), 0, 0, 0, 0},
                                                                {"z", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,z), 0, 0, 0, 0},
                                                        };

                                                        /* set up for getting vertex elements */
                                                        ply_get_property (ply, elem_name, &vert_props[0]);
                                                        ply_get_property (ply, elem_name, &vert_props[1]);
                                                        ply_get_property (ply, elem_name, &vert_props[2]);


                                                        /* grab all the vertex elements */
                                                        for (int j = 0; j < num_elems; j++) 
                                                        {
                                                                PlyVertex * pv = (PlyVertex *) malloc (sizeof (PlyVertex));

                                                                /* grab and element from the file */
                                                                ply_get_element (ply, (void*)pv);

                                                                Vec3f v = transform.mul_3D_point(Vec3f(pv->x, pv->y, pv->z));
                                                                verts.push_back(v);

                                                                Vec3f n = Ntransform.mul_3D_vector(Vec3f(0,0,1));
                                                                norms.push_back(n);

                                                                cen += v;
                                                                pmin = v_min(pmin,v);
                                                                bbsize = v_max(bbsize,v);
                                                        }
                                                }
                                        }
                                }
                        }
                        else
                        {
                                end=true;
                                fclose(pFile);
                        }
                }

                if (dist>0)
                {
                        Geometry::KDTree<CGLA::Vec3f,int>* tree = new Geometry::KDTree<CGLA::Vec3f,int>();
                        for (unsigned int i=0; i<verts.size(); ++i)
                                tree->insert(verts[i], i);
                        tree->build();

                        int skip=0;
                        for (unsigned int i=0; i<verts.size(); ++i)
                        {
                                if (i % 100000 == 0)
                                        cerr << ".";

                                vector<CGLA::Vec3f> neigbours;
                                vector<int> neigbour_ids;
                                int num = tree->in_sphere(verts[i], dist, neigbours, neigbour_ids);

                                if (num > 5)
                                {
                                        Mat3x3f A;
                                        Vec3f m = covariance(neigbours, A);
                                        Mat3x3f Q,L;
                                        int n = power_eigensolution(A, Q, L);

                                        int min_id;
                                        if ( L[0][0] < L[1][1])
                                        {
                                                if ( L[0][0] < L[2][2])
                                                        min_id = 0;
                                                else
                                                        min_id = 2;
                                        }
                                        else
                                        {
                                                if ( L[1][1] < L[2][2])
                                                        min_id = 1;
                                                else
                                                        min_id = 2;
                                        }

                                        Vec3f temp_n(Q[min_id][0], Q[min_id][1], Q[min_id][2]);
                                        temp_n.normalize();
                                        float sgn = sign(dot(temp_n, norms[i]));
                                        norms[i] = sgn*temp_n;
                                }
                                else
                                {
                                        norms[i] = Vec3f(0,0,0);
                                        skip++;
                                }
                        }

                        cout << skip << " of " << verts.size() << " with zero normal" << endl;;
                }
                cen /= (float)verts.size();
                bbsize =  bbsize-pmin;
                rad = 0.7f*bbsize.length();

                //for(unsigned int i=0; i<verts.size(); ++i )
                //  scale( verts[i], rad);
                //
                //pmin= Vec3f(0,0,0);
                //  //bbsize = Vec3f(cur_dim);
                //  bbsize = Vec3f(1,1,1);
                //  cen = 0.5f*bbsize;
        }

        void write_obj(string fn)
        {
                FILE* pFile = fopen (fn.c_str(),"w+");
                if (pFile==NULL)
                {
                        cout << "file error " << fn << endl;
                        return;
                }

                fprintf( pFile, "# %d vertices with normal\n", verts.size());
                //fprintf( pFile, "# center : %d vertices with normal", verts.size());
                
                for(unsigned int i=0; i<verts.size(); ++i )
                  fprintf( pFile, "v %f %f %f\n", verts[i][0], verts[i][1], verts[i][2]);
                for(unsigned int i=0; i<norms.size(); ++i )
                  fprintf( pFile, "vn %f %f %f\n", norms[i][0], norms[i][1], norms[i][2]);

                fclose(pFile);

        }


        void mouse_motion(int x, int y)
        {
                ball->roll_ball(Vec2i(x,y));
        }

        void mouse(int btn, int state, int x, int y)
        {
                if(state == GLUT_DOWN) 
                {
                        if(btn == GLUT_LEFT_BUTTON) 
                                ball->grab_ball(ROTATE_ACTION, Vec2i(x,y));
                        else if(btn == GLUT_MIDDLE_BUTTON) 
                                ball->grab_ball(ZOOM_ACTION, Vec2i(x, y));
                        else if(btn == GLUT_RIGHT_BUTTON) 
                                ball->grab_ball(PAN_ACTION, Vec2i(x, y));
                }
                else if(state == GLUT_UP)
                        ball->release_ball();   
        }

        void spin(int x)
        {
                ball->do_spin();
                glutTimerFunc(spin_timer, spin, 0);  
                glutPostRedisplay();
        }


        void draw()
        {
                glBegin(GL_POINTS);
                for(unsigned int i=0; i<verts.size(); ++i )
                {
                        glVertex3fv( verts[i].get());
                }
                glEnd();
        }

        void draw_normals(float l=0.001)
        {
                glBegin(GL_LINES);
                for(unsigned int i=0; i<verts.size(); ++i )
                {
                        Vec3f p1 = verts[i] + l*norms[i];
                        glVertex3fv( verts[i].get());
                        glVertex3fv( p1.get());
                }
                glEnd();
        }

        void display()
        {
                static bool washere = false;
                static unsigned int lp, ln;
                if(!washere)
                {
                        cout << "Creating display list" << endl;
                        lp = glGenLists(1);
                        glNewList(lp, GL_COMPILE);
                        draw();
                        glEndList();
                        cout << "Creating display list" << endl;
                        ln = glGenLists(1);
                        glNewList(ln, GL_COMPILE);
                        draw_normals();
                        glEndList();
                        
                        washere = true;
                        glutTimerFunc(spin_timer, spin, 0);     
                }
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                glLoadIdentity();
                ball->set_gl_modelview();
                glColor3f(0.9,0.1,0);
                glCallList(lp);
                glColor3f(0.0,0.9,0.5);
                glCallList(ln);
                
                glPushMatrix();
                glColor3f(0.7,0.9,0.3);

                glTranslatef(cen[0], cen[1], cen[2]);
                glScalef(bbsize[0], bbsize[1], bbsize[2]);
                glutWireCube(1.0);
                glPopMatrix();
                glutSwapBuffers();
        }

        void keyboard(unsigned char key, int x, int y)
        {
                switch(key)
                {
                case '\033': exit(0); break;
                        //case '+': ball->closer(); break;
                        //case '-': ball->farther(); break;
                        //default:
                        //    ball->up_axis(key);
                }
        }
}

int main(int argc, char** argv)
{
        // GLUT INIT
        glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
        glutInitWindowSize(win_size_x, win_size_y);
        glutInit(&argc, argv);
        main_window = glutCreateWindow("OBJ Viewer");
        glutDisplayFunc(display);
        glutKeyboardFunc(keyboard);
        glutMotionFunc(mouse_motion);
        glutMouseFunc(mouse);
        //glutIdleFunc(idle);

        // GL INIT
        glClearColor(.8f, 0.9f, 1.0f, 0.f);
        glEnable(GL_DEPTH_TEST);

        // LOAD OBJ
        string fn;
        if(argc>1)
                fn = argv[1];
        else
                fn = "bun.conf";

        verts_from_conf(fn, 0.002);

        cout << "Loading " << fn << endl;
        if(fn == "") exit(0);

        write_obj("bunny.obj");
        //return 0;

        // Initialize Trackball

        ball = new QuatTrackBall(cen,2*rad,800,800);

        // Setup projection
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(53,1.0f,rad/100.0,rad*3.0);
        glMatrixMode(GL_MODELVIEW);

        // Pass control to GLUT
        glutMainLoop();

        return 0;
}