blob: eca0050cc9eb6ecac2e0fb8d51484825d54b7091 [file] [log] [blame]
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
#include <stdio.h>
EXTERN_ENV;
include(radiosity.h)
static void add_radiosity_to_vertex(Edge *edge, long reverse, Element *elem, Vertex *p_c, long process_id);
static void _display_shaded_triangle(ElemVertex *ev1, ElemVertex *ev2, ElemVertex *ev3, Edge *e12, Edge *e23, Edge *e31, long process_id);
static void _disp_interactions(Element *elem, Interaction *inter, long mode, long process_id);
static void _ps_disp_interactions(Element *elem, Interaction *inter, long mode, long process_id);
/************************************************************************
*
* radiosity_averaging
*
*************************************************************************/
void radiosity_averaging(Element *elem, long mode, long process_id)
{
float inv_weight ;
Vertex pc ;
long reverse ;
if( ! LEAF_ELEMENT(elem) )
{
create_radavg_task( elem->center, mode, process_id ) ;
create_radavg_task( elem->top, mode, process_id ) ;
create_radavg_task( elem->right, mode, process_id ) ;
create_radavg_task( elem->left, mode, process_id ) ;
return ;
}
else if( mode == RAD_AVERAGING_MODE )
{
/* Compute center point */
center_point( &elem->ev1->p, &elem->ev2->p, &elem->ev3->p, &pc ) ;
reverse = EDGE_REVERSE( elem->e12, elem->ev1, elem->ev2 ) ;
foreach_leaf_edge( elem->e12, reverse, add_radiosity_to_vertex, (long)elem, (long)&pc, process_id ) ;
reverse = EDGE_REVERSE( elem->e23, elem->ev2, elem->ev3 ) ;
foreach_leaf_edge( elem->e23, reverse, add_radiosity_to_vertex, (long)elem, (long)&pc, process_id ) ;
reverse = EDGE_REVERSE( elem->e31, elem->ev3, elem->ev1 ) ;
foreach_leaf_edge( elem->e31, reverse, add_radiosity_to_vertex, (long)elem, (long)&pc, process_id ) ;
}
else
{
/* Normalize it */
LOCK(elem->ev1->ev_lock->lock);
if( elem->ev1->weight != 1.0 )
{
inv_weight = (float)1.0 / elem->ev1->weight ;
elem->ev1->col.r *= inv_weight ;
elem->ev1->col.g *= inv_weight ;
elem->ev1->col.b *= inv_weight ;
elem->ev1->weight = 1.0 ;
}
UNLOCK(elem->ev1->ev_lock->lock);
LOCK(elem->ev2->ev_lock->lock);
if( elem->ev2->weight != 1.0 )
{
inv_weight = (float)1.0 / elem->ev2->weight ;
elem->ev2->col.r *= inv_weight ;
elem->ev2->col.g *= inv_weight ;
elem->ev2->col.b *= inv_weight ;
elem->ev2->weight = 1.0 ;
}
UNLOCK(elem->ev2->ev_lock->lock);
LOCK(elem->ev3->ev_lock->lock);
if( elem->ev3->weight != 1.0 )
{
inv_weight = (float)1.0 / elem->ev3->weight ;
elem->ev3->col.r *= inv_weight ;
elem->ev3->col.g *= inv_weight ;
elem->ev3->col.b *= inv_weight ;
elem->ev3->weight = 1.0 ;
}
UNLOCK(elem->ev3->ev_lock->lock);
}
}
static void add_radiosity_to_vertex(Edge *edge, long reverse, Element *elem, Vertex *p_c, long process_id)
{
ElemVertex *ev ;
float weight ;
if( reverse )
ev = edge->pb ;
else
ev = edge->pa ;
weight = (float)1.0 / distance( &ev->p, p_c ) ;
weight = 1.0 ;
weight = elem->area ;
LOCK(ev->ev_lock->lock);
ev->col.r += (elem->rad.r * weight) ;
ev->col.g += (elem->rad.g * weight) ;
ev->col.b += (elem->rad.b * weight) ;
ev->weight += weight ;
UNLOCK(ev->ev_lock->lock);
}
/************************************************************************
*
* setup_view()
*
*************************************************************************/
Vertex view_vec ; /* Origin to the viewer */
static float view_rot_x, view_rot_y, view_dist, view_zoom ;
void setup_view(float rot_x, float rot_y, float dist, float zoom, long process_id)
{
Vertex v1, v2 ;
float cc, ss ;
/* Save parameters */
view_rot_x = rot_x ;
view_rot_y = rot_y ;
view_dist = dist ;
view_zoom = zoom ;
/* Compute view vector */
v1.x = 0.0 ;
v1.y = 0.0 ;
v1.z = 1.0 ;
/* Rotate view vector */
cc = cos( -rot_x * (M_PI / 180.0) ) ;
ss = sin( -rot_x * (M_PI / 180.0) ) ;
v2.x = v1.x ;
v2.y = cc * v1.y - ss * v1.z ;
v2.z = ss * v1.y + cc * v1.z ;
cc = cos( -rot_y * (M_PI / 180.0) ) ;
ss = sin( -rot_y * (M_PI / 180.0) ) ;
v1.z = cc * v2.z - ss * v2.x ;
v1.x = ss * v2.z + cc * v2.x ;
v1.y = v2.y ;
/* Store view vector */
view_vec = v1 ;
}
/************************************************************************
*
* display_scene()
*
*************************************************************************/
void display_scene(long fill_sw, long patch_sw, long mesh_sw, long interaction_sw, long process_id)
{
/* Clear the screen */
g_clear() ;
/* Set matrix */
g_setup_view( view_rot_x, view_rot_y, view_dist, view_zoom ) ;
if( fill_sw == 2 )
{
/* Fill surfaces */
display_elements_in_bsp_tree( DISPLAY_SHADED, process_id ) ;
}
if( fill_sw == 1 )
{
/* Fill surfaces */
display_elements_in_bsp_tree( DISPLAY_FILLED, process_id ) ;
}
if( mesh_sw )
{
/* Draw mesh */
g_color( G_BLUE ) ;
display_elements_in_bsp_tree( DISPLAY_EDGEONLY, process_id ) ;
}
if( patch_sw )
{
g_color( G_RED ) ;
display_patches_in_bsp_tree( DISPLAY_EDGEONLY, process_id ) ;
}
if( interaction_sw )
{
g_color( G_GREEN ) ;
display_interactions_in_bsp_tree(process_id) ;
}
/* Flush */
g_flush() ;
}
/************************************************************************
*
* display_patch()
*
*************************************************************************/
void display_patch(Patch *patch, long mode, long process_id)
{
Vertex p_buf[4] ;
Rgb c_buf[4] ;
if( mode == DISPLAY_SHADED )
{
if( inner_product( &patch->plane_equ.n, &view_vec ) < F_ZERO )
return ;
p_buf[0] = patch->p1 ;
p_buf[1] = patch->p2 ;
p_buf[2] = patch->p3 ;
c_buf[0] = patch->color ;
c_buf[1] = patch->color ;
c_buf[2] = patch->color ;
g_spolygon( 3, p_buf, c_buf ) ;
}
else if( mode == DISPLAY_FILLED )
{
if( inner_product( &patch->plane_equ.n, &view_vec ) < F_ZERO )
return ;
p_buf[0] = patch->p1 ;
p_buf[1] = patch->p2 ;
p_buf[2] = patch->p3 ;
g_polygon( 3, p_buf ) ;
}
else
{
g_line( &patch->p1, &patch->p2 ) ;
g_line( &patch->p2, &patch->p3 ) ;
g_line( &patch->p3, &patch->p1 ) ;
}
}
/************************************************************************
*
* display_patches_in_bsp_tree()
*
*************************************************************************/
void display_patches_in_bsp_tree(long mode, long process_id)
{
foreach_depth_sorted_patch( &view_vec, display_patch, (long)mode, process_id ) ;
}
/************************************************************************
*
* display_element()
*
*************************************************************************/
void display_element(Element *element, long mode, long process_id)
{
Vertex p_buf[4] ;
if( inner_product( &element->patch->plane_equ.n, &view_vec ) < F_ZERO )
return ;
if( mode == DISPLAY_SHADED )
{
_display_shaded_triangle( element->ev1, element->ev2,
element->ev3,
element->e12, element->e23, element->e31, process_id ) ;
}
else if( mode == DISPLAY_FILLED )
{
g_rgb( element->rad ) ;
p_buf[0] = element->ev1->p ;
p_buf[1] = element->ev2->p ;
p_buf[2] = element->ev3->p ;
g_polygon( 3, p_buf ) ;
}
else
{
g_line( &element->ev1->p, &element->ev2->p ) ;
g_line( &element->ev2->p, &element->ev3->p ) ;
g_line( &element->ev3->p, &element->ev1->p ) ;
}
}
static void _display_shaded_triangle(ElemVertex *ev1, ElemVertex *ev2, ElemVertex *ev3, Edge *e12, Edge *e23, Edge *e31, long process_id)
{
Vertex p_buf[4] ;
Rgb c_buf[4] ;
p_buf[0] = ev1->p ;
p_buf[1] = ev2->p ;
p_buf[2] = ev3->p ;
c_buf[0] = ev1->col ;
c_buf[1] = ev2->col ;
c_buf[2] = ev3->col ;
g_spolygon( 3, p_buf, c_buf ) ;
}
/************************************************************************
*
* display_elements_in_patch()
*
*************************************************************************/
void display_elements_in_patch(Patch *patch, long mode, long process_id)
{
foreach_leaf_element_in_patch( patch, display_element, mode, process_id ) ;
g_flush() ;
}
/************************************************************************
*
* display_elements_in_bsp_tree()
*
*************************************************************************/
void display_elements_in_bsp_tree(long mode, long process_id)
{
foreach_depth_sorted_patch( &view_vec, display_elements_in_patch, mode, process_id );
}
/************************************************************************
*
* display_interactions_in_element()
*
*************************************************************************/
void display_interactions_in_element(Element *elem, long mode, long process_id)
{
foreach_interaction_in_element( elem, _disp_interactions, mode, process_id ) ;
g_flush() ;
}
static void _disp_interactions(Element *elem, Interaction *inter, long mode, long process_id)
{
Vertex pa, pb ;
Element *edst ;
/* Display interactions only with a particular patch */
if( (mode == DISPLAY_HALF_INTERACTIONS)
&& (inter->destination->patch->seq_no >= elem->patch->seq_no ) )
return ;
/* Compute mid point of the element */
edst = inter->destination ;
center_point( &elem->ev1->p, &elem->ev2->p, &elem->ev3->p, &pa ) ;
center_point( &edst->ev1->p, &edst->ev2->p, &edst->ev3->p, &pb ) ;
/* Draw a line */
g_line( &pa, &pb ) ;
}
/************************************************************************
*
* display_interactions_in_patch
*
*************************************************************************/
void display_interactions_in_patch(Patch *patch, long mode, long process_id)
{
foreach_element_in_patch( patch, display_interactions_in_element, mode, process_id );
}
/************************************************************************
*
* display_interactions_in_bsp_tree
*
*************************************************************************/
void display_interactions_in_bsp_tree(long process_id)
{
foreach_patch_in_bsp( display_interactions_in_patch, DISPLAY_ALL_INTERACTIONS, process_id ) ;
}
/************************************************************************
*************************************************************************
*
* PostScript Version driver
*
*************************************************************************
*************************************************************************/
/************************************************************************
*
* ps_display_scene()
*
*************************************************************************/
void ps_display_scene(long fill_sw, long patch_sw, long mesh_sw, long interaction_sw, long process_id)
{
if( fill_sw )
{
/* Fill surfaces */
ps_display_elements_in_bsp_tree( DISPLAY_SHADED, process_id ) ;
}
if( mesh_sw )
{
/* Draw mesh */
ps_linewidth( 0.5 ) ;
ps_display_elements_in_bsp_tree( DISPLAY_EDGEONLY, process_id ) ;
}
if( patch_sw )
{
/* Draw patches */
ps_linewidth( 1.2 ) ;
ps_display_patches_in_bsp_tree( DISPLAY_EDGEONLY, process_id ) ;
}
if( interaction_sw )
{
/* Draw interactions */
ps_linewidth( 0.2 ) ;
ps_display_interactions_in_bsp_tree(process_id) ;
}
}
/************************************************************************
*
* ps_display_patch()
*
*************************************************************************/
void ps_display_patch(Patch *patch, long mode, long process_id)
{
Vertex p_buf[4] ;
Rgb c_buf[4] ;
if( mode == DISPLAY_SHADED )
{
if( inner_product( &patch->plane_equ.n, &view_vec ) < F_ZERO )
return ;
p_buf[0] = patch->p1 ;
p_buf[1] = patch->p2 ;
p_buf[2] = patch->p3 ;
c_buf[0] = patch->color ;
c_buf[1] = patch->color ;
c_buf[2] = patch->color ;
ps_spolygon( 3, p_buf, c_buf ) ;
}
else if( mode == DISPLAY_FILLED )
{
if( inner_product( &patch->plane_equ.n, &view_vec ) < F_ZERO )
return ;
p_buf[0] = patch->p1 ;
p_buf[1] = patch->p2 ;
p_buf[2] = patch->p3 ;
ps_polygon( 3, p_buf ) ;
}
else
{
p_buf[0] = patch->p1 ;
p_buf[1] = patch->p2 ;
p_buf[2] = patch->p3 ;
ps_polygonedge( 3, p_buf ) ;
}
}
/************************************************************************
*
* ps_display_patches_in_bsp_tree()
*
*************************************************************************/
void ps_display_patches_in_bsp_tree(long mode, long process_id)
{
foreach_depth_sorted_patch( &view_vec, ps_display_patch, (long)mode, process_id ) ;
}
/************************************************************************
*
* ps_display_element()
*
*************************************************************************/
void ps_display_element(Element *element, long mode, long process_id)
{
Vertex p_buf[4] ;
Rgb c_buf[4] ;
if( mode == DISPLAY_SHADED )
{
if( inner_product( &element->patch->plane_equ.n, &view_vec )
< F_ZERO )
return ;
p_buf[0] = element->ev1->p ;
p_buf[1] = element->ev2->p ;
p_buf[2] = element->ev3->p ;
c_buf[0] = element->rad ;
c_buf[1] = element->rad ;
c_buf[2] = element->rad ;
ps_spolygon( 3, p_buf, c_buf ) ;
}
else if( mode == DISPLAY_FILLED )
{
if( inner_product( &element->patch->plane_equ.n, &view_vec )
< F_ZERO )
return ;
p_buf[0] = element->ev1->p ;
p_buf[1] = element->ev2->p ;
p_buf[2] = element->ev3->p ;
ps_polygon( 3, p_buf ) ;
}
else
{
p_buf[0] = element->ev1->p ;
p_buf[1] = element->ev2->p ;
p_buf[2] = element->ev3->p ;
ps_polygonedge( 3, p_buf ) ;
}
}
/************************************************************************
*
* ps_display_elements_in_patch()
*
*************************************************************************/
void ps_display_elements_in_patch(Patch *patch, long mode, long process_id)
{
foreach_leaf_element_in_patch( patch, ps_display_element, mode, process_id ) ;
}
/************************************************************************
*
* ps_display_elements_in_bsp_tree()
*
*************************************************************************/
void ps_display_elements_in_bsp_tree(long mode, long process_id)
{
foreach_depth_sorted_patch( &view_vec, ps_display_elements_in_patch, mode, process_id ) ;
}
/************************************************************************
*
* ps_display_interactions_in_element()
*
*************************************************************************/
void ps_display_interactions_in_element(Element *elem, long mode, long process_id)
{
foreach_interaction_in_element( elem, _ps_disp_interactions, mode, process_id ) ;
}
static void _ps_disp_interactions(Element *elem, Interaction *inter, long mode, long process_id)
{
Vertex pa, pb ;
Element *edst ;
/* Display interactions only with a particular patch */
if( (mode == DISPLAY_HALF_INTERACTIONS)
&& (inter->destination->patch->seq_no >= elem->patch->seq_no ) )
return ;
/* Compute mid point of the element */
edst = inter->destination ;
center_point( &elem->ev1->p, &elem->ev2->p, &elem->ev3->p, &pa ) ;
center_point( &edst->ev1->p, &edst->ev2->p, &edst->ev3->p, &pb ) ;
/* Draw a line */
ps_line( &pa, &pb ) ;
}
/************************************************************************
*
* ps_display_interactions_in_patch
*
*************************************************************************/
void ps_display_interactions_in_patch(Patch *patch, long mode, long process_id)
{
foreach_element_in_patch( patch, ps_display_interactions_in_element, mode, process_id );
}
/************************************************************************
*
* ps_display_interactions_in_bsp_tree
*
*************************************************************************/
void ps_display_interactions_in_bsp_tree(long process_id)
{
foreach_patch_in_bsp( ps_display_interactions_in_patch, DISPLAY_ALL_INTERACTIONS, process_id ) ;
}