/*************************************************************************/ /* */ /* 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 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 ) ; }