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 }