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