Vous êtes sur la page 1sur 84

I II I O ) 1 D 1 D D D D ID

Laboratorio No1 Com putacin Paralela Creacin de un motor de RayTracing

Asignatura: Profesor: Ayudante: Integrantes:

Computacin Paralela Oscar Magna V. Matas Valdenegro

Bruno Camousseigt - Nicols Veas - Miguel Vergara - Nicols Villarroel


-

Fecha: 04/07/2008

111 1

INTRODUCCIN

En la actualidad, la generacin de grficos por computadora est cada vez ms presente en nuestra vida cotidiana. En pelculas, anuncios publicitarios, videos musicales, videojuegos, etc. nos encontramos con escenas generadas por computador, las que, con el avance de la tecnologa se han vuelto cada vez ms complejas y de mayor calidad, hacindonos, en algunos casos, casi imposible distinguir entre una escena real y una generada por computador. Sin embargo, este incremento en la calidad de las escenas tambin ha trado consigo un aumento en los tiempos de procesamiento de estos algoritmos. Ray Tracing es el nombre de una tcnica muy popular que se utiliza para generar imgenes 3D 3D, suena mejor) por computador, destacando por la sencillez de su (tridimensionales o implementacin y la calidad de los resultados que se obtienen. La principal desventaja de esta, y otras tcnicas de renderizado es su gran lentitud, requirindose en algunos casos, varias horas para renderizar una escena compleja. Es por ello, que para acelerar el proceso cobra una importancia vital la paralelizacin de ste. Las empresas dedicadas al rubro de las pelculas animadas o efectos especiales, suelen contar con verdaderas granjas de computadores, donde cientos de ellos trabajan en paralelo para generar una sola escena. En el presente trabajo, implementaremos esta tcnica realizando un motor de Raytracing en Java. Utilizando las capacidades de comunicacin por sockets con las que cuenta este lenguaje, renderizaremos una escena en paralelo entre cuatro computadores y realizremos comparaciones de rendimiento entre un render hecho en forma paralela y otro realizado por un solo computador.

ABSTRACT

Nowadays, computer generated images (CGI) are completely immersed in our lives. In movies, advertising, music videos or videogames we can find computer generated scenes, which, with the progress of technology had become more complex and detailed, to the point of making us unable to distinguish between a real life scene and a computer generated scene. However, this substantial quality increment has caused a substantial increase on the processing times of those algorithms. Raytracing is the name of one of the most popular rendering algorithms, due to its ease of implementation and the great quality of the results. The main disadvantage of this technique, and other advanced rendering techniques, is the low speed they have. Even with the cpu power of today computers, rendering a single image can take hours or even days on a single machine. That's why, to speed up the process, parallelization techniques play a fundamental role. Companies specialized on special effects and animated movie business have the so called "Rendering Farmes" rooms with hundreds of computers working in parallel to render a single scene. On this work, we will implement the parallelization on a Raytracing Rendering engine developed in Java. By using the socket communication capabilities of Java, we will render an animated raytraced scene using four computers. And then, we will compare the results of the same scene rendered on a single computer.

11

OBJETIVOS

o
- Comprender los aspectos bsicos de la representacin de imgenes tridimensionales en computador Estudiar los fundamentos matemticos en los que se basa la tcnica del Raytracing Desarrollar un motor de Raytracing capaz de . - Adaptar el motor de Raytracing para que ste sea capaz de realizar el trabajo tanto en serie como en paralelo en un ambiente cluster.

Realizar mediciones para comparar los tiempos obtenidos entre el trabajo realizado en serie y el trabajo realizado en paralelo.

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

1 1

I I MARCO TEORICO

Representacin de Imgenes Tridimensionales.

Una figura tridimensional puede ser generada de dos maneras. Una es en forma implcita, declarando la figura a partir de una ecuacin matemtica, lo cual nos permite crear desde simples objetos como esferas o cilindros, hasta complejas figuras fractales.

IP

La segunda forma para generar una figura tridimensional es en forma explcita. Figuras que no pueden ser creadas a partir de funciones matemticas, como por ejemplo un cubo o el modelo tridimensional de un ser humano, deben ser declarados explcitamente. Las figuras que son creadas de esta forma se conforman a partir de cuadrantes planos (quads), que ubicados uno junto a otro en el espacio forman una figura tridimensional. Una figura tridimensional declarada de esta forma, cuenta con cuatro parmetros bsicos. Vrtices . Aristas Caras . Normales

IP D

1 1

Los cuales podemos identificar en esta figura de un cubo.

1 1

1 1 1
ARISTA

1 1 1 1

1 1
Los vrtices definen los extremos de cada cuadrante. Las aristas son las lneas que unen los vrtices entre s. Las caras son la superficie visible del cuadrante (o quad) que est delimitada por los vrtices. Y la normal es un vector perpendicular a cada una de las caras, cuyo objetivo es indicar cul es la superficie visible del cuadrante, ya que, superficies en una representacin computacional, a diferencia de en el mundo real, tienen un solo lado. Sin embargo, falta un elemento indispensable para poder representar una figura tridimensional. Con los que elementos que hemos mencionado tan solo podramos ver lo que se conoce como una "malla poligonal". En la siguiente imagen podemos ver la malla poligonal de la carrocera de un vehculo.

wer,

1 1 1 1 1 1 1 1 1 1 1
Para poder representar objetos con una superficie slida, debemos agregar un elemento ms, que nos permite definir caractersticas como el color o el brillo de un objeto. Este elemento recibe el nombre de material.

1 1

1 1 1 1 1 1 1

Materiales
Para representar una imagen tridimensional, el aspecto bsico que debemos definir, es el material del cual estn formados los objetos en nuestra escena. Existen tres elementos bsicos que son inherentes a cualquier tipo de material que queramos representar. Para representar una imagen tridimensional, debemos describir las caractersticas de los materiales con el que estn formados los objetos que se encuentran en la escena. Para describir un material recurrimos a los elementos bsicos, inherentes a cualquier tipo de material que deseemos representar. Los elementos bsicos son tres, existen muchos ms que nos permiten representar materiales muchsimo mas complejos, pero nos limitaremos nicamente a los componentes elementales, que son los siguientes:

1
Color Difuso (Diffuse Color): El color difuso es el color ms distintivo de un objeto. Bsicamente, es el color que vemos cuando un objeto est sometido a luz blanca, y es percibido por el ser humano como el color del objeto en s ms que el color que vemos al reflejarse la luz sobre l. Por ejemplo, si decimos que una pelota es roja, es porque su color difuso es rojo; y es rojo porque est fabricada con un material, o cubierta de una pintura que tiene la caracterstica de hacer que la luz blanca que incide sobre ella sea reflejada y percibida por el ser humano de color rojo.

1 1 1 1 1 1 1 1 1 1

Especularidad. La especularidad determina qu tan brillante es un objeto, y la forma en que la luz se difumina sobre la superficie de ste. Por ejemplo, tomamos una linterna e iluminamos directamente una pelota de goma, veremos que algo como esto.

1 1 1 1 1 1
Las propiedades de la superficie hacen que la mayor parte de la luz sea absorbida y difuminada sobre el objeto, y slo una pequea cantidad de luz sea reflejada. Cuando esto ocurre, decimos que el material que conforma el objeto tiene una baja especularidad En cambio, si tomamos un objeto con una superficie perfectamente lisa y lustrada, como una bola de metal cromado o una bola de billar, veremos algo como esto

1 1 1

1 1 1 1 1 1

La superficie, al ser ms lisa, permite que la luz rebote de forma ms integra sobre el objeto, y sea mucho menos absorbida o difuminada por ste. Cuando esto ocurre, decimos que el material tiene una alta especularidad. La especularidad, adems de indicarnos la forma en que la luz incide sobre un objeto, tambin nos indica el color con que la luz es reflejada por ste. Si un objeto es iluminado por una luz blanca, no necesariamente la luz que ste refleje ser de color blanco. Las propiedades fisicoqumicas del material que conforma la superficie del objeto pueden hacer que la luz incidente cambie de color al entrar en contacto con la superficie En este ejemplo, el objeto es iluminado con una luz blanca, pero las propiedades del material de ste hacen que la luz se torne de color anaranjado al ser reflejada.

1 1 1 1 1 1

Luz ambiental Finalmente, la luz ambiente nos indica, el color de la luz que rodea a todos los objetos en la escena. La luz ambiental es una luz que siempre est presente, y se mezcla con el resto de las luces que situemos en la escena y el propio color difuso para crear el color definitivo que veremos en la superficie del objeto.

1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Estos tres elementos bsicos estn presentes en cualquier tipo de material Materiales ms complejos como cristales u otras superficies translcidas necesitan de otros elementos como por ejemplo el color de filtro, que nos indica el color que adquiere la luz al atravesar un objeto; materiales que generen luz propia tambin requieren un componente adicional para describir la intensidad y el color de dicha luz. Sin embargo, en este trabajo slo utilizaremos materiales bsicos por lo cual no se describirn en detalle otros componentes.

Ray Tracing
Ray Tracing es una tcnica para generar una imagen a partir de escenas tridimensionales, en donde las imgenes son generadas trazando la trayectoria de los rayos de luz en una escena. Esta tcnica es capaz de producir imgenes con un alto grado de fotorealismo, sin embargo, el costo computacional en el que incurre esta tcnica es muy alto. Por lo tanto, esta tcnica es utilizada principalmente para generar escenas pre-renderizadas, como fotografas o secuencias de video. En otro tipo de aplicaciones como simulaciones arquitectnicas o videojuegos, esta tcnica no es utilizada, ya que lo que se busca es obtener resultados en tiempo real en donde la velocidad de renderizado es un factor crucial; en las simulaciones en tiempo real deben generarse un promedio de 30 imgenes por segundo para que el usuario tenga una experiencia satisfactoria.

En el Ray Tracing, la trayectoria de los rayos de luz es trazada desde un ojo, o cmara imaginaria a travs de cada pixel de una pantalla virtual, y calculando el color del objeto visible a travs de dicha pantalla. En el esquema que vemos ms abajo, se ilustra el proceso de Ray Tracing. La cmara corresponde al ojo del observador, desde la cual se trazan los rayos de luz. stos pasan a travs de una "pantalla virtual" y en esa pantalla se calcula el color del pixel, de acuerdo al color que tenga el objeto sobre el punto en el cual incidi el rayo trazado. El color del objeto en ese punto est afectado por factores como la luz ambiental u otros tipos de fuentes de luz. Finalmente, todos los pixeles dibujados en esta "pantalla virtual" se convierten en la imagen final.

Pantalla Virtual Camara

Fuente de Luz

Ra o Trazado

ob eto de la Escena

Las escenas que son generadas utilizando Ray Tracing pueden ser descritas matemticamente por un programador, o generadas por un artista visual utilizando herramientas de diseo tridimensional como 3D Studio Max, Maya, Softlmage, Lightwave, Blender, etc. Al trazar cada rayo, el algoritmo verifica si ste intersecta algn objeto de la escena. Una vez que el objeto ms cercano al lugar de origen del rayo es identificado, el algoritmo calcula la cantidad de luz (luces ambientales u otro tipo de luz presente en la escena) incidente en dicho punto, las propiedades de la superficie del material del objeto en cuestin, y combina toda esta informacin para calcular el color definitivo del pixel que ser pintado en la pantalla virtual. Es frecuente que en las escenas en las que se realiza Ray Tracing hayan objetos que tengan materiales con superficies reflectantes (como es el caso de la escena que presentamos en este proyecto) o translcidos. En este caso, el algoritmo debe calcular la trayectoria que sigue el rayo despus de rebotar sobre una superficie reflectante o como se refracta al atravesar una superficie translcida.

Cuatro primitivas geomtricas, reflejndose entre s por medio de Ray Tracing.

Es interesante mencionar que en la tcnica del Ray Tracing, los rayos son trazados desde el observador hacia los objetos de la escena, contrario a lo que ocurre en la realidad, donde el observador percibe los rayos de luz que llegan a sus ojos desde los objetos y fuentes de luz. Hacer esto optimiza el proceso de representacin de la imagen, ya que en la naturaleza, la mayora de los rayos existentes en una escena no llegan al observador y trazar la trayectoria de rayos que en nada incidiran en la imagen final sera un desperdicio enorme de recursos. Sin embargo, existe una tcnica de renderizado en donde los rayos de luz son trazados desde las fuentes de luz hasta el observador. Esta tcnica es llamada "Mapeado de Fotones". Es muchsimo ms lenta que el Ray Tracing, pero en algunos casos es posible obtener resultados mucho ms realistas.

Otras tcnicas de renderizado


Ray Tracing no es la nica tcnica de renderizado existente. En el punto anterior mencionbamos la tcnica de Mapeado de Fotones (Photon Mapping) y adelantbamos que en simulaciones en tiempo real como videojuegos no se utilzaza Ray Tracing. El nombre de la tcnica de renderizado ms utilizada en simulaciones en tiempo real es el "Scanline Rendering". Explicaremos a grandes rasgos en que consiste cada tcnica.

Photon Mapping. El Mapeado de Fotones funciona de una manera similar al procedimiento de Ray Tracing. Mientras que el Ray Tracing trabaja con rayos que parten del foco de proyeccin, el Mapeado de Fotones aprovecha los rayos que parten de la fuente de luz. El Mapeado de Fotones trabaja con partculas virtuales, los llamados "fotones", desde los cuales la luz irradia al espacio. Si estos inciden en una superficie, son reflejados y los valores de iluminacin son guardados en ese lugar. En esta tcnica, a cada fotn se le da aleatoriamente una "energa inicial", la cual se reduce cada vez que un fotn impacta y es reflejado por una superficie. Cuando la energa de todos los fotones es cero el mapa de fotones est terminado. La informacin generada por este proceso es almacenada en un archivo, (el llamado Photon map) y este mapa de fotones es aplicado internamente a la escena cuando se realiza el render. La ventaja de almacenar la informacin de los fotones en un archivo es que, es posible cambiar la posicin de la cmara y volver a realizar el render sin tener que calcular la informacin de los fotones, lo que hace que el proceso sea mucho ms rpido (siempre que solamente se cambie la posicin de la cmara. Cambiar de posicin cualquier objeto o la fuente de luz alterara completamente la trayectoria de los fotones y el mapa tendra que volver a calcularse). Cuanto mayor sea el nmero de fotones presentes en el modelo, tanto mayor la fidelidad con la cual se modelar el comportamiento de la luz y mejor ser el resultado final del render. Pero tambin, obviamente, se incrementan los tiempos de procesamiento.

El Photon Mapping permite recrear un fenmeno ptico que no es posible recrear utilizando Ray Tracing. Este fenmeno es conocido como " Refracciones Custicas " (o simplemente Caustics en ingls). Cuando la luz pasa a travs de un objeto semitransparente, la trayectoria de los rayos es alterada, y dependiendo de la forma que tenga el objeto, los rayos de luz que son desviados pueden enfocarse y concentrarse en un nico punto. Todos hemos visto este efecto alguna vez al poner una lupa al sol y concentrar los rayos en un solo punto. En la siguiente imagen se pueden ver las Refracciones Custicas que produce la esfera de cristal sobre la superficie en el centro de su sombra.

Actualmente, el Photon Mapping puede usarse en conjunto con el Ray Tracing. Usando el mapa de fotones generado por la primera tcnica, se pueden obtener mucho mejores resultados cuando se realiza el Ray Tracing, ya que ste ultimo suele tener problemas cuando las escenas tienen fuentes de luz muy pequeas o de poca intensidad, las cuales no son representadas correctamente.

Aqu podemos ver una imagen renderizada slo con Ray Tracing (izquierda) y otra con Ray Tracing mejorado en conjunto con Photon Mapping (derecha).

1 1 1 1

1 1 1 1

Scanline Rendering. El Scanline Rendering, como mencionbamos anteriormente, es la tcnica de renderizado ms ampliamente usada cuando lo primordial es la rapidez. Est tcnica se basa en el renderizado "lnea a lnea", en lugar de un renderizado pixel a pixel como ocurre con las tcnicas anteriores, donde se calcula el color y la luminosidad que tendr la imagen un pixel a la vez. Todos los polgonos que sern renderizados en la escena son ordenados de acuerdo a su coordenada "Y" determinando as cul ser renderizado primero (la escena se renderiza desde arriba hacia abajo) y luego, se genera una lista. Una vez ordenada la escena se procede a renderizar la imagen. Cada lnea de la imagen es calculada usando la interseccin entre la "Scanline" con los polgonos que estn al frente en esta lista, cuando la interseccin se produce el color de los pixeles en la lnea se calcula segn las fuentes de luz, el ngulo que tienen stas con la normal del polgono, el material del objeto, etc. Para optimizar el proceso y no calcular polgonos que ya no son visibles, esta lista es constantemente actualizada para descartar polgonos que ya no son visibles, segn la Scanline progresa descendiendo por la imagen. La ventaja de esta tcnica es que no es necesario trasladar todos los vrtices de la memoria principal a la memoria cach, tan slo los vrtices que definan aristas que intersectan con la Scanline necesitan estar en memoria y cada vrtice es ledo una sola vez. Como la memoria principal es mucho mas lenta comparada con el enlace entre la CPU y la memoria cach, evitar acceder a vrtices innecesarios en la memoria principal brinda un aumento considerable en la velocidad.

La calidad de una escena renderizada con Scanline rendering es considerablemente menor a una renderizada con Ray Tracing o Photon Mapping, pero la altsima velocidad de renderizado compensa esta desventaja. En la imagen adjunta vemos una comparacin entre una misma escena renderizada con Scanline y Ray Tracing con Mapeo de Fotones

La calidad de la escena renderizada con Scanline es mucho menor, sin embargo fue renderizada en 0.5 segundos, a diferencia de los 87 segundos que tom la misma escena renderizada utilizando Ray Tracing y un Mapa de Fotones. (La escena fue renderizada utilizando el software 3D Studo Max 8 y el motor de RayTracing Mental Ray).


Situacin Actual

Hoy en da casi todos los grandes paquetes comerciales de modelado y diseo grfico implementan Ray Tracing, ya sea nativamente o como un aadido. Aunque tambin se puede encontrar en programas libres y de cdigo abierto, como el veterano POV-Ray, o el ms reciente YafRay, que est teniendo una gran aceptacin gracias a su integracin con modeladores como Wings 3D y Blender. Actualmente hacer un programa simple que implemente Ray Tracing resulta una tarea sencilla, ya que existe bastante informacin al respecto, y adems es fcil encontrar cdigo fuente listo para descargar de Internet. Incluso se suele exigir como prctica obligatoria a realizar en algunos cursos de programacin grfica de ciertas facultades. Hoy en da, se trabaja bastante en las tcnicas de Ray Tracing en tiempo real, denotadas normalmente por las siglas inglesas RTRT. Estas tcnicas tratan de reducir el impacto de uno de los mayores problemas del Ray Tracing, que es el enorme nmero de clculos a realizar para obtener imgenes de calidad, lo que ha llevado siempre a considerarla como una tcnica a realizar off-line, desatendida, en vez de on-line, en tiempo real. En bastantes sitios se empieza a hablar de que el futuro de los engines grficos 3D pasa por utilizar Ray Tracing en tiempo real como nica forma de aumentar la calidad de las imgenes generadas y aadir nuevos efectos. Inclusive, apostando por la incorporacin de chips especficamente diseados para implementar Ray Tracing en las tarjetas grficas.

e
e e O

1 e e O

e e O

Fundamentos Matemticos del Ray Tracing

En el punto anterior explicamos algunos aspectos bsicos de la computacin grfica, y explicamos adems, a grandes rasgos, como funciona el algoritmo del Ray Tracing. En este punto profundizaremos ms en los fundamentos matemticos en los que se basa este algoritmo. Ray Tracing, al fin y al cabo, no es ms que un algoritmo. Admite unas entradas, realiza un proceso y genera unas salidas. Como entradas del algoritmo estaran la posicin y caractersticas fsicas de cada uno de los objetos que forman la escena. Seguira la ubicacin, intensidad y tipo de las fuentes de luz presentes en la misma. Despus el modelo de iluminacin a utilizar, que describira como calcular el color en un punto de la superficie de un objeto. A continuacin la posicin y direccin desde la que se quiere representar la escena, es decir, la posicin del observador. Y en ltimo lugar la ubicacin y dimensiones del plano de proyeccin sobre el que ha de quedar reflejada la imagen, que normalmente equivale a la pantalla del ordenador donde se ver finalmente el resultado. En cuanto al algoritmo en s mismo, decir que el proceso bsico se basa en trazar un rayo a travs de cada uno de los pixels del plano de proyeccin, tomando como origen de los rayos la posicin del observador. Y para cada uno de estos rayos trazados estudiar si se produce una interseccin con alguno de los objetos de la escena. Si no se encuentra ningn objeto se termina el proceso para ese pxel y se le asigna un color de fondo por defecto. Por el contrario, si se encuentra un objeto, se miran sus caractersticas fsicas y se decide que hacer en funcin del modelo de iluminacin. En la prctica, todos los elementos que intervienen en el proceso se tratan como entidades matemticas muy simples. Los objetos se definen mediante primitivas geomtricas como esferas, planos o polgonos, aunque se tiende a utilizar mallas de tringulos ya que asi funcionan la mayora de programas de modelado actuales. Los rayos se tratan como vectores, con un punto de origen y una direccin de propagacin. Y por tanto, el clculo de intersecciones entre rayos y objetos se reduce a la resolucin de ecuaciones en las que intervienen vectores y primitivas.

111.

e e e e e e e e

e e e e

e
Ray Tracing: Barrido del Plano de Proyeccin
En este punto se detalla el proceso de construccin del algoritmo encargado de realizar el barrido con rayos del plano de proyeccin en un sistema bsico de Ray Tracing. Indicando, uno a uno, qu parmetros de entrada son necesarios, y qu valores se calculan a partir de ellos. Siendo el objetivo final generar un rayo por cada pixel. Rayos que partan de la posicin del observador, y pasen por el centro de cada uno de los pixeles del plano de proyeccin. El plano de proyeccin es la superficie sobre la que representa la imagen bidimensional generada a partir de la escena definida tridimensionalmente. En la prctica el plano tiene una extensin continua ilimitada, pero de l slo se toma una pequea regin, normalmente rectngular, a modo de ventana. Esta ventana se divide a su vez en una cuadrcula rectngular de filas y columnas en la que cada celda representa un pixel al que puede asignrsele un color individualmente.

e
Sistema de Referencia
En lo sucesivo consideraremos un sistema de referencia en el que el eje horizontal X crece de izquierda a derecha, el vertical Y de abajo hacia arriba, y los valores sobre el eje de profundidad Z aumentan a medida que se penetra en el plano XY (adentrndose en la pantalla del monitor, si se toma este como referencia).

e e

e e e

e e e e

e e e e e

Direccin en la que mira el Observador


Los primeros parmetros de entrada al sistema a considerar son la posicin que ocupa el observador y el punto concreto al que mira. Normalmente el observador de la escena recibe el nombre de "cmara". Denotaremos con EYE a la posicin del observador, y LOOKAT al punto concreto que mira.


y
VIEW

EYE

LOOKAT

El primer valor calculado ser la direccin VIEW en la que mira el observador, que es la direccin del vector que une EYE con LOOKAT: VIEW = (LOOKAT - EYE) / ILOOKAT - EYEI La mayora de los vectores que se calculen se normalizarn para simplificar clculos posteriores. Es decir, se dividirn por su mdulo (longitud) para convertirlos en vectores unitarios. Los vectores unitarios tienen mdulo unidad, lo que interesa de ellos es su direccin y sentido. Los parmetros EYE y LOOKAT se pueden inicializar con valores por defecto evitando tener que pedir al usuario que los introduzca. Por ejemplo, EYE = (O, O, O) y LOOKAT = (1, 1, 1) situan al observador en el origen de coordenadas mirando a un punto situado arriba a su derecha. Aunque lo normal es que se obligue a introducir al menos uno de estos dos valores. En ningn caso EYE y LOOKAT deben ser iguales, ya que ello equivaldra a decir que el observador observa la misma posicin que ocupa, lo que es fsicamente imposible. Y matemticamente equivaldra a que la longitud de VIEW fuese cero, o sea, un punto en vez de un vector, no se podra realizar la divisin para normalizarlo.

1 1 1

1 1

Arriba y Abajo

El siguiente parmetro de entrada requiere una explicacin un poco ms detallada. Se trata de indicar cual es el plano vertical que considera el observador. Intentar explicarlo con un ejemplo. Supongamos que quiere hacer una fotografa. Se ubica, apunta al objetivo, y retrocede o avanza para captar mejor el motivo a fotografiar. Sin embargo, a veces no es posible incluir todo lo observable en la fotografa, no cabe. Como cuando se retrata a una persona de pie. Si se apunta con la cmara en su postura natural las piernas salen "cortadas". Por lo que se utiliza el truco de girar la cmara y ponerla en posicin vertical para que la persona salga completa, a lo ancho de la fotografa en vez de a lo alto. Lo que estaba "arriba" ahora est en un lateral. El observador de una escena, al igual que un fotgrafo, debe especificar que parte de la escena debe quedar "arriba", para que no exista ningn tipo de ambigedad con respecto al resultado buscado. Para ello se define otro parmetro de entrada al sistema, el vector unitario UP que apunta hacia "arriba". El vector UP suele tomar el valor (0, 1, 0) por defecto, es decir, apuntando hacia el "cielo". Y como se ver en el siguiente apartado, su direccin no tiene porque ser perpendicular (formar un ngulo recto) a la direccin en la que mira el observador.

e
Los ejes de coordenadas se definen matemticamente con un punto origen, que ya se tiene (CENTER), y tres vectores, del que tambin se tiene uno (VIEW). El vector VIEW permite moverse en profundidad con respecto al plano de proyeccin, y el eje de coordenadas se completar aadiendo dos nuevos vectores, HORZ y VERT, que permitan moverse horizontal y verticalmente. El vector HORZ es normal al plano que contiene a los vectores unitarios UP y VIEW, por lo que su clculo es sencillo. Se obtiene del producto cruzado (vectorial) de UP por VIEW: HORZ = (UP x VIEW) / UP x VIEWI Se tiene que tener en cuenta que UP y VIEW no pueden tener la misma direccin, ya que HORZ no podra calcularse. Este caso ocurre cuando se indica que la direccin en la que mira el observador es la misma que la direccin indicada para "arriba". Un sistema as definido no es coherente. Por su parte, el vector VERT es normal al plano que contiene a los vectores unitarios VIEW y HORZ. Por lo que puede obtenerse del producto cruzado de ambos vectores: VERT = (VIEW x HORZ) / 'VIEW x HORZI Este punto CENTER se utilizar como origen de un eje de coordenadas locales sobre la ventana en la que se proyecta la escena, es decir, un eje centrado en ella que ser, a la postre, el que permita moverse por ella recorriendo todos los pixels que la forman.

La explicacin de qu consiste el producto vectorial queda fuera del alcance de este artculo, puede encontrarse en cualquier tutorial bsico de clculo de vectores. Baste decir que dados dos vectores A = (ax, ay, az) y B = (bx, by, bz), el producto vectorial es el vector resultante de evaluar la siguiente expresin:

11

Tamao de la Ventana de Proyeccin

El tamao de la ventana de proyeccin es el tamao del rectngulo en el que se impresiona la escena observada. Para su clculo necesitamos introducir dos nuevos parmetros de entrada, dos ngulos. El ngulo de visin del observador en el plano horizontal hfov, y el ngulo de visin del observador en el plano vertical vfov. La nomenclatura de los nombres procede del ingls "Field Of View" (Campo de Visin). Estos ngulos determinan el ancho y alto de la ventana de proyeccin en la medida que las partes visibles de la escena sern slo aquellas que se encuentren dentro de estos ngulos de visin. Para calcular el ancho de la ventana de proyeccin se debe notar que el observador y el centro de la ventana se encuentran ambos contenidos dentro del plano que definen VIEW y HORZ, por lo que el clculo se puede reducir a un problema de trigonometra 2D sobre este plano:

dis

EYE

hsize

r
HOR2

VIEW

5 Resolviendo el tringulo superior de la imagen se obtiene el ancho del campo de visin: TAN(hfov / 2) = (hsize / 2) / dis hsize = 2 * dis * TAN(hfov / 2) Y siguiendo el mismo razonamiento se obtiene la altura del campo de visin: vsize = 2 * dis * TAN(vfov / 2) Los dos ngulos pueden tomar un mismo valor de entrada por defecto, unos 45 grados, lo que hara que se genere una ventana de proyeccin cuadrada. Algunos sistemas prefieren que se indique el aspect ratio (cociente entre el ancho y alto) de la imagen deseada, y calcular los ngulos a partir de esta cantidad.

Tamao y Posicin de un Pixel

El ltimo parmetro de entrada al sistema es la resolucin (tamao) en pixels que se quiere que tenga la imagen resultante, width x height. Con la resolucin se determina el nmero de pixels totales y el tamao de cada pixel individual en la ventana de proyeccin.

El tamao horizontal de un pixel en la ventana de proyeccin se calcula diviendo el tamao horizontal de la ventana de proyeccin por el ancho en pixels de la imagen deseada: hpixel = hsize / width

Y de forma anloga se obtiene el tamao vertical de un pixel: vpixel = vsize / height

Como parmetro de entrada, la resolucin puede tomar un valor por defecto, por ejemplo 100x100, o se puede obligar a introducirla obligatoriamente. En cualquier caso, tanto la resolucin vertical como la horizontal deben ser mayores que cero. Sin fueran cero no se podra realizar la divisin para obtener el tamao de un pixel, sera como decir que los pixels no tienen dimensiones.

hpixel
4

hsize
14 01

vpixe

ORIGIN

<1=
CENTER vsize

VERT 1 +HOR2


1111

De entre todos los pixels interesa destacar la posicin del que se encuentra en la esquina superior izquierda de la ventana de proyeccin, porque ser el primero en visitarse. Su ubicacin se obtiene partiendo del centro de la ventana y desplazndose hacia la izquierda y hacia arriba una distancia equivalente a la mitad de la resolucin deseada: ORIGIN = CENTER - ( ( (width - 1) / 2) * hpixel * HORZ) + ( ( (height 1) / 2) * vpixel *VERT)

Y este mismo criterio se puede aplicar al resto de pixels con el objetivo de obtener una expresin ms genrica que obtenga el centro de cualquier pixel (i, j) dentro de la ventana de proyeccin: PIXEL (i, j) = ORIGIN + (i * hpixel * HORZ) - (j * vpixel * VERT)

Notar que en esta ltima expresin la direccin de avance vertical est invertida, debido a que se parte de ORIGIN, y que la numeracin vertical habitual de los pixels crece de arriba hacia abajo. El pixel (O, O) est localizado en la esquina superior izquierda y el pixel (width - 1, height - 1) en la esquina inferior derecha.

Generacin de Rayos

le

e
Una vez definido completamente el sistema, se puede proceder al barrido de la ventana de proyeccin con rayos, mediante dos bucles que recorran los pixels de izquierda a derecha y de arriba hacia abajo, generando para cada pixel (i, j) un rayo que parta de la posicin del observador y atraviese el centro del pixel: FOR j = O TO height - 1 FOR i = O TO width - 1 RAY (i, j, t) = EYE + ( (PIXEL(i, j) - EYE) / IPIXEL (i, j) EYEI ) * t NEXT i NEXT j Definidos de esta forma, los rayos no son ms que vectores con un origen, el punto EYE, y una direccin, la que une el origen con el centro del pixel. El parmetro t de la ecuacin del rayo nos permite movernos sobre la lnea recta imaginaria que define el mismo. Un valor cero nos sita en el origen, un valor negativo por detrs de este y uno positivo por delante. Este parmetro t ser adems el que se utilice para el clculo de intersecciones con los objetos de la escena.

En este punto se explicar el mtodo para que los ratos se intersecten con una esfera. Se ver una solucin algebraica sencilla, siempre tenindose en cuenta que no es la nica que se puede utilizar, existen otras, como las geomtricas, ms eficientes, que pueden encontrarse en los textos de referencia.

Ray Tracinq: Interseccin y Normal a una Esfera

Interseccin con una Esfera


Una esfera se define por su centro C = (cx, cy, cz) y su radio r, de forma que los puntos (x, y, z) sobre su superficie son aquellos que verifican la siguiente ecuacin: (x - cx)A2 + (y - cy)A2 + (z - cz)A2 = rA2 Bsicamente, lo que dice la expresin matemtica es que la superficie de una esfera es el conjunto de todos los puntos que se encuentran a una distancia r de un punto C.

111

e e e e
La expresin cannica se obtiene considerando una esfera con centro (O, O, O) y radio 1: ( x - 0)^2 + (y - 0)1'2 + (z - 0)1\2 = 1 A2 xA2 + yA2 + zA2 = 1

e e e /

Un rayo puede intersectar con una esfera en uno o dos puntos de la superficie de la misma. En dos puntos cuando el rayo atraviesa la esfera, con una interseccin de entrada y otra de salida. Y en un nico punto cuando, o bien el rayo tiene su origen en el interior de la esfera, y slo presenta una interseccin de salida, o bien el rayo es tangente a la esfera, es decir, que la toca en un nico punto de su superficie.

ri://<

sz,/

Los puntos de interseccin entre una esfera cannica y un rayo transformado R'(t) = O' + D' * t, de origen O' = (ox', oy', oz') y vector direccin normalizado D' = (dx', dy', dz'), son aquellos puntos (x, y, z) sobre la superficie de la esfera que verifican la ecuacin del rayo: (ox' + dx' *t)A2 + (oy' + dy' * t)A2 + (oz' + dz' * t)A2 = 1 Resolviendo por t:
ox'A2 + (dx' * t)A2 + 2 * ox' *dx' * t + oy'A2 + (dy' * t)A2 + 2 *oy' * dy' * t + oz'A2 + (dz' * t)A2 + 2 * oz' * dz' * t = 1 (dx1A2 + dy'A2 + diA2) * tA2 + 2 * (ox' * dx' + oy' * dy' + oz' * dz') * t + ox'A2 + oy'A2 + oz'A2 - 1 =0

Expresin que puede simplificarse recordando que el vector D' est normalizado, de forma que su mdulo es 1:
ID'i = SCIRT(dx'A2 + dy'A2 + dz'A2) = 1 dx1^2 + dy1^2 + diA2 = 1

