pipeobj.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,446 行 · 第 1/3 页
C
1,446 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
/*
Description:
============
Routines to manipulate rend_obj's.
*/
#include "icgr.h"
#include <string.h>
#ifndef PROD
#define INCLUDE_DEBUG_ROUTINES
#endif
static point invalid_pt = { 0., 0., 0., 0. };
typedef struct face_pts { // used for calculating normal of a face
face * side;
point * pts;
} face_pts;
extern rend_obj * rend_obj_new_poly(
/**********************************/
void
) {
rend_obj * new;
polygon * poly;
_new( new, 1 );
new->type = REND_OBJ_POLY;
poly = &(new->obj.poly); // shorthand
poly->num_pts = 0;
poly->index = NULL;
_new( poly->pts, 1 );
poly->pts->num_pts = 0;
poly->pts->pts = NULL;
return( new );
}
static index_elt * identity_index(
/********************************/
int num_elt,
bool * edges
) {
index_elt * index;
int curr_elt;
_new( index, num_elt );
if( index != NULL ) {
for( curr_elt = 0; curr_elt < num_elt; curr_elt++ ) {
index[ curr_elt ].pt_num = curr_elt;
if( edges != NULL ) {
index[ curr_elt ].hilight_edge = edges[ curr_elt ];
} else {
index[ curr_elt ].hilight_edge = TRUE;
}
index[ curr_elt ].force_rgn_pt = FALSE;
}
}
return( index );
}
extern rend_obj * rend_obj_create_poly(
/*************************************/
int num_pts,
point * pts,
hls_colour base,
bool black_edges,
region_info * rgn,
bool * edges,
int rgn_pt_iter
) {
rend_obj * new;
polygon * poly;
new = rend_obj_new_poly();
if( new != NULL ) {
new->base_colour = base;
new->black_edges = black_edges;
new->rgn = *rgn;
poly = &new->obj.poly; // shorthand
poly->pts->num_pts = num_pts;
poly->pts->pts = pts;
poly->rgn_pt_iter = rgn_pt_iter;
poly->num_pts = num_pts;
poly->index = identity_index( num_pts, edges );
}
return( new );
}
extern rend_obj * rend_obj_create_line(
/*************************************/
point start,
point end,
hls_colour colour,
line_style style,
region_info * rgn
) {
rend_obj * obj;
_new( obj, 1 );
if( obj != NULL ) {
obj->type = REND_OBJ_LINE;
obj->base_colour = colour;
obj->black_edges = FALSE;
obj->rgn = *rgn;
obj->obj.line.start = start;
obj->obj.line.end = end;
obj->obj.line.style = style;
}
return( obj );
}
static vertex_list * dup_vertex_list(
/***********************************/
vertex_list * old
) {
vertex_list * new;
_pipenew( new, 1 );
new->num_pts = old->num_pts;
_pipenew( new->pts, new->num_pts );
memcpy( new->pts, old->pts, new->num_pts * sizeof(point) );
return( new );
}
static index_elt * dup_index(
/***************************/
index_elt * old,
int num_entries
) {
index_elt * new;
_pipenew( new, num_entries );
memcpy( new, old, num_entries * sizeof(*new) );
return( new );
}
static void copy_poly(
/********************/
polygon * old,
polygon * new
) {
new->normal = old->normal;
new->num_pts = old->num_pts;
new->index = dup_index( old->index, old->num_pts );
new->pts = dup_vertex_list( old->pts );
}
static void point_min(
/********************/
point pt1,
point pt2,
point * min
) {
min->p[0] = _min( pt1.p[0], pt2.p[0] );
min->p[1] = _min( pt1.p[1], pt2.p[1] );
min->p[2] = _min( pt1.p[2], pt2.p[2] );
min->p[3] = _min( pt1.p[3], pt2.p[3] );
}
static void point_max(
/********************/
point pt1,
point pt2,
point * max
) {
max->p[0] = _max( pt1.p[0], pt2.p[0] );
max->p[1] = _max( pt1.p[1], pt2.p[1] );
max->p[2] = _max( pt1.p[2], pt2.p[2] );
max->p[3] = _max( pt1.p[3], pt2.p[3] );
}
static bool face_visible(
/***********************/
face * curr_face,
vertex_list * pts_list,
visible_info * vis
) {
point * min;
point * max;
float x1, y1;
float x2, y2;
index_elt * index; // shorthand
int num_pts; // shorthand
point * pts; // shorthand
int curr_pt;
index = curr_face->index;
num_pts = curr_face->num_pts;
pts = pts_list->pts;
min = &vis->min;
max = &vis->max;
vis->mark = FALSE;
*min = pts[ index[0].pt_num ];
*max = pts[ index[0].pt_num ];
for( curr_pt = 1; curr_pt < num_pts; curr_pt++ ) {
point_min( *min, pts[ index[ curr_pt ].pt_num ], min );
point_max( *max, pts[ index[ curr_pt ].pt_num ], max );
}
project_pt( *min, &x1, &y1 );
project_pt( *max, &x2, &y2 );
return( _wrectvisible( x1, y1, x2, y2 ) );
}
static void add_solid_to_list(
/****************************/
/* solids are not added to the list directly, instead they are broken up */
/* into their component faces and these are added as polygons */
/* NOTE: The memory that is occupied by the points list of the polygon becomes*/
/* shared by the component polygons after this call. This doesn't present a */
/* problem in the pipemem memory manager since it is allocate only. If a real */
/* memory manager is being used then either a reference count would have to */
/* be maintained or each polygon could get a copy of the points that they */
/* reference. */
rend_obj * obj,
rend_list * list
) {
rend_obj * new;
polygon * new_poly;
vertex_list * pts;
face * curr_face;
face_list * old_faces;
visible_info vis;
old_faces = &(obj->obj.solid.faces); // shorthand
/* All the polygons will refer to the same vertex list. This is OK */
/* if the solid is consitent */
pts = dup_vertex_list( &(obj->obj.solid.pts) );
for (curr_face = old_faces->faces;
curr_face < old_faces->faces + old_faces->num_faces; curr_face++ ) {
/* back face culling */
if( curr_face->normal.v[2] > FUZZY_ZERO &&
face_visible( curr_face, pts, &vis ) ) {
_pipenew( new, 1 );
new->type = REND_OBJ_POLY;
new->vis = vis;
if( curr_face->black ) {
new->base_colour = Black_hls;
} else {
new->base_colour = obj->base_colour;
}
new->black_edges = obj->black_edges;
new->rgn = obj->rgn;
new_poly = &(new->obj.poly); // shorthand
new_poly->normal = curr_face->normal;
new_poly->num_pts = curr_face->num_pts;
new_poly->index = dup_index( curr_face->index, curr_face->num_pts );
new_poly->rgn_pt_iter = curr_face->rgn_pt_iter;
new_poly->pts = pts; // use the common vertex list
rend_list_add( list, new );
}
}
}
extern rend_obj * rend_obj_dup(
/*****************************/
/* duplicates obj into pipe_mem memory */
rend_obj * obj
) {
rend_obj * new_obj;
switch (obj->type) {
case REND_OBJ_PT:
case REND_OBJ_LINE:
_pipenew( new_obj, 1 );
*new_obj = *obj; // point and line structures don't have pointers
break;
case REND_OBJ_POLY:
_pipenew( new_obj, 1 );
*new_obj = *obj;
copy_poly( &(obj->obj.poly), &(new_obj->obj.poly) );
break;
case REND_OBJ_SOLID:
new_obj = NULL;
break;
}
return( new_obj );
}
extern void rend_obj_add_to_list(
/*******************************/
rend_obj * obj,
rend_list * list
) {
rend_obj * new_obj;
if (obj->type == REND_OBJ_SOLID) {
add_solid_to_list( obj, list );
} else {
new_obj = rend_obj_dup( obj );
rend_obj_compute_vis_info( new_obj );
rend_list_add( list, new_obj );
}
}
extern void rend_obj_lfree(
/*************************/
/* free a rend_obj from local memory */
/* NOTE: do not call this function for rend_obj's that have been added */
/* to the rend_list via a rend_obj_add_to_list call; they are not in */
/* local memory. */
rend_obj * obj
) {
polygon * poly;
vertex_list * pts;
face_list * faces;
face * curr_face;
switch (obj->type) {
case REND_OBJ_POLY:
poly = &(obj->obj.poly); // shorthand
pts = poly->pts; // shorthand
_free( pts->pts );
_free( pts );
_free( poly->index );
break;
case REND_OBJ_SOLID:
pts = &(obj->obj.solid.pts); // shorthand
faces = &(obj->obj.solid.faces); // shorthand
_free( pts->pts );
for (curr_face = faces->faces;
curr_face < faces->faces + faces->num_faces; curr_face++ ) {
_free( curr_face->index );
}
_free( faces->faces );
break;
}
_free( obj );
}
static void compute_poly_vis_info(
/********************************/
polygon * poly,
visible_info * ext
) {
int curr_pt;
ext->min = _polygon_get_pt( *poly, 0 );
ext->max = _polygon_get_pt( *poly, 0 );
for (curr_pt = 1; curr_pt < poly->num_pts; curr_pt++) {
point_min( ext->min, _polygon_get_pt( *poly, curr_pt ), &ext->min );
point_max( ext->max, _polygon_get_pt( *poly, curr_pt ), &ext->max );
}
}
static void compute_solid_vis_info(
/*********************************/
/* assume that all points mentioned in the vertex_list are reference by at */
/* at least one face */
polyhedron * solid,
visible_info * ext
) {
point * pt;
pt = solid->pts.pts;
ext->min = *pt;
ext->max = *pt;
while (pt < solid->pts.pts + solid->pts.num_pts) {
point_min( ext->min, *pt, &ext->min );
point_max( ext->max, *pt, &ext->max );
pt++;
}
}
extern void rend_obj_compute_vis_info(
/************************************/
rend_obj * obj
) {
switch (obj->type) {
case REND_OBJ_PT:
obj->vis.min = obj->obj.pt;
obj->vis.max = obj->obj.pt;
break;
case REND_OBJ_LINE:
point_min( obj->obj.line.start, obj->obj.line.end, &obj->vis.min );
point_max( obj->obj.line.start, obj->obj.line.end, &obj->vis.max );
break;
case REND_OBJ_POLY:
compute_poly_vis_info( &(obj->obj.poly), &(obj->vis) );
break;
case REND_OBJ_SOLID:
compute_solid_vis_info( &(obj->obj.solid), &(obj->vis) );
break;
}
obj->vis.mark = FALSE;
}
#if 0
/* macroed */
extern visible_info * rend_obj_get_vis(
/*************************************/
rend_obj * obj
) {
return( &(obj->vis) );
}
#endif
extern vector rend_obj_get_norm(
/******************************/
rend_obj * obj
) {
vector norm;
if (obj->type == REND_OBJ_POLY) {
norm = obj->obj.poly.normal;
} else {
norm.v[0] = 0.;
norm.v[1] = 0.;
norm.v[2] = 0.;
norm.v[3] = 0.;
}
return( norm );
}
extern int rend_obj_get_num_pts(
/******************************/
rend_obj * obj
) {
switch (obj->type) {
case REND_OBJ_SOLID:
return( obj->obj.solid.pts.num_pts );
break;
case REND_OBJ_POLY:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?