C-Kurs/DreiD/Musterlösung: Unterschied zwischen den Versionen
AndyF (Diskussion | Beiträge) |
PaulG (Diskussion | Beiträge) K (verschob „Ckurs/DreiD/Musterlösung“ nach „C-Kurs/DreiD/Musterlösung“) |
||
(2 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
+ | Dies ist die <code>main.c</code>. Mit FIGURE kannst du eine von drei Figuren auswählen. | ||
+ | |||
<pre> | <pre> | ||
#include <stdio.h> | #include <stdio.h> | ||
Zeile 8: | Zeile 10: | ||
#include "screen.h" | #include "screen.h" | ||
+ | |||
+ | /* Figur: 0=Würfel,1=Kegel,2=Ellipsoid */ | ||
+ | #define FIGURE 1 | ||
/* Rotationsgeschwindigkeiten (frei wählbar) */ | /* Rotationsgeschwindigkeiten (frei wählbar) */ | ||
Zeile 19: | Zeile 24: | ||
#define LIGHT_V_BETA 0.0f | #define LIGHT_V_BETA 0.0f | ||
/* Drahtgitter-Modus: 1=an, 0=aus */ | /* Drahtgitter-Modus: 1=an, 0=aus */ | ||
− | #define WIREFRAMES_MODE | + | #define WIREFRAMES_MODE 0 |
Zeile 84: | Zeile 89: | ||
}; | }; | ||
− | + | Matrix rot_y = { | |
− | + | ||
+ | { cos(alpha), 0.0f , sin(alpha)}, | ||
+ | |||
+ | { 0.0f , 1.0f , 0.0f }, | ||
+ | |||
+ | { -sin(alpha), 0.0f , cos(alpha)} | ||
+ | |||
+ | }; | ||
/* Matrix-Multiplikation */ | /* 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]; | ||
− | + | } | |
Zeile 107: | Zeile 132: | ||
float h_y = *y; | float h_y = *y; | ||
float h_z = *z; | float h_z = *z; | ||
− | |||
− | *x = h_x; | + | *x = transform[0][0] * h_x + transform[0][1] * h_y + transform[0][2] * h_z; |
− | *y = h_y; | + | *y = transform[1][0] * h_x + transform[1][1] * h_y + transform[1][2] * h_z; |
− | *z = h_z; | + | *z = transform[2][0] * h_x + transform[2][1] * h_y + transform[2][2] * h_z; |
} | } | ||
Zeile 133: | Zeile 157: | ||
apply_transform(&x3,&y3,&z3); | 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 */ | /* 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 */ | /* Dreiecke zeichnen */ | ||
− | set_color(color_r, color_g, color_b); | + | set_color(color_r*brightness,color_g*brightness,color_b*brightness); |
if(WIREFRAMES_MODE) | if(WIREFRAMES_MODE) | ||
{ | { | ||
− | draw_line(x1,y1, x2,y2); | + | draw_line(x1,y1,x2,y2); |
− | draw_line(x2,y2, x3,y3); | + | draw_line(x2,y2,x3,y3); |
− | draw_line(x3,y3, x1,y1); | + | draw_line(x3,y3,x1,y1); |
}else | }else | ||
− | draw_triangle(x1,y1, x2,y2, x3,y3); | + | draw_triangle(x1,y1,x2,y2,x3,y3); |
} | } | ||
Zeile 269: | Zeile 322: | ||
begin_scene(); | 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(); | end_scene(); |
Aktuelle Version vom 5. März 2013, 17:37 Uhr
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; }