Sustituyendo: tA2 + 2 * (ox' *dx' + oy' * dy' + oz' * dz') * t +


ox'A2 + or2 + oz'A2 - 1 =0

e
e

La expresin resultante es una ecuacin de segundo grado de la forma: a*t^ 2+b*t+c=0

Donde: a= 1 b = 2 * (ox' *dx' + oy' *dy' + oz' * di) c = ox'A2 + oy'A2 + oz1^2 1

Y con dos posibles soluciones para t: tO' = (-b + SQRT(bA2 - 4 * a c) ) / (2 * a) tl' = (-b 2-4 4 * *c) ) / (2 *a) a*

Soluciones que pueden simplificarse ya que a = 1: tO' = (-b + SQRT(bA2 - 4 * c) ) / 2 tl' = (-b - SQRT(b^2 - 4 * c) ) / 2

Por otra parte, considerando la forma que tiene la expresin de b: b = 2 * k, con k = ox' * dx' + oy' * dy' + oz'* dz'

Puede simplificarse t0', por ejemplo, igual sera para tl': tO' = ( -(2 * k) + SQRT( (2 * k)^2 - 4 * c) ) / 2 tO' = ( -(2 * k) + SQRT(4 *102 - 4 * c) ) / 2 tO' = ( -(2 * k) + SORT(4 * (102 - c) ) / 2 tO' = ( -(2 * k) + 2* SQRT(kA2 - c) ) / 2 tO' = -k + SQRT(k^2 - c)

