C-Kurs/DreiD/Musterlösung
< C-Kurs | DreiD
Version vom 5. März 2013, 17:37 Uhr von PaulG (Diskussion | Beiträge) (verschob „Ckurs/DreiD/Musterlösung“ nach „C-Kurs/DreiD/Musterlösung“)
Dies ist die main.c
. Mit FIGURE kannst du eine von drei Figuren auswählen.
#include <stdio.h> #include <stdlib.h> #include <math.h> #include "screen.h" /* Figur: 0=Würfel,1=Kegel,2=Ellipsoid */ #define FIGURE 1 /* Rotationsgeschwindigkeiten (frei wählbar) */ #define ROT_V_ALPHA 0.1f #define ROT_V_BETA 0.03f #define LIGHT_V_ALPHA 0.0f #define LIGHT_V_BETA 0.0f /* Drahtgitter-Modus: 1=an, 0=aus */ #define WIREFRAMES_MODE 0 /* 3x3-Matrix-Repräsentation als 2-dimensionales Array */ typedef float Matrix[3][3]; /* Aktuelle Transformation */ Matrix transform; /* Aktuelle Zeichenfarbe mit Werten zwischen 0 und 1 */ float color_r; float color_g; float color_b; /* Aktueller Lichtvektor */ float lgt_x; float lgt_y; float lgt_z; /* --- Prototypen --- */ /* Gibt eine 3x3-Matrix aus und beendet das Programm */ void print_matrix(Matrix matrix); /* Gibt einen Vektor, bestehend aus 3 floats, aus und beendet das Programm */ void print_vector(float x, float y, float z); /* Bildet aus zwei Winkeln die resultierende Transformationsmatrix */ void refresh_transformation_matrix(float alpha, float beta) { /* Rotationsmatrizen */ Matrix rot_x = { { 1.0f , 0.0f , 0.0f }, { 0.0f , cos(beta) , -sin(beta) }, { 0.0f , sin(beta) , cos(beta) } }; Matrix rot_y = { { cos(alpha), 0.0f , sin(alpha)}, { 0.0f , 1.0f , 0.0f }, { -sin(alpha), 0.0f , cos(alpha)} }; /* Matrix-Multiplikation */ int i,j,k; for(i=0;i<3;i++) for(j=0;j<3;j++) { transform[i][j] = 0; for(k=0;k<3;k++) transform[i][j] += rot_x[j][k]*rot_y[k][i]; } } /* Rotiert den gegebenen Vektor, bestehend aus 3 Floats, entsprechend der aktuellen transform-Matrix */ void apply_transform(float * x,float * y,float * z) { float h_x = *x; float h_y = *y; float h_z = *z; *x = transform[0][0] * h_x + transform[0][1] * h_y + transform[0][2] * h_z; *y = transform[1][0] * h_x + transform[1][1] * h_y + transform[1][2] * h_z; *z = transform[2][0] * h_x + transform[2][1] * h_y + transform[2][2] * h_z; } /* Zeichnet ein dreidimensionales Dreieck auf die zweidimensionale Fläche entsprechend der aktuellen transform-Matrix */ void render_primitive(float x1,float y1,float z1, float x2,float y2,float z2, float x3,float y3,float z3) { /* Koordinaten transformieren */ apply_transform(&x1,&y1,&z1); apply_transform(&x2,&y2,&z2); apply_transform(&x3,&y3,&z3); /* Kreuzprodukt bilden */ float v1[3] = {x2-x1,y2-y1,z2-z1}; float v2[3] = {x3-x1,y3-y1,z3-z1}; float cross_x = v1[1]*v2[2] - v1[2]*v2[1]; float cross_y = v1[2]*v2[0] - v1[0]*v2[2]; float cross_z = v1[0]*v2[1] - v1[1]*v2[0]; float cross = 1/sqrt(cross_x*cross_x + cross_y*cross_y + cross_z*cross_z); //Normalisieren cross_x *= cross; cross_y *= cross; cross_z *= cross; /* Culling */ if(cross_z<0) return; /* Licht */ float brightness = lgt_x*cross_x + lgt_y*cross_y + lgt_z*cross_z; brightness = (brightness + 0.5)/1.5f; if(brightness>1) brightness = 1; if(brightness<0.025) brightness = 0.025; brightness = sqrt(brightness); /* Dreiecke zeichnen */ set_color(color_r*brightness,color_g*brightness,color_b*brightness); if(WIREFRAMES_MODE) { draw_line(x1,y1,x2,y2); draw_line(x2,y2,x3,y3); draw_line(x3,y3,x1,y1); }else draw_triangle(x1,y1,x2,y2,x3,y3); } /* ----------------Ab hier alles Vorlage---------------- */ /* Aktuelle Rotationen */ float trf_alpha = 0; float trf_beta = 0; float lgt_alpha = 0; float lgt_beta = 0; /* Anzahl der bisher gezeichneten Frames */ int c_time = 0; /* Gibt eine 3x3-Matrix aus und beendet das Programm */ void print_matrix(Matrix matrix) { printf("%f %f %f\n",matrix[0][0],matrix[0][1],matrix[0][2]); printf("%f %f %f\n",matrix[1][0],matrix[1][1],matrix[1][2]); printf("%f %f %f\n",matrix[2][0],matrix[2][1],matrix[2][2]); system("PAUSE"); exit(EXIT_SUCCESS); } /* Gibt einen Vektor, bestehend aus 3 floats, aus und beendet das Programm */ void print_vector(float x, float y, float z) { printf("%f %f %f\n",x,y,z); system("PAUSE"); exit(EXIT_SUCCESS); } /* Setzt die aktuelle Farbe für nachfolgende render_* Aufrufe */ void refresh_color(float r,float g, float b) { color_r = r; color_g = g; color_b = b; } /* Rendert dreidimensionale viereckige Fläche (bestehend aus zwei Dreiecken) */ void render_face(float x1,float y1,float z1, float x2,float y2,float z2, float x3,float y3,float z3, float x4,float y4,float z4) { render_primitive(x1,y1,z1,x2,y2,z2,x3,y3,z3); render_primitive(x1,y1,z1,x3,y3,z3,x4,y4,z4); } /* Komplette Ausgabe */ void output() { /* Transformation aktualisieren */ refresh_transformation_matrix(trf_alpha,trf_beta); /* Licht-Vektor setzen */ lgt_x = cos(lgt_beta); lgt_y = sin(lgt_beta); lgt_z = sin(lgt_alpha)*lgt_x; lgt_x = cos(lgt_alpha)*lgt_x; /* Szene rendern */ begin_scene(); if(FIGURE == 1) { /* Kegel */ int acc = 32; //Genauigkeit float rad = 1.2; //Radius int i; float ang = 0, lst_ang; for(i=1; i<acc+1; i++) { refresh_color(0.8,0.8,1); lst_ang = ang; ang = (float)i/acc*2*M_PI; render_primitive(0,-1.2,0, sin(ang)*rad,1.2,cos(ang)*rad, sin(lst_ang)*rad,1.2,cos(lst_ang)*rad); if(i%2 == 0) refresh_color(0.1,0.1,0.5); else refresh_color(0.2,0.2,0.6); render_primitive(0,1.2,0, sin(lst_ang)*rad,1.2,cos(lst_ang)*rad, sin(ang)*rad,1.2,cos(ang)*rad); } }else if(FIGURE == 2) { /* Ellipsoid */ refresh_color(1,1,1); float rad_a = 1.0f, rad_b = 1.5f; //Radius a und b int acc = 14; //Genauigkeit int i, j; float x = -1, lst_x; float ang = 0, lst_ang; float rad = 0, lst_rad, anim_rad; for(j=1; j<acc+1; j++) { lst_x = x; lst_rad = rad; x = (((float)j/acc)-0.5)*2; if(x>1) x = 1; rad = sqrt(1-x*x)*(1+sin(((float)c_time+x*15)*0.4f)*0.05f); ang = 0; for(i=1; i<acc+1; i++) { lst_ang=ang; ang=(float)i/acc*2*M_PI; render_face( sin(lst_ang)*lst_rad*rad_a,lst_x,cos(lst_ang)*lst_rad*rad_b, sin(ang)*lst_rad*rad_a,lst_x,cos(ang)*lst_rad*rad_b, sin(ang)*rad*rad_a,x,cos(ang)*rad*rad_b, sin(lst_ang)*rad*rad_a,x,cos(lst_ang)*rad*rad_b ); } } }else{ /* Würfel */ refresh_color(1,0,0); render_face(-1,-1,1, 1,-1,1, 1,1,1, -1,1,1); //Front render_face(1,-1,-1, -1,-1,-1, -1,1,-1, 1,1,-1); //Back refresh_color(1,1,0); render_face(-1,-1,1, -1,1,1, -1,1,-1, -1,-1,-1); //Left render_face(1,1,1, 1,-1,1, 1,-1,-1, 1,1,-1); //Right refresh_color(1,0.5,0); render_face(1,-1,1, -1,-1,1, -1,-1,-1, 1,-1,-1); //Top render_face(-1,1,1, 1,1,1, 1,1,-1, -1,1,-1); //Bottom } end_scene(); } int main(void) { /* Fenster initialisieren */ if(create_window(400,400,0x220000) != 0){ printf("Fehler beim Fenster Erstellen. Bitte wende dich an einen Tutor.\n"); return EXIT_FAILURE; } /* Startwerte setzen */ zoom = 0.5; trf_alpha = M_PI/2; trf_beta = M_PI/3; lgt_alpha = M_PI*2/3; lgt_beta = -M_PI/4; /* Figur wiederholt rendern */ while(1) { trf_alpha += ROT_V_ALPHA; trf_beta += ROT_V_BETA; lgt_alpha += LIGHT_V_ALPHA; lgt_beta += LIGHT_V_BETA; output(); c_time++; usleep(50000); } /* Programmende */ close_window(); return EXIT_SUCCESS; }