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;
}