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