Subversion Repositories gelsvn

Rev

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

Rev Author Line No. Line
386 jab 1
/*
2
 *  MeshEdit is a small application which allows you to load and edit a mesh.
3
 *  The mesh will be stored in GEL's half edge based Manifold data structure.
4
 *  A number of editing operations are supported. Most of these are accessible from the 
5
 *  console that pops up when you hit 'esc'.
6
 *
7
 *  Created by J. Andreas Bærentzen on 15/08/08.
8
 *  Copyright 2008 __MyCompanyName__. All rights reserved.
9
 *
10
 */
11
#include <iostream>
12
#include <CGLA/eigensolution.h>
13
#include <CGLA/Vec2d.h>
14
#include <CGLA/Vec3d.h>
15
#include <CGLA/Mat3x3d.h>
16
#include <CGLA/Mat2x2d.h>
17
#include <CGLA/Mat2x3d.h>
18
 
19
#include <LinAlg/Matrix.h>
20
#include <LinAlg/Vector.h>
21
#include <LinAlg/LapackFunc.h>
22
 
23
#include <Util/Timer.h>
24
#include <Util/ArgExtracter.h>
25
 
26
#include <GL/glew.h>
27
#include <GLGraphics/gel_glut.h>
28
#include <GLGraphics/draw.h>
29
#include <GLGraphics/glsl_shader.h>
30
#include <GLGraphics/GLViewController.h>
31
 
32
#include <HMesh/Manifold.h>
33
#include <HMesh/VertexCirculator.h>
34
#include <HMesh/FaceCirculator.h>
35
#include <HMesh/build_manifold.h>
36
#include <HMesh/mesh_optimization.h>
37
#include <HMesh/triangulate.h>
38
#include <HMesh/load.h>
387 jab 39
#include <HMesh/quadric_simplify.h>
40
#include <HMesh/smooth.h>
386 jab 41
#include <HMesh/x3d_save.h>
388 jab 42
#include <HMesh/obj_save.h>
387 jab 43
#include <HMesh/mesh_optimization.h>
388 jab 44
#include <HMesh/triangulate.h>
45
#include <HMesh/close_holes.h>
46
#include <HMesh/caps_and_needles.h>
47
#include <HMesh/refine_edges.h>
48
#include <HMesh/subdivision.h>
386 jab 49
 
50
#include <GLConsole/GLConsole.h>
51
 
52
#include "harmonics.h"
53
#include "wireframe.h"
54
 
55
 
56
// Single global instance so glut can get access
57
GLConsole theConsole;
58
 
59
////////////////////////////////////////////////////////////////////////////////
60
char* ConsoleHelp(std::vector<std::string> &args)
61
{
62
    theConsole.Printf("");
63
    theConsole.Printf("----------------- HELP -----------------");
64
    theConsole.Printf("Press ~ key to open and close console");
65
    theConsole.Printf("Press TAB to see the available commands and functions");
66
    theConsole.Printf("Functions are shown in green and variables in yellow");
67
    theConsole.Printf("Setting a value: [command] = value");
68
    theConsole.Printf("Getting a value: [command]");
69
    theConsole.Printf("Functions: [function] [arg1] [arg2] ...");
70
    theConsole.Printf("Entering just the function name will give a description.");
71
    theConsole.Printf("History: Up and Down arrow keys move through history.");
72
    theConsole.Printf("Tab Completion: TAB does tab completion and makes suggestions.");
73
    theConsole.Printf("----------------- HELP -----------------");
74
    theConsole.Printf("");
75
    return "";
76
}
77
 
78
using namespace std;
79
using namespace HMesh;
80
using namespace Geometry;
81
using namespace GLGraphics;
82
using namespace CGLA;
83
using namespace Util;
84
using namespace LinAlg;
85
 
86
 
87
 
88
namespace 
89
{
90
	GLViewController* view_ctrl;
91
	int WINX=800, WINY=800;
388 jab 92
	string file;
386 jab 93
 
94
	Manifold mani;	
95
	bool create_display_list = true;
96
}
97
 
