Subversion Repositories gelsvn

Rev

Rev 335 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
335 jab 1
// ----------------------------------------
2
// A simple Range Scan Viewer
3
//
4
// Controls:
5
// - left mouse down + mouse motion : rotate
6
// - Scroll button and +- buttons   : zoom
7
// - right mouse click              : centre trackball
8
// - esc                            : exits
9
// - x,y,z buttons                  : switch trackball up axis
10
// ----------------------------------------
11
 
12
#if (_MSC_VER >= 1200)
13
#pragma warning (disable: 4786)
14
#endif
15
 
16
#include <list>
17
#include <vector>
18
 
19
#include <assert.h>
20
#include <stdio.h>
21
#ifdef WIN32
22
#include <windows.h>
23
#include <io.h>
24
#endif
25
#include <string.h>
26
#include <stdlib.h>
27
 
28
#include <iostream>
29
#include <CGLA/Vec2i.h>
30
#include <CGLA/Vec2f.h>
31
 
32
#include <CGLA/Vec3f.h>
33
#include <CGLA/Mat4x4f.h>
34
#include "GLGraphics/gel_glut.h"
35
#include "GLGraphics/QuatTrackBall.h"
36
#include "Geometry/KDTree.h"
37
 
38
 
39
#include "ply.h"
40
 
41
#include <CGLA/statistics.h>
42
#include <CGLA/eigensolution.h>
43
 
44
using namespace std;
45
using namespace CGLA;
46
using namespace Geometry;
47
using namespace GLGraphics;
48
 
49
namespace
50
{
51
	int win_size_x = 800;
52
	int win_size_y = 800;
53
 
54
	QuatTrackBall* ball;
55
	int spin_timer = 20;
56
	void spin(int x);
57
 
58
	int main_window;
59
 
60
	Vec3f cen;
61
	Vec3f pmin;
62
	Vec3f bbsize;
63
	std::vector<CGLA::Vec3f> verts;
64
	std::vector<CGLA::Vec3f> norms;
65
	float rad;
66
 
67
	void verts_from_conf(std::string filename, float dist=0.002)
68
	{
69
		verts.clear();
70
		norms.clear();
71
 
72
		CGLA::Quatf qrot;
73
		CGLA::Vec3f tr;
74
		CGLA::Mat4x4f transform;
75
		CGLA::Mat4x4f Ntransform;
76
 
77
		char plyfile[50];
78
		char elemtag[50];
79
		FILE * pFile;
80
		//filename = "data/" + filename;
81
		pFile = fopen (filename.c_str(),"r");
82
		if (pFile==NULL)
83
		{
84
			cout << "file error " << filename << endl;
85
			return;
86
		}
87
 
88
		bool end=false;
89
 
90
		cen=Vec3f(0,0,0);
91
		pmin=Vec3f(1000,10000,1000);
92
		bbsize=Vec3f(-100,-100,-100);
93
 
94
		cout << "using file " << filename << endl;
95
 
96
		while(!end)
97
		{
98
			//bmesh bun045.ply -0.0520211 -0.000383981 -0.0109223 0.00548449 -0.294635 -0.0038555 0.955586
99
 
100
			//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]);
101
			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 );
102
			//int params = fscanf (pFile, "%s ", &elemtag);
103
			if (params>0)
104
			{
105
				if ( strcmp(elemtag, "bmesh")==0 )
106
				{
107
					//  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 );
108
					string splyfile = string(plyfile);
109
					cout << "found plyfile " << splyfile << endl;
110
 
111
					qrot = qrot.inverse();
112
					transform = CGLA::translation_Mat4x4f(tr) * qrot.get_Mat4x4f();
113
					Ntransform = transform;
114
					Ntransform = invert(Ntransform);
115
					Ntransform = transpose(Ntransform);
116
 
117
					PlyFile *ply;
118
					int nelems;
119
					int nprops;
120
					char **elist;
121
					int file_type;
122
					float version;
123
					int num_elems;
124
					//PlyProperty **plist;
125
					char *elem_name;
126
 
127
 
128
					ply = ply_open_for_reading(splyfile.c_str(), &nelems, &elist, &file_type, &version);
129
 
130
					/* print what we found out about the file */
131
					printf ("version %f\n", version);
132
					printf ("type %d\n", file_type);
133
 
134
					/* go through each kind of element that we learned is in the file */
135
					/* and read them */
136
 
596 jab 137
                    cout << "nelems: " << nelems << endl;
335 jab 138
					for (int i = 0; i < nelems; i++) 
139
					{
140
 
596 jab 141
                        cout << "." << flush;
335 jab 142
						/* get the description of the first element */
143
						elem_name = elist[i];
144
						//plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);
145
						ply_get_element_description (ply, elem_name, &num_elems, &nprops);
146
 
147
						/* print the name of the element, for debugging */
148
						printf ("element %s %d\n", elem_name, num_elems);
149
 
150
						/* if we're on vertex elements, read them in */
151
						if (equal_strings ("vertex", elem_name)) 
152
						{
596 jab 153
                            cout << "v" << flush;
335 jab 154
							typedef struct PlyVertex {
155
								float x,y,z;             /* the usual 3-space position of a vertex */
156
							} PlyVertex;
157
 
158
							PlyProperty vert_props[] = { /* list of property information for a vertex */
159
								{"x", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,x), 0, 0, 0, 0},
160
								{"y", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,y), 0, 0, 0, 0},
161
								{"z", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,z), 0, 0, 0, 0},
162
							};
163
 
164
							/* set up for getting vertex elements */
165
							ply_get_property (ply, elem_name, &vert_props[0]);
166
							ply_get_property (ply, elem_name, &vert_props[1]);
167
							ply_get_property (ply, elem_name, &vert_props[2]);
168
 
169
 
170
							/* grab all the vertex elements */
171
							for (int j = 0; j < num_elems; j++) 
172
							{
173
								PlyVertex * pv = (PlyVertex *) malloc (sizeof (PlyVertex));
174
 
175
								/* grab and element from the file */
176
								ply_get_element (ply, (void*)pv);
177
 
596 jab 178
								Vec3f v = 	Ntransform.mul_3D_point(Vec3f(pv->x, pv->y, pv->z));
335 jab 179
								verts.push_back(v);
180
 
181
								Vec3f n = Ntransform.mul_3D_vector(Vec3f(0,0,1));
182
								norms.push_back(n);
183
 
184
								cen += v;
185
								pmin = v_min(pmin,v);
186
								bbsize = v_max(bbsize,v);
187
							}
188
						}
189
					}
190
				}
