pipe2.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,160 行 · 第 1/3 页
C
1,160 行
rend_obj * obj_poly1,
rend_obj * obj_poly2
) {
point edge1[2];
point edge2[2];
int num_pts1;
int num_pts2;
int curr_pt1;
int curr_pt2;
polygon *poly1;
polygon *poly2;
int num_crosses;
visible_info *vis1;
visible_info *vis2;
vis1 = _rend_obj_get_vis( obj_poly1 );
vis2 = _rend_obj_get_vis( obj_poly2 );
poly1 = rend_obj_get_poly( obj_poly1 );
poly2 = rend_obj_get_poly( obj_poly2 );
num_pts1 = _polygon_get_num_pts( *poly1 );
num_pts2 = _polygon_get_num_pts( *poly2 );
/* start with the edge between point 0 and point (num_pts1-1) */
edge1[0] = _polygon_get_pt( *poly1, num_pts1-1 );
for (curr_pt1 = 0; curr_pt1 < num_pts1; curr_pt1++) {
edge1[1] = _polygon_get_pt( *poly1, curr_pt1 );
/* start with the edge between point 0 and point (num_pts2-1) */
edge2[0] = _polygon_get_pt( *poly2, num_pts2-1 );
for (curr_pt2 = 0; curr_pt2 < num_pts2; curr_pt2++) {
edge2[1] = _polygon_get_pt( *poly2, curr_pt2 );
if (proj_line_intersection( edge1, edge2 )) {
return( TRUE );
}
edge2[0] = edge2[1];
}
edge1[0] = edge1[1];
}
/* either poly 1 is contained in poly 2 . . . */
num_crosses = 0;
edge2[0] = _polygon_get_pt( *poly2, num_pts2-1 );
edge2[1] = edge2[0];
edge2[1].p[0] = vis1->min.p[0] - .1;
edge1[0] = _polygon_get_pt( *poly1, num_pts1-1 );
for (curr_pt1 = 0; curr_pt1 < num_pts1; curr_pt1++) {
edge1[1] = _polygon_get_pt( *poly1, curr_pt1 );
if (proj_line_intersection( edge1, edge2 )) {
num_crosses += 1;
}
edge1[0] = edge1[1];
}
if( num_crosses % 2 == 1 ) {
return( TRUE );
}
/* or poly 2 is contained in poly 1 . . . */
num_crosses = 0;
edge2[0] = _polygon_get_pt( *poly1, num_pts1-1 );
edge2[1] = edge2[0];
edge2[1].p[0] = vis2->min.p[0] - .1;
edge1[0] = _polygon_get_pt( *poly2, num_pts2-1 );
for (curr_pt2 = 0; curr_pt2 < num_pts2; curr_pt2++) {
edge1[1] = _polygon_get_pt( *poly2, curr_pt2 );
if (proj_line_intersection( edge1, edge2 )) {
num_crosses += 1;
}
edge1[0] = edge1[1];
}
if( num_crosses % 2 == 1 ) {
return( TRUE );
}
/* or they are truly disjoint */
return( FALSE );
}
static bool proj_overlap(
/***********************/
/* Tests whether the projection of obj1 and obj2 into the x-y plane overlaps */
/* NOTE: This function assumes that extent testing has been performed and */
/* that the extents do overlap */
rend_obj * obj1,
rend_obj * obj2
) {
rend_type type1;
rend_type type2;
type1 = _rend_obj_get_type( obj1 );
type2 = _rend_obj_get_type( obj2 );
/* the extent for a point is the point itself so if the extents overlap */
/* then the projections will overlap */
if (type1 == REND_OBJ_PT || type2 == REND_OBJ_PT) {
return( TRUE );
}
switch (type1) {
case REND_OBJ_LINE:
switch (type2) {
case REND_OBJ_LINE:
return( proj_overlap_ln_ln( obj1, obj2 ) );
break;
case REND_OBJ_POLY:
return( proj_overlap_ln_poly( obj1, obj2 ) );
break;
}
break;
case REND_OBJ_POLY:
switch (type2) {
case REND_OBJ_LINE:
return( proj_overlap_ln_poly( obj2, obj1 ) );
break;
case REND_OBJ_POLY:
return( proj_overlap_poly_poly( obj1, obj2 ) );
break;
}
break;
}
return( TRUE );
}
static bool test_for_overlap(
/***************************/
/* This function implements tests 1-5 for the depth-sort algorithm. */
rend_obj * qobj, // p and q refer to names on p. 673
rend_obj * pobj
) {
visible_info * qvis;
visible_info * pvis;
qvis = _rend_obj_get_vis( qobj );
pvis = _rend_obj_get_vis( pobj );
/* test 1 */
if (!_extent_overlap( qvis, pvis, 0 )) {
return( FALSE );
}
/* test 2 */
if (!_extent_overlap( qvis, pvis, 1 )) {
return( FALSE );
}
/* test 3 */
if (far_half_space( pobj, qobj )) {
return( FALSE );
}
/* test 4 */
if (near_half_space( qobj, pobj )) {
return( FALSE );
}
/* test 5 */
if (!proj_overlap( qobj, pobj )) {
return( FALSE );
}
return( TRUE );
}
static bool test_for_mtf(
/************************/
/* Tests whether it is safe to move qobj to before pobj in the list. */
/* mtf -- move to front */
/* This function impliments test 3' and 4' from the depth-sort alogorithm */
rend_obj * qobj, // p and q refer to names on p. 673
rend_obj * pobj
) {
/* test 3' */
if (far_half_space( qobj, pobj )) {
return( TRUE );
}
/* test 4' */
if (near_half_space( pobj, qobj )) {
return( TRUE );
}
return( FALSE );
}
static void get_first_unmarked(
/*****************************/
rend_list * list,
rend_list_ref * ref
) {
visible_info * vis;
_rend_list_first( list, ref );
while (!_rend_list_is_after_last( list, *ref )) {
vis = _rend_obj_get_vis( _rend_list_get_obj( list, *ref ) );
if (!vis->mark) {
return;
}
_rend_list_next( list, ref );
}
}
static void split_object(
/***********************/
/* Split obj1 by the plane of obj2 and insert the pieces into list in proper */
/* z-min order after any marked objects. */
rend_list * list,
rend_obj * obj1,
rend_obj * obj2
) {
vector norm; // plane of obj2
rend_obj * p; // pieces of obj1 in local memory
rend_obj * g; // in pipe memory
rend_list_ref start; // for specifying the sublist to insert into
rend_list_ref end;
int i;
norm = calculate_object_norm( obj2, obj1 );
p = rend_obj_clip( obj1, norm );
if (p != NULL) {
g = rend_obj_dup( p );
rend_obj_lfree( p );
rend_obj_compute_vis_info( g );
get_first_unmarked( list, &start );
_rend_list_last( list, &end );
rend_list_bin_insert( list, start, end, &g, compare_zmin );
}
/* Change the direction of the normal */
for (i=0; i<4; i++) {
norm.v[i] *= -1;
}
p = rend_obj_clip( obj1, norm );
if (p != NULL) {
g = rend_obj_dup( p );
rend_obj_lfree( p );
rend_obj_compute_vis_info( g );
get_first_unmarked( list, &start );
_rend_list_last( list, &end );
rend_list_bin_insert( list, start, end, &g, compare_zmin );
}
}
static void split_marked_object(
/******************************/
/* This routine determines which of obj1 or obj2 to split the splits it and */
/* inserts the pieces into list */
rend_list * list,
rend_obj * obj1,
rend_obj * obj2
) {
if (check_half_space( obj1, obj2 ) == HALF_SPACE_NONE) {
split_object( list, obj1, obj2 );
} else if (check_half_space( obj2, obj1 ) == HALF_SPACE_NONE) {
split_object( list, obj2, obj1 );
} else {
// Neither obj1 nor obj2 is split by the plane of the other so some
// other splitting criterion should be applied to one of the objects
// and the resulting pieces inserted into the list.
// Since this case should not occur and I can't think of such a
// criterion this case is considered a fatal error.
WPI_INST inst;
inst = inst;
#ifdef PLAT_OS2
_wpi_setanchorblock( HWND_DESKTOP, inst );
#endif
_wpi_fatalappexit( inst, 0, "Internal wcgr error." );
}
}
static void check_overlap(
/************************/
rend_list * list,
rend_list_ref * dref // reference to the candidate for drawing
) {
rend_list_ref cref; // reference to the obj to check
rend_obj * dobj;
rend_obj * cobj;
visible_info * dvis;
visible_info * cvis;
cref = *dref;
_rend_list_next( list, &cref );
/* note: a for loop is used here so the continue will work */
for (; !_rend_list_is_after_last( list, cref );
_rend_list_next( list, &cref ) ) {
cobj = _rend_list_get_obj( list, cref );
dobj = _rend_list_get_obj( list, *dref );
cvis = _rend_obj_get_vis( cobj );
dvis = _rend_obj_get_vis( dobj );
/* Check if the objects overlap in z */
if (dvis->max.p[2] < cvis->min.p[2]) {
if (cvis->mark) {
/* if the object is marked it is not in sorted order so */
/* continue checking other objects in the list */
/**/ continue;
} else {
/* if the object is not marked it is in sorted order in the */
/* list so all objects later in the list have zmin >= zmin of */
/* cobj so it is safe to draw dobj now */
/**/ break;
}
}
if (test_for_overlap( cobj, dobj )) {
if (cvis->mark) {
/* This case handles cyclical overlap which should not occur */
/* in a 3d chart, but just in case ... */
split_marked_object( list, dobj, cobj );
} else {
if (test_for_mtf( cobj, dobj )) {
/* mark cobj and move it to the front of the list */
cvis->mark = TRUE;
rend_list_delete( list, &cref );
_rend_list_first( list, &cref );
rend_list_insert( list, &cref, cobj, TRUE );
} else {
/* ASSERT: dobj is not a point */
/* remove dref from list */
rend_list_delete( list, dref );
/* if we get here we know that dobj lies on both sides of */
/* the plane of cobj so split dobj by the plane of cobj */
/* and insert the pieces into the list in the proper spots*/
split_object( list, dobj, cobj );
}
}
_rend_list_first( list, dref );
cref = *dref;
}
}
}
#if 0
static void unmark_list(
/**********************/
rend_list * list
) {
rend_list_ref curr;
visible_info * vis;
if (_rend_list_is_empty( list )) {
return;
}
_rend_list_first( list, &curr );
while (!_rend_list_is_after_last( list, curr )) {
vis = _rend_obj_get_vis( _rend_list_get_obj( list, curr ) );
vis->mark = FALSE;
_rend_list_next( list, &curr );
}
}
#endif
static void display_visible_surfaces(
/***********************************/
rend_list * list
) {
rend_list_ref curr_ref; // reference to obj we wish to draw
// compute_extents( list );
rend_list_sort( list, compare_zmin );
while (!_rend_list_is_empty( list )) {
_rend_list_first( list, &curr_ref );
check_overlap( list, &curr_ref );
draw_illuminated_obj( _rend_list_get_obj( list, curr_ref ) );
rend_list_delete( list, &curr_ref );
}
}
extern void pipe3d_display(
/*************************/
void
) {
display_visible_surfaces( Pipe3dList );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?