o
Con lo que finalmente: tO' = -k + SQRT(kA2 - c) t1' = -k - SQRT(k"2 - c)

Si el discriminante (la expresin dentro de la raz cuadrada) es menor que cero, no puede resolverse la ecuacin, no existen soluciones reales, por lo que no se produce interseccin. Si el discriminante es cero, entonces slo existe una solucin, el rayo es tangente a la esfera, y puede tomarse tO' t1' indistintamente. Por ltimo, si el discriminante es mayor que cero entonces hay dos posibles soluciones, siendo la positiva de menor valor la ms cercana al origen del rayo. Cada valor ti' vlido encontrado se corregira para llevarlo de vuelta correctamente al espacio de coordenadas globales de la escena, dividindolo por la longitud del vector direccin del rayo

original por la inversa de la matriz de transformacin del objeto, y se aplicara en la ecuacin del rayo para obtener el punto I intersectado: ti = ti' 11D * INV(M)I I = R(ti)

Normal al Punto de Interseccin con una Esfera

La normal a un punto de interseccin I sobre la superficie de una esfera es el vector unitario Ni que une el centro de la esfera C con dicho punto de la superficie:

Ni = (I - C) / II - CI
Sin embargo, esto es slo vlido considerando el centro real de la esfera en el espacio de coordenadas globales de la escena. El resultado no ser vlido si se toma la expresin de la esfera cannica en la que el centro es (O, O, O). Si se quiere seguir considerando el espacio local de la esfera entonces se tiene que transformar el punto 1 utilizando la inversa de la matriz de transformacin M antes de aplicarlo en la expresin de la normal: = i* INV(M)

O, alternativamente, evaluando el valor ti' encontrado en la expresin del rayo transformado: = R'(ti')

1
Independientemente de cual de los dos mtodos se utilice, se deber usar la traspuesta de la inversa de la matriz de transformaciones para corregir el ngulo de la normal:

Ni = ( (I' - C) * TRAS( INV(M) ) ) ) / 1(1' - C) * TRAS( INV(M)


Y teniendo en cuenta que C = (O, O, O) en la expresin cannica de la esfera:

Ni = (I' * TRAS( INV(M) ) ) / 11' * TRAS( INV(M) )1

Ray Tracinq: Plano, Tringulo y Cubo


En esta seccin se presenta el clculo de intersecciones, y obtencin de normales, de un rayo con un plano, un tringulo y un cubo. Estos tres objetos se estudian a un mismo tiempo porque todos se basan en el primero de ellos, es decir, el plano. Un tringulo es una regin finita dentro de un plano infinito, y un cubo es un conjunto de seis planos enfrentados dos a dos.

Interseccin con un Plano


Un plano se define por un vector normalizado perpendicular a la superficie del mismo N = (nx, ny, nz), y la distancia d que le separa del origen de coordenadas, de forma que los puntos (x, y, z) sobre su superficie son aquellos que verifican la siguiente ecuacin: nx*x+ ny * y + nz*z+d=0 En este caso particular no ha lugar hablar de expresin cannica. Las optimizaciones vendran si se consideraran planos paralelos a cada uno de los ejes, en los que una de las coordenadas de la normal es 1 y las otras dos O, pero son casos particulares, no soluciones generales. Es ms, para el clculo de la interseccin del rayo con el plano se considerar el rayo sin transformar, esto es, expresado en las coordenadas globales de la escena. Un rayo puede intersectar con un plano en un nico punto de su superficie, ya sea en su cara anterior o posterior. O puede ser paralelo, o estar completamente incluido dentro del mismo, en cuyo caso no se considera que se produzca interseccin alguna.

o
ti

/1'

o
x

e El punto de interseccin entre un plano cualquiera y un rayo R(t) = O + D * t, con su origen O = (ox, oy, oz) y vector direccin normalizado D = (dx, dy, dz), es aquel punto (x, y, z) sobre la superficie del plano que verifica la ecuacin del rayo: nx * (ox + dx * t) + ny * (oy + dy * t) + nz * (oz + dz * t) + d = O

Resolviendo por t: nx * ox + nx *dx * t + ny * oy + ny *dy * t + nz *oz + nz * dz * t + d = o (nx *dx + ny * dy + nz *dz) * t + nx * ox + ny * oy + nz* oz + d = 0 t = - (nx * ox + ny * oy + nz * oz + d) / (nx *dx + ny *dy + nz * dz)

El punto de interseccin 1 sera simplemente el resultado de evaluar el t calculado en la ecuacin del rayo: I = R(t)

Notar que el denominador de la ecuacin de clculo de t es el producto escalar del vector normal al plano y el vector direccin del rayo: nx *dx + ny *dy + nz *dz = N D El producto escalar de dos vectores es cero si los vectores son perpendiculares, por lo que si el denominador de la expresin de t vale cero, querr decir que el rayo es paralelo al plano, o est contenido completamente en el mismo, y no existe interseccin. Por otra parte, el signo del producto escalar indica si los dos vectores apuntan hacia un mismo lado, signo positivo, o hacia lados contrarios, signo negativo. Por lo que el signo ser negativo si el rayo incide en la cara anterior del plano (apunta en direccin contraria a la normal), y positivo si incide sobre la cara posterior (apunta en la misma direccin que la normal).

11/

Normal al Punto de Interseccin con un Plano

Si el rayo incide en la cara anterior se tomar la normal en el punto de interseccin como la normal al plano: Ni = N Si el rayo incide en la cara posterior se tomar la normal al plano con el signo cambiado: Ni = -N

Interseccin con un Tringulo


El clculo de la interseccin con un tringulo es un caso particular de la interseccin con un plano. La nica diferencia es que el rea de interseccin es finita y con una forma definida, y no infinita como en el plano. El algoritmo que se aplica para este objeto consiste bsicamente en estudiar primero si se produce una interseccin con el plano que lo contiene, y a continuacin determinar si el punto de interseccin encontrado est dentro del rea del tringulo. Un tringulo es un polgono definido por tres vrtices (puntos), (x2, y2, z2) y V3 = (x3, y2, z3), no co-lineales, es decir, que no se encuentran alineados sobre una lnea recta.

V1 = (x1, y1, z1), V2 =

1 1
El vector unitario normal a la superficie del plano que contiene al tringulo, N = (nx, ny, nz), se obtiene mediante el producto vectorial de dos vectores construidos con los vrtices del polgono:

N = ( (V2 - V1) x (V3 - V1) ) / (V2 - V1) x (V3 - V1)

1 1 1 1

El orden en que se definen los vrtices es importante, ya que la direccin de la normal vara en funcin de ello. Para nuestros propsitos consideraremos los vrtices ordenados, sobre el plano, en el mismo sentido del avance de las agujas del reloj.

Vi
Y
iz

Vi

11

La distancia d del origen de coordenadas al plano que contiene el tringulo se obtiene despejando de la ecuacin del plano: nx*x+ ny * y + nz*z+d=0 d=-(nx*x+ny* y+ nz* z) Y evaluando para algn vrtice del tringulo, por ejemplo V1: d = - (nx * x1 + ny * y1 + nz * z1)

Un rayo puede intersectar con un tringulo en un nico punto de su superficie, ya sea en su cara anterior o posterior. O puede ser paralelo, o estar completamente incluido dentro del mismo, en cuyo caso no se considera que se produzca interseccin alguna.

El clculo de t para hallar el punto de interseccin con un tringulo se realiza de igual forma que para el plano. La nica diferencia consiste en que se debe realizar un paso posterior al clculo de t, para determinar si el punto 1, resultante de aplicar el valor t encontrado en la ecuacin del rayo, se encuentra dentro del rea del tringulo. El problema se resuelve en dos dimensiones proyectando los vrtices del tringulo y el punto 1 encontrado en el plano X-Z, Z-Y, o Y-X. Para ello se comprueba cual es la componente de mayor valor de la normal, y se elimina esa componente de todos los puntos. Esta operacin tiene como resultado la proyeccin de todos los puntos en un mismo plano. Y adems, con la particularidad de que dicho plano contiene la proyeccin del tringulo de mayor rea de las tres posibles, con lo que se reducen los problemas de precisin en el clculo. Una vez proyectados todos los puntos sobre un mismo plano, se procede a comprobar el punto
1 con cada una de los lados (aristas) del tringulo. Lo que se hace es ver si el punto se encuentra

a un mismo lado respecto a cada una de las aristas. Es decir, si se encuentra a la izquierda o derecha de las mismas, ya que los puntos interiores a un tringulo se encuentran siempre todos a un mismo lado con respecto a sus aristas.

1
Y

Para hacer esto se calcula el producto vectorial de los vectores que forman los vrtices de cada arista y cada vrtice con el punto, y se realiza el producto escalar con la normal al tringulo. Si el signo de todos los productos escalares es el mismo, entonces el punto 1 se encuentra dentro del tringulo. O sea, se comprueba si los vectores que se obtienen del producto cruzado entre cada arista, y cada vrtice con el punto, tienen la misma orientacin que la normal al tringulo.
s1 = ( (V2 - V1) x (1 - V1) ) N s2 = ( (V3 - V2) x (1 - V2) ) N s3 = ( (V1 - V3) x (1 - V3) ) N

1 1

Si s1, s2 y s3 tienen el mismo signo entonces 1 est dentro del tringulo. En todo caso ha de tenerse en cuenta que el algoritmo de interseccin para tringulos descrito en este artculo no es el nico que puede utilizarse, ni tampoco el ms eficiente, existen otros que pueden encontrarse en los textos de referencia.

Normal al Punto de Interseccin con un Tringulo

De igual forma que se vio anteriormente para el plano, si el rayo incide en la cara anterior se tomar como normal en el punto de interseccin la normal al tringulo:

Ni = N

Y si el rayo incide en la cara posterior se tomar la normal al tringulo con el signo cambiado:

Ni = -N

Interseccin con un Cubo

Un cubo puede definirse mediante dos puntos P1 = (x1, y1, z1) y P2 = (x2, y2, z2), los correspondientes a las coordenadas de dos esquinas del cubo enfrentadas diagonalmente. Estas coordenadas definen seis planos, paralelos dos a dos, donde se encuentran las caras del cubo. Un rayo puede intersectar con un cubo en dos puntos de su superficie, cuando atraviesa dos de sus caras. O en un nico punto, cuando su origen est en el interior del cubo o es tangente al mismo. O puede ser paralelo, o estar completamente incluido dentro de una de las caras, en cuyo caso no se considera que se produzca interseccin alguna.

pp.

e 411

Una forma de calcular las posibles intersecciones sera comprobar si se produce alguna interseccin con cada uno de los planos del cubo, y ver a continuacin si el punto de interseccin encontrado est dentro de la cara de los planos intersectados. Sin embargo, para evitar todo este clculo, se suele utilizar una definicin simplificada del cubo basada en seis planos alineados dos a dos con los ejes de coordenadas. Esta disposicin permite utilizar un algoritmo, propuesto por Kay y Kajiya, que minimiza el nmero y complejidad de los clculos a realizar. Para aplicar este algoritmo es mejor considerar un cubo cannico centrado en el origen y radio la unidad, P1 = (-1, -1, -1) y P2 = (1, 1, 1), y el rayo transformado R'(t) = O' + D' * t, con punto origen O' = (ox', oy', oz') y vector direccin unitario D' = (dx', dy', dz'). El algoritmo comienza declarando e inicializando dos variables, con valores lmites, que contendrn los valores de t para las posibles intersecciones: tnear = -INFINITE tfar = INFINITE

A continuacin estudia los planos del cubo de dos en dos, considerando dos planos paralelos cada vez, y comparando los puntos de interseccin de los planos y el rayo con los ejes. Veamos el caso para el eje X (igual sera para los otros ejes): SI dx' = O ENTONCES el rayo es paralelo a los planos estudiados: Si ox' < xi ox' > x2 ENTONCES el rayo no intersecta el cubo y se retorna FALSE SI NO, el rayo no es paralelo, y se calculan dos posibles intersecciones, una por plano: tl' = (xl - ox') / dx' t2' = (x2 - ox') / dx' SI t1' > t2' ENTONCES se intercambian t1' y t2 SI t1' > tnear ENTONCES tnear = ti' SI t2' < tfar ENTONCES tfar = t2' SI tnear > tfar ENTONCES el rayo no intersecta el cubo y se retorna FALSE SI tfar < O ENTONCES el cubo est por detrs del rayo y se retorna FALSE Si el rayo supera todas las comprobaciones con las tres parejas de planos, entonces el algoritmo retorna TRUE, y tnear y tfar contienen los valores de t para los que se producen las intersecciones. Si el rayo tiene su origen dentro del cubo, el valor de tnear se corresponder con una interseccin que se encuentra por detrs del origen del rayo y deber rechazarse. De la forma acostumbrada, los valores resultantes debern corregirse para llevarlos de vuelta al espacio de coordenadas globales de la escena.

Normal al Punto de Interseccin con un Cubo

La normal Ni' en el punto de interseccin es un vector unitario perpendicular a la cara intersectada: Cara anterior: Ni' = (0, 0, -1) Cara posterior: Ni' = (0, 0, 1) Cara superior: Ni' = (0, 1, 0) Cara inferior: Ni' = (0, -1, 0) Cara izquierda: Ni' = (-1, 0, 0) Cara derecha: Ni' = (1, 0, 0)

De igual forma que en casos anteriores, la normal se corregir para devolverla al espacio global de coordenadas de la escena, y si el rayo incide en alguna cara interior se tomar con el signo cambiado.

Ray Tracinq: Cilindro y Cono


e Este artculo muestra las ecuaciones que permiten obtener los puntos de interseccin entre un rayo y un cilindro, y entre un rayo y un cono. Adicionalmente, despus del estudio de la interseccin, se indica como obtener las normales en dichos puntos de interseccin. Cilindro y cono se definen de una forma muy similar, motivo por el que se estudian a un mismo tiempo. Para definir un cilidro se necesitan tres parmetros: ubicacin, orientacin y ancho. La ubicacin la determina un punto en el espacio, la orientacin un eje (vector) que pasa por el punto de ubicacin, y el ancho un radio tomado alrededor del eje. Por su parte, para definir un cono se necesitan tambin tres parmetros: ubicacin, orientacin y apertura. La ubicacin la determina un punto en el espacio, la orientacin un eje que pasa por el punto de ubicacin, y la apertura un ngulo tomado en el punto de ubicacin alrededor del eje. Tal y como se han definido, estas primitivas tienen una extensin ilimitada, pero en la prctica se suelen acotar superior e inferiormente para dar lugar a objetos finitos cerrados. En este artculo se ver tambin como tratar estos casos.

111

IP

10

Interseccin con un Cilindro

= (lx, ly, Iz) que pasa por el punto C = (cx, cy, cz), son aquellos que se encuentran a una distancia r de dicho eje:

Los puntos sobre la superficie de un cilindro, con un eje central definido por el vector unitario L

(x-cx)^2 + (y-cy)^2 + (z-cz)A2 = rA2 + (lx * (x-cx) + ly * (y-cy) + Iz * (z-cz) )^2

e e e e e e
e La expresin cannica se obtiene considerando un cilindro definido por un eje vertical con vector (0, 1, 0) que pasa por el origen de coordenadas (O, 0, 0), y que tiene radio 1: (x-0)^2 + (y-0)^2 + (z-0)^2 = 11 '2 + (O * (x-0) + 1 * (y-0) + O * (z-O) )^2 x^2 + yA2 + zA2 = 1 + yA2 x^2 + zA2 = 1

11111

Un rayo puede intersectar con un cilindro en uno o dos puntos de la superficie del mismo. En dos puntos cuando el rayo atraviesa el cilindro, con una interseccin de entrada y otra de salida. Y en un nico punto cuando el rayo tiene su origen en el interior del cilindro y slo presenta una interseccin de salida, o cuando el rayo es tangente al cilindro, es decir, que lo toca en un nico punto de su superficie.

er
Los puntos de interseccin entre un cilindro cannico y un rayo transformado R'(t) = O' + D' * t, de origen O' = (ox', oy', oz') y vector direccin normalizado D' = (dx', dy', dz'), son aquellos puntos (x, y, z) sobre la superficie del cilindro que verifican la ecuacin del rayo: (ox' + dx' * t)^2 + (oz' + dz' * t)^2 = 1

1 1 1 111,

1101 11>

Resolviendo por t:

ox'A2 + (dx' * t)A2 + 2 * ox'* dx' * t + oz'A2 + (dz' * t)A2 + 2 * oz' *dz' * t =1 (dx1 A2 + dziA2) * t"2 + 2 * (ox' * dx' + oz' * dz') * t + ox'A2 + oz'A2 - 1 =0

1
La expresin resultante es una ecuacin de segundo grado de la forma: a * tA2 + b * t + c =

Donde: a = dx1 ^2 + dz'A2 b = 2 * (ox' dx' + oz' dzI) c = ox'A2 + ozIA2 - 1

Y con dos posibles soluciones para t: tO' = (-b + SQRT(b^2 - 4 * a * c) ) / (2 * a) t1' = (-b - SQRT(bA2 - 4 * a * c) ) / (2 * a)

Expresiones que pueden simplificarse de igual forma que se hizo con la ecuacin de la esfera en un artculo anterior: b = 2 * k, con k = ox'* dx' + oz'* dz' tO' = (-k + SQRT(kA2 - a * c) ) / a tl' = (-k - SQRT(102 - a * c) ) / a

Si a es cero, o el discriminante (la expresin dentro de la raz cuadrada) es menor que cero, no puede resolverse la ecuacin, no existen soluciones reales, por lo que no se produce interseccin.

Si el discriminante es cero, entonces slo existe una solucin, el rayo es tangente al cilindro, y puede tomarse tO' t1' indistintamente. Por ltimo, si el discriminante es mayor que cero entonces hay dos posibles soluciones, siendo la positiva de menor valor la ms cercana al origen del rayo.

vio

El valor ti' encontrado, se corregira, y se aplicara en la ecuacin del rayo para obtener el punto 1 intersectado:
ti = ti' / ID * INV(M)I 1 = R(ti)

o o o

Interseccin con un Cilindro Acotado

Es prctica habitual limitar la naturaleza infinita de la longitud de los cilindros, acotando superior e inferiormente los mismos, mediante dos "tapas". Las tapas son dos planos horizontales que acotan la extensin del cilindro, y cuyas normales coinciden con el vector direccin del mismo, una con el mismo sentido (0, 1, 0), y otra con sentido contrario (0, -1, 0).

Para tener en cuenta estos dos planos se aaden nuevas condiciones a la definicin de cilindro cannico, limitando la extensin (altura) del cilindro a 1 unidad. De forma que slo se produce una interseccin si la componente vertical iy' del punto de interseccin 1' es mayor o igual que cero y menor o igual que 1: Si O <= iy' <= 1 se produce interseccin

Las posibles intersecciones con cada una de las tapas se calculan como intersecciones entre el rayo y los planos horizontales que contienen las tapas, utilizando la ecuacin de interseccin entre rayo y plano que se explic en un artculo anterior:

t = - (nx * ox' + ny * oy' + nz *oz' + d) / (nx *dx' + ny * dy' + nz * dzI)

El plano que contiene a la tapa superior tiene por normal (nx, ny, nz) = (0, 1, 0), y se encuentra a una distancia d = 1 del origen de coordenadas. Sustituyendo:
t =- (0* ox'+ 1* oy+0 * oz1 +1)/(0*dx'+1*dy+0*dzi) t = - (oy' + 1) / dy'

Debe ser claro que si dy' = O entonces no se produce interseccin. El rayo es paralelo al plano, o se encuentra contenido en el mismo. Si el rayo intersecta con el plano, entonces se debe comprobar si el nuevo punto de interseccin resultante de aplicar t en la ecuacin del rayo (1' = O' + D' * t), se encuentra dentro del rea circular delimitada por la tapa. Para ello basta con comprobar si el punto se encuentra sobre el plano horizontal separado del centro del cilindro C = (O, O, 0) una distancia menor o igual a la del radio r = 1:

Si (ix'A2 + iz'A2) <= 1 se produce interseccin

Una vez terminada con la tapa superior, se operara de igual forma con la tapa inferior, teniendo en cuenta que tiene por normal (nx, ny, nz) = (0, -1, 0), y se encuentra a una distancia d = O del origen de coordenadas:

t = - (O * ox' - 1 * oy' + O * oz' + O) / (O * dx' - 1 *dy' + O *dzi) t = oy' / dy'

Normal al Punto de Interseccin con un Cilindro

La normal al punto de interseccin depender de la parte concreta del cilindro en la que se produzca la interseccin. Si la interseccin se produce con las tapas, la normal ser un vector vertical, orientado hacia arriba o hacia abajo, dependiendo de la tapa. Si la interseccin se produce en el lateral, la normal ser igual al vector que une el punto de interseccin con el punto ms cercano al mismo situado sobre el eje que atraviesa el cilindro.

1
Si se mira el cilindro desde arriba, sobre su vertical, es fcil comprobar que cuando la interseccin se produce en el lateral, la normal se corresponde siempre con la proyeccin del punto de interseccin 1' sobre el plano horizontal X-Z. Es decir, se puede prescindir de la componente vertical y resolver el problema en dos dimensiones. Tapa superior: Ni' = (0, 1, 0) Tapa inferior: Ni' = (0, -1, 0) Lateral: Ni' = (ix', 0, iz')

5
De igual forma que en casos anteriores, la normal se corregir para devolverla al espacio global de coordenadas de la escena, y si el rayo incide en alguna cara interior se tomar con el signo cambiado.

Interseccin con un Cono

Los puntos sobre la superficie de un cono, con un eje central definido por el vector unitario L = (Ix, ly, Iz), son aquellos que forman un ngulo alfa con un punto concreto C = (cx, cy, cz) situado sobre su eje:

( (x-cx)*Ix + (y-cy)*ly + (z-cz)*lz) / SQRT( (x-xc)^2 + (y-yc)^2 + (z-zc)^2) = COS(alfa)

La expresin cannica se obtiene considerando un cono definido por un eje vertical con vector (O, 1, 0), el punto (O, O, O), y un ngulo de 45 grados: ( (x-0)*0 + (y-0)*1 + (z-0)*0) / SQRT( (x-0)A2 + (y-0)A2 + (z-0)A2) = COS(PI/4) y / SQRT(xA2 + yA2 + zA2) = 1 / SQRT(2) yA2 / (xA2 + yA2 + zA2) = 1 / 2 2 * yA2 = xA2 + yA2 + zA2 xA2 - yA2 + zA2 = O

Los puntos de interseccin entre un rayo tranformado y un cono cannico, son aquellos puntos (x, y, z) sobre la superficie del cono que verifican la ecuacin del rayo: (ox' + dx' *9 1'2 - (oy' + dy' *t)"2 + (oz' + dz' * t)^2 = O

Resolviendo por t: ox'A2 + (dx' * t)^2 + 2 * IDX1 * dx' *t oy'A2 - (dy' * t)^2 - 2 * oy' *dy' *t + oz1 ^2 + (dz' * t)^2 + 2 * oz' * dz' * t =0 (dx1 ^2 - dy'A2 + dz'A2) * tA2 + 2 * (ox' * dx' - oy' * dy' + oz' * dz') * t + ox'A2 - or2 + ozIA2 =0

La expresin resultante es una ecuacin de segundo grado de la forma: a * tA2 + b * t + c = 0 Donde: a = dx1 ^2 - dy'A2 + dziA2 b = 2 * (ox' * dx' - oy' * dly' + oz' * dz') c = ox'A2 - or2 + oz'A2

1 Y con dos posibles soluciones para t: tO' = (-b + SQRT(bA2 - 4 * a * c) ) 1(2 *a) t1' = (-b - SQRT(b^2 - 4 * a * c) ) / (2 * a)

Expresiones que pueden simplificarse de igual forma que se hizo con la ecuacin de la esfera en un artculo anterior: b = 2 * k, con k = ox' * dx' - oy' *dy' + oz' *dz' tO' = (-k + SQRT(kA2 - a * c) ) / a ti' = (-k - SQRT(kA2 - a * c) ) / a

Si a es cero, o el discriminante (la expresin dentro de la raz cuadrada) es menor que cero, no puede resolverse la ecuacin, no existen soluciones reales, por lo que no se produce interseccin. Si el discriminante es cero, entonces slo existe una solucin, el rayo es tangente al cono, y puede tomarse tO' t1' indistintamente. Y por ltimo, si el discriminante es mayor que cero, entonces hay dos posibles soluciones, siendo la positiva de menor valor la ms cercana al origen del rayo. El valor ti' encontrado, se corregira, y se aplicara en la ecuacin del rayo para obtener el punto 1 intersectado: ti = ti' / ID * INV(M)I I = R(ti)

Interseccin con un Cono Acotado

Es prctica habitual eliminar la simetria vertical, y limitar la naturaleza infinita de la longitud de los conos, acotando superiormente los mismos, mediante una tapa.La tapa es un plano horizontal que acota la extensin del cono, y cuya normal coincide con el vector direccin del mismo, (0, 1, 0). Para contemplar estas dos acotaciones, se aaden nuevas condiciones a la definicin de cono cannico, limitando la extensin (altura) del cono a 1 unidad. De forma que slo se produce una interseccin, si la componente vertical, iy', del punto de interseccin 1', es mayor o igual que cero y menor o igual que 1: Si O <= iy' <= 1 se produce interseccin La posible interseccin con la tapa se calcula como una interseccin entre el rayo y el plano horizontal que contiene la tapa, utilizando la ecuacin de interseccin entre rayo y plano que se explic en un artculo anterior:
t=- (nx *ox' + ny * oy' + nz *oz' + d) / (nx *dx' + ny * dy' + nz * dzi)

El plano que contiene a la tapa tiene por normal (nx, ny, nz) = (0, 1, 0), y se encuentra a una distancia d = 1 del origen de coordenadas. Sustituyendo: t = - (O * ox' + 1 * oy' + O *oz' + 1) / (O *dx' + 1 *dy' + O * dzi) t = - (oy' + 1) / dy'

Debe ser claro que si dy' = O entonces no se produce interseccin. El rayo es paralelo al plano, o se encuentra contenido en el mismo. Si el rayo intersecta con el plano, entonces se debe comprobar si el nuevo punto de interseccin 1', resultante de aplicar t en la ecuacin del rayo (1' = O' + D' * t), se encuentra dentro del rea circular delimitada por la tapa. Para ello basta con comprobar si el punto se encuentra sobre el plano horizontal separado del centro del cono C = (O, O, O) una distancia menor o igual a 1, longitud del radio de la tapa: Si (ix'A2 + iz1^2) <= 1 se produce interseccin

1-1

er,

wo.

Normal al Punto de Interseccin con un Cono

La normal al punto de interseccin depender de la parte concreta del cono en la que se produzca la interseccin. Si la interseccin se produce con la tapa, la normal ser un vector vertical, orientado hacia arriba. Si la interseccin se produce en el lateral, la normal es muy sencilla de obtener, aunque requiere una explicacin un poco detallada. La clave consiste en notar que el vector que une el punto de interseccin con el origen de coordenadas est sobre la superficie del cono. Y como la normal no es ms que un vector perpendicular a la superficie, basta girar 90 grados dicho vector con respecto al eje vertical para obtener la normal. Girar un vector 90 grados en uno de los ejes es tan simple como invertir el signo del componente correspondiente a ese eje:

Tapa: Ni' = (0, 1, 0) Lateral: Ni' = (ix',

iz')

De igual forma que en casos anteriores, la normal se corregir para devolverla al espacio global de coordenadas de la escena, y si el rayo incide en alguna cara interior se tomar con el signo cambiado.

111

Diseo y Arquitectura de Software

El motor de Raytracer que hemos realizado entrega como salida una secuencia animada en formato AVI mostrando una serie de primitivas geomtricas iluminadas por luces direccionales (o spotlights) desplazndose a travs del espacio mientras se reflejan unas sobre otras. En la escena se tienen cuatro luces. Una roja, una azul y una verde, situadas en los costados, y una luz blanca central. El usuario puede elegir si quiere realizar el rendering en utilizando un solo nodo, o en paralelo, usando de 1 a 3 nodos esclavos. El usuario adems puede elegir cuantos fotogramas (frames) desea que tenga esta animacin. El software que hemos desarrollado est paralelizado, de tal forma que cada nodo renderee una cantidad determinada de fotogramas. El software se encarga de dividir la carga de trabajo entre la cantidad de nodos disponibles que estn formando el cluster. Si tenemos el caso de que la divisin de la carga no sea par, por ejemplo, si decimos que se renderee una secuencia de 42 fotogramas entre cuatro nodos, el programa reparte la carga de la siguiente forma: 11 fotogramas para el primer nodo, 11 para el segundo, 10 para el tercero y 10 para el cuarto; en otras palabras, nunca se deja un nodo con ms de un fotograma respecto al anterior, es decir, siempre se reparte la carga en forma equitativa. El tipo de paralelismo con el que funciona nuestro programa, es paralelismo independiente, ya que cada nodo realiza su trabajo, valga la redundancia, en forma independiente de los dems, ningn nodo depende de datos de otro para trabajar, ni se debe esperar que un nodo termine para que el otro comience a trabajar Respecto a la arquitectura, el programa est diseado para que soporte Clusters MPP. Y tambin est diseado para soportar un cluster Virtual, ya que, debido a las capacidades del lenguaje Java, que nos provee de una robusta plataforma de comunicacin por medio de sockets, es posible realizar la comunicacin via puertos, lo que nos faculta realizar la comunicacin a travs de internet. Por otro lado, el diseo del programa hace que este sea excelente para la tecnologa SMP, es decir, procesadores multincleo con memoria compartida, como los Intel Core2duo/quad o la lnea Phenom del fabricante AMD. Esto es debido a que el programa genera cada cuadro (frame) a travs de hilos de ejecucin, optimizando as el rendimiento en procesadores Multincleo. Finalmente, respecto a la granuralidad de la paralelizacin, podemos decir que los nodos se comunican poco entre ellos. La mayor parte del tiempo los nodos estn trabajando, y comunicacin se concentra al principio y al final del algoritmo. Por lo tanto, podemos decir que este software tiene un paralelismo de grano grueso.

1 1 o

Herramientas Utilizadas

Nuestro software de Raytracing fue desarrollado en Java versin 1.6.0_05. Es importante destacar que el programa requiere de esta versin de Java para funcionar correctamente. Como Java no trae soporte por defecto para representar imgenes tridimensionales, utilizamos la API Java3d versin 1.3 que puede descargarse desde la pgina oficial de SUN en el siguiente enlace. http://java.sun.com/javase/technologies/desktop/java3d/. Para algunas imgenes del Marco Terico, utilizamos el software 3D Studio Max 9. Bsicamente para generar imgenes comparativos usando Raytracer, Scanline Rendering y Poton Mapping. Para generar la secuencia de video .AVI a partir de las imgenes BMP generadas por el motor de raytrace. Utilizamos una pequea aplicacin que puede ser ejecutada por linea de comando llamada BMP2AVI desarrollado por Willsoft, la aplicacin puede ser descargada, con su cdigo fuente, de este enlace http://willsoft.free.fr/

1 1

1 1 1 1 1

Medidas de Rendimiento

El programa fue sometido a pruebas de rendimiento en las siguientes plataformas. Se realiz un render en serie en un equipo Intel Core2Duo E6750 de 2.66 Ghz, El proceso consisti en renderizar una secuencia de 60 fotogramas, obtenindose el siguiente resultado.

Numero de l'ames: Esfera

W Nodos

n;~ii0t Carga
Cubo 571 1.

Crear Reo dei

<brames Completados 60130

100 %
0% 0%

Nodo Maestro: Ter minado en 187.82 s Nodo 1: No Activo Nodo 2: No Activo Nodo 3: No Activo

;,

Como podemos ver en la imagen adjunta, el proceso de renderizado demor 187.782 segundos.

Se realizaron dos pruebas de render en paralelo. Una con un cluster no homogneo, y la otro con un cluster homogneo. En ambas pruebas, el cluster estuvo formato por 4 equipos. La carga, consistente en 60 fotogramas, fue dividida en partes iguales entre los cuatro equipos. En consecuencia, cada equipo proces 15 fotogramas

1 1

Prueba N1: Cluster No Homodeneo

Nodo Maestro: Intel core2duo e6750 2.66 ghz, 4GB Ram, 4mb cache Nodo 1: Amd Turion X2, 1.6 ghz, 2GB Ram, 1mb cache Nodo 2: Amd Athlon X2 5000 ghz, 2GB Ram, 1mb cache Nodo 3: Intel core2duo e4500 2.2 ghz, 2GB Ram, 2mb cache

Obtenindose el siguiente resultado

Numero de Fr ames: Esfera llames Completados 15-15 Fi ames Completados 15-15 r ames Completados 15-15 Fi ames Completados 15 , 15

Pr Nodos Cribo 100 % 100.0 ", 100.0 100.0

Crear ender

Nodo Maestro: Terminado en 47.672000000000004 s Nodo 1: Terminado en 75.5 s Nodo 2: Terminado en 50.469 s Nodo 2: Terminado en 50.125 s

El tiempo en paralelo est dado por el nodo N1, que fue el que ms demor en terminar el proceso, con un tiempo total de 75.5 segundos

Aplicando las mtricas de rendimiento a estos resultados, obtenemos lo siguiente.

111

Speed Up: 187.82 / 75.5 = 2.48 Eficiencia: 2,48 /4 = 62%

Prueba N2: Cluster Homogeneo

Nodo Maestro: Intel core2duo e6750 2.66 ghz, 4GB Ram, 4mb cache Nodo 1: Intel core2duo e6750 2.66 ghz, 4GB Ram, 4mb cache Nodo 2: Intel core2duo e6750 2.66 ghz, 4GB Ram, 4mb cache Nodo 3: Intel core2duo e6750 2.66 ghz, 4GB Ram, 4mb cache

Numel o de trames: Esfera trames Completados 1515 Ft ames Completados 1515 Fi Miles Completados 15'15 Frames Completados 1515 100% 100.0 %

ear Render

Nodo Maestro: Terminado en 49.74 s Nodo 1: Ter minado en 47.72 s Nodo 2: Ter minado ell 41.19 s Nodo 2: Ter minado en 47.929 s

100.0 %
100.0%

El tiempo en paralelo est dado por el nodo Maestro, con un tiempo de 49.74 segundos Aplicando las mtricas de rendimiento a estos resultados, obtenemos lo siguiente.

Speed Up: 187.82 / 49.74 = 3,77 Eficiencia: 3.77 / 4 = 94.2%

Con estos resultados podemos concluir que el algoritmo presenta una excelente escalabilidad, Aumentar el nmero de procesadores, disminuye considerablemente el tiempo de procesamiento. El SpeedUp conseguido con el cluster homogneo es de 3.77, un nmero cercano al speedup lineal que es el mximo que podramos haber alcanzado. La eficiencia de un 94.2% refleja tambin la alta escalabilidad del algoritmo.

Comparacin Secuencial Vs Paralelo


Como qued demostrado en el punto anterior, la ejecucin del algoritmo en paralelo fue muchsimo mas rpida que la alternativa secuencial, quedando demostrada as la alta escala bilidad que presenta el algoritmo de Raytracing, Es por eso que las compaas que desarrollan pelculas animadas o se dedican a crear efectos especiales utilizan verdaderas las llamadas "Granjas de Render", que son habitaciones repletas de computadores dedicados a renderizar en conjunto una nica escena.

~~^--. --

Granja de Render de "Digital Domain"

e e e e e e

ee

A continuacin se adjuntan grficos comparativos mostrando los tiempos del algoritmo ejecutado tanto en serie como en paralelo, en un cluster homogneo y no homogneo

Secuencia! Vs Paralelo (No homogneo)

Secuencia! Vs Paralelo no Homogeneo (segundos`,

75.5


P7 ,7; 0-11


Como podemos ver, la solucin secuencial demora ms del doble de tiempo que la solucin en paralelo, an cuando se est trabajando en un cluster No homogneo.
e

e e

e e
e

Secuencial Vs Paralelo (Homogneo)

Secuencia! Vs Paralelo no Homogeneo (segundos)

49.74

e
e

En un cluster homogneo, la solucin paralela triplica fcilmente la velocidad de la solucin secuencial.

e e e

e e e

Eficiencia Cluster

Homogeneo Vs No Homogeneo

4rtnrnrm

/40

94.2

HonienEww

( porcentaje ;

El cluster homogneo fue mucho ms eficiente.

e e e

o e

e e o

Utilizacin de CPU (ejecucin serial)

Utilizacin de CPU (porcentaje; 99.3 100 80 60 40 20

Secuencial

Utilizacin de CPU (ejecucin paralela)

Utilizacin de CPU (porcentaje; 99.3 98.3 98.9 99.13 100 801 601 401 201 0 Nodo Nodo 1 Nodo 2 Nodo 3 Maestro
En ambas soluciones, la utilizacin del CPU fue cercana al 100%. Paralelo

Conclusiones
Tras realizar esta experiencia de laboratorio, fuimos capaces de cumplir con nuestros objetivos. Fuimos capaces de desarrollar un motor de Raytracing, capaz de representar diversas figuras geomtricas que puede generar imgenes trabajando tanto en serie como en paralelo. La aplicacin adems de funcionar en un ambiente de cluster tradicional, puede operar bajo clusters virtuales formados travs de internet, Y al trabajar cada fotograma en un hilo independiente, es capaz de aprovechar al mximo las capacidades de los procesadores multincleo. Al realizar las mediciones pudimos constatar, utilizando la teora que aprendimos en la ctedra, las ventajas de realizar el proceso en paralelo, disminuyendo considerablemente los tiempos de procesamiento, en una operacin que requiere de tanto trabajo de computo, (y que es tan utilizada en la actualidad) como es el Raytracing.

e e

e e e

ANEXOS Manual de Usuario


Requisitos de Software
- Windows XP Java Runtime Environment 1.6.0_05 Tener el puerto 80 abierto para utilizar el programa en paralelo

Utilizacin del Programa

Para utilizar el programa, descomprimimos el contenido del archivo BekhoRay.rar en una carpeta cualquiera.

La aplicacin esta compuesta de dos programas. El programa Maestro y el programa Esclavo Para ejecutar el programa esclavo, simplemente haga click en el icono "Maestro.bat" en la carpeta "Raytracer Maestro" Al ejecutar el programa se desplegar el siguiente cuadro de dialogo _
Numero de naipes: Estet a N" Nodos
Cubo


En la pestaa Nmero de Frames. Indicamos cuantos fotogramas queremos que tenga la secuencia que se va a renderizar. Si queremos hacer una prueba rpida del motor, simplemente escribimos 1 para renderizar una sola imagen, Sin embargo si queremos ver la secuencia animada correctamente, se recomienda ingresar un valor entre 30 y 60

En las pestaas esfera y cubo, seleccionamos las figuras que queremos renderizar. Si queremos utilizar el programa en serie. En la pestaa N Nodos debemos introducir e nmero O, y luego hacer click en dividir carga (haciendo esto todo el trabajo es asignado al nodo maestro). Una vez dividida la carga, hacemos click en Crear Render, para el proceso de renderizado. El progreso se muestra en el cuadro de dialogo, y al terminar. Se genera un video en formato AVI con la escena creada.

iii

,Numero (le Fratries: Esfera ames Completados 60130 100% 0% 0% i 0% Nodo Maestro: Terminado en 244.782 s Nodo 1: No Activo Nodo 2: No Activo Nodo 3: No Activo

Si queremos realizar el render en paralelo. Debemos ingresar la cantidad de esclavos en la pestaa N Nodos. Si tenemos un maestro y 1 esclavo, ingresamos 1, si tenemos 2 esclavos, ingresamos 2, etc. Una vez que se ha ingresado la cantidad de esclavos, hacemos click en el botn Dividir Carga. Para separar el trabajo entre el Maestro y los esclavos. Una vez dividida la carga, procedemos a ejecutar el programa Esclavo en los nodos que actuarn de esclavo. Haciendo click en "Esclavo.bat" en la carpeta "Raytracer Esclavo" ejecutamos el programa esclavo. En el cuadro de dialogo que se despliega, debemos ingresar la direccin IP del nodo Maestro. En el programa se nos mostrar el estado de cada uno de los nodos, indicando si estos estn activos o no. Una vez que todos los esclavos estn activos, estamos en condiciones de iniciar el proceso de renderizado, haciendo click en Crear Render, El progreso de cada nodo se muestra en el cuadro de dilogo.

Numero de Frames: Este., a Fiarnos Completados 15 15 llames Completados 15 15 Trames Completados 15 15 l'ames Completados 15 15

N Nodos
Cubo 100% 100.0 % 100.0 100.0% Nodo Maestro: Terminado en 47.672000000000004 s Nodo 1: Terminado en 75.5 s Nodo 2: Ter minado en 50.469s Nodo 2: enninado en 50.125 s

Al realizar el proceso en paralelo, la secuencia de video no se genera automticamente, por lo cual debemos realizar manualmente el proceso. Para esto, debemos copiar todas las imgenes generadas por cada nodo a la carpeta "Raytracer Maestro" y ejecutar "CreaVideo.bat" Es importante destacar que cada vez que se realiza un render, se borra el anterior, as que si deseamos conservar un render debemos copiarlo a otra carpeta.

1 1 1

Cdigo Fuente
BekhoRay java
import java.lang.Math; import java.awt.*; import java.util.*; import java.io.*; import java.net.*; import java.lang.*; import java.text.*; import javax.swing.*; import java.awt.event.*;

el e :o e
e e

public class BekhoRay extends Thread implements ActionListener public static imagenI0 creaImagen[] = new imagenI0[10000]; public static imagenI0 creaCubo = new imagenI0(); private static int stop = O; public static nodoM master; public static int numNodos; public static int carga = O; public static int cargaExtra = O; public static int numNodosConnect = O; public static boolean RenderStart = false; public static long Time1; static public static static static static static static static static static static JFrame clientef = new JFrame("Bekho RenderMax"); static int cuentaImagenes = O; int contadorFrames = O; JLabel 11 = new JLabel("Numero de Frames: "); JLabel 14 = new JLabel(""); JLabel 16 = new JLabel("Nodo Maestro: Activo"); JLabel rl = new JLabel("Esfera"); JLabel r2 = new JLabel("Cubo"); JLabel r3 = new JLabel(""); JLabel r4 = new JLabel(""); JCheckBox boxl = new JCheckBox("",true); JCheckBox box2 = new JCheckBox();

static JLabel 141 = new JLabel(""); static JLabel 161 = new JLabel("Nodo 1: No Activo"); static JLabel 142 = new JLabel("") static JLabel 162 = new JLabel("Nodo 2: No Activo"); static JLabel 143 = new JLabel(""); static JLabel 163 = new JLabel("Nodo 3: No Activo"); static JLabel nodos = new JLabel("N Nodos"); static JTextField nodost = new JTextField(20); static static static static JTextField framest = new JTextField(20); JPanel panel = new JPanel(); JPanel panel2 = new JPanel(); JPanel panel3 = new JPanel();

static static static static static static static

JPanel JPanel JPanel JPanel JPanel JPanel JPanel

panel4 = new JPane1(); panel5 = new JPanel(); panel6 = new JPanel(); panel4l = new JPanel(); panel5l = new JPanel(); panel6l = new JPanel(); panelB = new JPanel();

static JButton boton = new JButton("Crear Render"); static JButton botonP = new JButton("Dividir Carga"); static JProgressBar barra = new JProgressBar(); static JLabel porcentaje = new JLabel("0 %"); static JProgressBar barral = new JProgressBar(); static JLabel porcentajel = new JLabel("0 %"); static JProgressBar barra2 = new JProgressBar(); static JLabel porcentaje2 = new JLabel("0 %"); static JProgressBar barra3= new JProgressBar(); static JLabel porcentaje3 = new JLabel("0 %");

BekhoRay() clientef.setSize(760,200); clientef.setLocation(400,300); clientef.setBackground(new Color(215,215,215)); barra.setPreferredSize( new Dimension( 300, 40 ) ); barra.setMinimum( O ); barra.setMaximum( 100 ); barra.setValue( O ); barra3.setPreferredSize( new Dimension( 300, 40 ) ); barra3.setMinimum( O ); barra3.setMaximum( 100 ); barra3.setValue( O ); barral.setPreferredSize( new Dimension( 300, 40 ) ); barral.setMinimum( O ); barra1.setMaximum( 100 ); barral.setValue( O );

barra2.setPreferredSize( new Dimension( 300, 40 ) ); barra2.setMinimum( O ); barra2.setMaximum( 100 ); barra2.setValue( O ); clientef.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); framest.setCursor(new Cursor(Cursor.HANDCURSOR) ); clientef.setLayout(new GridLayout(0,1)); panel.setLayout(new GridLayout(0,6)); panelB.setLayout(new GridLayout(0,6)); pane12.setLayout(new GridLayout(0,1));

panel3.setLayout(new GridLayout(0,3));

panel4.setLayout(new GridLayout(0,1)); pane141.setLayout(new GridLayout(0,3)); panel5.setLayout(new GridLayout(0,1)); pane151.setLayout(new GridLayout(0,3));

panel6.setLayout(new GridLayout(0,1)); pane161.setLayout(new GridLayout(0,3)); boton.setEnabled(false); panel.add(11); panel.add(framest); panel.add(nodos); panel.add(nodost); panel.add(botonP); panel.add(boton); panelB.add(r3); panelB.add(rl); panelB.add(boxl); panelB.add(r4); panelB.add(r2); panelB.add(box2); panel2.add(barra); pane13.add(14); pane13.add(porcentaje); pane13.add(16); nodost.setText("3"); pane14.add(barral); pane141.add(141); pane141.add(porcentajel); pane141.add(161); panel5.add(barra2); pane151.add(142); pane151.add(porcentaje2); pane151.add(162); panel6.add(barra3); pane161.add(143); pane161.add(porcentaje3); pane161.add(163);

clientef.add(pane1); clientef.add(panelB); clientef.add(pane12); clientef.add(panel3); clientef.add(panel4); clientef.add(panel4l); clientef.add(panel5); clientef.add(pane151); clientef.add(panel6); clientef.add(pane161);

clientef.setVisible(true); framest.addActionListener(this); framest.setActionCommand("digitando_ip");

boton.addActionListener(this); boton.setActionCommand("crearRender"); botonP.addActionListener(this); botonP.setActionCommand("paralelizar"); boxl.addActionListener(this); boxl.setActionCommand("esfera"); box2.addActionListener(this); box2.setActionCommand("cubo");

RayT creaRay; boolean first; float pixeiColor[]; int thisPixel; int xStart; int yStart; int zShift; double v[]; double w[]; double focalLength; boolean damage; Cube c; Cube c2; private static final long serialVersionUID = 1L; private static int focalLengthCubo = 3; private RayTracer rt = new RayTracer(); PhongTexture tl = new PhongTexture(new double[] .6, 0 }, new double[] .2, .2, .2 }, 10);

.3, .3, 0 }, new double[] { .6,

PhongTexture t2 = new PhongTexture(new double[] { .3, 0, 0 0, 0 }, new double[] { .02, .02, .02 }, 4); public void run() double double double double double xlzq xDer yIzq yDer foco = = = = = -7.5; 7.5; -9; 8.5; 0.2;

new double[] { .8,

int pixel = 0; int H = 600; int W = 600; Timel = new Date().getTime(); if(carga == 0) carga = Integer.parseInt(framest.getText())/(numNodos + 1); while(BekhoRay.cargaExtra > 0) carga = carga + 1; cargaExtra = cargaExtra - 1; } System.out.println("Nodo MAESTRO"); System.out.println(String.value0f(carga));

if(boxl.isSelected() == true) while(stop < carga) first = true; focalLength = foco; foco = foco + (3.1/Integer.parseInt(framest.getText())); creaRay = new RayT(); creaRay.setBGC(Color.white); xIzq = xIzq + (6.5/Integer.parseInt(framest.getText())); yIzq = yIzq + (8.5/Integer.parseInt(framest.getText())); creaRay.addEsfera(.2, .2, .9, 10, xIzq, yIzq, -8, .9); System.out.printin(String.value0f(xIzq)); creaRay.spheres[0].setSpecular(.3, .3, .3); //creaRay.addEsfera(.9, .2, .2, 10, 1.6, 1.6, -8, .9); //creaRay.spheres[1].setSpecular(.2, .2, .2); //creaRay.addEsfera(.2, .9, .2, 10, 1.6, -1.6, -8, .9); //creaRay.spheres[2].setSpecular(.8, .8, .8); xDer = xDer - (6.5/Integer.parseInt(framest.getText())); yDer = yDer - (8.5/Integer.parseInt(framest.getText())): creaRay.addEsfera(.8, .8, .8, 20, xDer, yDer, -8, .9); creaRay.spheres[1].setSpecular(.9, .9, .9); creaRay.addLuces(0, 0, 1, .8, .8, .8); creaRay.addLuces(1, 1, 0, .8, .2, .2); creaRay.addLuces(1, -1, 0, .2, .8, .2); creaRay.addLuces(-1, 0, 0, .2, .2, .8); creaRay.setCenter(0, 0, -8); = new double[3]; w = new double[3]; pixelColor = new float[3]; thisPixel = 0; v[0] = 0; v[1] = 0; v[2] = 0; xStart = 0; yStart = 0; damage = true; creaImagen[contadorFrames] = new imagenI0(); int[][][] image = creaImagen[contadorFrames].makeNewImage(600, 600); for (int i = 0; i < W; i++) for (int j = 0; j < H; j++) w[0] = (double) (i - W / 2) / (W / 2); w[1] = (double) (H / 2 - j) / (W / 2); w[2] = -focalLength; pixelColor = creaRay.rayTrace(v, w); image[j][i][0] = ((int) (pixelColor[0] * 255)); image[j][i][1] = ((int) (pixelColor[1] * 255)); } image[j][i][2] = ((int) (pixelColor[2] * 255)); creaImagen[contadorFrames].imagePixels = image; creaImagen[contadorFrames].contadorFrames = contadorFrames; creaImagen[contadorFrames].start(); contadorFrames = contadorFrames + 1; stop = stop +1;

else if(box2.isSelected() == true)

PhongTexture tO = new PhongTexture(

new double[] {0, .3 , 0}, new double[] {0, .3, 0}, new double[] {.2, .2, .2}, 2

);
PhongTexture tl new double[] new double[] new double[] 2 ); = new PhongTexture( {2, .4 , 0}, {0, .4, 0}, {.2, .2, .2},

c = new Cube(t0); c.translate(0, -1.5, -12); c.rotateZ(Math.PI / 3); c2 = new Cube(tl); c2.translate(0, 1.5, -12); c2.rotateZ(Math.PI / 3); double double double double double double rotXcl rotXc2 rotYcl rotYc2 rotZcl rotZc2 = = = = = = 0; 0; 0; 0; 0; 0;

while(stop < carga) { first = true; focalLengthCubo = 3; c.rotateY(rotYcl); c.rotateX(rotXcl); c.rotateZ(rotZcl); c2.rotateY(rotYc2); c2.rotateX(rotXc2); c2.rotateZ(rotZc2); rt.add(c); rt.add(c2); rotXcl = rotXcl + ((Math.PI*(360/(Integer.parseInt(framest.getText())*6)))/180); rotXc2 = rotXc2 ((Math.PI*(360/(Integer.parseInt(framest.getText())*6)))/180); rotYcl = rotYcl + ((Math.PI*(360/(Integer.parseInt(framest.getText())*6)))/180); rotYc2 = rotYc2 ((Math.PI*(360/(Integer.parseInt(framest.getText())*8)))/180); rotZcl = rotZcl + ((Math.PI*(360/(Integer.parseInt(framest.getText())*6)))/180); rotZc2 = rotZc2 ((Math.PI*(360/(Integer.parseInt(framest.getText())*6)))/180); int rgb[]; double v[] = new double[3]; double w[] = new double[3]; v[0] = 0; v[1] = 0; v[2] = 0; int n = 0; creaImagen[contadorFrames] = new imagenI0(); int[][][] image = creaImagen[contadorFrames].makeNewImage(600, 600); for (int i = 0; i < W; i++)

for (int j = O; j < H; j++) w[1] = (double) (i - W / 2) / (W / 2); w[0] = (double) (H / 2 - j) / (W / 2); w[2] = -focalLengthCubo; w = MatrixCube.normalize(w); rgb = rt.rayTrace(v, w, 3); image[j] [i] [0] = (int)rgb[0]; image[j][i][1] = (int)rgb[1]; image[j][i][2] = (int)rgb[2];

I/

10

el creaImagen[contadorFrames].imagePixels = image; creaImagen[contadorFrames].contadorFrames = contadorFrames; creaImagen[contadorFrames].start(); contadorFrames = contadorFrames + 1; stop = stop +1;

el

10

el public void actionPerformed(ActionEvent e)

if (e.getActionCommand() == "crearRender") if(framest.getText().equals("")) JOptionPane.showMessageDialog(null,"Dijite la cantidad de frames primero"); else if(Integer.parseInt(framest.getText()) <=4) es de 5"); JOptionPane.showMessageDialog(null,"El minimo de Frames para Renderizar else if(numNodosConnect != numNodos) JOptionPane.showMessageDialog(null,"El numero de Nodos Activos debe ser igual a la cantidad de nodos sealadas, verifique la comunicacion del cluster o si el programa esclavo esta ejecutandose correctamente en sus nodos"); else boton.setEnabled(false); RenderStart = true; Runtime aplicacion = Runtime.getRuntime(); try aplicacion.exec("delete *.bmp"); aplicacion.exec("delete *.avi"); 1 catch(Exception ex){} start();

I/

if (e.getActionCommand() == "paralelizar") if(framest.getText().equals(""))

primero");
}

JOptionPane.showMessageDialog(null,"Dijite la cantidad de frames else if(Integer.parseInt(framest.getText()) <=4) { JOptionPane.showMessageDialog(null,"El mnimo de Frames para Renderizar

00

es de 5");

}
else if(nodost.getText().equals("")) { JOptionPane.showMessageDialog(null,"Dijite la cantidad de Nodos

primero");

10

10

10

else if(Integer.parseInt(nodost.getText()) <0 11 Integer.parseInt(nodost.getText()) > 3) { JOptionPane.showMessageDialog(null,"El rango de nodos permitido es O para una solucion en serie, y 3 para el maximo total posible de paralelismo"); } else { framest.setEnabled(false); botonP.setEnabled(false); nodost.setEnabled(false); numNodos = Integer.parselnt(nodost.getText()); if(numNodos > O) f JOptionPane.showMessageDialog(null,"Precione Ok y luego ejecute el programa esclavo en los nodos para verlos activos, una vez hecho esto presione el boton Crear Render"); master.start(); else JOptionPane.showMessageDialog(null,"Se ejecutara el programa en Serie, presione el boton Ok y luego Crear Render para comenzar"); } boton.setEnabled(true);

10

I/

I/

10

1,

10

10

10

10

} {

110

II

10 }

if (e.getActionCommand() == "esfera") { boxl.setSelected(true); box2.setSelected(false); } if (e.getActionCommand() == "cubo") { box2.setSelected(true); boxl.setSelected(false); }

10 {

public static void main(String[] args) BekhoRay mrkarate = new BekhoRay(); master = new nodoM(); }


RayTracing.java

import java.applet.*; import java.awt.*; import java.util.*; public class RayTracing extends pixApplet { RayWorld myWorld; boolean first; float pixelColor[]; int thisPixel; int xStart; int yStart; int zShift; double v[]; double w[]; double focalLength, boolean damage; Matrix3d camRot;

e e

e
public void init() { super.init(); first = true; focalLength = 3; camRot = new Matrix3d(); myWorld = new RayWorld(); myWorld.setBGC(Color.white); /* valores de cada esfera (R,G,B, especularidad, X, Y, X, Radio) R = cantidad de Rojo G = cantidad de Verde B = Cantidad ed Azul especularidad = La forma en que la esfera refleja la luz; con un valor bajo la luz se difumina sobre la esfera, con un valor alto, la luz rebota ms otorgando un mayor brillo, por ejemplo, una pelota de goma tiene baja especularidad porque al ser iluminada la luz de difumina, pero una pelota de acero tiene especularidad alta, ya al ser iluminada la luz rebota mucho ms

Setspecular indica, en valores RGB, el color que tendr el brillo en cada esfera

// esfera superior myWorld.addSphere(.2, .2, .9, 10, -1.6, 0, -8, .9); myWorld.spheres[0].setSpecular(.3, .3, .3); // esfera inferior izquierda myWorld.addSphere(.9, .2, .2, 10, 1.6, 1.6, -8, .9); myWorld.spheres[1].setSpecular(.2, .2, .2); II esfera inferior derecha

myWorld.addSphere(.2, .9, .2, 10, 1.6, -1.6, -8, .9); myWorld.spheres[2].setSpecular(.8, .8, .8); // esfera central myWorld.addSphere(.8, .8, .8, 20, .3, 0, -8, 0.6); myWorld.spheres[3].setSpecular(.9, .9, .9);

e
// Valores de las luces: (X, Y, Z y color de cada luz, en RGB)

e
H luz central blanca
myWorld.addLight(0, 0, 1, .8, .8, .8);

// luz roja myWorld.addLight(1, 1, 0, .8, .2, .2); // luz verde myWorld.adclLight(1, -1, 0, .2, .8, .2); luz Azul myWorld.addLight(-1, 0, 0, .2, .2, .8);

e e

myWorld.setCenter(0, 0, -8); = new double[3]; w = new double[3]; pixelColor = new float[3]; thisPixel = 0;
v[o] = 0;

v[1] = 0; v[2] = 0; xStart = 0; yStart = 0; damage = true;

public void setPix(double deltaT) { int pixel = 0; for (int i = 0; i < W; i++) { // LOOP OVER IMAGE COLUMNS for (int j = 0; j < H; j++) { // LOOP OVER IMAGE ROWS w[0] = (double) (i - W / 2) / (W / 2); // COMPUTE RAY DIRECTION AT EACH PIXEL w[1] = (double) (H / 2 - j) / (W / 2); // w[2] = -focalLength; // PLACE IMAGE PLANE AT z=-focalLength camRot.transform(w, w); pixelColor = myWorld.rayTrace(v, w); thisPixel = pack(((int) (pixelColor[0] * 255)), ((int) (pixelColor[1] * 255)), ((int) (pixelColor[2] * 255))); pix[pixel] = thisPixel; pixel++;

} }

public boolean keyllp(Event e, int key) { switch (key) { case '=': focalLength += .2; break; case '-': focalLength -= .2; break; case 'w': // sphere[n] indica la esfera a mover nnyWorld.spheres[2].center[2] -= .5; break; case 's': myWorld.spheres[2].center[2] += .5; break; case 'a': /* camRot.xRot(-.2); myWorld.rotateWorld(ca mRot); camRot.identity(); myWorld.setBGC(Color. red); break;

case 'd': camRot.xRot(.2); myWorld.rotateWorld(camRot); camRot.identity(); break; case 'q': camRot.xRot(-.2); myWorld. rotShapes(camRot); camRot.identity(); break; case 'e': camRot.xRot(.2); myWorld.rotShapes(camRot); camRot.identity(); break; case '1': myWorld.lights[1].on = !myWorld .lights[1].on; break; case '2': nnyWorld.lights[2].on = !myWorld. lights[2].on; break; case '3': myWorld.lights[3].on = !myWorld. lights[3].on; break; case 'O': myWorld.lights[0].on = !myWorld. lights[0],on;

e e

break; damage = true; return true;

e
public boolean mou:seDown(Event e, int x, int y) { xStart = x; yStart = y; return true;

e e
e public boolean mouseDrag(Event e, int x, int y) { damage = true; return true;

e
e

public boolean mouseUp(Event e, int x, int y) { damage = true; return true;

111

lar

}
class RayWorld {

public Light lights[]; int numLights; public Sphere spheres[]; int numSpheres; Matrix3d reCenter; Matrix3d deCenter; Color bgColor;

public RayWorld() { bgColor = Color.black; numSpheres = O; reCenter = new Matrix3d(); deCenter = new Matrix3d(); spheres = new Sphere[100]; lights = new Light[10]; numLights = O;

public void setCenter(double x, double y, double z) { reCenter.identity(); reCenter.translate(-x, -y, -z); deCenter. identity(); deCenter.translate(x, y, z);

public void setBGC(Color colour) { bgColor = colour;

public void addLight(double x, double y, double z, double r, double g, double b) { // add a light to world double yec[] = new double[3]; vec[0] = x; vec[1] = y; vec[2] = z; normalize(vec); lights[numLights] = new Light(vec[0], vec[1], vec[2], (float) r, (float) g, (float) b); numLights++;

e
.

public void addSphere(double r, double g, double b, double spec, double x, double y, double z, double rad) { // add a sphere to the world spheres[numSpheres] = new Sphere((float) r, (float) g, (float) b, spec, x, y, z, rad); numSpheres++;

public void removeSphere(int sphereNum) { // remove a sphere from the world for (int i = sphereNum; i < (numSpheres - 1); i++) { spheres[i] = spheres[i + 1]; } numSpheres--; }

110 111

11

public void rotateWorld(Matrix3d rot) { for (int j = O; j < numSpheres; j++) // move alI objects back to the "origin" reCenter.transform(spheres[j].center, spheres[j].center); } for (int j = O; j < numSpheres; j++) { // rotate all objects rot.transform(spheres[j].center, spheres[j].center); } for (int j = O; j < numSpheres; j++) { // place alI objects back in front of the camera deCenter.transform(spheres[j].center, spheres[j].center); for (int j = O; j < numLights; j++) { // rotate alI lights rot.transform(lights[j].dir, lights[j].dir);

lo

1
public void rotShapes(Matrix3d rot) { for (int j = O; j < numSpheres; j++) { // move all objects back to the "origin" reCenter.transform(spheres[j].center, spheres[j].center);


for (int j = 0; j < numSpheres; j++) { rotate all objects rot.transform(spheres[j].center, spheres[j].center); } for (int j = 0; j < numSpheres; j++) // place all objects back in front of the camera deCenter.transform(spheres[j].center, spheres[j].center);

/1

float[] rayTrace(double[] start, double[] dir) float rayColor[] = new float[3]; bgColor.getColorComponents(rayColor); float lightColor[] = new float[3]; int sphere = -1; double a = 0; double b = O; double c = 0; double discriminant = 0; double t = Double.POSITIVE_INFINITY; double root = 0; double refSrc[] = new double[3]; for (int i = 0; i < numSpheres; i++) // this loop can be extended for any group of shape objects II the hit detection will probably end up in another method a = O; b = 0; c = 0; a = Math.pow(dir[0], 2.0) + Math.pow(dir[1], 2.0) + Math.pow(dir[2], 2.0); b += 2 * (start[0] - spheres[i].center[0]) * dir[0]; b += 2 * (start[1] - spheres[i].center[1]) * dir[1]; b += 2 * (start[2] - spheres[i].center[2]) * dir[2]; c += Math.pow((start[0] - spheres[i].center[0]), 2); c += Math.pow((start[1] - spheres[i].center[1]), 2); c Math.pow((start[2] - spheres[i].center[2]), 2); c -= Math.pow(spheres[i].r, 2); discrinninant = (Math.pow(b, 2) - 4 * a * c); if (discriminant >= 0) root = Math.min((-b + Math.sqrt(discriminant)) / (2 * a), (-b Math.sqrt(discriminant)) / (2 * a)); if (root < t && root > .0001) for (int j = 0; j < 3; j++) { // refSrc holds the starting point for reflected ray refSrc[j] = start[j] + root * dir[j]; } sphere = i; t = root; } } if (sphere != -1) { double refDir[] = new double[3]; double normal[] = new double[3]; normal[0] = (refSrc[0] - spheres[sphere].center[0]) / spheres[sphere].r; norman] = (refSrc[1] - spheres[sphere].center[1]) / spheres[sphere].r; normal[2] = (refSrc[2] - spheres[sphere].center[2]) / spheres[sphere].r; normalize(normal); normalize(dir); root = dotProd(normal, dir);

111

111

11/

11/

refDir[0] = -2 * root * normal[0] + dir[0]; // refDir will now be direction for reflection refDir[1] = -2 * root * normal[1] + dir[1]; refDir[2] = -2 * root * normal[2] + dir[2]; normalize(refDir); //get color from subsequent reflections of ray //and get their product with color of this object rayColor = getColor(sphere, refSrc, normal, refDir); // do some phonging here lightColor = rayTrace(refSrc, refDir); for (int j = 0; j < 3; j++) { rayColor[j] = rayColor[j] * lightColor[j]; return rayColor;

10

public float[] getColor(int sphere, double[] point, double[] norm, double[] dir) { float surfaceColor[] = new float[3]; float specCornponent[] = new float[3]; for (int j = O; j < 3; j++) { surfaceColor[j] = spheres[sphere].ambient[j]; } for (int j = 0; j < numLights; j++) { if (lights[j].on && isLit(point, lights[j])) { for (int i = 0; i < 3; i++) { surfaceColor[i] += (lights[j].color[i] * spheres[sphere].diffuse[i] * Math.max(0, dotProd(lights[j].dir, norm))); surfaceColor[i] += (lights[j].color[i] * spheres[sphere].specular[i] * Math.pow(Math.max(0, dotProd(lights[j].dir, dir)), spheres[sphere].specularity)); }

for (int i = 0; i < 3; i++) { surfaceColor[i] = Math.min(1, surfaceColor[i]); return surfaceColor;

115 public boolean isLit(clouble[] point, Light I) { double a = 0; double b = 0; double c = 0; double root = 0; double discriminant = 0; //see if any objects are on the path from point to light source for (int i = 0; i < numSpheres; i++) { a = 0; b = 0; c = 0; a = Math.pow(l.dir[0], 2.0) + Math.pow(l.dir[1], 2.0) + Math.pow(l.dir[2], 2.0); b += 2 * (point[0] - spheres[i].center[0]) * I.dir[0]; b += 2 * (point[1] - spheres[i].center[1]) * I.dir[1]; b += 2 * (point[2] - spheres[i].center[2]) * I.dir[2]; c += Math.pow((point[0] - spheres[i].center[0]), 2); c += Math.pow((point[1] - spheres[i].center[1]), 2); c += Math.pow((point[2] - spheres[i].center[2]), 2); c -= Math.pow(spheres[i].r, 2);

lin


discriminant = (Math.pow(b, 2) - 4 * a * c); if (discriminant >= 0) { root = Math.min((-b + Math.sqrt(discriminant)) / (2 * a), (-b Math.sqrt(discriminant)) / (2 * a)); if (root > .00001) { return false;

return true;

public double dotProd(double[] vecl, double[] vec2) { double sum = 0; for (int j = O; j < 3; j++) { sum += veci[j] * vec2[j]; } return sum;
}

1
public void normalize(double[] vec) { double norm = Math.sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]); for (int j = 0; j < 3; j++) { vec[j] /= norm; } } } class Sphere {

public float diffuse[]; public float specular[]; public float ambient[]; public double specularity; public double center[]; public double r;

public Sphere(float red, float g, float b, double spec, double xCenter, double yCenter, double zCenter, double radius) { diffuse = new float[3]; specular = new float[3]; ambient = new float[3]; center = new double[3]; for (int j = 0; j < 3; j++) { specular[j] = 1; } diffuse[0] = red; diffuse[1] = g; diffuse[2] = b; ambient[0] = red / 200; ambient[1] = g / 200; ambient[2] = b / 200; specularity = spec; center[0] = xCenter; center[1] = yCenter;

e e

center[2] = zCenter; r = radius;

e
e public void setDiffuse(double r, double g, double b) { diffuse[0] = (float) r; diffuse[1] = (float) g; diffuse[2] = (float) b; ambient[0] = (float) (r / 200); ambient[1] (float) (g / 200); ambient[2] = (float) (b / 200);

public void setSpecular(double r, double g, double b) { specular[0] = (float) r; specular[1] = (float) g; specular[2] (float) b;

class Light {

public float color[]; public double dir[]; public boolean on;

public Light(double x, double y, double z, float r, float g, float b) { color = new float[3]; dir = new double[3]; on = true; dir[0] = x; dir[1] = y; dir[2] = z; color[0] = r; color[1] = g; color[2] = b; }

Esfera.java

public class Esfera {

public float diffuse[]; public float specular[]; public float ambient[]; public double specularity; public double center[]; public double r;

public Esfera(float red, float g, float b, double spec, double xCenter, double yCenter, double zCenter, double radius) { diffuse = new float[3]; specular = new float[3]; ambient = new float[3]; center = new double[3]; for (int j = 0; j < 3; j++) { specular[j] = 1; } diffuse[0] = red; diffuse[1] = g; diffuse[2] = b; ambient[0] = red / 200; ambient[1] = g / 20C); ambient[2] = b / 200; specularity = spec; center[0] = xCenter; center[1] = yCenter; center[2] = zCenter; r = radius;

11>

public void setDiffuse(double r, double g, double b) { diffuse[0] = (float) r; diffuse[1] = (float) g; diffuse[2] = (float) b; ambient[0] = (float) (r / 200); ambient[1] = (float) (g / 200); ambient[2] = (float) (b / 200); }

public void setSpecular(double r, double g, double b) { specular[0] = (float) r; specular[1] = (float) g; specular[2] = (float) b; }

Luces.java
public class Luces { public float color[]; public double dir[]; public boolean on;

public Luces(double x, double y, double z, float r, float g, float b) color = new float[3]; dir = new double[3]; on = true; dir[0] = x; dir[1] = y; dir[2] = z; color[0] = r; color[1] = g; color[2] = b;

1 1 II



Cu be. 'alza
public class Cube extends Shape { private double[][] orig = new double[][] { { -1, 0, 0, -1 }, { 1, 0, 0, -1 }, { 0, -1, 0, -1 }, { 0, 1, 0, -1 }, { 0, 0, -1, -1 }, { 0, 0, 1, -1 } }; private double[][] hs = orig; private MatrixCube matrix = new MatrixCube(); public Cube(PhongTexture text) { super(text);

I/

10

110

10

@Override public Double intersect(double[] Y, double[] w) { double t, num, denom; double enter = Double.NEGATIVE INFINITY; double exit = Double.POSITIVEINFINITY; // t = -( avO + bvl + cv2 + d ) / ( aw0 + bwl + cw2 ) // num = avO + bvl + cv2 + d // denom = aw0 + bwl + cw2 for (int i = 0; i < hs.length; i++) { num = O; denom = 0; for (int j = 0; j < 3; j++) { num += hs[i][j] * v[j]; denom += hs[i][j] * w[j]; // avoid divide by zero if (denom == O) continue; num += hs[i][3]; t = -num / denom; // exiting if (denom > O) { if (t < exit) exit = t; // entering else if (t > enter) enter = t; // end loop if (enter < exit) return enter; else return null; @Override public double[] normal(double x, double y, double z) { double sum; for (int i=0; i < hs.length;i++) { sum = hs[i][0]*x + hs[i][1]*y + hs[i][2]*z + hs[i][3]; if (Math.abs(sum) < 0.0001) return new double[] {hs[i][0], hs[i][1], hs[i][2]};

10

10

10

10

10

11/

} throw new RuntimeException("Normal calculation error");


}

public void translate(double x, double y, double matrix.translate(x, y, z); multByInverseTranspose();


}

z) {

public void scale(double x, double y, double z) { matrix.scale(x, y, z); multByInverseTranspose();


}

public void rotateY(double theta) { matrix.rotateX(theta); multByInverseTranspose();


}

public void rotateY(double theta) { matrix.rotateX(theta); multByInverseTranspose();


}

public void rotateZ(double theta) { matrix.rotateZ(theta); multByInverseTranspose(); } public void multByInverseTranspose() { MatrixCube m = new MatrixCube(MatrixCube.invert(matrix)); m.transpose(); double[][] tmp = new double[hs.length][4]; for (int i = 0; i < hs.length; i++) { m.transform2(orig[i], tmp[i]); } hs = tmp;
}

public static void main(String[] args) { PhongTexture tl = new PhongTexture(new double[] { .1, .1, 0 .3, .3, 0 }, new double[] { .1, .i, .1 }, 10); Cube c = new Cube(ti); c.scale(6,6, 8);
} }

},

new double[] {

Imgenes de la Secuencia Renderizada

A continuacin se adjuntas algunas imgenes de la secuencia de renderizado de las esferas.

FRAME O

FRAME 1

FRAME 2

FRAME 3

FRAME 4

FRAME 5

FRAME 6

FRAME 7

FRAME 8

FRAME 9

FRAME 10


ip

e e o

FRAME 11

D D D

1 1 0 1 1 1 I I I 1 1 1 1 1 1

FRAME 12

FRAME 13

Vous aimerez peut-être aussi