191
			}
192
			else
193
			{
194
				end=true;
195
				fclose(pFile);
196
			}
197
		}
198
 
199
		if (dist>0)
200
		{
201
			Geometry::KDTree<CGLA::Vec3f,int>* tree = new Geometry::KDTree<CGLA::Vec3f,int>();
202
			for (unsigned int i=0; i<verts.size(); ++i)
203
				tree->insert(verts[i], i);
204
			tree->build();
205
 
206
			int skip=0;
207
			for (unsigned int i=0; i<verts.size(); ++i)
208
			{
209
				if (i % 100000 == 0)
210
					cerr << ".";
211
 
212
				vector<CGLA::Vec3f> neigbours;
213
				vector<int> neigbour_ids;
214
				int num = tree->in_sphere(verts[i], dist, neigbours, neigbour_ids);
215
 
216
				if (num > 5)
217
				{
218
					Mat3x3f A;
219
					Vec3f m = covariance(neigbours, A);
220
					Mat3x3f Q,L;
221
					int n = power_eigensolution(A, Q, L);
222
 
223
					int min_id;
224
					if ( L[0][0] < L[1][1])
225
					{
226
						if ( L[0][0] < L[2][2])
227
							min_id = 0;
228
						else
229
							min_id = 2;
230
					}
231
					else
232
					{
233
						if ( L[1][1] < L[2][2])
234
							min_id = 1;
235
						else
236
							min_id = 2;
237
					}
238
 
239
					Vec3f temp_n(Q[min_id][0], Q[min_id][1], Q[min_id][2]);
240
					temp_n.normalize();
241
					float sgn = sign(dot(temp_n, norms[i]));
242
					norms[i] = sgn*temp_n;
243
				}
244
				else
245
				{
246
					norms[i] = Vec3f(0,0,0);
247
					skip++;
248
				}
249
			}
250
 
251
			cout << skip << " of " << verts.size() << " with zero normal" << endl;;
252
		}
253
		cen /= (float)verts.size();
254
		bbsize =  bbsize-pmin;
255
		rad = 0.7f*bbsize.length();
256
 
257
		//for(unsigned int i=0; i<verts.size(); ++i )
258
		//  scale( verts[i], rad);
259
		//
260
		//pmin= Vec3f(0,0,0);
261
		//  //bbsize = Vec3f(cur_dim);
262
		//  bbsize = Vec3f(1,1,1);
263
		//  cen = 0.5f*bbsize;
264
	}
265
 
266
	void write_obj(string fn)
267
	{
268
		FILE* pFile = fopen (fn.c_str(),"w+");
269
		if (pFile==NULL)
270
		{
271
			cout << "file error " << fn << endl;
272
			return;
273
		}
274
 
596 jab 275
		fprintf( pFile, "# %lu vertices with normal\n", verts.size());
335 jab 276
		//fprintf( pFile, "# center : %d vertices with normal", verts.size());
277
 
278
		for(unsigned int i=0; i<verts.size(); ++i )
279
		  fprintf( pFile, "v %f %f %f\n", verts[i][0], verts[i][1], verts[i][2]);
280
		for(unsigned int i=0; i<norms.size(); ++i )
281
		  fprintf( pFile, "vn %f %f %f\n", norms[i][0], norms[i][1], norms[i][2]);
282
 
283
		fclose(pFile);
284
 
285
	}
286
 
287
 
288
	void mouse_motion(int x, int y)