388 jab 98
char* console_save(std::vector<std::string> &args)
99
{
100
	string& file_name = args[0];
101
	if(args.size() == 1)
102
	{
103
		if(file_name.substr(file_name.length()-4,file_name.length())==".obj")
104
		{
105
			obj_save(file_name, mani);
106
			return "";
107
		}
108
		else if(file_name.substr(file_name.length()-4,file_name.length())==".x3d")
109
		{
110
			x3d_save(file_name, mani);
111
			return "";
112
		}
113
		return "unknown format";
114
	}
115
	return "usage: save <name.x3d|name.obj> ";
116
}
386 jab 117
 
388 jab 118
char* console_refine_edges(std::vector<std::string> &args)
119
{
120
	float thresh = 0.5;
121
	if(args.size()>0)
122
	{
123
		istringstream a0(args[0]);
124
		a0 >> thresh;
125
	}
126
	float avg_length = average_edge_length(mani);
127
	refine_edges(mani, thresh * avg_length);
128
	return "";
129
 
130
}
131
 
132
char* console_refine_faces(std::vector<std::string> &args)
133
{
134
	safe_triangulate(mani);
135
	return "";
136
 
137
}
138
 
139
char* console_cc_subdivide(std::vector<std::string> &args)
140
{
141
	cc_split(mani,mani);
142
	return "";
143
}
144
 
145
 
146
 
387 jab 147
char* console_minimize_curvature(std::vector<std::string> &args)
148
{
149
	bool anneal=false;
150
	if(args.size()>0)
151
	{
152
		istringstream a0(args[0]);
153
		a0 >> anneal;
154
	}
386 jab 155
 
387 jab 156
	minimize_curvature(mani, anneal);
388 jab 157
	create_display_list = true;
387 jab 158
	return "";
159
}
160
 
161
char* console_minimize_dihedral(std::vector<std::string> &args)
162
{
163
	int iter = 1000;
164
	if(args.size()>0)
165
	{
166
		istringstream a0(args[0]);
167
		a0 >> iter;
168
	}
169
 
170
	bool anneal = false;
171
	if(args.size()>1)
172
	{
173
		istringstream a0(args[0]);
174
		a0 >> anneal;
175
	}
176
 
177
	bool use_alpha = true;
388 jab 178
	if(args.size()>2)
387 jab 179
	{
180
		istringstream a0(args[0]);
181
		a0 >> use_alpha;
182
	}
183
 
184
	float gamma = 4.0;
185
	if(args.size()>3)
186
	{
187
		istringstream a0(args[0]);
188
		a0 >> gamma;
189
	}
190
 
191
 
192
	minimize_dihedral_angle(mani, iter, anneal, use_alpha, gamma);
193
	return "";
194
}
195
 
388 jab 196
char* console_maximize_min_angle(std::vector<std::string> &args)
197
{
198
	float thresh=0.0;
199
	if(args.size()>0)
200
	{
201
		istringstream a0(args[0]);
202
		a0 >> thresh;
203
	}
204
	bool anneal=false;
205
	if(args.size()>1)
206
	{
207
		istringstream a0(args[0]);
208
		a0 >> anneal;
209
	}
210
	maximize_min_angle(mani,thresh,anneal);
211
	return "";
212
}
213
 
214
 
387 jab 215
char* console_optimize_valency(std::vector<std::string> &args)
216
{
217
	bool anneal=false;
218
	if(args.size()>0)
219
	{
220
		istringstream a0(args[0]);
221
		a0 >> anneal;
222
	}
223
	optimize_valency(mani, anneal);
224
	return "";
225
}
226
 
388 jab 227
char* console_analyze(std::vector<std::string> &args)
228
{
229
	analyze_mesh(mani);
230
	return "";
231
}
232
 
233
 
386 jab 234
char* console_partial_reconstruct(std::vector<std::string> &args)
235
{
236
	int E0,E1;
237
	float scale;
238
	istringstream a0(args[0]);
239
	a0 >> E0;
240
	istringstream a1(args[1]);
241
	a1 >> E1;
242
	istringstream a2(args[2]);
243
	a2 >> scale;
244
	partial_reconstruct(mani, E0,E1,scale);
245
	return "";
246
}
247
 
248
char* console_reset_shape(std::vector<std::string> &args)
249
{
250
	reset_shape(mani);
251
	return "";
252
}
253
 
254
void reshape(int W, int H)
255
{
256
	view_ctrl->reshape(W,H);
257
}
258
 
388 jab 259
char* console_close_holes(std::vector<std::string> &args)
260
{
261
	close_holes(mani);
262
	return "";
263
}
386 jab 264
 
