Sitzung: Jeden Freitag in der Vorlesungszeit ab 16 Uhr c. t. im MAR 0.005. In der vorlesungsfreien Zeit unregelmäßig (Jemensch da?). Macht mit!

C-Kurs/DreiD/Musterlösung: Unterschied zwischen den Versionen

< C-Kurs‎ | DreiD
 
 
(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 1
+
#define WIREFRAMES_MODE 0
  
  
Zeile 84: Zeile 89:
 
                     };
 
                     };
  
      
+
     Matrix rot_y = {
    //... (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;
    /* Transformation anwenden */
 
  
     *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);
+
    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); //Front
    render_face(1,-1,-1, -1,-1,-1, -1,1,-1, 1,1,-1); //Back
+
    render_face(1,-1,-1, -1,-1,-1, -1,1,-1, 1,1,-1); //Back
    refresh_color(1,1,0);
+
    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); //Left
  
    render_face(1,1,1, 1,-1,1, 1,-1,-1, 1,1,-1); //Right
+
    render_face(1,1,1, 1,-1,1, 1,-1,-1, 1,1,-1); //Right
  
    refresh_color(1,0.5,0);
+
    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); //Top
    render_face(-1,1,1, 1,1,1, 1,1,-1, -1,1,-1); //Bottom  
+
    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;

}