Un-ignored: the dev drive is the ground truth the restoration and emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio content). Kept in-repo for the pod-owner community. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2408 lines
67 KiB
C++
2408 lines
67 KiB
C++
/*{{{ banner*/
|
|
/* **************************************************
|
|
|
|
Copyright DIVISION Limited (c) 1994
|
|
All rights reserved
|
|
|
|
|
|
File : vr_draw.c
|
|
Project : dpl interface / velocirender
|
|
Author : PJA
|
|
Date : 14/07/94
|
|
|
|
Function: Implements the draw pass of v-render
|
|
The current scene has been culled, into a
|
|
drawable displaylist. The only items in this display
|
|
list are cull_GEOGROUPs and cull_LMODELS.
|
|
|
|
History : Rev 1.1, 14 / 07 / 1994
|
|
|
|
**************************** */
|
|
/*}}} */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include "dpltypes.h"
|
|
#include "culltype.h"
|
|
#include "vr_cull.h"
|
|
#include "texture.h"
|
|
#include "multicpu.h"
|
|
#include "speclght.h"
|
|
#include "pxpl5sup\divpxmap.h"
|
|
#include "pxpl5sup\pxpl5sup.h"
|
|
#include "pxpl5sup\pxpl5tri.h"
|
|
#include "pxpl5sup\dmaengn.h"
|
|
#include "\projects\dbi0150\dbi0151\ucode\igc_opco.h"
|
|
#include "\projects\dbi0150\dbi0151\ucode\igc_comm.h"
|
|
|
|
/*{{{ some globals here*/
|
|
int back_colour=0;
|
|
|
|
extern dpl_SCENE the_scene;
|
|
extern int current_frame_count;
|
|
|
|
|
|
/*}}} */
|
|
/*{{{ texture scrolling support*/
|
|
extern float Cdelta_u, Cdelta_v;
|
|
/*}}} */
|
|
|
|
/*{{{ specular lighting*/
|
|
float *vr_phong_table;
|
|
/*{{{ float *compute_phong_table ( float power )*/
|
|
float *compute_phong_table ( float power )
|
|
{
|
|
int ipower=(int) power;
|
|
float *t;
|
|
|
|
if (ipower < 2)
|
|
return &vr_phong_table[0];
|
|
|
|
ipower--;
|
|
|
|
if (ipower > max_power)
|
|
ipower=max_power-1;
|
|
|
|
ipower<<=phong_precision_shift;
|
|
|
|
t=&(vr_phong_table[ipower]);
|
|
/* printf ("compute_phong_table returning 0x%x %f %f %f %f\n", t, t[20], t[40], t[60], t[80] ); */
|
|
|
|
return t;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void init_phong ( void )*/
|
|
void init_phong ( void )
|
|
{
|
|
/*
|
|
this mallocs and intializes an array of max_power tables,
|
|
each table phong_precision long
|
|
this is indexed by a.b to return exp(a,b)
|
|
table initialized by first setting table[i] to i,
|
|
then for each pass setting table[i] to i*prev_table[i]
|
|
*/
|
|
float *p;
|
|
int i, j;
|
|
|
|
vr_phong_table = (float *) malloc ( sizeof(float) * max_power * phong_precision );
|
|
|
|
for (j=0; j<phong_precision; j++ ) {
|
|
vr_phong_table[j] = ((float) (j+1)) / (float) phong_precision;
|
|
}
|
|
|
|
p=vr_phong_table;
|
|
|
|
for (i=1; i<max_power; i++) {
|
|
for (j=0; j<phong_precision; j++ ) {
|
|
float prev=*p;
|
|
float this=vr_phong_table[j];
|
|
|
|
p[phong_precision] = prev * this;
|
|
p++;
|
|
}
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*}}} */
|
|
|
|
/*{{{ some very pxpl5-specific stuff*/
|
|
/*{{{ a pile of statics and not-so-statics*/
|
|
#define MAX_RAMPS 4
|
|
|
|
extern concurrency_control *shared_cntl;
|
|
extern int* tile_poke_address;
|
|
extern int* wait_poke_address;
|
|
extern int* trans_wait_poke_address;
|
|
extern int *texture_table_iptr;
|
|
extern int _processorId,
|
|
_numProcessors;
|
|
|
|
static int display_tile_base=0;
|
|
static int timing_frames=0;
|
|
static int rendered_frames=0;
|
|
static int very_first_frame=0;
|
|
static int x_display_tiles, y_display_tiles;
|
|
static int first_framebuf_y = 0,
|
|
framebuf_flip = 4,
|
|
second_screen_flip=16;
|
|
|
|
static screenbin *prevBin=NULL;
|
|
static int prevX,
|
|
prevY;
|
|
|
|
static int unclipped_tris = 0;
|
|
static int farz_drawn_tris = 0;
|
|
static int farz_rejected_tris = 0;
|
|
static int clipped_tris = 0;
|
|
static int clipped_patches = 0;
|
|
static int unclipped_patches = 0;
|
|
/*}}} */
|
|
|
|
/*{{{ void multisync()*/
|
|
int multisyncs=0;
|
|
|
|
void multisync(void) /* char * str ) */
|
|
{
|
|
/*{{{ multisync algorithm*/
|
|
/*
|
|
this function interlocks all processors on a shared memory board,
|
|
and must leave the shared_cntl region in the same state as when
|
|
it entered
|
|
|
|
algorithm - a single lock determines how many processors are
|
|
currently spinning. The processor which increments the lock up
|
|
to numProcessors clears the lock and triggers all other processors
|
|
to go -
|
|
|
|
semwait();
|
|
shared->lock++;
|
|
if (shared->lock==num_processors) {
|
|
shared->lock=0;
|
|
for (i=0; i<num_processors; i++) {
|
|
go[i]=0;
|
|
}
|
|
semsignal();
|
|
}
|
|
else {
|
|
go[i]=1;
|
|
semsignal();
|
|
while (go[i])
|
|
bla();
|
|
}
|
|
}
|
|
*/
|
|
/*}}} */
|
|
|
|
concurrency_control *shared=shared_cntl;
|
|
Semaphore *sem=&shared->sem;
|
|
int i, t,
|
|
me =_processorId,
|
|
them=_numProcessors,
|
|
*spin=&shared->go[me];
|
|
return;
|
|
|
|
multisyncs++;
|
|
/*
|
|
printf ("(%d) multisync %d : %s\n",
|
|
_processorId, multisyncs, str );
|
|
*/
|
|
|
|
SemWait ( sem, me );
|
|
t=++shared->locker;
|
|
|
|
if (t==them) {
|
|
shared->locker=0;
|
|
shared->go[0]=0;
|
|
shared->go[1]=0;
|
|
shared->go[2]=0;
|
|
shared->go[3]=0;
|
|
}
|
|
else
|
|
*spin=1;
|
|
|
|
/* quick signal */
|
|
sem->lock[me]=0;
|
|
|
|
while (*spin)
|
|
bla(100); /* hit uncached ram every 3 uS */
|
|
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ static void start_frame_stats ( void )*/
|
|
static void start_frame_stats ( void )
|
|
{
|
|
unclipped_tris = 0;
|
|
farz_drawn_tris = 0;
|
|
farz_rejected_tris = 0;
|
|
clipped_tris = 0;
|
|
clipped_patches = 0;
|
|
unclipped_patches = 0;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ static void add_DMA_opcodes ( screenbin *bin, int *opcodes, int n_opcodes )*/
|
|
static void add_DMA_opcodes ( screenbin *bin, int *opcodes, int n_opcodes )
|
|
{
|
|
binchunk *chunk=bin->tail;
|
|
|
|
int usage=chunk->usage;
|
|
int index=usage>>2;
|
|
|
|
/* usage in bytes */
|
|
|
|
if ((BIN_FULL - usage) < (n_opcodes << 2)) {
|
|
/*{{{ grab a new one*/
|
|
chunk->next=next_binchunk ();
|
|
|
|
chunk->DMA_opcodes[index ]=(int) (&chunk->next->DMA_opcodes[0]);
|
|
chunk->DMA_opcodes[index+1]=DMA_GOTO_VAL;
|
|
chunk->usage=BIN_FULL;
|
|
|
|
chunk=chunk->next;
|
|
chunk->next=NULL;
|
|
bin->tail=chunk;
|
|
|
|
usage=0;
|
|
index=0;
|
|
/*}}} */
|
|
}
|
|
|
|
memcpy ( &chunk->DMA_opcodes[index], opcodes, n_opcodes<<2 );
|
|
chunk->usage+=n_opcodes<<2;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void setpxpl5VideoMode ( int magicVal )*/
|
|
void setpxpl5VideoMode ( int mode )
|
|
{
|
|
if (mode & 4) {
|
|
first_framebuf_y= 16;
|
|
framebuf_flip = 4;
|
|
}
|
|
else if (mode & 16) {
|
|
framebuf_flip = 4;
|
|
}
|
|
else if (mode & 8) {
|
|
/* hi-res 1024x1024 */
|
|
first_framebuf_y = 0;
|
|
framebuf_flip = 8;
|
|
}
|
|
else {
|
|
first_framebuf_y = 0;
|
|
framebuf_flip = 4;
|
|
}
|
|
|
|
if (mode & 128)
|
|
first_framebuf_y= 16;
|
|
}
|
|
/*}}} */
|
|
static int *DMA_copy,
|
|
*transp_DMA_copy;
|
|
|
|
int recompute_end_of_frame=1;
|
|
|
|
/*{{{ static screenbin *strap_up_transptiles ( int x_display_tiles,*/
|
|
static screenbin *strap_up_transptiles ( int x_display_tiles,
|
|
int y_display_tiles,
|
|
screenbin *screenbins,
|
|
screenbin *trans_screenbins,
|
|
int first_framebuf_y,
|
|
int strap_last )
|
|
{
|
|
/* ************************************************
|
|
This is a bit tricky, since we are dealing with the PREVIOUS opaque
|
|
tile and the CURRENT transparent tile. We are holding a pointer to
|
|
the previous opaque bin, a pointer to the current opaque bin, and
|
|
a pointer to the current transparent bin. If there is any transparent
|
|
stuff, we patch the PREV opaque to point to the current transp. Then
|
|
patch the current transp to point to the current opaque. If no transp
|
|
stuff, we patch the previous opaque to the current opaque. At the end,
|
|
we just patch the previous opaque bin to NULL.
|
|
************************************* */
|
|
|
|
int x, y,
|
|
px=prevX,
|
|
py=prevY;
|
|
|
|
screenbin *prevbin=prevBin;
|
|
screenbin *headbin=NULL;
|
|
|
|
int *DMA_seq = shared_cntl->eof_DMA_sequence;
|
|
int *transp_DMA_seq = shared_cntl->transp_eof_DMA_sequence;
|
|
int *eot_DMA_seq = shared_cntl->eot_DMA_sequence;
|
|
int *transp_eot_DMA_seq = shared_cntl->transp_eot_DMA_sequence;
|
|
int eofwords = shared_cntl->eof_DMA_words;
|
|
int transp_eofwords = shared_cntl->transp_eof_DMA_words;
|
|
|
|
for (x=0; x<x_display_tiles; x++ ) {
|
|
for (y=0; y<y_display_tiles; y++ ) {
|
|
screenbin *thisbin =&screenbins [x+(y*(1024/64))];
|
|
screenbin *transbin=&trans_screenbins[x+(y*(1024/64))];
|
|
|
|
float *hack =(float *) &thisbin->head->DMA_opcodes[0];
|
|
float *trans_hack=(float *) &transbin->head->DMA_opcodes[0];
|
|
|
|
if (transbin->head->usage!=transbin->head->DMA_opcodes[63]) {
|
|
/*{{{ transparent branch*/
|
|
/* copy end-of-frame DMA opcodes into opaque bin */
|
|
|
|
if (prevbin != NULL) {
|
|
*tile_poke_address =px | ((py+display_tile_base) << 5);
|
|
*wait_poke_address =DMA_WAIT_VAL;
|
|
|
|
/* prev opaque GOTO this transp */
|
|
DMA_seq[eofwords ]=(int) &transbin->head->DMA_opcodes[2];
|
|
DMA_seq[eofwords+1]=DMA_GOTO_VAL;
|
|
|
|
/* this transp GOTO this opaque */
|
|
transp_DMA_seq[transp_eofwords ]=(int) &thisbin->head->DMA_opcodes[2];
|
|
transp_DMA_seq[transp_eofwords+1]=DMA_GOTO_VAL;
|
|
|
|
add_DMA_opcodes ( prevbin, DMA_seq, eofwords+2 );
|
|
add_DMA_opcodes ( transbin, transp_DMA_seq, transp_eofwords+2 );
|
|
|
|
*trans_wait_poke_address=DMA_WAIT_VAL;
|
|
|
|
}
|
|
else {
|
|
/* must patch up the transp bin, as he is head of DMA execute op */
|
|
|
|
headbin=transbin;
|
|
|
|
transbin->head->DMA_opcodes[0]=0;
|
|
transbin->head->DMA_opcodes[1]=0;
|
|
|
|
/* this transp GOTO this opaque */
|
|
transp_DMA_seq[transp_eofwords ]=(int) &thisbin->head->DMA_opcodes[2];
|
|
transp_DMA_seq[transp_eofwords+1]=DMA_GOTO_VAL;
|
|
|
|
add_DMA_opcodes ( transbin, transp_DMA_seq, transp_eofwords+2 );
|
|
|
|
*trans_wait_poke_address=DMA_WAIT_VAL;
|
|
}
|
|
/*}}} */
|
|
}
|
|
else {
|
|
/*{{{ opaque*/
|
|
if (prevbin != NULL) {
|
|
*tile_poke_address=px | ((py+display_tile_base) << 5);
|
|
|
|
DMA_seq[eofwords ]=(int) &thisbin->head->DMA_opcodes[2];
|
|
DMA_seq[eofwords+1]=DMA_GOTO_VAL;
|
|
|
|
add_DMA_opcodes ( prevbin, DMA_seq, eofwords+2 );
|
|
*wait_poke_address=DMA_WAIT_VAL;
|
|
}
|
|
else {
|
|
headbin=thisbin;
|
|
|
|
thisbin->head->DMA_opcodes[0]=0;
|
|
thisbin->head->DMA_opcodes[1]=0;
|
|
}
|
|
/*}}} */
|
|
}
|
|
py=y+first_framebuf_y;
|
|
px=x;
|
|
|
|
prevbin=thisbin;
|
|
}
|
|
}
|
|
|
|
if (strap_last) {
|
|
*tile_poke_address=px | ((py+display_tile_base) << 5);
|
|
|
|
DMA_seq[eofwords ]=0;
|
|
DMA_seq[eofwords+1]=DMA_STOP_VAL | 0x08000000;
|
|
|
|
add_DMA_opcodes ( prevbin, DMA_seq, eofwords+2 );
|
|
}
|
|
else
|
|
prevBin =prevbin;
|
|
|
|
prevX=px;
|
|
prevY=py;
|
|
|
|
return headbin;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ static void redo_end_of_frame()*/
|
|
extern int eof_FOG_rval,
|
|
eof_FOG_gval,
|
|
eof_FOG_bval,
|
|
eof_backR,
|
|
eof_backG,
|
|
eof_backB,
|
|
eof_Z_near,
|
|
eof_Z_far,
|
|
eof_farZ;
|
|
|
|
static void redo_end_of_frame ( void )
|
|
{
|
|
shared_cntl->eof_DMA_words = short_end_of_frame_DMA ( shared_cntl->eof_DMA_sequence,
|
|
shared_cntl->eof_sequence,
|
|
shared_cntl->eot_DMA_sequence );
|
|
|
|
shared_cntl->eot_DMA_words = end_of_textr_DMA ( shared_cntl->eot_DMA_sequence,
|
|
shared_cntl->eot_sequence );
|
|
|
|
recompute_end_of_frame=0;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ static void pxpl5_flip ( int me, int nodes )*/
|
|
static void pxpl5_flip ( int me, int nodes )
|
|
{
|
|
/*{{{ what we do*/
|
|
/* *********************************
|
|
|
|
We need to construct a linked list of tiles.
|
|
|
|
For all tiles the first DMA instruction is a GOT0 (next tile). For the
|
|
last tile, the destination is NULL. These instructions are
|
|
never executed, but they are used by the driver to re-trigger
|
|
the DMA engine per tile.
|
|
|
|
*/
|
|
/*}}} */
|
|
/*{{{ declare variables*/
|
|
|
|
extern int dN_pxpl5_dma ( int *address, int *ack_address, int *txdn_address,
|
|
vfptr pre_dma );
|
|
extern int replying;
|
|
extern cull_RAMP texture_ramps[MAX_RAMPS];
|
|
screenbin *headbin;
|
|
|
|
int stereo=0;
|
|
int spintime, words;
|
|
int i;
|
|
int pthen, pnow, pmicrosex;
|
|
/*}}} */
|
|
|
|
prevBin=NULL;
|
|
|
|
/*{{{ patch in texture ramps*/
|
|
if (texture_table_iptr) {
|
|
for (i=0; i<MAX_RAMPS; i++ ) {
|
|
texture_table_iptr[(i*3)+2]=texture_ramps[i].codeWord;
|
|
}
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ strap up tiles*/
|
|
/*
|
|
this now does NO interrupting of tranny, except for very last tile
|
|
|
|
this needs tidying, all these fn calls will cost around 1mS!!
|
|
*/
|
|
|
|
headbin=strap_up_transptiles ( x_display_tiles, y_display_tiles,
|
|
screenbins, trans_screenbins,
|
|
first_framebuf_y,
|
|
1 );
|
|
|
|
|
|
/* needs to deal with stereo on a single pipe, such as ... */
|
|
/* first_framebuf_y^=second_screen_flip; */
|
|
|
|
/*}}} */
|
|
|
|
/*{{{ RENDER THIS FRAME ! ! ! ! do DMA rendering*/
|
|
|
|
/* spin on an uncached location */
|
|
|
|
|
|
if (_processorId==0) {
|
|
/* flush(); */
|
|
vfptr eof;
|
|
|
|
if (recompute_end_of_frame)
|
|
eof=&redo_end_of_frame;
|
|
else
|
|
eof=NULL;
|
|
|
|
spintime=dN_pxpl5_dma ((int *)(headbin->head),
|
|
shared_cntl->uncache_debug_block,
|
|
shared_cntl->eot_DMA_sequence,
|
|
eof );
|
|
if (spintime > 500000)
|
|
printf ("is this right - spintime=%d\n", spintime );
|
|
|
|
recompute_end_of_frame=0;
|
|
|
|
multisync();
|
|
}
|
|
else {
|
|
multisync();
|
|
}
|
|
|
|
/*}}} */
|
|
start_frame_stats();
|
|
/*{{{ flip all buffer space*/
|
|
|
|
if (screenbins == screen0bins) {
|
|
screenbins =screen1bins;
|
|
trans_screenbins =trans_screen1bins;
|
|
}
|
|
else if (screenbins == screen1bins) {
|
|
screenbins =screen0bins;
|
|
trans_screenbins =trans_screen0bins;
|
|
}
|
|
else {
|
|
printf ("WHOAH - screenbins neither screen0 nor screen1 0x%x 0x%x 0x%x\n",
|
|
screenbins, screen0bins, screen1bins );
|
|
while (1)
|
|
;
|
|
}
|
|
|
|
liberate_screenbins ( screenbins, 1024, 768 );
|
|
liberate_screenbins ( trans_screenbins, 1024, 768 );
|
|
|
|
if (lastcoeffptr == (float *) coeffstore0) {
|
|
coefficient_ptr = (float *) coeffstore1;
|
|
last_coeffchunk = coeffstore1;
|
|
}
|
|
else {
|
|
coefficient_ptr = (float *) coeffstore0;
|
|
last_coeffchunk = coeffstore0;
|
|
}
|
|
|
|
lastcoeffptr=coefficient_ptr;
|
|
|
|
/*}}} */
|
|
/*{{{ housekeeping*/
|
|
|
|
display_tile_base^=framebuf_flip;
|
|
|
|
/*}}} */
|
|
}
|
|
/*}}} */
|
|
/*{{{ void flip_screens( int me, int nodes )*/
|
|
|
|
void flip_screens( int me, int nodes )
|
|
{
|
|
int xd, yd, back_c;
|
|
|
|
if (very_first_frame==0) {
|
|
int i, j, tile=0;
|
|
int *cptr=shared_cntl->eof_sequence,
|
|
*cptr0=cptr;
|
|
|
|
for (i=0; i<64; i++ )
|
|
cptr[i]=0x0;
|
|
|
|
IGC_SETENABS ( cptr );
|
|
IGC_CLEAR ( cptr, 0, 32 );
|
|
IGC_BSWAIT ( cptr );
|
|
IGC_NOOP ( cptr );
|
|
IGC_NOOP ( cptr );
|
|
IGC_NOOP ( cptr );
|
|
IGC_VRAMWrite ( cptr, 4 );
|
|
IGC_NOOP ( cptr );
|
|
IGC_NOOP ( cptr );
|
|
IGC_NOOP ( cptr );
|
|
IGC_NOOP ( cptr );
|
|
|
|
for ( i=0; i<32; i++ ) {
|
|
/*{{{ */
|
|
int *ptr =shared_cntl->eof_DMA_sequence,
|
|
*ptr0=ptr;
|
|
|
|
*ptr++=0x0;
|
|
*ptr++=0x0;
|
|
|
|
for (j=0; j<32; j++ ) {
|
|
*ptr++=tile;
|
|
*ptr++=DMA_TILE_VAL;
|
|
|
|
*ptr++=(int32) cptr;
|
|
*ptr++=DMA_FLUSH_VAL;
|
|
|
|
*ptr++=(int32) cptr;
|
|
*ptr++=DMA_FLUSH_VAL;
|
|
|
|
*ptr++=(int32) cptr0;
|
|
*ptr++=DMA_SEND_VAL | 16;
|
|
|
|
*ptr++=(int32) cptr;
|
|
*ptr++=DMA_FLUSH_VAL;
|
|
|
|
*ptr++=0;
|
|
*ptr++=DMA_FLUSH_VAL;
|
|
|
|
tile++;
|
|
}
|
|
|
|
*ptr++=0;
|
|
*ptr++=DMA_STOP_VAL | 0x08000000;
|
|
/*}}} */
|
|
|
|
dN_pxpl5_dma (ptr0,
|
|
shared_cntl->uncache_debug_block,
|
|
shared_cntl->eot_DMA_sequence,
|
|
NULL );
|
|
}
|
|
very_first_frame++;
|
|
|
|
shared_cntl->eof_DMA_words = short_end_of_frame_DMA ( shared_cntl->eof_DMA_sequence,
|
|
shared_cntl->eof_sequence,
|
|
shared_cntl->eot_DMA_sequence );
|
|
|
|
}
|
|
|
|
pxpl5_flip ( me, nodes );
|
|
|
|
return;
|
|
|
|
if (very_first_frame < 2) {
|
|
back_c=back_colour;
|
|
|
|
back_colour=0;
|
|
|
|
yd=y_display_tiles;
|
|
xd=x_display_tiles;
|
|
|
|
x_display_tiles= 1024/64;
|
|
y_display_tiles= 768/128;
|
|
}
|
|
|
|
pxpl5_flip ( me, nodes );
|
|
|
|
if (very_first_frame<2) {
|
|
back_colour=back_c;
|
|
|
|
y_display_tiles=yd;
|
|
x_display_tiles=xd;
|
|
|
|
very_first_frame++;
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ void render_init()*/
|
|
/* this is a job for cull, in my book */
|
|
|
|
extern int getFsr ( void );
|
|
extern void setFsr ( int fsr );
|
|
|
|
static int render_inited=0;
|
|
|
|
void render_init( int x_size, int y_size )
|
|
{
|
|
int i, j;
|
|
int *p;
|
|
float then, now;
|
|
int *time_end_of_frame;
|
|
|
|
multisync();
|
|
|
|
if (render_inited == 0) {
|
|
int fsr;
|
|
render_inited=1;
|
|
|
|
setRampEntry ( &texture_ramps[0], 0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0 );
|
|
setRampEntry ( &texture_ramps[1], 1, 0.3, 0.0, 0.0, 1.0, 1.0, 0.9 );
|
|
setRampEntry ( &texture_ramps[2], 2, 0.0, 0.5, 0.0, 1.0, 1.0, 1.0 );
|
|
setRampEntry ( &texture_ramps[3], 3, 0.0, 0.0, 0.4, 0.9, 0.9, 1.0 );
|
|
|
|
texInit ();
|
|
|
|
setFsr(1|getFsr());
|
|
|
|
x_display_tiles=(x_size + 63) >> 6;
|
|
y_display_tiles=(y_size + 127) >> 7;
|
|
display_tile_base=0;
|
|
|
|
/*
|
|
printf ( "x_tiles = %d y_tiles = %d\n",
|
|
x_display_tiles,
|
|
y_display_tiles );
|
|
*/
|
|
|
|
init_phong ();
|
|
|
|
if (_processorId==0) {
|
|
/* printf ("render_init shared_cntl at 0x%x\n", shared_cntl ); */
|
|
|
|
shared_cntl->uncache_debug_block = newBytes(4096*2);
|
|
|
|
shared_cntl->eof_DMA_sequence = newBytes(4096*2);
|
|
shared_cntl->eof_sequence = newBytes(4096*2);
|
|
|
|
DMA_copy=malloc(2048);
|
|
|
|
shared_cntl->transp_eof_DMA_sequence = newBytes(4096*2);
|
|
shared_cntl->transp_eof_sequence = newBytes(4096*2);
|
|
|
|
transp_DMA_copy=malloc(2048);
|
|
|
|
shared_cntl->eot_DMA_sequence = newBytes(4096*2);
|
|
shared_cntl->eot_sequence = newBytes(4096*2);
|
|
|
|
shared_cntl->transp_eot_DMA_sequence = newBytes(4096*2);
|
|
shared_cntl->transp_eot_sequence = newBytes(4096*2);
|
|
|
|
shared_cntl->uncached_flush_location = newBytes(4096*2);
|
|
|
|
/*
|
|
printf ("eof_DMA_sequence = 0x%x\n", shared_cntl->eof_DMA_sequence );
|
|
printf ("eof_sequence = 0x%x\n", shared_cntl->eof_sequence );
|
|
printf ("eot_DMA_sequence = 0x%x\n", shared_cntl->eot_DMA_sequence );
|
|
printf ("eot_sequence = 0x%x\n", shared_cntl->eot_sequence );
|
|
|
|
printf ("treof_DMA_sequence = 0x%x\n", shared_cntl->transp_eof_DMA_sequence );
|
|
printf ("treof_sequence = 0x%x\n", shared_cntl->transp_eof_sequence );
|
|
printf ("treot_DMA_sequence = 0x%x\n", shared_cntl->transp_eot_DMA_sequence );
|
|
printf ("treot_sequence = 0x%x\n", shared_cntl->transp_eot_sequence );
|
|
*/
|
|
|
|
/* we have 64k bytes to fit in end_of_frame and end_of_texture sequences */
|
|
|
|
shared_cntl->eot_DMA_words = end_of_textr_DMA ( shared_cntl->eot_DMA_sequence,
|
|
shared_cntl->eot_sequence );
|
|
|
|
shared_cntl->transp_eot_DMA_words = end_of_transp_DMA ( shared_cntl->transp_eot_DMA_sequence,
|
|
shared_cntl->transp_eot_sequence );
|
|
|
|
shared_cntl->eof_DMA_words = short_end_of_frame_DMA ( shared_cntl->eof_DMA_sequence,
|
|
shared_cntl->eof_sequence,
|
|
shared_cntl->eot_DMA_sequence,
|
|
45, 66, 135, 20 );
|
|
|
|
shared_cntl->transp_eof_DMA_words = end_of_transframe_DMA ( shared_cntl->transp_eof_DMA_sequence,
|
|
shared_cntl->transp_eof_sequence,
|
|
shared_cntl->transp_eot_DMA_sequence );
|
|
|
|
multisync();
|
|
}
|
|
else
|
|
multisync();
|
|
|
|
#if 0
|
|
/*{{{ time end of frame*/
|
|
/* attempt to time end-of-frame, end of texture */
|
|
time_end_of_frame=newBytes(128*4*(shared_cntl->eot_DMA_words+shared_cntl->eof_DMA_words));
|
|
|
|
{
|
|
int usecs, then, now, index=0, ix;
|
|
|
|
time_end_of_frame[index++]=0x0;
|
|
time_end_of_frame[index++]=0x0;
|
|
|
|
for (i=0; i<128;i++) {
|
|
for (ix=0; ix<shared_cntl->eof_DMA_words;ix++ ) {
|
|
time_end_of_frame[index++]=shared_cntl->eof_DMA_sequence[ix];
|
|
}
|
|
}
|
|
|
|
time_end_of_frame[index++]=0x0;
|
|
time_end_of_frame[index++]=0xf8000000;
|
|
|
|
dN_timer (&then);
|
|
for (i=0; i<128; i++ )
|
|
dN_pxpl5_dma ( time_end_of_frame, shared_cntl->uncache_debug_block, shared_cntl->eot_DMA_sequence );
|
|
dN_timer (&now);
|
|
|
|
usecs=now - then;
|
|
then=now;
|
|
|
|
printf ("%d uSecs for 16384 end-of-frames\n", usecs );
|
|
|
|
}
|
|
/*}}} */
|
|
/*{{{ time end of texture*/
|
|
/* attempt to time end-of-frame, end of texture */
|
|
time_end_of_frame=newBytes(128*4*(shared_cntl->eot_DMA_words+shared_cntl->eof_DMA_words));
|
|
|
|
{
|
|
int usecs, then, now, index=0, ix;
|
|
|
|
time_end_of_frame[index++]=0x0;
|
|
time_end_of_frame[index++]=0x0;
|
|
|
|
for (i=0; i<128;i++) {
|
|
for (ix=0; ix<shared_cntl->eot_DMA_words;ix++ ) {
|
|
time_end_of_frame[index++]=shared_cntl->eot_DMA_sequence[ix];
|
|
}
|
|
}
|
|
|
|
time_end_of_frame[index++]=0x0;
|
|
time_end_of_frame[index++]=0xf8000000;
|
|
|
|
dN_timer (&then);
|
|
for (i=0; i<128; i++ )
|
|
dN_pxpl5_dma ( time_end_of_frame, shared_cntl->uncache_debug_block, shared_cntl->eot_DMA_sequence );
|
|
dN_timer (&now);
|
|
|
|
usecs=now - then;
|
|
then=now;
|
|
|
|
printf ("%d uSecs for 16384 end-of-textures\n", usecs );
|
|
|
|
}
|
|
/*}}} */
|
|
/*{{{ time end of frame and texture*/
|
|
/* attempt to time end-of-frame, end of texture */
|
|
time_end_of_frame=newBytes(128*4*(shared_cntl->eot_DMA_words+shared_cntl->eof_DMA_words));
|
|
|
|
{
|
|
int usecs, then, now, index=0, ix;
|
|
|
|
time_end_of_frame[index++]=0x0;
|
|
time_end_of_frame[index++]=0x0;
|
|
|
|
for (i=0; i<128;i++) {
|
|
for (ix=0; ix<shared_cntl->eof_DMA_words;ix++ ) {
|
|
time_end_of_frame[index++]=shared_cntl->eof_DMA_sequence[ix];
|
|
}
|
|
for (ix=0; ix<shared_cntl->eot_DMA_words;ix++ ) {
|
|
time_end_of_frame[index++]=shared_cntl->eot_DMA_sequence[ix];
|
|
}
|
|
}
|
|
|
|
time_end_of_frame[index++]=0x0;
|
|
time_end_of_frame[index++]=0xf8000000;
|
|
|
|
dN_timer (&then);
|
|
for (i=0; i<128; i++ )
|
|
dN_pxpl5_dma ( time_end_of_frame, shared_cntl->uncache_debug_block, shared_cntl->eot_DMA_sequence );
|
|
dN_timer (&now);
|
|
|
|
usecs=now - then;
|
|
then=now;
|
|
|
|
printf ("%d uSecs for 16384 end-of-frame / textures\n", usecs );
|
|
|
|
}
|
|
/*}}} */
|
|
#endif
|
|
|
|
create_screenbins ( 1024, 768, x_size == 1024 );
|
|
{
|
|
extern float Cmax_y, Cmax_x;
|
|
|
|
Cmax_x=((float) x_size) - 0.01f;
|
|
Cmax_y=((float) y_size) - 0.01f;
|
|
}
|
|
|
|
/*
|
|
printf ("screen0bins =0x%x\n", screen0bins );
|
|
printf ("screen1bins =0x%x\n", screen1bins );
|
|
printf ("and screenbins=0x%x\n", screenbins );
|
|
*/
|
|
|
|
multisync();
|
|
|
|
}
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ vpx_geometry_function vpx_drawstuff ( float *codeword,*/
|
|
vpx_geometry_function vpx_drawstuff ( float *codeword,
|
|
int *opcode0,
|
|
cull_GEOGROUP *cull_gg,
|
|
cull_MATERIAL *mtl )
|
|
{
|
|
*(int *) codeword=mtl->pxpl5_cntl_word;
|
|
*opcode0 = 31 - (int) (31.0f * mtl->diffuse[3]);
|
|
|
|
if (mtl->pxpl5_cntl_word != 0) {
|
|
if (cull_gg->draw_mode & (dpl_draw_smooth|dpl_draw_colored))
|
|
return (vpx_geometry_function) tri_zb_rgb_t;
|
|
else
|
|
return (vpx_geometry_function) tri_zb_f_t;
|
|
}
|
|
else {
|
|
if (cull_gg->draw_mode & (dpl_draw_smooth|dpl_draw_colored))
|
|
return (vpx_geometry_function) tri_zb_rgb;
|
|
else
|
|
return (vpx_geometry_function) tri_zb_f;
|
|
}
|
|
}
|
|
/*}}} */
|
|
|
|
/*}}} */
|
|
|
|
/*{{{ lighting geometries*/
|
|
/*{{{ eval_lmodel ( cull_LMODEL *lm, cull_GEOGROUP *gg )*/
|
|
static void
|
|
eval_lmodel ( cull_LMODEL *lm, cull_GEOGROUP *gg )
|
|
{
|
|
extern void printf_matrix ( dpl_MATRIX m );
|
|
extern void quick_renorm ( float *, float, float, float, float );
|
|
|
|
int i, dest_ix=0;
|
|
cull_LIGHT *dest_p=&lm->lights[0];
|
|
dpl_LMODEL *dlm=lm->lmodel;
|
|
dpl_list *l;
|
|
|
|
register float m00=gg->invModel[0][0];
|
|
register float m01=gg->invModel[0][1];
|
|
register float m02=gg->invModel[0][2];
|
|
register float m10=gg->invModel[1][0];
|
|
register float m11=gg->invModel[1][1];
|
|
register float m12=gg->invModel[1][2];
|
|
register float m20=gg->invModel[2][0];
|
|
register float m21=gg->invModel[2][1];
|
|
register float m22=gg->invModel[2][2];
|
|
|
|
lm->evaluated=1;
|
|
|
|
if (dlm) {
|
|
for (l=dlm->light_list.head; l; l=l->next ) {
|
|
dpl_LIGHT *source_p=(dpl_LIGHT *) l->item;
|
|
|
|
if (source_p->light_type == dpl_light_type_directional) {
|
|
/*{{{ transform its direction cosine*/
|
|
float sx, sy, sz,
|
|
dx, dy, dz;
|
|
|
|
dest_p->light_type=dpl_light_type_directional;
|
|
|
|
sx=source_p->position[0];
|
|
sy=source_p->position[1];
|
|
sz=source_p->position[2];
|
|
|
|
dx = (sx*m00) + (sy*m10) + (sz*m20);
|
|
dy = (sx*m01) + (sy*m11) + (sz*m21);
|
|
dz = (sx*m02) + (sy*m12) + (sz*m22);
|
|
|
|
dest_p->color[0]=source_p->color[0];
|
|
dest_p->color[1]=source_p->color[1];
|
|
dest_p->color[2]=source_p->color[2];
|
|
|
|
quick_renorm ( dest_p->direction, dx, dy, dz, 1.0f );
|
|
|
|
/*
|
|
printf ( "evaled lmodel to %f,%f,%f\n",
|
|
dest_p->direction[0],
|
|
dest_p->direction[1],
|
|
dest_p->direction[2] );
|
|
*/
|
|
dest_ix++;
|
|
dest_p++;
|
|
|
|
if (dest_ix==MAX_CULL_LIGHTS) break;
|
|
/*}}} */
|
|
}
|
|
else if (source_p->light_type == dpl_light_type_ambient) {
|
|
/*{{{ do ambience thing*/
|
|
lm->ambience[0]=source_p->color[0];
|
|
lm->ambience[1]=source_p->color[1];
|
|
lm->ambience[2]=source_p->color[2];
|
|
/*}}} */
|
|
}
|
|
/* what about positional ?? */
|
|
}
|
|
lm->n_lights=dest_ix;
|
|
/* printf ("eval_lmodel found %d lights\n", dest_ix ); */
|
|
}
|
|
}
|
|
/*}}} */
|
|
#if 0
|
|
/*{{{ void light_vertices ( dpl_VERTEX *v,*/
|
|
/* this needs a general diffuse_light_structure,
|
|
with normal_offset,
|
|
rendered_color_offset,
|
|
next_offset
|
|
and i can then assembly code it
|
|
*/
|
|
void light_vertices ( dpl_VERTEX *v,
|
|
cull_LMODEL *clm,
|
|
cull_MATERIAL *cm,
|
|
float normfactor,
|
|
int n_vertices )
|
|
{
|
|
float mtl_r=cm->diffuse[0]*255.0f;
|
|
float mtl_g=cm->diffuse[1]*255.0f;
|
|
float mtl_b=cm->diffuse[2]*255.0f;
|
|
|
|
float ar=clm->ambience[0];
|
|
float ag=clm->ambience[1];
|
|
float ab=clm->ambience[2];
|
|
|
|
while (v) {
|
|
int i, n_lights=clm->n_lights;
|
|
float dot;
|
|
cull_LIGHT *cl=&clm->lights[0];
|
|
|
|
float nx=v->normcol[0];
|
|
float ny=v->normcol[1];
|
|
float nz=v->normcol[2];
|
|
|
|
float r=ar;
|
|
float g=ag;
|
|
float b=ab;
|
|
|
|
if (n_lights<1) goto accum;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<2) goto accum;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<3) goto accum;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<4) goto accum;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<5) goto accum;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<6) goto accum;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<7) goto accum;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
|
|
accum:
|
|
v->rendered_color[0]=r*mtl_r;
|
|
v->rendered_color[1]=g*mtl_g;
|
|
v->rendered_color[2]=b*mtl_b;
|
|
|
|
v=v->next;
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ void light_facets ( dpl_CONNECTION *v,*/
|
|
void light_facets ( dpl_CONNECTION *v,
|
|
cull_LMODEL *clm,
|
|
cull_MATERIAL *cm,
|
|
float normfactor,
|
|
int n_vertices )
|
|
{
|
|
float mtl_r=cm->diffuse[0]*255.0f;
|
|
float mtl_g=cm->diffuse[1]*255.0f;
|
|
float mtl_b=cm->diffuse[2]*255.0f;
|
|
|
|
float ar=clm->ambience[0];
|
|
float ag=clm->ambience[1];
|
|
float ab=clm->ambience[2];
|
|
|
|
while (v) {
|
|
float dot;
|
|
int i, n_lights=clm->n_lights;
|
|
cull_LIGHT *cl=&clm->lights[0];
|
|
|
|
float nx=v->planeEqn[0];
|
|
float ny=v->planeEqn[1];
|
|
float nz=v->planeEqn[2];
|
|
|
|
float r=ar;
|
|
float g=ag;
|
|
float b=ab;
|
|
|
|
if (n_lights<1) goto accumf;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<2) goto accumf;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<3) goto accumf;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<4) goto accumf;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<5) goto accumf;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<6) goto accumf;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<7) goto accumf;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
|
|
accumf:
|
|
v->rendered_color[0]=r*mtl_r;
|
|
v->rendered_color[1]=g*mtl_g;
|
|
v->rendered_color[2]=b*mtl_b;
|
|
|
|
v=v->next;
|
|
}
|
|
}
|
|
/*}}} */
|
|
#endif
|
|
/*{{{ void light_structure ( char *structure,*/
|
|
void light_structure ( char *structure,
|
|
cull_LMODEL *clm,
|
|
cull_MATERIAL *cm,
|
|
float normfactor,
|
|
int n_vertices,
|
|
int normal_offset,
|
|
int next_offset,
|
|
int rendered_color_offset,
|
|
int touched_offset )
|
|
{
|
|
float mtl_r=cm->diffuse[0]*255.0f;
|
|
float mtl_g=cm->diffuse[1]*255.0f;
|
|
float mtl_b=cm->diffuse[2]*255.0f;
|
|
|
|
float ar=clm->ambience[0];
|
|
float ag=clm->ambience[1];
|
|
float ab=clm->ambience[2];
|
|
|
|
while (structure) {
|
|
if (*(int *)(structure+touched_offset)) {
|
|
float dot;
|
|
int i, n_lights=clm->n_lights;
|
|
cull_LIGHT *cl=&clm->lights[0];
|
|
|
|
float nx=((float *)(structure+normal_offset))[0];
|
|
float ny=((float *)(structure+normal_offset))[1];
|
|
float nz=((float *)(structure+normal_offset))[2];
|
|
|
|
float r=ar;
|
|
float g=ag;
|
|
float b=ab;
|
|
float *rc;
|
|
|
|
if (n_lights<1) goto accums;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<2) goto accums;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<3) goto accums;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<4) goto accums;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<5) goto accums;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<6) goto accums;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
if (n_lights<7) goto accums;
|
|
/*{{{ */
|
|
dot=normfactor*((nx*cl->direction[0])+
|
|
(ny*cl->direction[1])+
|
|
(nz*cl->direction[2]));
|
|
if (dot > 0.0f) {
|
|
r+=dot*cl->color[0];
|
|
g+=dot*cl->color[1];
|
|
b+=dot*cl->color[2];
|
|
}
|
|
cl++;
|
|
/*}}} */
|
|
/* a goto label ! */
|
|
accums:
|
|
rc=(float *) (structure+rendered_color_offset);
|
|
|
|
*rc++=r*mtl_r;
|
|
*rc++=g*mtl_g;
|
|
*rc++=b*mtl_b;
|
|
|
|
}
|
|
structure = *((char **)(structure+next_offset));
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ cookize_vertices ( dpl_VERTEX *v, int nv )*/
|
|
static void
|
|
cookize_vertices ( dpl_VERTEX *v, int nv,
|
|
cull_MATERIAL *cm )
|
|
{
|
|
float cook_val=255.0f;
|
|
float cook_mtl=31.0f;
|
|
float mtl_opacity=cm->diffuse[3];
|
|
|
|
int i;
|
|
float r, g, b, a, r1, g1, b1;
|
|
|
|
for (i=0; i<nv; i++) {
|
|
if (v->touched) {
|
|
r=v->normcol[0];
|
|
g=v->normcol[1];
|
|
b=v->normcol[2];
|
|
a=v->normcol[3];
|
|
|
|
v->rendered_color[0]=cook_val*r;
|
|
v->rendered_color[1]=cook_val*g;
|
|
v->rendered_color[2]=cook_val*b;
|
|
/* damn, have i shagged this or what ? */
|
|
v->texcoords[2]=cook_mtl * (1.0f - (a * mtl_opacity));
|
|
}
|
|
v=v->next;
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*}}} */
|
|
|
|
/*{{{ back-surface culling of goemetries*/
|
|
/*{{{ static void clear_vertices ( dpl_VERTEX_LIST *vl, int value )*/
|
|
static void clear_vertices ( dpl_VERTEX_LIST *vl, int value )
|
|
{
|
|
/*
|
|
this coding is used rather than while(v) ... v=v->next to avoid
|
|
excessive cache-reads when chaining down linked list
|
|
|
|
warning - DONT CHANGE vertices_per_block!
|
|
*/
|
|
while (vl) {
|
|
|
|
vl->vertices[0].touched=value;
|
|
vl->vertices[1].touched=value;
|
|
vl->vertices[2].touched=value;
|
|
vl->vertices[3].touched=value;
|
|
vl->vertices[4].touched=value;
|
|
vl->vertices[5].touched=value;
|
|
vl->vertices[6].touched=value;
|
|
vl->vertices[7].touched=value;
|
|
|
|
vl=vl->next;
|
|
}
|
|
}
|
|
|
|
/*}}} */
|
|
/*{{{ static void clear_facets ( dpl_CONNECTION_LIST *vl, int value )*/
|
|
static void clear_facets ( dpl_CONNECTION_LIST *vl, int value )
|
|
{
|
|
/*
|
|
this coding is used rather than while(v) ... v=v->next to avoid
|
|
excessive cache-reads when chaining down linked list
|
|
|
|
warning - DONT CHANGE vertices_per_block!
|
|
*/
|
|
while (vl) {
|
|
|
|
vl->connections[0].touched=value;
|
|
vl->connections[1].touched=value;
|
|
vl->connections[2].touched=value;
|
|
vl->connections[3].touched=value;
|
|
vl->connections[4].touched=value;
|
|
vl->connections[5].touched=value;
|
|
vl->connections[6].touched=value;
|
|
vl->connections[7].touched=value;
|
|
|
|
vl=vl->next;
|
|
}
|
|
}
|
|
|
|
/*}}} */
|
|
/*{{{ static void solve ( dpl_CONNECTION_LIST *cl, dpl_VERTEX_LIST *vl,*/
|
|
#define solve_plane(point,plane) \
|
|
(point[dpl_X]*plane[dpl_X])+(point[dpl_Y]*plane[dpl_Y])+(point[dpl_Z]*plane[dpl_Z])+(plane[dpl_W]*point[dpl_W])
|
|
|
|
#define solve_plane_points(point,px,py,pz,pw) \
|
|
(point[dpl_X]*px)+(point[dpl_Y]*py)+(point[dpl_Z]*pz)+(point[dpl_W]*pw)
|
|
|
|
extern void solve_fn ( dpl_CONNECTION_LIST *cl,
|
|
dpl_POINT view );
|
|
|
|
static void solve ( dpl_CONNECTION_LIST *cl,
|
|
dpl_POINT view )
|
|
{
|
|
/*
|
|
solve viewpoint with plane eqn, flagging each triangle as needing
|
|
to be drawn or not, and flagging each vertex as needing to be xformed
|
|
or not
|
|
|
|
note to deal with back-facing triangles we call this with all 4
|
|
coordinates of VIEW negated
|
|
|
|
This takes 72 ticks to accept a triangle, 31 ticks to reject,
|
|
average execution time 1uS per triangle
|
|
*/
|
|
int i, j;
|
|
register float px=view[0], py=view[1], pz=view[2], pw=view[3];
|
|
|
|
dpl_CONNECTION *c;
|
|
|
|
c=&cl->connections[0];
|
|
|
|
while (c) {
|
|
if (solve_plane_points(c->planeEqn,px,py,pz,pw) > 0.0f) {
|
|
/* flag this triangle as needed */
|
|
c->touched=1;
|
|
|
|
/* flag all my vertices as needed */
|
|
c->indices[0]->touched=1;
|
|
c->indices[1]->touched=1;
|
|
c->indices[2]->touched=1;
|
|
|
|
for (j=3; j<c->n_verts; j++) {
|
|
c->indices[j]->touched=1;
|
|
}
|
|
}
|
|
else {
|
|
/* flag this triangle as not needed */
|
|
c->touched=0;
|
|
}
|
|
c=c->next;
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*}}} */
|
|
|
|
/*{{{ projecting and clipping of geometries*/
|
|
/*{{{ clipping ?*/
|
|
/*
|
|
|
|
I feel some optimized triangle clipping coming on. Currently, if
|
|
i have to clip i just bite the bullet and fire all unprojected
|
|
triangles thru the clipper and then project the clipped output.
|
|
However, I should be able to do something more optimal by scanning
|
|
the vertex list, and touching any vertices which are behind the
|
|
near clip plane.
|
|
|
|
The correct algorithm is - determine which triangles need clipping,
|
|
and clip them, and untouch them. Project all still touched vertices.
|
|
Call draw_geometry as normal. This order of operation guarantees that
|
|
i dont accidentally project a vertex which will be needed for
|
|
subsequent clipping. It may involve so many traversals of the
|
|
connection list that its a pain in the butt, BUT it will probably
|
|
still turn out cheaper than splitting out all triangles, potentially
|
|
clipping them, then passing them thru the projector.
|
|
|
|
*/
|
|
/*}}} */
|
|
/*{{{ clipping !*/
|
|
/*
|
|
|
|
quit the bugshit. clipping is always gruesome, dicking with too many
|
|
pointers and too many selctive memcpies for my liking. and anyway, the
|
|
code is optimized for avoiding clipping at all costs, so when it
|
|
happens, who cares if it costs a lot.
|
|
|
|
so, when clipping polygon geometry, everything is reduced to triangles.
|
|
triangles in, triangles out.
|
|
|
|
so the clipper needs to know
|
|
|
|
a) the triangle function, the opcode, the material code
|
|
b) the incoming triangle
|
|
c) the incoming vertices
|
|
|
|
and generates a set of outgoing vertices (note a triangle becomes at
|
|
most a quad, i am just clipping against 1 plane)
|
|
|
|
*/
|
|
/*}}} */
|
|
/*{{{ variables to aid clipping and projection*/
|
|
static dpl_VERTEX_LIST *clip_vertices=NULL;
|
|
static dpl_CONNECTION_LIST *clip_connections=NULL;
|
|
|
|
/* this is the john rhoades voodoo .... which appears shagged ? huh ? */
|
|
float sub_pixel_correct= 0.0f; /* 1024.0f*1024.0f; */
|
|
float Czscale=1.04857588E+06f;
|
|
/*}}} */
|
|
|
|
/*{{{ static void clip_vertex_copy ( dpl_VERTEX *dest, dpl_VERTEX *src )*/
|
|
static void clip_vertex_copy ( dpl_VERTEX *dest, dpl_VERTEX *src )
|
|
{
|
|
float *d, *s;
|
|
|
|
d=dest->texcoords; s=src->texcoords;
|
|
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
|
|
d=dest->xform_posn; s=src->xform_posn;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
|
|
d=dest->rendered_color; s=src->rendered_color;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ and_project ( cull_VIEW *eye,*/
|
|
static void
|
|
and_project ( cull_VIEW *eye,
|
|
cull_GEOGROUP *cull_g,
|
|
dpl_VERTEX_LIST *vl )
|
|
{
|
|
register float sx;
|
|
register float sy;
|
|
register float sz;
|
|
|
|
register float john_rhoades_sub= sub_pixel_correct,
|
|
width_eye_d = eye->screen_half_width*eye->d,
|
|
height_eye_d = eye->screen_half_height*eye->d,
|
|
Czscale_eye_d = eye->d*eye->zscale*Czscale;
|
|
|
|
register float shx=(eye->screen_half_width *(eye->shift_x+1.0f))+john_rhoades_sub;
|
|
register float shy=(eye->screen_half_height*(eye->shift_y+1.0f))+john_rhoades_sub;
|
|
|
|
register dpl_VERTEX *v=&vl->vertices[0];
|
|
register int i, t, nv=vl->n_vertices;
|
|
|
|
for (i=0; i<nv; i++ ) {
|
|
sx =v->xform_posn[0];
|
|
sy =v->xform_posn[1];
|
|
sz =1.0f / v->xform_posn[2];
|
|
|
|
v->xform_posn[0] = ((sx*width_eye_d *sz)+shx) - john_rhoades_sub;
|
|
v->xform_posn[1] = ((sy*height_eye_d*sz)+shy) - john_rhoades_sub;
|
|
v->xform_posn[2] = sz*Czscale_eye_d;
|
|
|
|
v=v->next;
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ xform_and_project ( cull_GEOGROUP *cull_g,*/
|
|
/* declare assembly-coded version */
|
|
extern void
|
|
xform_and_project_fn ( cull_VIEW *eye,
|
|
cull_GEOGROUP *cull_g,
|
|
dpl_VERTEX_LIST *vl );
|
|
|
|
static void
|
|
xform_and_project ( cull_VIEW *eye,
|
|
cull_GEOGROUP *cull_g,
|
|
dpl_VERTEX_LIST *vl )
|
|
{
|
|
register float sx;
|
|
register float sy;
|
|
register float sz;
|
|
|
|
register float m00=cull_g->forward[0][0];
|
|
register float m01=cull_g->forward[0][1];
|
|
register float m02=cull_g->forward[0][2];
|
|
register float m10=cull_g->forward[1][0];
|
|
register float m11=cull_g->forward[1][1];
|
|
register float m12=cull_g->forward[1][2];
|
|
register float m20=cull_g->forward[2][0];
|
|
register float m21=cull_g->forward[2][1];
|
|
register float m22=cull_g->forward[2][2];
|
|
register float m30=cull_g->forward[3][0];
|
|
register float m31=cull_g->forward[3][1];
|
|
register float m32=cull_g->forward[3][2];
|
|
|
|
register float john_rhoades_sub= sub_pixel_correct,
|
|
width_eye_d = eye->screen_half_width*eye->d,
|
|
height_eye_d = eye->screen_half_height*eye->d,
|
|
Czscale_eye_d = eye->d*eye->zscale*Czscale,
|
|
dx, dy;
|
|
|
|
register float shx=(eye->screen_half_width *(eye->shift_x+1.0f))+john_rhoades_sub;
|
|
register float shy=(eye->screen_half_height*(eye->shift_y+1.0f))+john_rhoades_sub;
|
|
|
|
register dpl_VERTEX *v=&vl->vertices[0];
|
|
register int i, t, nv=vl->n_vertices;
|
|
|
|
for (i=0; i<nv; i++ ) {
|
|
sx =v->position[0];
|
|
sy =v->position[1];
|
|
sz =v->position[2];
|
|
|
|
dx = (sx*m00) + (sy*m10) + (sz*m20) + m30;
|
|
dy = (sx*m01) + (sy*m11) + (sz*m21) + m31;
|
|
sz = 1.0f /
|
|
((sx*m02) + (sy*m12) + (sz*m22) + m32);
|
|
|
|
v->xform_posn[0] = ((dx*width_eye_d *sz)+shx) - john_rhoades_sub;
|
|
v->xform_posn[1] = ((dy*height_eye_d*sz)+shy) - john_rhoades_sub;
|
|
v->xform_posn[2] = sz*Czscale_eye_d;
|
|
|
|
v=v->next;
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ xform ( cull_GEOGROUP *cull_g,*/
|
|
static void
|
|
xform ( cull_VIEW *eye,
|
|
cull_GEOGROUP *cull_g,
|
|
dpl_VERTEX_LIST *vl )
|
|
{
|
|
register float m00=cull_g->forward[0][0];
|
|
register float m01=cull_g->forward[0][1];
|
|
register float m02=cull_g->forward[0][2];
|
|
register float m10=cull_g->forward[1][0];
|
|
register float m11=cull_g->forward[1][1];
|
|
register float m12=cull_g->forward[1][2];
|
|
register float m20=cull_g->forward[2][0];
|
|
register float m21=cull_g->forward[2][1];
|
|
register float m22=cull_g->forward[2][2];
|
|
register float m30=cull_g->forward[3][0];
|
|
register float m31=cull_g->forward[3][1];
|
|
register float m32=cull_g->forward[3][2];
|
|
register float sx;
|
|
register float sy;
|
|
register float sz;
|
|
register float dx, dy, *d;
|
|
|
|
register int i, nv=vl->n_vertices;
|
|
dpl_VERTEX *v=&vl->vertices[0];
|
|
|
|
for (i=0; i<nv; i++ ) {
|
|
if (v->touched) {
|
|
d=v->xform_posn;
|
|
|
|
sx =v->position[0];
|
|
sy =v->position[1];
|
|
sz =v->position[2];
|
|
|
|
d[0] = (sx*m00) + (sy*m10) + (sz*m20) + m30;
|
|
d[1] = (sx*m01) + (sy*m11) + (sz*m21) + m31;
|
|
d[2] = (sx*m02) + (sy*m12) + (sz*m22) + m32;
|
|
}
|
|
v=v->next;
|
|
}
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ static int do_clipping ( dpl_VERTEX **p1, dpl_VERTEX **p2, int draw_mode )*/
|
|
static int do_clipping ( dpl_VERTEX *out,
|
|
dpl_VERTEX **p1,
|
|
dpl_VERTEX **p2,
|
|
float edge,
|
|
int draw_mode )
|
|
{
|
|
register float v1, v2, vv1, vv2;
|
|
register int i, outn=0, b1, b2;
|
|
|
|
#define clipperize(f,ix,t) \
|
|
out->f[ix]=(*p1)->f[ix]+(t*(((*p2)->f[ix])-((*p1)->f[ix])))
|
|
|
|
vv1=(*p1)->xform_posn[dpl_Z];
|
|
v1=vv1-edge;
|
|
b1=(v1>=0);
|
|
|
|
for (i = 0; i<3; i++ ) {
|
|
vv2=(*p2)->xform_posn[dpl_Z];
|
|
v2=vv2-edge;
|
|
b2=(v2>=0);
|
|
if (b1 && b2) {
|
|
/*{{{ clip vertex copy in-line*/
|
|
{
|
|
float *d, *s;
|
|
|
|
d=out->texcoords; s=(*p2)->texcoords;
|
|
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
|
|
d=out->xform_posn; s=(*p2)->xform_posn;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
|
|
d=out->rendered_color; s=(*p2)->rendered_color;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
}
|
|
/*}}} */
|
|
/* clip_vertex_copy ( out, (*p2) ); */
|
|
out++; outn++;
|
|
}
|
|
else {
|
|
if (b2||b1) {
|
|
/*{{{ intersect*/
|
|
float t;
|
|
|
|
t = (edge - vv1) / (vv2 - vv1);
|
|
|
|
out->xform_posn[2]=edge;
|
|
|
|
clipperize ( xform_posn, X, t );
|
|
clipperize ( xform_posn, Y, t );
|
|
|
|
/* the shaded alpha - sorry ! */
|
|
clipperize ( texcoords, 2, t );
|
|
|
|
if (draw_mode & dpl_draw_textured) {
|
|
clipperize ( texcoords, 0, t );
|
|
clipperize ( texcoords, 1, t );
|
|
}
|
|
else if (draw_mode & dpl_draw_3dtextured) {
|
|
clipperize ( texcoords, 0, t );
|
|
clipperize ( texcoords, 1, t );
|
|
}
|
|
if (draw_mode & (dpl_draw_smooth|dpl_draw_colored)) {
|
|
clipperize ( rendered_color, 0, t );
|
|
clipperize ( rendered_color, 1, t );
|
|
clipperize ( rendered_color, 2, t );
|
|
clipperize ( rendered_color, 3, t );
|
|
}
|
|
/*}}} */
|
|
out++; outn++;
|
|
}
|
|
if (b2) {
|
|
/*{{{ clip vertex copy in-line*/
|
|
{
|
|
float *d, *s;
|
|
|
|
d=out->texcoords; s=(*p2)->texcoords;
|
|
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
|
|
d=out->xform_posn; s=(*p2)->xform_posn;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
|
|
d=out->rendered_color; s=(*p2)->rendered_color;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
*d++=*s++;
|
|
}
|
|
/*}}} */
|
|
/* clip_vertex_copy ( out, (*p2)); */
|
|
out++; outn++;
|
|
}
|
|
}
|
|
vv1=vv2; v1=v2; p1=p2; b1=b2; p2++;
|
|
}
|
|
return outn;
|
|
}
|
|
/*}}} */
|
|
/*{{{ clip_polygon ( int *icoeff_pp,*/
|
|
static void
|
|
clip_triangle ( int *icoeff_pp,
|
|
int *icoeff_basep,
|
|
dpl_CONNECTION *conn,
|
|
dpl_VERTEX *va,
|
|
dpl_VERTEX *vb,
|
|
dpl_VERTEX *vc,
|
|
cull_VIEW *eye,
|
|
cull_GEOGROUP *cull_g,
|
|
int backwards,
|
|
vpx_geometry_function vpx,
|
|
int opcode0,
|
|
float codeword )
|
|
{
|
|
int icoeff_p=*icoeff_pp;
|
|
int icoeff_base=*icoeff_basep;
|
|
float edge=eye->hither;
|
|
|
|
dpl_CONNECTION *clipcon=&clip_connections->connections[0];
|
|
dpl_VERTEX *tri[3],
|
|
*out=&clip_vertices->vertices[0];
|
|
|
|
int outn;
|
|
|
|
tri[0]=va; tri[1]=vb; tri[2]=vc;
|
|
|
|
/* if (cull_g->draw_mode & (dpl_draw_smooth|dpl_draw_colored) == 0) { */
|
|
clipcon->rendered_color[0]=conn->rendered_color[0];
|
|
clipcon->rendered_color[1]=conn->rendered_color[1];
|
|
clipcon->rendered_color[2]=conn->rendered_color[2];
|
|
/* } */
|
|
|
|
outn=do_clipping ( out, &tri[2], &tri[0], edge, cull_g->draw_mode );
|
|
|
|
/*
|
|
okee dokee - here we have outn vertices in clipped_vertices,
|
|
all ready to be draw
|
|
*/
|
|
|
|
if (outn > 2) {
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=icoeff_p + COEFF_FULL;
|
|
}
|
|
|
|
clip_vertices->n_vertices=outn;
|
|
and_project ( eye, cull_g, clip_vertices );
|
|
|
|
clipcon->n_verts=3;
|
|
|
|
icoeff_p = vpx ( icoeff_p, codeword, opcode0, clipcon, backwards );
|
|
|
|
if (outn == 4) {
|
|
dpl_VERTEX *save=clipcon->indices[1];
|
|
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=icoeff_p + COEFF_FULL;
|
|
}
|
|
|
|
clipcon->indices[1]=clipcon->indices[2];
|
|
clipcon->indices[2]=clipcon->indices[3];
|
|
|
|
icoeff_p = vpx ( icoeff_p, codeword, opcode0, clipcon, backwards );
|
|
|
|
clipcon->indices[2]=clipcon->indices[1];
|
|
clipcon->indices[1]=save;
|
|
}
|
|
}
|
|
|
|
*icoeff_pp=icoeff_p;
|
|
*icoeff_basep=icoeff_base;
|
|
|
|
return;
|
|
}
|
|
/*}}} */
|
|
|
|
/*}}} */
|
|
|
|
/*{{{ drawing geometries*/
|
|
/*
|
|
typedef int (*vpx_geometry_function)(int,float,int,dpl_CONNECTION*,int );
|
|
typedef void (*vpx_totalgeom_function)(int**,float,int,dpl_CONNECTION*,int,int );
|
|
icoeff_p = vpx ( icoeff_p, codeword, opcode0, conn, backwards );
|
|
*/
|
|
|
|
/*{{{ draw_total_geometry ( cull_GEOGROUP *cull_g,*/
|
|
static void
|
|
draw_total_geometry ( dpl_GEOMETRY *g,
|
|
int backwards,
|
|
vpx_totalgeom_function vpx,
|
|
int opcode0,
|
|
float codeword )
|
|
{
|
|
vpx ( &coefficient_ptr, codeword, opcode0,
|
|
&g->connections->connections[0],
|
|
backwards,
|
|
g->connections->n_connections );
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ draw_unclipped_geometry ( cull_GEOGROUP *cull_g,*/
|
|
static void
|
|
draw_unclipped_geometry ( dpl_GEOMETRY *g,
|
|
int backwards,
|
|
vpx_geometry_function vpx,
|
|
int opcode0,
|
|
float codeword )
|
|
{
|
|
/*{{{ locals*/
|
|
int icoeff_p =(int) coefficient_ptr;
|
|
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
|
|
|
|
int i, nv=g->connections->n_connections;
|
|
dpl_CONNECTION *conn=&g->connections->connections[0];
|
|
/*}}} */
|
|
|
|
for ( i=0; i<nv; i++ ) {
|
|
if (conn->touched) {
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=icoeff_p + COEFF_FULL;
|
|
}
|
|
|
|
icoeff_p = vpx ( icoeff_p, codeword, opcode0, conn, backwards );
|
|
}
|
|
conn=conn->next;
|
|
}
|
|
coefficient_ptr=(float *) icoeff_p;
|
|
}
|
|
/*}}} */
|
|
/*{{{ draw_hither_clipped_geometry ( cull_GEOGROUP *cull_g,*/
|
|
|
|
static void
|
|
draw_hither_clipped_geometry ( cull_GEOGROUP *cull_g,
|
|
dpl_GEOMETRY *g,
|
|
int backwards,
|
|
cull_VIEW *eye,
|
|
vpx_geometry_function vpx,
|
|
int opcode0,
|
|
float codeword )
|
|
{
|
|
/*{{{ locals*/
|
|
float hither=eye->hither;
|
|
int icoeff_p =(int) coefficient_ptr;
|
|
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
|
|
|
|
int i, j, nv=g->connections->n_connections;
|
|
dpl_CONNECTION *conn =&g->connections->connections[0];
|
|
dpl_CONNECTION *clipcon=&clip_connections->connections[0];
|
|
/*}}} */
|
|
|
|
for ( i=0; i<nv; i++ ) {
|
|
if (conn->touched) {
|
|
int behinds, verts;
|
|
dpl_VERTEX **vp;
|
|
dpl_VERTEX *destp;
|
|
|
|
/*{{{ how many vertices in polygon straddle near clip plane?*/
|
|
vp=&conn->indices[0];
|
|
for (behinds=0, verts=conn->n_verts; verts; verts--) {
|
|
behinds+=((*vp)->xform_posn[2] < hither);
|
|
vp++;
|
|
}
|
|
/*}}} */
|
|
|
|
|
|
if (behinds == 0) {
|
|
/*{{{ all beyond near clip, can safely project and draw the poly*/
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=icoeff_p + COEFF_FULL;
|
|
}
|
|
|
|
vp =&conn->indices[0];
|
|
destp=&clip_vertices->vertices[0];
|
|
|
|
for (verts=conn->n_verts; verts; verts--) {
|
|
clip_vertex_copy ( destp, *vp );
|
|
vp++;
|
|
destp++;
|
|
}
|
|
/* if (cull_g->draw_mode & (dpl_draw_smooth|dpl_draw_colored) == 0) { */
|
|
clipcon->rendered_color[0]=conn->rendered_color[0];
|
|
clipcon->rendered_color[1]=conn->rendered_color[1];
|
|
clipcon->rendered_color[2]=conn->rendered_color[2];
|
|
/* } */
|
|
|
|
/* now make sure project does right no of vertices */
|
|
clip_vertices->n_vertices=conn->n_verts;
|
|
|
|
/* and make sure triangle_fn does right no of vertices */
|
|
clipcon->n_verts=conn->n_verts;
|
|
|
|
and_project ( eye, cull_g, clip_vertices );
|
|
|
|
icoeff_p = vpx ( icoeff_p, codeword, opcode0, clipcon, backwards );
|
|
/*}}} */
|
|
}
|
|
else if (behinds < (verts=conn->n_verts)) {
|
|
/*{{{ clip and draw the poly*/
|
|
for (j=1; j<verts-1; j++ )
|
|
clip_triangle ( &icoeff_p, &icoeff_base,
|
|
conn,
|
|
conn->indices[0],
|
|
conn->indices[j],
|
|
conn->indices[j+1],
|
|
eye, cull_g, backwards,
|
|
vpx, opcode0, codeword );
|
|
/*}}} */
|
|
}
|
|
}
|
|
conn=conn->next;
|
|
}
|
|
coefficient_ptr=(float *) icoeff_p;
|
|
}
|
|
/*}}} */
|
|
/*{{{ draw_yon_clipped_geometry ( cull_GEOGROUP *cull_g,*/
|
|
static void
|
|
draw_yon_clipped_geometry ( dpl_GEOMETRY *g,
|
|
int backwards,
|
|
cull_VIEW *eye,
|
|
vpx_geometry_function vpx,
|
|
int opcode0, float codeword )
|
|
{
|
|
/*{{{ locals*/
|
|
float yon=eye->d*eye->zscale*Czscale / eye->yon;
|
|
int icoeff_p =(int) coefficient_ptr;
|
|
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
|
|
|
|
int i, nv=g->connections->n_connections;
|
|
dpl_CONNECTION *conn=&g->connections->connections[0];
|
|
/*}}} */
|
|
|
|
for ( i=0; i<nv; i++ ) {
|
|
if (conn->touched) {
|
|
int v, verts=conn->n_verts;
|
|
dpl_VERTEX **vp=&conn->indices[0];
|
|
|
|
for (v=0; v<verts; v++) {
|
|
/*{{{ if a single vertex closer than yon, draw poly => GOTO IN HERE!*/
|
|
/* NOTE > since we are in 1/z perspective space */
|
|
if ((*vp)->xform_posn[2] > yon) {
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=icoeff_p + COEFF_FULL;
|
|
}
|
|
icoeff_p = vpx ( icoeff_p, codeword, opcode0, conn, backwards );
|
|
goto drawn_it;
|
|
}
|
|
/*}}} */
|
|
}
|
|
drawn_it: ;
|
|
}
|
|
conn=conn->next;
|
|
}
|
|
coefficient_ptr=(float *) icoeff_p;
|
|
}
|
|
/*}}} */
|
|
/*}}} */
|
|
|
|
/*{{{ draw_geogroup ( cull_GEOGROUP *gg )*/
|
|
static void
|
|
draw_geogroup ( cull_VIEW *eye,
|
|
cull_GEOGROUP *cull_gg,
|
|
cull_LMODEL *cull_lm )
|
|
{
|
|
/*{{{ some offsets for nasty hand-coded shading function*/
|
|
#define VERTEX_NORMAL_OFFSET 16
|
|
#define VERTEX_NEXT_OFFSET 44
|
|
#define VERTEX_RENDCOLOR_OFFSET 64
|
|
#define VERTEX_TOUCHED_OFFSET 76
|
|
|
|
#define FACET_NORMAL_OFFSET 32
|
|
#define FACET_NEXT_OFFSET 0
|
|
#define FACET_RENDCOLOR_OFFSET 48
|
|
#define FACET_TOUCHED_OFFSET 60
|
|
/*}}} */
|
|
|
|
/*{{{ locals*/
|
|
dpl_GEOGROUP *g_grp=cull_gg->geo;
|
|
cull_MATERIAL *fm, *bm;
|
|
dpl_list *list;
|
|
|
|
vpx_geometry_function vpx, vpx_b;
|
|
int opcode0, opcode0_b;
|
|
float codeword, codeword_b;
|
|
|
|
int drawmode=cull_gg->draw_mode;
|
|
int clipcode=cull_gg->clip_code;
|
|
/*}}} */
|
|
|
|
/* printf ("draw geogroup, drawmode 0x%x\n", drawmode ); */
|
|
|
|
/*{{{ do very late evaluation of lmodel*/
|
|
if (cull_lm->evaluated==0)
|
|
eval_lmodel ( cull_lm, cull_gg );
|
|
/*}}} */
|
|
/*{{{ set up polygon drawing functions*/
|
|
if (drawmode & dpl_draw_front)
|
|
vpx = vpx_drawstuff ( &codeword, &opcode0,
|
|
cull_gg, &cull_gg->front_mtl_data );
|
|
if (drawmode & dpl_draw_back)
|
|
vpx_b = vpx_drawstuff ( &codeword_b, &opcode0_b,
|
|
cull_gg, &cull_gg->back_mtl_data );
|
|
/*}}} */
|
|
|
|
fm=&cull_gg->front_mtl_data;
|
|
bm=&cull_gg->back_mtl_data;
|
|
|
|
for (list=g_grp->geometry_list.head; list; list=list->next) {
|
|
dpl_GEOMETRY *g=(dpl_GEOMETRY *) list->item;
|
|
vpx_geometry_function usevpx_f=vpx, usevpx_b=vpx_b;
|
|
/*{{{ modify function based on opacity*/
|
|
if (g->variable_alpha) {
|
|
/*{{{ f*/
|
|
if (vpx == (vpx_geometry_function) tri_zb_rgb)
|
|
usevpx_f = (vpx_geometry_function) tri_zb_rgb; /* not impl yet ! */
|
|
else if (vpx == (vpx_geometry_function) tri_zb_rgb_t)
|
|
usevpx_f = (vpx_geometry_function) tri_zb_rgb_o_t;
|
|
/*}}} */
|
|
/*{{{ and b*/
|
|
if (vpx_b == (vpx_geometry_function) tri_zb_rgb)
|
|
usevpx_b = (vpx_geometry_function) tri_zb_rgb; /* not impl yet ! */
|
|
else if (vpx_b == (vpx_geometry_function) tri_zb_rgb_t)
|
|
usevpx_b = (vpx_geometry_function) tri_zb_rgb_o_t;
|
|
/*}}} */
|
|
}
|
|
/*}}} */
|
|
if (drawmode & dpl_draw_front) {
|
|
/*{{{ do the front faces, solve with real eye*/
|
|
Cdelta_u=fm->du;
|
|
Cdelta_v=fm->dv;
|
|
|
|
clear_vertices ( g->vertices, 0 );
|
|
solve ( g->connections, cull_gg->xform_eye );
|
|
|
|
if ((drawmode & (dpl_draw_smooth | dpl_draw_colored)) == 0)
|
|
light_structure ( (char *) &g->connections->connections[0],
|
|
cull_lm,
|
|
fm, 1.0f,
|
|
g->connections->n_connections,
|
|
FACET_NORMAL_OFFSET,
|
|
FACET_NEXT_OFFSET,
|
|
FACET_RENDCOLOR_OFFSET,
|
|
FACET_TOUCHED_OFFSET );
|
|
else if (drawmode & dpl_draw_smooth)
|
|
light_structure ( (char *) &g->vertices->vertices[0],
|
|
cull_lm,
|
|
fm, 1.0f,
|
|
g->vertices->n_vertices,
|
|
VERTEX_NORMAL_OFFSET,
|
|
VERTEX_NEXT_OFFSET,
|
|
VERTEX_RENDCOLOR_OFFSET,
|
|
VERTEX_TOUCHED_OFFSET );
|
|
else if (drawmode & dpl_draw_colored)
|
|
cookize_vertices ( &g->vertices->vertices[0],
|
|
g->vertices->n_vertices,
|
|
fm );
|
|
|
|
if (clipcode & clip_hither) {
|
|
xform ( eye, cull_gg, g->vertices );
|
|
draw_hither_clipped_geometry ( cull_gg, g, 0, eye,
|
|
usevpx_f, opcode0, codeword );
|
|
}
|
|
else {
|
|
xform_and_project_fn ( eye, cull_gg, g->vertices );
|
|
/*
|
|
if (clipcode & clip_yon)
|
|
draw_yon_clipped_geometry ( cull_gg, g, 0, eye,
|
|
usevpx_f, opcode0, codeword );
|
|
else
|
|
draw_unclipped_geometry ( cull_gg, g, 0,
|
|
usevpx_f, opcode0, codeword );
|
|
*/
|
|
draw_unclipped_geometry ( g, 0,
|
|
usevpx_f, opcode0, codeword );
|
|
}
|
|
/*}}} */
|
|
}
|
|
if (drawmode & dpl_draw_back) {
|
|
/*{{{ do the back faces, solve with -eye, flip the normals*/
|
|
Cdelta_u=bm->du;
|
|
Cdelta_v=bm->dv;
|
|
|
|
clear_vertices ( g->vertices, 0 );
|
|
solve ( g->connections, cull_gg->back_xf_eye );
|
|
|
|
if ((drawmode & (dpl_draw_smooth | dpl_draw_colored)) == 0) {
|
|
light_structure ( (char *) &g->connections->connections[0],
|
|
cull_lm,
|
|
bm, -1.0f,
|
|
g->connections->n_connections,
|
|
FACET_NORMAL_OFFSET,
|
|
FACET_NEXT_OFFSET,
|
|
FACET_RENDCOLOR_OFFSET,
|
|
FACET_TOUCHED_OFFSET );
|
|
}
|
|
else if (drawmode & dpl_draw_smooth) {
|
|
light_structure ( (char *) &g->vertices->vertices[0],
|
|
cull_lm,
|
|
bm, -1.0f,
|
|
g->vertices->n_vertices,
|
|
VERTEX_NORMAL_OFFSET,
|
|
VERTEX_NEXT_OFFSET,
|
|
VERTEX_RENDCOLOR_OFFSET,
|
|
VERTEX_TOUCHED_OFFSET );
|
|
}
|
|
else if (drawmode & dpl_draw_colored) {
|
|
cookize_vertices ( &g->vertices->vertices[0],
|
|
g->vertices->n_vertices,
|
|
bm );
|
|
}
|
|
|
|
if (clipcode & clip_hither) {
|
|
xform ( eye, cull_gg, g->vertices );
|
|
draw_hither_clipped_geometry ( cull_gg, g, 1, eye,
|
|
usevpx_b, opcode0_b, codeword_b );
|
|
}
|
|
else {
|
|
xform_and_project_fn ( eye, cull_gg, g->vertices );
|
|
/*
|
|
if (clipcode & clip_yon)
|
|
draw_yon_clipped_geometry ( cull_gg, g, 1, eye,
|
|
usevpx_b, opcode0_b, codeword_b );
|
|
else
|
|
*/
|
|
draw_unclipped_geometry ( g, 1,
|
|
usevpx_b, opcode0_b, codeword_b );
|
|
}
|
|
/*}}} */
|
|
}
|
|
}
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ int *veloci_draw ( cull_VIEW *v )*/
|
|
static
|
|
int *veloci_draw ( cull_VIEW *v )
|
|
{
|
|
/*
|
|
The draw process - reads each displaylist item in turn, if item is
|
|
an lmodel, it is evaluated and becomes the current lmodel. If item
|
|
is a geogroup it is lit with the current lmodel
|
|
*/
|
|
|
|
ggroup_render_chunk *chunk;
|
|
char *cp;
|
|
cull_GEOGROUP *gg;
|
|
cull_LMODEL *lm=NULL;
|
|
int i, last;
|
|
|
|
chunk=v->geogroup_head;
|
|
|
|
if (chunk) {
|
|
do {
|
|
last=chunk->terminal;
|
|
|
|
cp=chunk->ggroup_data;
|
|
|
|
for(i=0; i<chunk->ggroup_count; i++ ) {
|
|
gg=(cull_GEOGROUP *) cp;
|
|
|
|
if (gg->identifier == dpl_type_geogroup) {
|
|
draw_geogroup ( v, gg, lm );
|
|
cp+=ggroup_bump_val;
|
|
}
|
|
else if (gg->identifier == dpl_type_lmodel) {
|
|
lm=(cull_LMODEL *) cp;
|
|
cp+=lmodel_bump_val;
|
|
}
|
|
else {
|
|
printf ("ERROR - bad displaylist tag 0x%x\n", gg->identifier);
|
|
return;
|
|
}
|
|
}
|
|
chunk=chunk->next;
|
|
} while (last==0);
|
|
}
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void veloci_rasterize ( int *dma_ptr )*/
|
|
static void
|
|
veloci_rasterize ( int *dma_ptr )
|
|
{
|
|
/* printf ("velocirasterize dataptr 0x%x\n", dma_ptr ); */
|
|
|
|
return;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void veloci_swap_buffers ( int wait_for_retrace )*/
|
|
static void
|
|
veloci_swap_buffers ( int wait_for_retrace )
|
|
{
|
|
/* printf ("velociswapbuffers wait_for_retrace=%d\n", wait_for_retrace ); */
|
|
|
|
flip_screens ( 2, 2 );
|
|
|
|
return;
|
|
}
|
|
/*}}} */
|
|
|
|
extern void reinit_screenbins ( int, int, int );
|
|
int animate_time_0,
|
|
animate_time;
|
|
float animate_elapsed_time=0;
|
|
|
|
/*{{{ void vr_draw_scene ()*/
|
|
void
|
|
vr_draw_scene ( int double_buffered )
|
|
{
|
|
dpl_list *eyetem;
|
|
dpl_POINT origin;
|
|
int then, now, cull;
|
|
|
|
/*
|
|
printf ("vr_draw_scene, view head=0x%x\n",
|
|
the_scene.view_list.head );
|
|
*/
|
|
|
|
if (clip_vertices==NULL) {
|
|
/*{{{ allocate + init clip vertex memory*/
|
|
int i;
|
|
dpl_CONNECTION *con;
|
|
dpl_VERTEX *vert;
|
|
|
|
clip_vertices =(dpl_VERTEX_LIST *) malloc(sizeof(dpl_VERTEX_LIST));
|
|
clip_connections=(dpl_CONNECTION_LIST *) malloc(sizeof(dpl_CONNECTION_LIST));
|
|
|
|
clip_vertices->next=NULL;
|
|
clip_connections->next=NULL;
|
|
clip_connections->n_connections=1;
|
|
con=&clip_connections->connections[0];
|
|
vert=&clip_vertices->vertices[0];
|
|
|
|
for (i=0; i<DPL_CONNECTIONS_PER_BLOCK; i++ ) {
|
|
con->indices[i]=&clip_vertices->vertices[i];
|
|
}
|
|
|
|
for (i=0; i<DPL_VERTICES_PER_BLOCK; i++ ) {
|
|
dpl_VERTEX *prev=vert;
|
|
vert++;
|
|
prev->next=vert;
|
|
}
|
|
/*}}} */
|
|
dN_timer ( &animate_time_0 );
|
|
}
|
|
dN_timer ( &animate_time );
|
|
|
|
animate_elapsed_time=(animate_time - animate_time_0) / 1.0e6f;
|
|
|
|
origin[0]=0.0f;
|
|
origin[1]=0.0f;
|
|
origin[2]=0.0f;
|
|
origin[3]=1.0f;
|
|
|
|
for (eyetem=the_scene.view_list.head;eyetem;eyetem=eyetem->next ) {
|
|
dpl_VIEW *eye=(dpl_VIEW *) eyetem->item;
|
|
|
|
if (eye) {
|
|
cull_VIEW *v;
|
|
int *dma_ptr;
|
|
|
|
dN_timer(&then);
|
|
v=veloci_cull ( eye, origin );
|
|
dN_timer(&cull);
|
|
dma_ptr=veloci_draw ( v );
|
|
veloci_rasterize ( dma_ptr );
|
|
dN_timer(&now);
|
|
}
|
|
}
|
|
|
|
veloci_swap_buffers ( double_buffered );
|
|
}
|
|
/*}}} */
|
|
|