388 jab 265
char* console_reload(std::vector<std::string> &args)
266
{
267
	if(args.size()>0)
268
		file = args[0];
269
	mani.clear();
270
	load(file, mani); 
271
	Vec3f c(0,0,0);
272
	float r = 5;
273
	mani.get_bsphere(c,r);
274
	delete view_ctrl;
275
	view_ctrl = new GLViewController(WINX,WINY, c,r*2);
276
	return "";
277
}
278
 
279
 
387 jab 280
char* console_simplify(std::vector<std::string> &args)
281
{
282
	float keep_fraction;
283
	if(args.size()==0) return "you must specify fraction of vertices to keep";
284
	istringstream a0(args[0]);
285
	a0 >> keep_fraction;
386 jab 286
 
387 jab 287
	Vec3f p0, p7;
288
	mani.get_bbox(p0, p7);
289
	Vec3f d = p7-p0;
290
	float s = 1.0/d.max_coord();
291
	Vec3f pcentre = (p7+p0)/2.0;
292
	for(VertexIter vi = mani.vertices_begin(); vi != mani.vertices_end(); ++vi)
293
		vi->pos = (vi->pos - pcentre) * s;
294
	quadric_simplify(mani,keep_fraction,0.0001f,true);
295
	for(VertexIter vi = mani.vertices_begin(); vi != mani.vertices_end(); ++vi)
296
		vi->pos = vi->pos*d.max_coord() + pcentre;
297
	return "";
298
}
299
 
300
char* console_laplacian_smooth(std::vector<std::string> &args)
301
{
302
	float t=1.0;
303
	if(args.size()>0)
304
	{
305
		istringstream a0(args[0]);
306
		a0 >> t;
307
	}
308
	/// Simple laplacian smoothing with an optional weight.
309
	laplacian_smooth(mani, t);
310
	return "";
311
}
312
 
313
char* console_taubin_smooth(std::vector<std::string> &args)
314
{
315
	int iter=1;
316
	if(args.size()>0)
317
	{
318
		istringstream a0(args[0]);
319
		a0 >> iter;
320
	}
321
 
322
	/// Taubin smoothing is similar to laplacian smoothing but reduces shrinkage
323
	taubin_smooth(mani,  iter);
324
	return "";
325
}
326
 
327
char* console_fvm_smooth(std::vector<std::string> &args)
328
{	
329
	int iter=1;
330
	if(args.size()>0)
331
	{
332
		istringstream a0(args[0]);
333
		a0 >> iter;
334
	}
335
	/** Fuzzy vector median smoothing is effective when it comes to
336
	 preserving sharp edges. */
337
	fvm_smooth(mani,  iter);
338
	return "";
339
 
340
}
341
 
388 jab 342
char* console_triangulate(std::vector<std::string> &args)
343
{	
344
	shortest_edge_triangulate(mani);
345
	return "";
346
}
347
 
348
 
349
char* console_remove_caps(std::vector<std::string> &args)
350
{	
351
	remove_caps_from_trimesh(mani, static_cast<float>(M_PI) * 0.85f);
352
	return "";
353
}
354
 
355
char* console_remove_needles(std::vector<std::string> &args)
356
{	
357
	float thresh = 0.1;
358
	if(args.size()>0)
359
	{
360
		istringstream a0(args[0]);
361
		a0 >> thresh;
362
	}
363
	float avg_length = average_edge_length(mani);
364
	remove_needles_from_trimesh(mani, thresh * avg_length);
365
	return "";
366
}
367
 
386 jab 368
void display() 
369
{
370
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
371
 
388 jab 372
	static CVar<int> display_wireframe("display.wireframe",0);
373
	static CVar<int> display_eigenmodes("display.eigenmodes",0);
374
	static CVar<int> display_flat("display.flatshading",0);
386 jab 375
 
376
	glPushMatrix();
377
 
378
	view_ctrl->set_gl_modelview();
379
 
380
	if(create_display_list)
381
	{
382
		create_display_list = false;
383
 
384
		glNewList(1,GL_COMPILE);
388 jab 385
		if(display_wireframe)
386 jab 386
			{
387
				enable_wireframe();
388
				draw(mani);
388 jab 389
				glUseProgram(0);	
386 jab 390
			}
388 jab 391
		else if(display_eigenmodes)
386 jab 392
			draw_eigenvalues(mani);
388 jab 393
		else 
394
			draw(mani,!display_flat);
386 jab 395
		glEndList();
396
	}
397
	glCallList(1);
398
 
399
	glPopMatrix();
400
 
401
	glUseProgram(0);
402
	theConsole.RenderConsole();
403
 
404
	glutSwapBuffers();
405
}
406
 