289
	{
290
		ball->roll_ball(Vec2i(x,y));
291
	}
292
 
293
	void mouse(int btn, int state, int x, int y)
294
	{
295
		if(state == GLUT_DOWN) 
296
		{
297
			if(btn == GLUT_LEFT_BUTTON) 
298
				ball->grab_ball(ROTATE_ACTION, Vec2i(x,y));
299
			else if(btn == GLUT_MIDDLE_BUTTON) 
300
				ball->grab_ball(ZOOM_ACTION, Vec2i(x, y));
301
			else if(btn == GLUT_RIGHT_BUTTON) 
302
				ball->grab_ball(PAN_ACTION, Vec2i(x, y));
303
		}
304
		else if(state == GLUT_UP)
305
			ball->release_ball();	
306
	}
307
 
308
	void spin(int x)
309
	{
310
		ball->do_spin();
311
		glutTimerFunc(spin_timer, spin, 0);  
312
		glutPostRedisplay();
313
	}
314
 
315
 
316
	void draw()
317
	{
318
		glBegin(GL_POINTS);
319
		for(unsigned int i=0; i<verts.size(); ++i )
320
		{
321
			glVertex3fv( verts[i].get());
322
		}
323
		glEnd();
324
	}
325
 
326
	void draw_normals(float l=0.001)
327
	{
328
		glBegin(GL_LINES);
329
		for(unsigned int i=0; i<verts.size(); ++i )
330
		{
331
			Vec3f p1 = verts[i] + l*norms[i];
332
			glVertex3fv( verts[i].get());
333
			glVertex3fv( p1.get());
334
		}
335
		glEnd();
336
	}
337
 
338
	void display()
339
	{
340
		static bool washere = false;
341
		static unsigned int lp, ln;
342
		if(!washere)
343
		{
344
			cout << "Creating display list" << endl;
345
			lp = glGenLists(1);
346
			glNewList(lp, GL_COMPILE);
347
			draw();
348
			glEndList();
349
			cout << "Creating display list" << endl;
350
			ln = glGenLists(1);
351
			glNewList(ln, GL_COMPILE);
352
			draw_normals();
353
			glEndList();
354
 
355
			washere = true;
356
			glutTimerFunc(spin_timer, spin, 0);	
357
		}
358
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
359
		glLoadIdentity();
360
		ball->set_gl_modelview();
361
		glColor3f(0.9,0.1,0);
362
		glCallList(lp);
363
		glColor3f(0.0,0.9,0.5);
364
		glCallList(ln);
365
 
366
		glPushMatrix();
367
		glColor3f(0.7,0.9,0.3);
368
 
369
		glTranslatef(cen[0], cen[1], cen[2]);
370
		glScalef(bbsize[0], bbsize[1], bbsize[2]);
371
		glutWireCube(1.0);
372
		glPopMatrix();
373
		glutSwapBuffers();
374
	}
375
 
376
	void keyboard(unsigned char key, int x, int y)
377
	{
378
		switch(key)
379
		{
380
		case '\033': exit(0); break;
381
			//case '+': ball->closer(); break;
382
			//case '-': ball->farther(); break;
383
			//default:
384
			//    ball->up_axis(key);
385
		}
386
	}
387
}
388
 
389
int main(int argc, char** argv)
390
{
391
	// GLUT INIT
392
	glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
393
	glutInitWindowSize(win_size_x, win_size_y);
394
	glutInit(&argc, argv);
395
	main_window = glutCreateWindow("OBJ Viewer");
396
	glutDisplayFunc(display);
397
	glutKeyboardFunc(keyboard);
398
	glutMotionFunc(mouse_motion);
399
	glutMouseFunc(mouse);
400
	//glutIdleFunc(idle);
401
 
402
	// GL INIT
403
	glClearColor(.8f, 0.9f, 1.0f, 0.f);
404
	glEnable(GL_DEPTH_TEST);
405
 
406
	// LOAD OBJ
407
	string fn;
408
	if(argc>1)
409
		fn = argv[1];
410
	else
596 jab 411
		fn = "/Users/jab/Studio/3DModels/OriginalBunnyScans/bunny/data/bun.conf";
335 jab 412
 
413
	verts_from_conf(fn, 0.002);
414
 
415
	cout << "Loading " << fn << endl;
416
	if(fn == "") exit(0);
417
 
596 jab 418
	write_obj("/Users/jab/Studio/3DModels/OriginalBunnyScans/bunny/data/bunny.obj");
335 jab 419
	//return 0;
420
 
421
	// Initialize Trackball
422
 
423
	ball = new QuatTrackBall(cen,2*rad,800,800);
424
 
425
	// Setup projection
426
	glMatrixMode(GL_PROJECTION);
427
	glLoadIdentity();
428
	gluPerspective(53,1.0f,rad/100.0,rad*3.0);
429
	glMatrixMode(GL_MODELVIEW);
430
 
431
	// Pass control to GLUT
432
	glutMainLoop();
433
 
434
	return 0;
435
}