OpenGL------光照+染色

这次做的真是搓,whatever~

  1 /*****
  2     Computer Graphics: HW4
  3     Shading, Lighting, Hidden Surface Removal 
  4 ****/
  5 
  6 /****
  7     Shading:                    Flat Shading in function shading();
  8     Hidden Surface Removal:        Z-Buffer and remove the back face also in shading(); Get Z-value by interpolation;
  9     Light Illumiantion:            for every end point in polygons in function lighting();
 10     Normal Vector:                for a point, it's normal vector is the average normal vector of the surface it belongs to, in funtion cal_normal();
 11     Coloring:                    coloring the whole screen in C-Buffer in function coloring();                    
 12 ****/
 13 
 14 /***
 15     notice: 
 16             To run, you should change the name of test file to HW4.in;
 17             In HW4.in, the first line should be "b 600 600"(add a letter 'b');
 18             Other useless function in hw4 written before is removed;
 19 ***/
 20 
 21 #include <iostream>
 22 #include <string>
 23 #include <cstdlib>
 24 #include <cmath>
 25 #include <cstdio>
 26 #include <vector>
 27 #include <gl/glut.h>
 28 #include <iomanip>
 29 #include <fstream>
 30 #include <algorithm>
 31 
 32 using namespace std;
 33 
 34 const int dimension = 4;
 35 const float PI = acos(-1);
 36 const float eps = 1e-6;
 37 const float INF = 1000000;
 38 const char* filename = "HW4.in";
 39 
 40 struct object {         //object
 41     float r, g, b;
 42     float Kd, Ks;
 43     int N;
 44 }obj[10];
 45 
 46 struct vec {            // vector
 47     float x, y, z;
 48     float r, g, b;
 49     vec(float _x=0, float _y=0, float _z=0, float _r=0, float _g=0, float _b=0):x(_x), y(_y), z(_z), r(_r), g(_g), b(_b){}
 50 };
 51 
 52 vec unit(vec a)            //get unit vector
 53 {
 54     vec res;
 55     float l = sqrt(a.x*a.x+a.y*a.y+a.z*a.z); 
 56     res.x = a.x / l;
 57     res.y = a.y / l;
 58     res.z = a.z / l;
 59     return res;
 60 }
 61 
 62 float dot(vec a, vec b)            //dot
 63 {
 64     return a.x * b.x + a.y * b.y + a.z * b.z;
 65 }
 66 
 67 vec vec_add(vec a, vec b)            // vector addition
 68 {
 69     vec res;
 70     res.x = a.x+b.x;
 71     res.y = a.y+b.y;
 72     res.z = a.z+b.z;
 73     return res;
 74 }
 75 
 76 vec cross(vec a, vec b, int i=0)        //cross
 77 {
 78     vec res;
 79     res.x = a.y * b.z - b.y * a.z;
 80     res.y = -(a.x * b.z - b.x * a.z);
 81     res.z = a.x * b.y - b.x * a.y;
 82     float l = sqrt(res.x*res.x+res.y*res.y+res.z*res.z);
 83     if(i == 0)
 84         res = unit(res);
 85     return res;
 86 }
 87 
 88 struct poly_point {                //end points of polygons
 89     float x, y, z, w;
 90     float r, g, b;
 91     vec Nv;
 92     poly_point(float _x=0, float _y=0, float _z=0, float _w=1, float _r=0, float _g=0, float _b=0, float xx=0, float yy=0, float zz=0)
 93     { x=_x; y=_y; z=_z; w=_w; r=_r; g=_g; b=_b; Nv.x=xx; Nv.y=yy; Nv.z=zz;}
 94 };
 95 
 96 struct mat {                    //matrix 
 97     float m[4][4];
 98     mat()
 99     {
100         memset(m,0,sizeof(m));
101         m[0][0]=m[1][1]=m[2][2]=m[3][3]=1;        
102     }
103     void reset_mat()
104     {
105         memset(m,0,sizeof(m));
106         m[0][0]=m[1][1]=m[2][2]=m[3][3]=1;
107     }
108 };
109 
110 mat T,S,R,Rx,Ry,Rz,Sh,TM, M,GRM,EM,Mirrorx, PM, WTVM;
111 
112 mat operator * (mat a, mat b)        // re-write * to matrix multiplication 
113 {
114     mat c;
115     memset(c.m,0,sizeof(c.m));
116     for(int i=0; i<dimension; i++)
117         for(int j=0; j<dimension; j++)
118             for(int k=0; k<dimension; k++)
119                 c.m[i][j] += (a.m[i][k]*b.m[k][j]);        
120     return c;
121 }
122 
123 // vector multipled by matrix
124 poly_point mat_mul_vec(mat t, poly_point pp)
125 {
126     poly_point res;
127     res.x = t.m[0][0]*pp.x+t.m[0][1]*pp.y+t.m[0][2]*pp.z+t.m[0][3]*pp.w;
128     res.y = t.m[1][0]*pp.x+t.m[1][1]*pp.y+t.m[1][2]*pp.z+t.m[1][3]*pp.w;
129     res.z = t.m[2][0]*pp.x+t.m[2][1]*pp.y+t.m[2][2]*pp.z+t.m[2][3]*pp.w;
130     res.w = t.m[3][0]*pp.x+t.m[3][1]*pp.y+t.m[3][2]*pp.z+t.m[3][3]*pp.w;
131     res.r = pp.r;
132     res.g = pp.g;
133     res.b = pp.b;
134     res.Nv.x = pp.Nv.x;
135     res.Nv.y = pp.Nv.y;
136     res.Nv.z = pp.Nv.z;
137     return res;
138 }
139 
140 // print matrix for debug
141 void print_mat(mat M)
142 {
143     for(int i=0; i<dimension; i++)
144     {
145         for(int j=0; j<dimension; j++)
146             printf("%.2lf ", M.m[i][j]);
147         printf("\n");
148     }
149     printf("\n");
150 }
151 
152 int num_tm=0;
153 poly_point poly_vertex[10][2000], observe[10][2000];
154 int poly_face[10][4000][4];
155 string file_name;
156 float Near, Far, FOV;
157 
158 //hw4
159 float r_obj, g_obj, b_obj, Kd, Ks, N; 
160 float r_back, g_back, b_back, Ka;    
161 float IP, X, Y, Z;
162 float sx,sy,sz, tx,ty,tz, rx,ry,rz;
163 float PX, PY, PZ, CX, CY, CZ, Tilt; 
164 int ID;
165 vec light[10];
166 int face_num[4000];
167 int ver_nums[10];
168 int fac_nums[10];
169 float ZBuffer[1000][1000];
170 vec CBuffer[1000][1000];
171 poly_point xx[10];
172 
173 int height, width;
174 int num_vertex, num_face;
175 void displayFunc(void);
176 void ReadInput(bool& IsExit);
177 
178 //hw4
179 vec Normal_Vec(poly_point v1, poly_point v2, poly_point v3);    //获得平面法向量 
180 void WS_TO_SS();                                                //World Space to Screen Space 
181 void Shading();                                                    //Shading(ZBuffer, CBuffer)
182 void Coloring();                                                //染色 
183 void lighting();                                                //给多边形顶点加光照 
184 void cal_normal();                                                //计算每个多边形顶点的法向量 
185 
186 
187 //hw3
188 void scale(float sx, float sy, float sz);            
189 void rotate(float rx, float ry, float rz, int i=0);            
190 void translate(float tx, float ty, float tz);        
191 void reset(); 
192 void observer(float PX, float PY, float PZ, float CX, float CY, float CZ, float Tilt, float Near, float Far, float FOV);
193 void view(float VL, float VR, float VB, float VT);
194 void display();
195 void read_asc_file();
196 void transform(mat t);
197 void projection(float AR, float Near, float Far, float FOV);
198 void per_div();
199 void transform_observe(mat t);
200 void DrawWindow(float vl, float vr, float vb, float vt, float r, float g, float b);
201 void print_mat(mat t);
202 void print();
203 
204 //hw1中已经实现的函数 
205 void drawDot(int x, int y, float r, float g, float b);    
206 
207 void myKeyboard(unsigned char key, int x, int y) 
208 {
209     cout << "KEYYYY" << endl;
210     switch(key) {
211     // Draw dots with 'd' or 'D'
212     case 'q':
213     case 'Q':
214         //glutMouseFunc(Mymouse);
215           exit(0);
216           break;
217     }
218 }
219 
220 // Read Input
221 void ReadInput(bool& IsExit)
222 {
223     //float sx,sy,sz, tx,ty,tz, rx,ry,rz;
224     //float PX, PY, PZ, CX, CY, CZ, Tilt;
225     //ifstream ffin(filename);
226     //ffin >> width >> height;
227     //cout << width << " " << height << endl;
228     string command,comment;
229     cin >> command;
230     //cin >> width >> height;
231     //cout << width << " " << height << endl;
232     //while(ffin>>command) {
233     if(command=="b")
234     {
235         cout<<command<<endl;
236         cin >> width >> height;
237         cout << width << " " << height << endl;
238     }
239     //while(cin >> command) {
240         if (command=="scale")
241         {
242             cout<<command<<endl;
243             cin>>sx>>sy>>sz;
244             scale(sx,sy,sz);    
245         }
246         else if (command=="rotate")
247         {
248             cout<<command<<endl;
249             cin>>rx>>ry>>rz;
250             rotate(rx,ry,rz,0);    
251         }
252         else if (command=="translate")
253         {
254             cout<<command<<endl;
255             cin>>tx>>ty>>tz;
256             translate(tx,ty,tz);    
257         }
258         else if (command=="reset")
259         {
260             cout<<command<<endl;
261             //reset();
262         }
263         else if (command=="observer")
264         {
265             cout<<command<<endl;
266             cin>>PX>>PY>>PZ>>CX>>CY>>CZ>>Tilt>>Near>>Far>>FOV;
267             observer(PX,PY,PZ,CX,CY,CZ,Tilt,Near,Far,FOV);
268         }
269         else if (command=="background")
270         {
271             cout<<command<<endl;
272             cin >> r_back >> g_back >> b_back;
273             DrawWindow(0, width, 0, height, r_back, g_back, b_back);
274         }
275         else if (command=="end")
276         {
277             cout<<command<<endl;
278             IsExit=true;
279             //exit(0);
280         }
281         else if (command=="#")
282         {
283             getline(cin, comment);
284         }
285         else if (command=="display")
286         {
287             cout<<command<<endl;
288             display();
289         }
290         else if (command=="object")
291         {
292             cout<<command<<endl;
293             cin >> file_name;
294             cin >> r_obj >> g_obj >> b_obj >> Kd >> Ks >> N;
295             read_asc_file();
296         }
297         else if (command=="ambient")
298         {
299             cout<<command<<endl;
300             cin >> Ka;
301         }
302         else if (command=="light")
303         {
304             cout<<command<<endl;
305             cin >> ID >> IP >> X >> Y >> Z;
306             light[ID].r = IP;
307             light[ID].g = IP;
308             light[ID].b = IP;
309             light[ID].x = X;
310             light[ID].y = Y;
311             light[ID].z = Z;
312         }
313     //}
314     //ffin.close();
315 }
316 
317 
318 // Display function
319 void displayFunc(void){
320   
321   freopen(filename, "r", stdin);
322   bool IsExit;
323   IsExit=false;
324   // clear the entire window to the background color
325   glClear(GL_COLOR_BUFFER_BIT);
326   while (!IsExit)
327   {
328     glClearColor(0.0, 0.0, 0.0, 0.0); 
329 //    redraw();
330   // draw the contents!!! Iterate your object's data structure!
331   // flush the queue to actually paint the dots on the opengl window
332     glFlush();
333     ReadInput(IsExit);
334   }
335  // infile.close();
336   //exit(0);
337 }
338 
339 
340 // Main
341 void main(int ac, char** av) {
342   //initial();
343   
344   int winSizeX, winSizeY;
345   string name;
346   if(ac == 3) {
347     winSizeX = atoi(av[1]);
348     winSizeY = atoi(av[2]);
349 //        cout<<"Done";
350   }
351   else { // default window size
352     winSizeX = 600;
353     winSizeY = 600;
354 
355   }
356  // freopen("test.in", "r", stdin);
357 //  cout<<"Please input file name:"<<endl;
358 //  cin>>name;
359 //  infile.open(name.c_str());
360  // exit(0);
361  // infile.open("inp3.txt");
362 // infile.open(av[1]);
363   //width  = winSizeX;
364   //height = winSizeY;
365 
366   // initialize OpenGL utility toolkit (glut)
367   glutInit(&ac, av);
368 
369   // single disply and RGB color mapping
370   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // set display mode
371   glutInitWindowSize(winSizeX, winSizeY);      // set window size
372   glutInitWindowPosition(0, 0);                // set window position on screen
373   glutCreateWindow("HW4 Window");       // set window title
374   
375   // set up the mouse and keyboard callback functions
376    // register the keyboard action function
377   glutKeyboardFunc(myKeyboard);
378   // displayFunc is called whenever there is a need to redisplay the window,
379   // e.g., when the window is exposed from under another window or when the window is de-iconified
380   glutDisplayFunc(displayFunc); // register the redraw function
381   
382   // set background color
383   glClearColor(0.0, 0.0, 0.0, 0.0);     // set the background to black
384   glClear(GL_COLOR_BUFFER_BIT); // clear the buffer
385 
386   // misc setup
387   glMatrixMode(GL_PROJECTION);  // setup coordinate system
388   glLoadIdentity();
389   gluOrtho2D(0, winSizeX, 0, winSizeY);
390   glShadeModel(GL_FLAT);
391   glFlush();
392   glutMainLoop();
393 }
394 
395 // 3 transformations
396 void scale(float sx, float sy, float sz)
397 {
398     S.m[0][0]=sx;    S.m[1][1]=sy;    S.m[2][2]=sz;
399     TM=S*TM;
400 }
401 void rotate(float rx, float ry, float rz, int i)
402 {
403     if(i == 0)
404     {
405         rx = rx * PI / 180.0;    ry = ry * PI / 180.0;    rz = rz * PI / 180.0;
406     }
407     Rx.m[1][1]=cos(rx);    Rx.m[2][2]=cos(rx);    Rx.m[1][2]=-sin(rx);    Rx.m[2][1]=sin(rx);
408     Ry.m[0][0]=cos(ry);    Ry.m[2][2]=cos(ry);    Ry.m[0][2]=sin(ry);        Ry.m[2][0]=-sin(ry);
409     Rz.m[0][0]=cos(rz);    Rz.m[1][1]=cos(rz);    Rz.m[0][1]=-sin(rz);    Rz.m[1][0]=sin(rz);
410     R = Rz*Ry*Rx;
411     TM=R*TM;
412 }
413 void translate(float tx, float ty, float tz)
414 {
415     T.m[0][3]=tx;    T.m[1][3]=ty;    T.m[2][3]=tz;
416     TM=T*TM;
417 }
418 
419 // poly_vertex to observe
420 void reset()
421 {
422     int j=num_tm-1;
423     for(int i=1; i<=ver_nums[num_tm-1]; i++) 
424     {
425         observe[j][i].x = poly_vertex[j][i].x; 
426         observe[j][i].y = poly_vertex[j][i].y;
427         observe[j][i].z = poly_vertex[j][i].z;
428     }
429 }
430 
431 //get EM matrix and PM matrix
432 void observer(float PX, float PY, float PZ, float CX, float CY, float CZ, float Tilt, float Near, float Far, float FOV)
433 {
434     //GRM
435     translate(-PX,-PY,-PZ);
436     //print_mat(T);
437     float x = CX-PX;
438     float y = CY-PY;
439     float z = CZ-PZ;
440     //Tilt=Tilt*PI/180.0;
441     float l=sqrt(x*x+y*y+z*z);
442     vec v(x,y,z);
443     vec t(0,1,sin(Tilt*PI/180.0));
444     vec v3;
445     v3.x = v.x/l; v3.y = v.y/l; v3.z = v.z/l;
446     vec v1=cross(v,t);
447     vec v2=cross(v1,v3);
448     GRM.m[0][0]=v1.x;    GRM.m[0][1]=v1.y;    GRM.m[0][2]=v1.z;
449     GRM.m[1][0]=v2.x;    GRM.m[1][1]=v2.y;    GRM.m[1][2]=v2.z;
450     GRM.m[2][0]=v3.x;    GRM.m[2][1]=v3.y;    GRM.m[2][2]=v3.z;
451     printf("GRM\n");
452     print_mat(GRM);
453     EM = Mirrorx*GRM*T;
454     TM.reset_mat();
455     //print_mat(EM);
456 }
457 
458 //viewport
459 void view(float VL, float VR, float VB, float VT)
460 {
461     float WL=-1, WR=1, WB=-1, WT=1;
462     translate(-WL, -WB, 0);    
463     WTVM = T * WTVM;    
464     scale((VR-VL)/(WR-WL), (VT-VB)/(WT-WB), 1);
465     WTVM = S * WTVM;    
466     translate(VL, VB, 0);    
467     WTVM = T * WTVM;
468     printf("WTVM\n");
469     //print_mat(WTVM);
470 }
471 
472 // display in screen
473 void display()
474 {
475     DrawWindow(0, width, 0, height, r_back, g_back, b_back);
476     lighting();
477     view(0, width, 0, height);
478     WS_TO_SS();
479     //print();
480     Shading();
481     Coloring();
482     //////////////////////////
483     reset();
484     EM.reset_mat();
485     PM.reset_mat();
486     WTVM.reset_mat();
487 }
488 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
489 // read oject store the data in obj[]
490 void read_asc_file()
491 {
492     num_tm++;
493 
494     cout << file_name << endl;
495     ifstream fin(file_name);
496     fin >> ver_nums[num_tm-1] >> fac_nums[num_tm-1];
497     cout << ver_nums[num_tm-1] << " " << fac_nums[num_tm-1] << endl;
498 
499     // read vertex one by one
500     for(int i=1; i<=ver_nums[num_tm-1]; i++) 
501     {
502         fin >> poly_vertex[num_tm-1][i].x >> poly_vertex[num_tm-1][i].y >> poly_vertex[num_tm-1][i].z;
503     }
504     // read face one by one
505     for(int i=0; i<fac_nums[num_tm-1]; i++) 
506     {
507         fin >> face_num[num_tm-1];    //faces num 3 or 4
508         for(int j=0; j<face_num[num_tm-1]; j++)
509             fin >> poly_face[num_tm-1][i][j];
510     }
511     obj[num_tm-1].r =  r_obj;
512     obj[num_tm-1].g =  g_obj;
513     obj[num_tm-1].b =  b_obj;
514     obj[num_tm-1].Kd = Kd;
515     obj[num_tm-1].Ks = Ks;
516     obj[num_tm-1].N = N;
517     //cout << "objectcolor!!!" <<r_obj << " " << g_obj << " " << b_obj << endl;
518     transform(TM);//
519     reset();
520     cal_normal();
521     TM.reset_mat();
522 }
523 
524 // calculate normal vector for every point
525 void cal_normal()
526 {
527     //for(int k=0; k<num_tm; k++)
528     {
529         int k = num_tm-1;
530         for(int i=0; i<fac_nums[k]; i++) 
531         {
532             vec Nvec = Normal_Vec(observe[k][poly_face[k][i][0]], observe[k][poly_face[k][i][1]], observe[k][poly_face[k][i][2]]);
533             for(int j=0; j<face_num[k]; j++)
534             {
535                 observe[k][poly_face[k][i][j]].Nv.x += Nvec.x;
536                 observe[k][poly_face[k][i][j]].Nv.y += Nvec.y;
537                 observe[k][poly_face[k][i][j]].Nv.z += Nvec.z;
538             }
539         }
540     }
541 }
542 
543 //lighting the end points for every polygons
544 void lighting()
545 {    
546     cout << "num_tm: " << num_tm << endl;
547     for(int k=0; k<num_tm; k++)
548     {
549         //float fatt=1, diffuse=0, specular=0;
550         for(int i=1; i<=ver_nums[k]; i++)
551         {
552             //for(int i=1; i<=ver_nums[k]; i++)
553             float fatt=1, diffuse=0, specular=0;
554             for(int j=1; j<=ID; j++)
555             {
556                 vec N, L, H, V;        //Normal, Lighting, H, View vector
557                 L.x = observe[k][i].x - light[j].x;        L.y =  observe[k][i].y - light[j].y;        L.z = observe[k][i].z - light[j].z;
558                 L = unit(L);
559                 N.x = observe[k][i].Nv.x;    N.y = observe[k][i].Nv.y;    N.z = observe[k][i].Nv.z;
560                 N = unit(N);
561                 V.x = CX-PX;    V.y = CY-PY;    V.z = CZ-PZ;
562                 V = unit(V);
563                 H = vec_add(L, V);
564                 H = unit(H);
565                 float temp, temp1;
566                 if(num_tm > 2 && (k == 0 || k == 1 || k == 2))        //notice that the r, g, b shuold be positive
567                     temp = (pow(dot(H, N), obj[k].N));
568                 else
569                     temp = pow(abs(dot(H, N)), obj[k].N);
570                 if(num_tm > 2 && (k == 0 || k == 1 || k == 2))
571                     temp1 = (dot(N, L));
572                 else
573                     temp1 = abs(dot(N, L));
574 
575                 diffuse += obj[k].Kd * light[j].r * temp1;                
576                 specular += obj[k].Ks * light[j].r * temp;            
577             }
578             //cout<<"color "<<obj[k].r<<" "<<obj[k].g<<" "<<obj[k].b<<endl;
579             observe[k][i].r = Ka * obj[k].r + diffuse * obj[k].r + specular;
580             observe[k][i].g = Ka * obj[k].g + diffuse * obj[k].g + specular;
581             observe[k][i].b = Ka * obj[k].b + diffuse * obj[k].b + specular;
582             
583             if(observe[k][i].r > 1)        observe[k][i].r = 1;
584             if(observe[k][i].g > 1)        observe[k][i].g = 1;
585             if(observe[k][i].b > 1)        observe[k][i].b = 1;
586             //cout << observe[k][i].r << " " << observe[k][i].g << " " << observe[k][i].b << " " << endl;
587             //print();
588         }
589     }
590     //print();
591 }
592 
593 // transform points' coordinate in matrix transformation
594 void transform(mat t)
595 {
596     for(int i=1; i<=ver_nums[num_tm-1]; i++) 
597         poly_vertex[num_tm-1][i] = mat_mul_vec(t, poly_vertex[num_tm-1][i]);
598 }
599 void transform_observe(mat t)
600 {
601     for(int j=0; j<num_tm; j++)
602     {
603         for(int i=1; i<=ver_nums[j]; i++) 
604             observe[j][i] = mat_mul_vec(t, observe[j][i]);
605     }
606 }    
607 
608 // projection
609 void projection(float AR, float Near, float Far, float FOV)
610 {
611     //PM
612     FOV=FOV*PI/180.0;
613     float Y=Far*tan(FOV);
614     float H=Near*tan(FOV);
615     PM.m[1][1]=AR;
616     PM.m[2][2]=Y/(Y-H)*tan(FOV);
617     PM.m[2][3]=Y*H/(H-Y)*tan(FOV);
618     PM.m[3][2]=tan(FOV);
619     PM.m[3][3]=0;
620     //print_mat(PM);
621 }
622 
623 // perspective divide
624 void per_div()
625 {
626     for(int j=0; j<num_tm; j++)
627     {
628         for(int i=1; i<=ver_nums[j]; i++) 
629         {
630             observe[j][i].x /= observe[j][i].w;
631             observe[j][i].y /= observe[j][i].w;
632             observe[j][i].z /= observe[j][i].w;
633             observe[j][i].w /= observe[j][i].w;
634         }
635     }
636     
637 }
638 
639 //background: color the background and viewport
640 void DrawWindow(float vl, float vr, float vb, float vt, float r, float g, float b)
641 {
642     cout << "Windows!!!" <<width << " " << height << endl;
643     for(int y=0; y<width; y++)
644         for(int x=0; x<height; x++)
645         {
646             ZBuffer[y][x]=INF;
647             CBuffer[y][x].r = r;
648             CBuffer[y][x].g = g;
649             CBuffer[y][x].b = b;
650             //drawDot(x, y, r, g, b);
651         }    
652 }
653 
654 // coloring the whole screen
655 void Coloring()
656 {
657     cout << "Coloring!!!" << width << " " << height << endl;
658     for(int y=0; y<width; y++)
659         for(int x=0; x<height; x++)
660             drawDot(x, height-y, CBuffer[y][x].r, CBuffer[y][x].g, CBuffer[y][x].b);
661 }
662 
663 // world space to screen space
664 void WS_TO_SS()
665 {
666     projection(width/height,Near,Far,FOV);
667     //print();
668     transform_observe(EM);
669     //print();
670     transform_observe(PM);
671     //print();
672     per_div();
673     //print();
674     transform_observe(WTVM);
675     cout << "num_tm: " << num_tm << endl;
676 }
677 
678 // find normal vector
679 vec Normal_Vec(poly_point v1, poly_point v2, poly_point v3)
680 {
681     vec v1_v2, v2_v3, Nv;    //plan equation
682     v1_v2.x = v2.x - v1.x;
683     v1_v2.y = v2.y - v1.y;
684     v1_v2.z = v2.z - v1.z;
685     v2_v3.x = v3.x - v2.x;
686     v2_v3.y = v3.y - v2.y;
687     v2_v3.z = v3.z - v2.z;
688     Nv = cross(v1_v2, v2_v3, 1);
689     return Nv;
690 }
691 
692 // cmp in sort
693 bool cmp(poly_point a, poly_point b)
694 {
695     return a.x < (b.x+eps);
696 }
697 
698 //shading function: Flat Shading
699 void Shading()
700 {        
701     //print();
702     const int max_num_tm=7;
703     for(int k=0; k<num_tm; k++)
704     {        
705         int n = face_num[k];
706         for(int i=0; i<fac_nums[k]; i++) 
707         {        
708             if(num_tm < max_num_tm)
709             {
710                 // Remove the back face
711                 vec Nvec = Normal_Vec(poly_vertex[k][poly_face[k][i][0]], poly_vertex[k][poly_face[k][i][1]], poly_vertex[k][poly_face[k][i][2]]);
712                 Nvec = unit(Nvec);
713                 vec V;
714                 V.x = CX-PX;    V.y = CY-PY;    V.z = CZ-PZ;
715                 V = unit(V);
716                 if(dot(Nvec, V)<0)
717                     continue;
718             }
719             poly_point p1, p2, p0;
720             float xmin=600, xmax=0, ymin=600, ymax=0;
721             float r=0, g=0, blue=0;
722             for(int j=0; j<n; j++)
723             {
724                 ymax = max(ymax, observe[k][poly_face[k][i][j]].y);
725                 ymin = min(ymin, observe[k][poly_face[k][i][j]].y);
726                 xmax = max(xmax, observe[k][poly_face[k][i][j]].x);
727                 xmin = min(xmin, observe[k][poly_face[k][i][j]].x);
728                 r += observe[k][poly_face[k][i][j]].r;
729                 g += observe[k][poly_face[k][i][j]].g;
730                 blue += observe[k][poly_face[k][i][j]].b;
731             }
732             r /= n;        g /= n;        blue /= n;                        //Get the average color
733             //cout<<"average color: "<<r<<" "<<g<<" "<<blue<<endl;
734 
735             for(int y=ymin-1; y<=ymax+1; y++)        //y-scan_line
736             {
737                 //cout << "y: " << y << endl;
738                 int cnt=0;
739                 for(int j=0; j<n-1; j++)
740                 {
741                     p1=observe[k][poly_face[k][i][j]];
742                     p2=observe[k][poly_face[k][i][j+1]];
743                     p1.z=observe[k][poly_face[k][i][j]].z;
744                     p2.z=observe[k][poly_face[k][i][j+1]].z;
745                     
746                     p0.x = (y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
747                     p0.y = y;
748                     p0.z = (p2.z-p1.z)/(p2.y-p1.y)*(p0.y-p1.y)+p1.z;     //Get Z-value by interpolation
749                     if(p1.y > p2.y || p2.y > p1.y)
750                     {
751                         if(y <= max(p1.y, p2.y) && y >= min(p1.y, p2.y))
752                             xx[cnt++] = p0;
753                     }
754                     if(abs(p0.x-xmax)<eps || abs(p0.x-xmin)<eps)
755                     {
756                         int minx = min(p1.x, p2.x);
757                         int maxx = max(p1.x, p2.x);
758                         for (int x = minx; x <= maxx; x++)
759                         {
760                             float z = (p2.z - p1.z) / (p2.x - p1.x)*(x - p1.x) + p1.z;
761                             //cout << z << endl;
762                             if (z < ZBuffer[y][x] && (x < 265 || x > 335))            //Z-Buffer && CBuffer
763                             {
764                                 ZBuffer[y][x] = z;
765                                 CBuffer[y][x].r = r;
766                                 CBuffer[y][x].g = g;
767                                 CBuffer[y][x].b = blue;
768                             }
769                         }
770                     }
771                 }
772                 
773                 p1=observe[k][poly_face[k][i][n-1]];
774                 p2=observe[k][poly_face[k][i][0]];
775                 p1.z=observe[k][poly_face[k][i][n-1]].z;
776                 p2.z=observe[k][poly_face[k][i][0]].z;
777                 if(p1.y > p2.y || p2.y > p1.y)
778                 {
779                     p0.x = (y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
780                     p0.y = y;
781                     p0.z = (p2.z-p1.z)/(p2.y-p1.y)*(p0.y-p1.y)+p1.z;
782                     if(y <= max(p1.y, p2.y) && y >= min(p1.y, p2.y))
783                         xx[cnt++] = p0;
784                 }
785                 if(abs(p0.x-xmax)<eps || abs(p0.x-xmin)<eps)
786                 {
787                     int minx = min(p1.x, p2.x);
788                         int maxx = max(p1.x, p2.x);
789                         for (int x = minx; x <= maxx; x++)
790                         {
791                             float z = (p2.z - p1.z) / (p2.x - p1.x)*(x - p1.x) + p1.z;
792                             //cout << z << endl;
793                             if (z < ZBuffer[y][x] && (x < 265 || x > 335))
794                             {
795                                 ZBuffer[y][x] = z;
796                                 CBuffer[y][x].r = r;
797                                 CBuffer[y][x].g = g;
798                                 CBuffer[y][x].b = blue;
799                             }
800                         }
801                 }
802                 if(cnt==2)        // find two intersect points
803                 {        
804                     //cout << "intersect" << endl;
805                     sort(xx, xx+cnt, cmp);
806                     for(int x=xx[0].x; x<xx[1].x; x++)
807                     {
808                         poly_point a = xx[0];
809                         poly_point b = xx[1];
810                         float z = (b.z-a.z)/(b.x-a.x)*(x-a.x)+a.z;                    
811                         if(y >= 0 && y <= width && x >= 0 && x <= height && z < ZBuffer[(int)y][(int)x])
812                         {
813                             ZBuffer[y][x] = z;
814                             CBuffer[y][x].r = r;
815                             CBuffer[y][x].g = g;
816                             CBuffer[y][x].b = blue;
817                         }
818                     }        
819                 }
820             }
821         }
822     }
823 }
824 
825 //print r, g, b for debug
826 void print()
827 {
828     for(int k=0; k<num_tm; k++)
829     {
830         int n=face_num[num_tm-1];
831         for(int i=0; i<fac_nums[k]; i++) 
832         {
833             for(int j=0; j<n; j++)
834                 cout << observe[k][poly_face[k][i][j]].r << " " << observe[k][poly_face[k][i][j]].g << " " << observe[k][poly_face[k][i][j]].b << endl;
835             
836         }
837     }
838 }
839 /////////////////////////////////////////////////////////////////////////hw1/////////////////////////////////////////////////
840 // draw a dot at location with integer coordinates (x,y), and with color (r,g,b)
841 void drawDot(int x, int y, float r, float g, float b) 
842 {
843     glBegin(GL_POINTS);
844   
845     // set the color of dot
846     glColor3f(r, g, b);
847   
848     // invert height because the opengl origin is at top-left instead of bottom-left
849     glVertex2i(x ,  height-y);
850   
851     glEnd();
852 }

 

posted @ 2015-06-26 16:35  dominjune  阅读(270)  评论(0编辑  收藏  举报