📄 codigo_imprimible.txt
字号:
y no se debe gastar tiempo creando objetos (i.e. haciento VECTOR delta; delta = new VECTOR(); ...). El código original de MIT resolvió ésto usando unos flotantes float dx, dy, dz; e implementando una versión adicional de VECTOR::producto_punto() que recibe 3 floats. Se considera que esa solución es "fea" y que al ofrecer el nuevo método `VECTOR::producto_punto` se le desorganiza la mente al usuario/programador. Por eso, se resolvió implementar otra solución (tal vez igual de fea): añadir un nuevo atributo de clase en ESFERA, y utilizarlo como su fuese una variable estática de tipo VECTOR dentro del método. Esto no es bueno porque gasta memoria, pero ... que más podrá hacerse? Al menos el tiempo de ejecución se mantiene igual respecto al código original de MIT. NOTA: Comparar este método modificado con la versión original en la etapa 1, con la ayuda de un profiler. ... */ _static_delta.x = _centro.x - inout_rayo.origin.x; _static_delta.y = _centro.y - inout_rayo.origin.y; _static_delta.z = _centro.z - inout_rayo.origin.z; float v = inout_rayo.direction.producto_punto(_static_delta); // Do the following quick check to see if there is even a chance // that an intersection here might be closer than a previous one if ( v - _radio > inout_rayo.t ) { return false; } // Test if the inout_rayo actually intersects the sphere float t = _radio_al_cuadrado + v*v - _static_delta.x*_static_delta.x - _static_delta.y*_static_delta.y - _static_delta.z*_static_delta.z; if ( t < 0 ) { return false; } // Test if the intersection is in the positive // inout_rayo direction and it is the closest so far t = v - ((float) Math.sqrt(t)); if ( (t > inout_rayo.t) || (t < 0) ) { return false; } inout_rayo.t = t; return true; } /** Dado un `in_rayo` que se intersecta con este objeto (a una distancia `in_t` desde su origen), este método escribe en los vectores `out_p` y `out_n` la siguiente informaciońn: - out_p: las coordenadas del punto en el que el `in_rayo` intersecta al objeto. - out_n: un vector unitario con la normal de la superficie del objeto en el punto de intersección `out_p`. PRE: Las referencias a VECTOR out_p y out_n YA deben existir. El método solo coloca información dentro de ellos. */ public void informacion_extra(RAYO in_rayo, float in_t, VECTOR out_p, VECTOR out_n) { out_p.x = in_rayo.origin.x + in_t*in_rayo.direction.x; out_p.y = in_rayo.origin.y + in_t*in_rayo.direction.y; out_p.z = in_rayo.origin.z + in_t*in_rayo.direction.z; out_n.x = out_p.x - _centro.x; out_n.y = out_p.y - _centro.y; out_n.z = out_p.z - _centro.z; out_n.normalizar(); }}//===========================================================================//= EOF =//===========================================================================//===========================================================================package vitral.toolkits.media;import java.io.File;import java.io.FileOutputStream;import java.io.BufferedOutputStream;import vitral.toolkits.media.PIXEL_RGB;public class IMAGEN_RGB { private PIXEL_RGB data[]; private int x_tam; private int y_tam; /** Constructora de imagen. OJO: No la inicializa, antes de usarla debe llamarse el método init. */ public IMAGEN_RGB() { x_tam = 0; y_tam = 0; data = null; } /** Esta es la destructora de la clase. Si es usted tan gentil, por favor llame este metodo al final del alcance de su objeto. */ public void dispose() { if ( data != null ) { for ( int i = 0; i < x_tam*y_tam; i++ ) { if ( data[i] != null ) { data[i] = null; } } x_tam = 0; y_tam = 0; data = null; System.gc(); } } /** Inicialización del contenido de una imagen. Recibe el ancho y el alto que debe tener esta IMAGEN_RGB (nótese que una imagen puede asi cambiar de tamaño en cualquier momento) y asigna la memoria necesaria para hacerlo. OJO: NO inicializa la imagen, solo asigna la memoria necesaria. Este método retorna true si todo sale bien, o false si no se pudo asignar la cantidad de memoria necesaria para almacenar la imagen del tamaño seleccionado. */ public boolean init(int ancho, int alto) { try { data = new PIXEL_RGB[ancho * alto]; for ( int i = 0; i < ancho*alto; i++ ) { data[i] = new PIXEL_RGB(); } } catch (Exception e) { data = null; return false; } x_tam = ancho; y_tam = alto; return true; } /** Este método cambia la posicion (x, y) de la matriz de imagen y escribe en ella un pixel con coordenadas (r, g, b). */ public void putpixel(int x, int y, byte r, byte g, byte b) { int index = x_tam*y + x; data[index].r = r; data[index].g = g; data[index].b = b; } /** Este método retorna las coordenadas de color (r, g, b) para el pixel de la posicion (x, y) de la imagen. */ public PIXEL_RGB getpixel(int x, int y) { PIXEL_RGB p = new PIXEL_RGB(); int index = x_tam*y + x; p.r = data[index].r; p.g = data[index].g; p.b = data[index].b; return new PIXEL_RGB(); } /** Este método genera un patron de prueba visual tipo ajedrez, con un par de lineas de colores atravezandolo por el centro. Puede utilizarse para probar otras operaciones de imagenes, o para inicializarlas. */ public void crear_patron_de_prueba() { int i; int j; byte r; byte g; byte b; for ( i = 0; i < y_tam ; i++ ) { for ( j = 0; j < x_tam ; j++ ) { if ( ((i % 2 != 0) && (j % 2 == 0)) || ((j % 2 != 0) && (i % 2 == 0)) ) { r = (byte)255; g = (byte)255; b = (byte)255; } else { r = 0; g = 0; b = 0; } if ( i == y_tam/2 ) { r = (byte)255; g = 0; b = 0; } if ( j == x_tam/2) { r = 0; g = (byte)255; b = 0; } putpixel(j, i, r, g, b); } } } /** Este método escribe los contenidos de la imagen actual en un archivo de imagen en formato PPM RGB (i.e. P6). Retorna true si todo sale bien o false si algo falla (i.e. como un problema de permisos o que se acabe el espacio en el dispositivo de almacenamiento `fd`). */ public boolean exportar_ppm(File fd) { try { FileOutputStream escritor = new FileOutputStream(fd); String linea1 = "P6\n"; String linea2 = x_tam + " " + y_tam + "\n"; String linea3 = "255\n"; byte arr[]; arr = linea1.getBytes(); escritor.write(arr, 0, arr.length); arr = linea2.getBytes(); escritor.write(arr, 0, arr.length); arr = linea3.getBytes(); escritor.write(arr, 0, arr.length); for ( int i = 0; i < x_tam*y_tam; i++ ) { escritor.write(data[i].r); escritor.write(data[i].g); escritor.write(data[i].b); } } catch (Exception e) { return false; } return true; } public int xtam() { return x_tam; } public int ytam() { return y_tam; }}//===========================================================================//= EOF =//===========================================================================//===========================================================================package vitral.toolkits.media;public class PIXEL_RGB { public byte r; public byte g; public byte b;}//===========================================================================//= EOF =//=========================================================================== /*************************************************** * An instructional Ray-Tracing Renderer written * for MIT 6.837 Fall '98 by Leonard McMillan. * Modified by Tomas Lozano-Perez for Fall '01 * Modified by Oscar Chavarro for Spring '04 * FUSM 05061. ****************************************************///===========================================================================// Paquetes de java utilizados para el manejo de archivosimport java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.io.IOException;// Paquetes de java utilizados para la agregacion multipleimport java.util.Vector;// Paquetes internos al sistema de raytracing / modelamientoimport vitral.toolkits.media.IMAGEN_RGB;import vitral.framework.visual.RAYTRACER_MIT;import vitral.framework.UNIVERSO;import vitral.toolkits.entorno.CAMARA;public class RaytracerSimple {//- Atributos --------------------------------------------------------------- // Modelo de la aplicacion private UNIVERSO la_escena; private IMAGEN_RGB la_imagen_resultado; private RAYTRACER_MIT el_visualizador;//- Metodos ----------------------------------------------------------------- public RaytracerSimple() { // Inicializacion del modelo (independiente de swing) la_escena = new UNIVERSO(); } private void pintar_offline(String nombre_de_archivo) { //- 1. Crear una imagen ------------------------------------------- File fd = new File("./salida.ppm"); la_imagen_resultado = new IMAGEN_RGB(); if ( !la_imagen_resultado.init(640, 480) ) { System.err.println("Error creando la imagen!!"); System.exit(1); } //- 2. Calcular la imagen ----------------------------------------- // 2.1. Leer la escena System.out.println("Leyendo " + nombre_de_archivo); InputStream is = null; try { is = new FileInputStream(new File(nombre_de_archivo)); la_escena.leerArchivoDeEscena(is); is.close(); } catch (IOException e) { System.err.println("Error leyendo " + nombre_de_archivo); System.exit(-1); } // 2.2. Procesar la escena el_visualizador = new RAYTRACER_MIT(); la_escena.camara.procesar_resize(la_imagen_resultado.xtam(), la_imagen_resultado.ytam()); el_visualizador.ejecutar(la_imagen_resultado, la_escena); //- 3. Exportar la imagen a un archivo ---------------------------- if ( !la_imagen_resultado.exportar_ppm(fd) ) { System.err.println("Error grabando la imagen!!"); System.exit(1); } System.out.println("Se ha generado una imagen llamada salida.ppm"); System.out.println("En Unix / Linux puede verla con el comando"); System.out.println(" display salida.ppm"); //- 4. Destruir las estructuras de datos -------------------------- // 4.1. Destruir la imagen la_imagen_resultado.dispose(); la_imagen_resultado = null; // 4.2. Destruir la escena el_visualizador = null; la_escena.dispose(); la_escena = null; // 4.3. Sugerir al recolector de basura de Java que libere la memoria System.gc(); } public static void main(String args[]) { RaytracerSimple instancia = new RaytracerSimple(); if ( args.length < 1 ) { instancia.pintar_offline("./etc/balls.ray"); } else { instancia.pintar_offline(args[0]); } }}//===========================================================================//= EOF =//===========================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -