pipeutil.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 754 行 · 第 1/2 页

C
754
字号
/****************************************************************************
*
*                            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:
 ============
 Utility routines used by the 3d graphics pipeline.

 The routines in this file use memory as follows:
    1. rend_obj's in the first half of the pipeline are kept in local
        memory since there will only be one of them being acted upon
        at any one time.
    2. At the end of the first half of the pipeline the rend_obj being acted
        upon is added to the rend_list but is first copied into memory
        managed by pipemem (see pipemem.c).
    3. The list part of the rend_list is kept in global memory as an array
        and is realloc'ed as necessary.

*/

#include "icgr.h"
#include <float.h>
#include <string.h>


#ifndef PROD
#define INCLUDE_DEBUG_ROUTINES
#endif

/* amount to grow a rend_list by when needed */
#define REND_LIST_GROW_SIZE     25


/* rend_list manipulation routines */
static void check_list_size(
/**************************/
    rend_list *     list
) {
    if (list->last + 1 >= list->size) {
        list->size += REND_LIST_GROW_SIZE;
        _grenew( list->list, list->size );
    }
}

extern bool rend_list_init(
/*************************/
    rend_list *     list
) {
    _gnew( list->list, REND_LIST_GROW_SIZE );
    list->last = -1;        // no entries in use

    if (list->list == NULL) {
        list->size = 0;
        return( FALSE );
    } else {
        list->size = REND_LIST_GROW_SIZE;
        return( TRUE );
    }
}

#if 0
/* macroed */
extern bool rend_list_is_empty(
/*****************************/
    rend_list *     list
) {
    return( list->last < 0 );
}
#endif

extern void rend_list_add(
/************************/
    rend_list *     list,
    rend_obj *      obj
) {
    check_list_size( list );

    list->last += 1;
    list->list[ list->last ] = obj;
}

extern void rend_list_free(
/*************************/
    rend_list *     list
) {
    _gfree( list->list );
}

extern void rend_list_sort(
/*************************/
    rend_list *     list,
    int             (*compare) (const rend_obj **, const rend_obj **)
) {
    qsort( list->list, list->last + 1, sizeof(rend_obj *), (int (*)(const void *, const void *))compare );
}

extern void rend_list_bin_insert(
/*******************************/
/* Uses a binary search to insert obj into a sublist of list. The sublist is */
/* given by start and end. */
/* NOTE: if start > end obj is inserted after end */
    rend_list *     list,
    rend_list_ref   start,
    rend_list_ref   end,
    rend_obj **     obj,
    int             (*compare) (const rend_obj **, const rend_obj **)
) {
    int             high;
    int             low;
    int             mid;
    int             comp_rc;

    low = start;
    high = end;
    mid = (low + high) / 2;

    while (low <= high ) {
        comp_rc = compare( (const rend_obj **)obj, (const rend_obj **)(list->list + mid) );
        if (comp_rc < 0) {
            high = mid - 1;
        } else if (comp_rc > 0) {
            low = mid + 1;
        } else {
            high = mid;
    /**/    break;
        }
        mid = (low + high) / 2;
    }

    /* Insert the elemtent after high. If high is -1 this means insert */
    /* the element before the first element and rend_list_insert handles */
    /* this case. */
    rend_list_insert( list, &high, *obj, FALSE );
}


extern void rend_list_insert(
/***************************/
    rend_list *     list,
    rend_list_ref * ref,
    rend_obj *      obj,
    bool            before
) {
    check_list_size( list );

    list->last += 1;

    if (before) {
        memmove( &(list->list[ *ref + 1 ]), &(list->list[ *ref ]),
                (list->last - *ref) * sizeof(rend_obj *) );
    } else {
        *ref += 1;
        memmove( &(list->list[ *ref + 1 ]), &(list->list[ *ref ]),
                (list->last - *ref) * sizeof(rend_obj *) );
    }

    list->list[ *ref ] = obj;
}

extern void rend_list_delete(
/***************************/
    rend_list *     list,
    rend_list_ref * ref
) {
    memmove( &(list->list[ *ref ]), &(list->list[ *ref + 1 ]),
            (list->last - *ref) * sizeof(rend_obj *) );
    list->last -= 1;
    if (*ref > list->last) {
        *ref = list->last;
    }
}

