viernes, 12 de abril de 2013

Comp. gráfica - Tarea 01 - IFS (Iterated Function Systems)

Toda la información se puede encontrar en el archivo zip que se da al final.

#include <iostream>
#include <cstring>
#include <fstream>
#include <cstdlib>
#include "matrix.h"
#include "image.h"

using namespace std;

void leer_matriz(char *input_file, float *v);
inline float aleat() { return (float)rand()/(float)RAND_MAX; }

ifstream source;                // Flujo de archivo de entrada.

const int NRO_PTS = 100000;     // Numero de puntos a dibujar.
const int NRO_TRANSF = 100;     // Numero de transformaciones por punto.

int main(int argc, char **argv) {

    /*************************************************************************
     * Código para parsear los datos ingresados por linea de comandos.
     *************************************************************************/

    char *input_file = NULL;
    int width = 100;
    int height = 100;
    char *output_file = NULL;
    float depth_min = 0;
    float depth_max = 1;
    char *depth_file = NULL;

    // Ejemplos de comandos de invocación:
    // raycast -input input.txt -size 100 100 -output output.tga
    // raycast -input input.txt -size 100 100 -depth 5.5 8.8 output.tga

    for (int i = 1; i < argc; i++) {
        if (!strcmp(argv[i],"-input")) {
            i++; assert (i < argc); 
            input_file = argv[i];
        } else if (!strcmp(argv[i],"-size")) {
            i++; assert (i < argc); 
            width = atoi(argv[i]);
            i++; assert (i < argc); 
            height = atoi(argv[i]);
        } else if (!strcmp(argv[i],"-output")) {
            i++; assert (i < argc); 
            output_file = argv[i];
        } else if (!strcmp(argv[i],"-depth")) {
            i++; assert (i < argc); 
            depth_min = atof(argv[i]);
            i++; assert (i < argc); 
            depth_max = atof(argv[i]);
            i++; assert (i < argc); 
            depth_file = argv[i];
        } else {
            printf ("Hay un error en la invocacion %d: '%s'\n",i,argv[i]);
            assert(0);
        }
    }



    /*************************************************************************
     * El siguiente código tiene como objetivo llenar las matrices m[i], 
     * ademas de llenar el arreglo 'probs' de probabilidades y transformar las
     * probabilidades absolutas a probabilidades acumuladas.
     *************************************************************************/

    int n;                          // Numero de transformaciones afines.
    float *v = new float[16];       // Vector temporal para crear la matriz.
    float *probs = new float[n];    // Probabilidad de hacer una transformacion

    source.open(input_file, ios_base::in);  // Lee el archivo dado en "-input".
    source >> n;                            // Lee el primer numero del archivo
    Matrix *m = new Matrix[n];              // Crea un array de 'n' matrices.

    float acum = 0;                 // La probabilidad acumulada.
    for (int i = 0; i < n; ++i) {
        source >> probs[i];         // Lee la probabilidad de transformacion.
        acum += probs[i];           // Acumula
        probs[i] = acum;            // Cambia la prob. absoluta por acumulada.
        leer_matriz(input_file, v); // Lee y guarda la matriz linealmente en v.
        m[i] = *(new Matrix(v));    // Crea la matriz basado en 'v'.
    }



    /*************************************************************************
     * Empieza el algoritmo IFS.
     *************************************************************************/

    Image img(4*width, 4*height);   // Se da suficiente tamanio a la imagen...
                                    // ...para no tener problemas de desborde.
    for (int j = 0; j < NRO_PTS; ++j) {
        // 'p' representa un punto aleatorio dentro del cuadrado de dimensiones
        // "width x height". Las dos primeras coordenadas son del plano del
        // cuadrado, mientras que el tercer parametro se establece a 'width' 
        // para que la traslacion sea consistente.
        Vec4f p(width*aleat(), height*aleat(), 2*width, 1);
        int i = 0;
        for (int k = 0; k < NRO_TRANSF; ++k) {
            // El siguiente 'for' tiene por finalidad generar un numero 
            // aleatorio no uniforme sino de acuerdo a las probabilidades dadas
            // en el arreglo 'probs'.
            float r = aleat();              // Aleatorio entre 0 y 1.
            for (int s = 0; s < n; ++s) {   // ¿Donde cae el r?
                if( r < probs[s] ){
                    i = s; break;
                }
            }
            // El algoritmo correria mas rapido si a cada transformacion se le
            // asigna la misma probabilidad. En ese caso eliminamos el 'for'
            // anterior y lo reemplazamos con una sola sentencia:
            // i = rand() % n   //genera un numero entero entre 0 y n-1.
            m[i].Transform(p);  // Transforma el punto 'p' de acuerdo a la...
                                // ...matriz m[i].
        }
        float x, y, z, w;       // Las cordenadas de 'p' luego de NRO_TRANSF... 
        p.Get(x, y, z, w);      // ...transformaciones (solo importan x e y).
        Vec3f blanco(1, 1, 1);  // Color del punto a dibujarse en la imagen.
        
        // Guarda el punto en el buffer 'img'. Se hace una traslacion extra al
        // punto a dibujar "(x+width, y+height)" para evitar los problemas de 
        // desborde.
        img.SetPixel(x+width, y+height, blanco);
    }
    img.SaveTGA(output_file);   //Guarda la imagen con formato TGA.
}



/*****************************************************************************
 * FUNCION - leer_matriz
 * lee numeros de un archivo de entrada y los guarda en el arreglo lineal 'v'.
 *****************************************************************************/

void leer_matriz(char *input_file, float *v) {
    for (int j = 0; j < 16; ++j) {      // las matrices son de 4x4.
        if( (j+1)%4 == 0 || j >= 12 ) { // la cuarta columna y cuarta fila ...
            v[j] = 0;                   // ... de la matriz se igualan a cero.
        } else {
            source >> v[j];             // se lee un numero y se guarda en 'v'.
        }
    }
}

 Las salidas de este programa son una imágenes de IFS.
   

Archivos fuentes: http://www.mediafire.com/?fm7diwh8p9v1ba2

0 comentarios:

Publicar un comentario