Commit f8a38243e17e73c5982ddb80a3ad5a2451d26cdb

Authored by David Mayerich
1 parent 6bf618a1

made changes to support vec3

Showing 2 changed files with 203 additions and 24 deletions   Show diff stats
CMakeLists.txt
... ... @@ -13,6 +13,9 @@ find_package(STIM REQUIRED)
13 13 find_package(OpenGL REQUIRED)
14 14 find_package(GLUT REQUIRED)
15 15  
  16 +#find BOOST
  17 +find_package(Boost REQUIRED)
  18 +
16 19 #find the pthreads package
17 20 find_package(Threads)
18 21  
... ... @@ -20,6 +23,7 @@ include_directories(
20 23 ${STIM_INCLUDE_DIRS}
21 24 ${GLUT_INCLUDE_DIR}
22 25 ${OpenGL_INCLUDE_DIRS}
  26 + ${Boost_INCLUDE_DIR}
23 27 )
24 28  
25 29 #Assign source files to the appropriate variables
... ...
main.cpp
... ... @@ -4,16 +4,18 @@
4 4  
5 5 #include <stim/visualization/camera.h>
6 6 #include <stim/parser/arguments.h>
7   -#include <stim/visualization/sph_harmonics.h>
  7 +#include <stim/visualization/obj.h>
  8 +#include <stim/visualization/gl_spharmonics.h>
8 9  
9 10 #define theta_scale 0.01
10 11 #define phi_scale 0.01
  12 +#define zoom_scale 0.1
11 13  
12 14 //create a global camera that will specify the viewport
13 15 stim::camera cam;
14 16 int mx, my; //mouse coordinates in the window space
15 17  
16   -stim::sph_harmonics S;
  18 +stim::gl_spharmonics<double> S;
17 19  
18 20 float d = 1.5; //initial distance between the camera and the sphere
19 21  
... ... @@ -21,9 +23,7 @@ bool rotate_zoom = true; //sets the current camera mode (rotation = true, zoom =
21 23  
22 24 stim::arglist args; //class for processing command line arguments
23 25  
24   -#ifdef _WIN32
25   - args.set_ansi(false);
26   -#endif
  26 +bool zaxis = false; //render the z-axis (set via a command line flag)
