world3.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 853 行 · 第 1/2 页
C
853 行
/****************************************************************************
*
* 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:
============
These are the 3d drawing primitives used in other parts of cgr. The 3d
pipeline should not be accessed by any part of cgr except this one.
*/
#include "icgr.h"
static hls_colour Curr_colour = { 0., 0., 0. };
static w3coord Curr_line_pt = { 0., 0., 0. };
static line_style Curr_line_style = LINE_SOLID;
static bool Black_edges = FALSE;
static region_info Region = { USE_RGN_NONE };
#define _range_constrain( val, low, high ) _max( _min( (val), (high) ), (low) )
/* mathematical constant e */
#define E 2.7182818
/* constants for the simple to real perspective conversion */
#define SIMP_PERSP_MIN 0.
#define SIMP_PERSP_MAX 100.
#define REAL_PERSP_MIN 0.5
#define REAL_PERSP_MAX 40.
static void set_vpn_vup(
/**********************/
/* set the vecotors ViewPlNorm and VUp based on h_angle and v_angle */
int h_angle,
int v_angle,
vector * vpn,
vector * vup
) {
float sintheta, costheta; /* h_angle values */
float sinphi, cosphi; /* v_angle values */
/* calculate the view plane normal */
sintheta = sin( _deg_to_rad( h_angle ) );
costheta = cos( _deg_to_rad( h_angle ) );
cosphi = cos( _deg_to_rad( v_angle ) );
sinphi = sin( _deg_to_rad( v_angle ) );
vpn->v[0] = cosphi * sintheta;
vpn->v[1] = sinphi;
vpn->v[2] = cosphi * costheta;
vpn->v[3] = 0;
/* set the up vector to (0,1,0) if -45 < v_angle < 45 otherwise */
/* set it according to h_angle */
if (v_angle >= 45) {
vup->v[0] = - sintheta;
vup->v[1] = 0.;
vup->v[2] = - costheta;
vup->v[3] = 0.;
} else if (v_angle <= -45) {
vup->v[0] = sintheta;
vup->v[1] = 0.;
vup->v[2] = costheta;
vup->v[3] = 0.;
} else {
vup->v[0] = 0.;
vup->v[1] = 1.;
vup->v[2] = 0.;
vup->v[3] = 0.;
}
}
static float calculate_real_perspective(
/**************************************/
int simp_persp
) {
float x;
/* set x to be simp_persp capped to SIMP_PERSP_MIN/MAX */
if( simp_persp < SIMP_PERSP_MIN ) {
x = SIMP_PERSP_MIN;
} else if( simp_persp > SIMP_PERSP_MAX ) {
x = SIMP_PERSP_MAX;
} else {
x = simp_persp;
}
/* scale x into [0,1] and reverse the direction */
x = 1 - (x - SIMP_PERSP_MIN)/(SIMP_PERSP_MAX - SIMP_PERSP_MIN);
/* apply exp to linearize the perspective, then scale into [0,1] */
x = exp( x );
x = (x - 1.) / (E - 1.);
/* futher linearize the perspective */
x = exp( x );
x = (x - 1.) / (E - 1.);
/* scale x into [REAL_PERSP_MIN, REAL_PERSP_MAX] */
x = x * (REAL_PERSP_MAX - REAL_PERSP_MIN) + REAL_PERSP_MIN;
return( x );
}
static void simple_to_pipe_view(
/******************************/
view_3d * simp,
pipe_view * view,
float base_zoom
) {
float zoom;
/* calculate the view plane normal and vup */
set_vpn_vup( simp->h_angle, simp->v_angle, &view->ViewPlNorm, &view->VUp );
/* calculate the view ref pt. */
view->ViewRefPt.p[0] = 0.5 + view->ViewPlNorm.v[0]/2.;
view->ViewRefPt.p[1] = 0.5 + view->ViewPlNorm.v[1]/2.;
view->ViewRefPt.p[2] = 0.5 + view->ViewPlNorm.v[2]/2.;
view->ViewRefPt.p[3] = 1.0;
/* set the window */
if( simp->zoom <= 0 ) {
zoom = 100. / base_zoom;
} else {
zoom = 100. / (simp->zoom * base_zoom);
}
view->vmin = - zoom;
view->vmax = zoom;
view->umin = - zoom;
view->umax = zoom;
/* set the projection ref. pt. */
view->ProjRefPt.p[0] = 0.;
view->ProjRefPt.p[1] = 0.;
view->ProjRefPt.p[2] = calculate_real_perspective( simp->perspective );
view->ProjRefPt.p[3] = 1.;
/* set the front and back clipping planes */
view->FrontClip = 0.; /* note FrontClip > BackClip */
view->BackClip = -1.;
view->type = simp->type;
}
static void set_light_dir(
/************************/
vector * dir,
light_vert_pos vert,
light_horz_pos horz,
light_depth_pos depth
) {
float len;
int i;
switch( horz ) {
case LIGHT_HORZ_LEFT:
dir->v[0] = -1.;
break;
case LIGHT_HORZ_MID:
dir->v[0] = 0.;
break;
case LIGHT_HORZ_RIGHT:
dir->v[0] = 1.;
break;
}
switch( vert ) {
case LIGHT_VERT_TOP:
dir->v[1] = 1.;
break;
case LIGHT_VERT_MID:
dir->v[1] = 0.;
break;
case LIGHT_VERT_BOTTOM:
dir->v[1] = -1.;
break;
}
switch( depth ) {
case LIGHT_DEPTH_FRONT:
dir->v[2] = 1.;
break;
case LIGHT_DEPTH_MID:
dir->v[2] = 0.;
break;
case LIGHT_DEPTH_BACK:
dir->v[2] = -1.;
break;
}
dir->v[3] = 0;
len = norm( *dir );
/* test for the middle, middle middle case */
if( len == 0. ) {
dir->v[2] = 1.; // make this middle, middle, front
} else {
/* otherwise normalize the vector */
for( i = 0; i < 4; i++ ) {
dir->v[i] /= len;
}
}
}
static void simple_to_pipe_illum(
/*******************************/
/*
NOTE: that since the lighting model is applied after the viewing
transformation has been performed the fact that h_angle and v_angle are
relitive to the viewing parameters is taken care of automagiclly.
NOTE: the centre of attention for the illumination model, relitive to which
the light source will be placed, is at (.5, .5, .5).
*/
light_3d * simp,
pipe_illum * pipe,
float distance,
light_vert_pos auto_pos
) {
vector dir;
float contrast;
float brightness;
pipe->at_infinity = (distance == 0.);
/* set the illumination point */
if( simp->type == LIGHT_AUTO ) {
set_light_dir( &dir, auto_pos, LIGHT_HORZ_LEFT,
LIGHT_DEPTH_FRONT );
} else {
set_light_dir( &dir, simp->vert, simp->horz, simp->depth );
}
if( pipe->at_infinity ) {
pipe->source.light_dir = dir;
} else {
pipe->source.light_pt.p[0] = .5 + distance * dir.v[0];
pipe->source.light_pt.p[1] = .5 + distance * dir.v[1];
pipe->source.light_pt.p[2] = .5 + distance * dir.v[2];
pipe->source.light_pt.p[3] = 1.;
}
contrast = _range_constrain( simp->contrast, 0, 100 ) / 100.;
brightness = _range_constrain( simp->brightness, 0, 100 ) / 50.;
pipe->amb_intensity = (1. - contrast) * brightness;
pipe->pt_intensity = contrast * brightness;
}
extern void _w3init(
/******************/
three_d_op * view,
float base_zoom,
float light_distance, // if 0 light is at infinity
light_vert_pos auto_pos,
bool all_poly_convex
) {
pipe_view * pview;
pipe_illum * pillum;
_new( pview, 1 );
_new( pillum, 1 );
simple_to_pipe_view( &view->view, pview, base_zoom );
simple_to_pipe_illum( &view->lighting, pillum, light_distance, auto_pos );
pipe3d_init( pview, pillum, all_poly_convex );
_free( pillum );
_free( pview );
}
extern void _w3shutdown(
/**********************/
void
) {
pipe3d_shutdown();
}
extern void _w3display_all(
/*************************/
void
) {
pipe3d_display();
}
extern void _w3get_view_dir(
/**************************/
/* Gets the viewing direction based on the angles given in view */
/* NOTE: The assumtion made in this routine are valid for the restricted */
/* viewing system employed in cgr but are not valid for the complete system */
/* as described in "Computer Graphics" by Foley et. al. */
view_3d * view,
w3coord * dir
) {
vector vpn;
vector dummy;
float len;
set_vpn_vup( view->h_angle, view->v_angle, &vpn, &dummy );
len = norm( vpn );
dir->xcoord = - vpn.v[0] / len;
dir->ycoord = - vpn.v[1] / len;
dir->zcoord = - vpn.v[2] / len;
}
extern void _w3setcolour(
/***********************/
COLORREF rgb
) {
rgb_to_hls( rgb, &Curr_colour );
}
extern void _w3setlinestyle(
/**************************/
line_style style
) {
Curr_line_style = style;
}
extern void _w3setblackedges(
/***************************/
bool black_edges
) {
Black_edges = black_edges;
}
static void rect_to_polar(
/************************/
float x,
float y,
float *r,
float *omega
) {
*r = sqrt( x*x + y*y );
if (*r == 0.) {
*omega = 0.; // this value is arbitrary
} else {
*omega = atan2( y, x );
}
}
static void polar_to_rect(
/************************/
float r,
float omega,
float *x,
float *y
) {
*x = r * cos( omega );
*y = r * sin( omega );
}
extern void ellipse_pt(
/*********************/
/* Calculated the point on the ellipse at angle alpha */
float h_sqr, // horizontal axis squared
float v_sqr, // vertical axis squared
float cx, // centre
float cy,
float alpha,
float * x,
float * y
) {
float calpha;
float salpha;
float r;
calpha = cos( alpha );
salpha = sin( alpha );
r = sqrt( 1./(calpha*calpha/h_sqr + salpha*salpha/v_sqr));
polar_to_rect( r, alpha, x, y );
*x += cx;
*y += cy;
}
static pt_edge * pie_to_poly(
/***************************/
/* returns a polynomial approximation to the pie wedge given */
/* The points in the polygon approximation are layed out in counter clockwise */
/* order as seen from below so that the sweep by height will put the solid in */
/* the 0-1 cube */
float x1,
float z1,
float x2,
float z2,
float x3,
float z3,
float x4,
float z4,
float y,
int resolution,
int * num_pts,
text_info * text,
bool all_pie
) {
pt_edge *pts; // polygon that will approximate the pie
int num_regions; // number of regions to devide the pie into
float cx, cz; // centre of ellipse
float h_sqr, w_sqr; // square of the half height & width
float alpha; // angle of current point from x-axis
float omega; // angle between start and end of pie
float beta; // angle of mid point of pie
float dummy;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?