#if 0
/* macroed */
extern rend_obj * rend_list_get_obj(
/**********************************/
    rend_list *     list,
    rend_list_ref   ref
) {
    return( list->list[ ref ] );
}
#endif

#if 0
/* macroed */
extern void rend_list_set_obj(
/****************************/
    rend_list *     list,
    rend_list_ref   ref,
    rend_obj *      obj
) {
    list->list[ ref ] = obj;
}
#endif

#if 0
/* macroed */
extern bool rend_list_next(
/*************************/
    rend_list *     list,
    rend_list_ref * ref
) {
    *ref += 1;
    return( *ref > list->last );
}
#endif

#if 0
/* macroed */
extern bool rend_list_prev(
/*************************/
    rend_list *     list,
    rend_list_ref * ref
) {
    list = list;        // other representaions of rend_list may need list

    *ref -= 1;
    return( *ref < 0 );
}
#endif

#if 0
/* macroed */
extern bool rend_list_is_before_first(
/************************************/
    rend_list *     list,
    rend_list_ref   ref
) {
    list = list;        // other representations of rend_list may need list

    return( ref < 0 );
}
#endif

#if 0
/* macroed */
extern bool rend_list_is_after_last(
/**********************************/
    rend_list *     list,
    rend_list_ref   ref
) {
    return( ref > list->last );
}
#endif

#if 0
/* macroed */
extern void rend_list_first(
/**************************/
    rend_list *     list,
    rend_list_ref * ref
) {
    list = list;        // other representations of rend_list may need list

    *ref = 0;
}
#endif

#if 0
/* macroed */
extern void rend_list_last(
/*************************/
    rend_list *     list,
    rend_list_ref * ref
) {
    *ref = list->last;
}
#endif


/* vector manipulation routines */
extern vector cross_prod(
/***********************/
    vector  v,
    vector  w
) {
    vector  r;

    r.v[0] = v.v[1]*w.v[2] - v.v[2]*w.v[1];
    r.v[1] = v.v[2]*w.v[0] - v.v[0]*w.v[2];
    r.v[2] = v.v[0]*w.v[1] - v.v[1]*w.v[0];

    return( r );
}

extern float norm(
/****************/
/* This function computes the norm of a vector. Don't confuse this with */
/* the normal vector (of a plane) which is sometime called norm in this code */
    vector  v
) {
    return( sqrt(v.v[0]*v.v[0] + v.v[1]*v.v[1] + v.v[2]*v.v[2]) );
}

#if 0
/* macroed */
extern float dot_prod_vp(
/***********************/
/* Dot product of a vector and a point. Used to evaluate plane equations */
    vector  vect,
    point   pt
) {
    return( pt.p[0]*vect.v[0] + pt.p[1]*vect.v[1] + pt.p[2]*vect.v[2] +
                pt.p[3]*vect.v[3] );
}

extern float dot_prod_vv(
/***********************/
/* Dot product of two vectors */
/* bound. */
    vector  vect1,
    vector  vect2
) {
    return( vect1.v[0]*vect2.v[0] + vect1.v[1]*vect2.v[1] +
            vect1.v[2]*vect2.v[2] + vect1.v[3]*vect2.v[3] );
}
#endif

extern vector calculate_normal_vector(
/************************************/
/* This uses the techniques describe in "Computer Graphics" by Foley et. al. */
/* section 11.1.3, pp. 476, 477 */
    int     num_pts,
    void    *data,          // passed to get_next_pt only
    point   (* get_pt) ( void *, int point_num )
) {
    vector  normal;
    float   len;            // norm of normal
    int     count;
    point   curr_pt;
    point   next_pt;

    normal.v[0] = 0.;
    normal.v[1] = 0.;
    normal.v[2] = 0.;
    normal.v[3] = 0.;

    for (count = 0; count < num_pts; count++) {
        curr_pt = (*get_pt)( data, count );
        next_pt = (*get_pt)( data, (count + 1) % num_pts );
        normal.v[0] += (next_pt.p[2] + curr_pt.p[2]) *
                            (next_pt.p[1] - curr_pt.p[1]);
        normal.v[1] += (next_pt.p[2] + curr_pt.p[2]) *
                            (next_pt.p[0] - curr_pt.p[0]);
        normal.v[2] += (next_pt.p[1] + curr_pt.p[1]) *
                            (next_pt.p[0] - curr_pt.p[0]);
    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?