407
void animate() 
408
{	
409
	usleep( (int)1e4 );
410
	view_ctrl->try_spin();
411
	glutPostRedisplay();
412
}
413
 
414
 
415
void mouse(int button, int state, int x, int y) 
416
{
417
	Vec2i pos(x,y);
418
	if (state==GLUT_DOWN) 
419
	{
420
		if (button==GLUT_LEFT_BUTTON) 
421
			view_ctrl->grab_ball(ROTATE_ACTION,pos);
422
		else if (button==GLUT_MIDDLE_BUTTON) 
423
			view_ctrl->grab_ball(ZOOM_ACTION,pos);
424
		else if (button==GLUT_RIGHT_BUTTON) 
425
			view_ctrl->grab_ball(PAN_ACTION,pos);
426
	}
427
	else if (state==GLUT_UP)
428
		view_ctrl->release_ball();
429
}
430
 
431
void motion(int x, int y) {
432
	Vec2i pos(x,y);
433
	view_ctrl->roll_ball(Vec2i(x,y));
434
}
435
 
436
void keyboard_spec(int key, int x, int y)
437
{
438
   int mod = glutGetModifiers();
388 jab 439
   if( theConsole.isOpen() ) {
386 jab 440
        // If shift held, scroll the console
441
        if( mod == GLUT_ACTIVE_SHIFT ) {
442
            switch (key){
443
                case GLUT_KEY_UP:
444
                    theConsole.ScrollDownLine();
445
                    break;
446
                case GLUT_KEY_DOWN: 
447
                    theConsole.ScrollUpLine();
448
                    break;
449
            }
450
        } else {
451
            theConsole.StandardKeyBindings( key );
452
        }
453
    }
454
}
455
 
456
template<typename T>
457
T& get_CVar_ref(const std::string& s)
458
{
459
	return *reinterpret_cast<T*> (GetCVarData(s));
460
}
461
 
462
void keyboard(unsigned char key, int x, int y) 
463
{	
464
	if(theConsole.isOpen())
388 jab 465
		{
386 jab 466
		switch(key) {
467
			case '\033': 
468
				theConsole.ToggleConsole();
469
			default:      
470
				//send keystroke to console
471
				if( theConsole.isOpen() ){
472
					theConsole.EnterCommandCharacter(key);
473
				}
474
				break;
388 jab 475
		}
476
		if(key == 13)	create_display_list = true;
477
 
386 jab 478
		}	
479
	else {
388 jab 480
		int& display_eigenvalue = get_CVar_ref<int>("display.harmonics.eigenvalue");
386 jab 481
		int& display_wireframe = get_CVar_ref<int>("display.wireframe");
388 jab 482
		int& display_diffuse = get_CVar_ref<int>("display.harmonics.diffuse");
483
		int& display_highlight = get_CVar_ref<int>("display.harmonics.highlight");
484
		int& display_flat = get_CVar_ref<int>("display.flatshading");
386 jab 485
 
486
		switch(key) {
487
			case 'q': exit(0);
488
			case '\033':
489
				theConsole.ToggleConsole();
490
				break;
388 jab 491
			case 'f': display_flat = !display_flat;
386 jab 492
			case '+': 
493
				display_eigenvalue = min(display_eigenvalue+1, MAX_E); 
494
				break;
495
			case '-': 
496
				display_eigenvalue = max(display_eigenvalue-1, 0); 
497
				break;
498
			case '1': E = 1; reconstruct(mani,E); 
499
				break;
500
			case '>': if(E < MAX_E) partial_reconstruct(mani,E,++E); 
501
				break;
502
			case '<': E = max(E-1, 0); reconstruct(mani,E); 
503
				break;
504
			case 'd':	
505
				display_diffuse = !display_diffuse; 
506
				break;
507
			case 'h':
508
				display_highlight = !display_highlight;
509
				break;			
510
			case 'w':
511
				display_wireframe = !display_wireframe;
512
				break;
513
		}
388 jab 514
		create_display_list = true;
515
 
386 jab 516
	}
517
}
518
 