27 27  
28 28 bool init(){
29 29  
... ... @@ -36,16 +36,6 @@ bool init(){
36 36 cam.setFOV(40);
37 37  
38 38 //initialize the texture map stuff
39   -
40   - srand(time(NULL));
41   - unsigned int T = 40;
42   - double c;
43   - for(unsigned int t = 0; t < T; t++){
44   -
45   - c = (double)rand() / RAND_MAX - 0.5;
46   - S.push(c);
47   - }
48   -
49 39 S.glInit(256);
50 40  
51 41 return true;
... ... @@ -67,9 +57,9 @@ void display(){
67 57 glLoadIdentity(); //set it to the identity matrix
68 58  
69 59 //get the camera parameters
70   - stim::vec<float, 3> p = cam.getPosition();
71   - stim::vec<float, 3> u = cam.getUp();
72   - stim::vec<float, 3> d = cam.getDirection();
  60 + stim::vec3<float> p = cam.getPosition();
  61 + stim::vec3<float> u = cam.getUp();
  62 + stim::vec3<float> d = cam.getDirection();
73 63  
74 64 //specify the camera parameters to OpenGL
75 65 gluLookAt(p[0], p[1], p[2], d[0], d[1], d[2], u[0], u[1], u[2]);
... ... @@ -77,6 +67,18 @@ void display(){
77 67 //draw the sphere
78 68 S.glRender();
79 69  
  70 + //glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
  71 +
  72 + //draw the z-axis if requested
  73 + if(zaxis){
  74 + glDisable(GL_TEXTURE_2D);
  75 + glColor3f(0.0f, 1.0f, 0.0f);
  76 + glBegin(GL_LINES);
  77 + glVertex3f(0.0, 0.0, 0.0);
  78 + glVertex3f(0.0, 0.0, 100.0);
  79 + glEnd();
  80 + }
  81 +
80 82 //flush commands on the GPU
81 83 glutSwapBuffers();
82 84 }
... ... @@ -86,7 +88,7 @@ void mouse_press(int button, int state, int x, int y){
86 88 //set the camera motion mode based on the mouse button pressed
87 89 if(button == GLUT_LEFT_BUTTON)
88 90 rotate_zoom = true;
89   - else if(button == GLUT_MIDDLE_BUTTON)
  91 + else if(button == GLUT_RIGHT_BUTTON)
90 92 rotate_zoom = false;
91 93  
92 94 //if the mouse is pressed
... ... @@ -108,7 +110,7 @@ void mouse_drag(int x, int y){
108 110 }
109 111 //otherwize zoom
110 112 else{
111   - cam.Push(my - y);
  113 + cam.Push(zoom_scale*(my - y));
112 114 }
113 115  
114 116 //update the mouse position
... ... @@ -120,20 +122,189 @@ void mouse_drag(int x, int y){
120 122 void process_arguments(int argc, char* argv[]){
121 123  
122 124 args.add("help", "prints this help");
  125 + args.add("rand", "generates a random set of SH coefficients", "", "[N min max]");
  126 + args.add("sparse", "generates a function based on a set of sparse basis functions", "", "[l0 m0 c0 l1 m1 c1 l2 m2 c2 ...]");
  127 + args.add("basis", "displays the specified SH basis function", "", "n, or [l m]");
  128 + args.add("obj", "approximates a geometric object given as a Wavefront OBJ file", "", "filename");
  129 + args.add("out", "filename for outputting spherical harmonics coefficients", "", "filename");
  130 + args.add("zaxis", "render the z-axis as a green line");
123 131  
124 132 //process the command line arguments
125 133 args.parse(argc, argv);
126 134  
  135 + //set the z-axis flag
  136 + if(args["zaxis"].is_set())
  137 + zaxis = true;
  138 +
  139 + //if arguments are specified, push them as coefficients
  140 + if(args.nargs() > 0){
  141 + //push all of the arguments to the spherical harmonics class as coefficients
  142 + for(unsigned int a = 0; a < args.nargs(); a++)
  143 + S.push(atof(args.arg(a).c_str()));
  144 + }
  145 +
  146 + //if the user wants to use a random set of SH coefficients
  147 + else if(args["rand"].is_set()){
  148 +
  149 + //return an error if the user specifies both fixed and random coefficients
  150 + if(args.nargs() != 0){
  151 + std::cout<<"Error: both fixed and random coefficients are specified"<<std::endl;
  152 + exit(1);
  153 + }
  154 +
  155 + //seed the random number generator
  156 + srand(time(NULL));
  157 +
  158 + unsigned int N = args["rand"].as_int(0); //get the number of random coefficients
  159 + double Cmin = args["rand"].as_float(1); //get the minimum and maximum coefficient values
  160 + double Cmax = args["rand"].as_float(2);
  161 +
  162 + //generate the coefficients
  163 + for(unsigned int c = 0; c < N; c++){
  164 +
  165 + double norm = (double) rand() / RAND_MAX; //calculate a random number in the range [0, 1]
  166 + double scaled = norm * (Cmax - Cmin) + Cmin; //scale the random number to [Cmin, Cmax]
  167 + S.push(scaled); //push the value as a coefficient
  168 + }
  169 + }
  170 + else if(args["sparse"].is_set()){
  171 +
  172 + //calculate the number of sparse coefficients
  173 + unsigned int nC = args["sparse"].nargs() / 3;
  174 +
  175 + std::vector<unsigned int> C; //vector of 1D coefficients
  176 + unsigned int Cmax = 0; //maximum coefficient provided
  177 +
  178 + std::vector<double> V; //vector of 1D coefficient values
  179 +
  180 + unsigned int c;
  181 + int l, m;
  182 + double v;
  183 + //for each provided coefficient
  184 + for(unsigned int i = 0; i < nC; i++){
  185 +
  186 + //load data for a single coefficient from the command line
  187 + l = args["sparse"].as_int( i * 3 + 0 );
  188 + m = args["sparse"].as_int( i * 3 + 1 );
  189 + v = args["sparse"].as_float( i * 3 + 2 );
  190 +
  191 + //calculate the 1D coefficient
  192 + c = pow(l + 1, 2) - (l - m) - 1;
  193 +
  194 + //update the maximum coefficient index
  195 + if(c > Cmax) Cmax = c;
127 196  
128   - //push all of the arguments to the spherical harmonics class as coefficients
129   - for(unsigned int a = 0; a < args.nargs(); a++)
130   - S.push(atof(args.arg(a).c_str()));
  197 + //insert the coefficient and value into vectors
  198 + C.push_back(c);
  199 + V.push_back(v);
  200 + }
  201 +
  202 + //set the size of the SH coefficient array
  203 + S.resize(Cmax + 1);
  204 +
  205 + //insert each coefficient
  206 + for(unsigned int i = 0; i < nC; i++){
  207 + S.setc(C[i], V[i]);
  208 + }
  209 +
  210 + }
  211 + else if(args["obj"].is_set()){
  212 +
  213 + std::string filename = args["obj"].as_string(0);
  214 + unsigned int l = args["obj"].as_int(1);
  215 +
  216 + //create an obj object
  217 + stim::obj<double> object(filename);
  218 +
  219 + //get the centroid of the object
  220 + stim::vec<double> c = object.centroid();
  221 +
  222 + //get the number of vertices in the model
  223 + unsigned int nV = object.numV();
  224 +
  225 + //for each vertex in the model, create an MC sample
  226 + std::vector< stim::vec<double> > spherical;
  227 + stim::vec<float> sample;
  228 + stim::vec<float> centered;
  229 + for(unsigned int i = 0; i < nV; i++){
  230 +
  231 + sample = object.getV(i); //get a vertex in cartesian coordinates
  232 + centered = sample - c;
  233 + spherical.push_back(centered.cart2sph());
  234 + }
  235 +
  236 + //generate the spherical PDF
  237 + stim::spharmonics<double> P;
  238 + P.pdf(spherical, l, l);
  239 +
  240 + //begin Monte-Carlo sampling, using the model vertices as samples
  241 + S.mcBegin(l, l);
  242 + double theta, phi, fx, px;
  243 + for(unsigned int i = 0; i < nV; i++){
  244 + theta = spherical[i][1];
  245 + phi = spherical[i][2];
  246 + fx = spherical[i][0];
  247 + px = P(theta, phi);
  248 + S.mcSample(theta, phi, fx / px);
  249 + }
  250 + S.mcEnd();
  251 + }
  252 +
  253 + //if the user specifies an SH basis function
  254 + else if(args["basis"].is_set()){
  255 +
  256 + unsigned int n;
  257 +
  258 + //if the user specifies one index for the basis function
  259 + if(args["basis"].nargs() == 1)
  260 + n = args["basis"].as_int(0);
  261 + else if(args["basis"].nargs() == 2){
  262 + int l = args["basis"].as_int(0); //2D indexing (l, m)
  263 + int m = args["basis"].as_int(1);
  264 +
  265 + n = pow(l+1, 2) - (l - m) - 1; //calculate the 1D index
  266 + }
  267 +
  268 + //add zeros for the first (n-1) coefficients
  269 + for(unsigned int c = 0; c < n; c++)
  270 + S.push(0);
  271 +
  272 + //add the n'th coefficient
  273 + S.push(1);
  274 + }
  275 +
  276 + //output the spherical harmonics coefficients if requested
  277 + if(args["out"].is_set()){
  278 +
  279 + if(args["out"].nargs() == 0)
  280 + std::cout<<S.str()<<std::endl;
  281 + else{
  282 +
  283 + //open the output file
  284 + std::ofstream outfile;
  285 + outfile.open(args["out"].as_string(0).c_str());
  286 +
  287 + outfile<<S.str();
  288 +
  289 + outfile.close();
  290 + }
  291 + }
  292 +
  293 +
  294 +
  295 +
131 296  
132 297 //if the user asks for help, give it and exit
133 298 if(args["help"].is_set()){
134 299 std::cout<<"usage: shview c0 c1 c2 c3 ... --option [A B C]"<<std::endl;
135 300 std::cout<<"examples:"<<std::endl;
136   - std::cout<<" shview 1 2 3 4"<<std::endl;
  301 + std::cout<<" generate a spherical function with 4 coefficients (l=0 to 2)"<<std::endl;
  302 + std::cout<<" shview 1.3 0.2 2.3 1.34"<<std::endl;
  303 + std::cout<<" display a spherical function representing the spherical harmonic l = 3, m = -2"<<std::endl;
  304 + std::cout<<" shview --basis 3 -2"<<std::endl;
  305 +
  306 +
  307 +
137 308 std::cout<<args.str();
138 309 exit(0);
139 310 }
... ... @@ -141,6 +312,10 @@ void process_arguments(int argc, char* argv[]){
141 312  
142 313 int main(int argc, char *argv[]){
143 314  
  315 +#ifdef _WIN32
  316 + args.set_ansi(false);
  317 +#endif
  318 +
144 319 //initialize GLUT
145 320 glutInit(&argc, argv);
146 321  
... ...