519
void init_glut(int argc, char** argv)
520
{
521
	glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
522
	glutInitWindowSize(WINX, WINY);
523
	glutInit(&argc, argv);
524
	glutCreateWindow("Shape Harmonics");
525
	glutDisplayFunc(display);
526
	glutKeyboardFunc(keyboard);
527
	glutSpecialFunc(keyboard_spec);
528
	glutReshapeFunc(reshape);
529
	glutMouseFunc(mouse);
530
	glutMotionFunc(motion);
531
	glutIdleFunc(animate);
532
}
533
 
534
void init_gl()
535
{
536
	glewInit();
537
	glEnable(GL_LIGHTING);
538
	glEnable(GL_LIGHT0);
388 jab 539
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
386 jab 540
	Vec3f c(0,0,0);
541
	float r = 5;
542
	mani.get_bsphere(c,r);
543
	view_ctrl = new GLViewController(WINX,WINY, c,r*2);
544
 
545
	initialize_wireframe_shaders();
546
 
547
 
548
	// Set the value of a uniform
549
	//glUniform2f(glGetUniformLocation(prog_P0,"WIN_SCALE"), win_size_x/2.0, win_size_y/2.0);
550
 
551
	glMatrixMode(GL_MODELVIEW);
552
	glLoadIdentity();
553
	glClearColor(0.50f, 0.50f, 0.50f, 0.f);
554
	glColor4f(1.0f, 1.0f, 1.0f, 0.f);
555
	glEnable(GL_DEPTH_TEST);
556
 
557
	static CVar<ConsoleFunc> help( "help", ConsoleHelp );
388 jab 558
	static CVar<ConsoleFunc> rs("harmonics_reset_shape", console_reset_shape);
559
	static CVar<ConsoleFunc> ha("harmonics_analyze", console_analyze);
560
	static CVar<ConsoleFunc> pr("harmonics_partial_reconstruct", console_partial_reconstruct);
387 jab 561
	static CVar<ConsoleFunc> simpl("simplify", console_simplify);
562
	static CVar<ConsoleFunc> lsmooth("laplacian_smooth", console_laplacian_smooth);
563
	static CVar<ConsoleFunc> tsmooth("taubin_smooth", console_taubin_smooth);
564
	static CVar<ConsoleFunc> fsmooth("fvm_smooth", console_fvm_smooth);
386 jab 565
 
387 jab 566
	static CVar<ConsoleFunc> opt_val("optimize_valency", console_optimize_valency);
567
	static CVar<ConsoleFunc> min_dih("minimize_dihedral", console_minimize_dihedral);
568
	static CVar<ConsoleFunc> min_curv("minimize_curvature", console_minimize_curvature);
388 jab 569
	static CVar<ConsoleFunc> max_min_angle("maximize_min_angle", console_maximize_min_angle);
570
	static CVar<ConsoleFunc> close_holes_fun("close_holes", console_close_holes);
571
	static CVar<ConsoleFunc> reload_fun("reload", console_reload);
572
 
573
	static CVar<ConsoleFunc> rem_caps_fun("remove_caps", console_remove_caps);
574
	static CVar<ConsoleFunc> rem_needles_fun("remove_needles", console_remove_needles);
575
	static CVar<ConsoleFunc> triangulate_fun("triangulate", console_triangulate);
576
	static CVar<ConsoleFunc> refine_fun("refine_edges", console_refine_edges);
577
	static CVar<ConsoleFunc> refine_face_fun("refine_faces", console_refine_faces);
578
	static CVar<ConsoleFunc> subd_fun("refine_catmull_clark", console_cc_subdivide);
579
	static CVar<ConsoleFunc> save_fun("save", console_save);
387 jab 580
 
581
 
386 jab 582
}
583
 
584
int main(int argc, char** argv)
585
{
586
	ArgExtracter ae(argc, argv);
587
	ae.extract("-E", E);
588
    if(argc>1)
589
	{		
388 jab 590
		 file = ae.get_last_arg();
386 jab 591
		load(file, mani);
592
	}
593
 
594
 
595
	init_glut(argc,argv);
596
	init_gl();
388 jab 597
	init_harmonics();
386 jab 598
 
599
	glutMainLoop();
600
}
601
 
602