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>
3237 lines
84 KiB
C++
3237 lines
84 KiB
C++
/*{{{ comment*/
|
|
/*
|
|
|
|
File render.c
|
|
|
|
Contains all rendering entrypoints
|
|
|
|
Phil Atkin
|
|
|
|
(c) Division Ltd. 1991
|
|
*/
|
|
|
|
/*
|
|
|
|
generates tristrips direct as output, for optimum HSP performance
|
|
|
|
algorithm - walk down tristrip, substituting plane equation into
|
|
viewpoint. As soon as sign change occurs, render current tristrip
|
|
with appropriate surface properties, and restart from offending printf
|
|
vertex
|
|
|
|
*/
|
|
/*}}} */
|
|
/*{{{ includes*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <dnc.h>
|
|
#include <math.h>
|
|
#include "pazpl5.h"
|
|
#include "viz.h"
|
|
#include "macros.h"
|
|
#include "pazstore.h"
|
|
#include "geometry.h"
|
|
#include "lighting.h"
|
|
#include "texture.h"
|
|
#include "matrix.h"
|
|
#include "pazread.h"
|
|
#include "optfloat.h"
|
|
#include "speclght.h"
|
|
#include "cm200io.h"
|
|
#include "pxpl5sup\divpxmap.h"
|
|
#include "pxpl5sup\pxpl5sup.h"
|
|
#include "pxpl5sup\pxpl5tri.h"
|
|
#include "pxpl5sup\dmaengn.h"
|
|
#include "u:\projects\dbi0150\dbi0151\ucode\igc_opco.h"
|
|
#include "u:\projects\dbi0150\dbi0151\ucode\igc_comm.h"
|
|
#include "i860sem.h"
|
|
#include "sfx.h"
|
|
/*}}} */
|
|
|
|
/*{{{ typedefs an ting*/
|
|
typedef int* (*vertex_fn)(int*, float*, float*, float* );
|
|
typedef void (*draw_fn)(VERTEX*, VERTEX*, VERTEX*, int, int, VIEW *);
|
|
typedef void (*strip_fn)(VSTRIP*, VERTEX*, VIEW*, int );
|
|
typedef void (*flip_fn)(int, int );
|
|
|
|
draw_fn draw_triangle;
|
|
strip_fn draw_strip;
|
|
flip_fn flipper;
|
|
vertex_fn draw_vertex;
|
|
|
|
/*}}} */
|
|
/*{{{ externs, statics*/
|
|
#define set_head(v,h,w,a) if (v->strip_type==strip_type_tri) h=w; else h=a
|
|
|
|
extern int total_grab_patch,
|
|
total_grab_light;
|
|
|
|
|
|
extern SCENE *currentScene;
|
|
extern VIEWRT *vrthead;
|
|
extern void spin ( int link );
|
|
extern void fn_solve_strip ( float *p, float *pl, int n_tris, int twosided, float texscale );
|
|
extern void fn_solve_pmesh ( float *p, float *pl, int n_tris, int twosided, float texscale );
|
|
extern void vertex_copy( VERTEX *render_strip, VERTEX *render_head, int n);
|
|
extern void matrix_copy ( MATRIX, MATRIX );
|
|
|
|
extern int* tile_poke_address;
|
|
extern int* wait_poke_address;
|
|
extern int* trans_wait_poke_address;
|
|
extern unsigned int __frameTime;
|
|
extern int cull_pass_microsex;
|
|
extern unsigned int __trianglesRendered;
|
|
|
|
void render_all_patches ( patch_render_chunk *);
|
|
|
|
int *texture_table_iptr=NULL;
|
|
|
|
unsigned int __verticesRendered=0;
|
|
|
|
int nodes, back_colour=-1;
|
|
int tex=0;
|
|
int type_override=0;
|
|
int my_id, view_id, total_views;
|
|
int then=0, now=0;
|
|
int x_display_tiles, y_display_tiles;
|
|
|
|
float ambient_value;
|
|
float curr_texscale=1.0f;
|
|
float Hz=0.0f;
|
|
|
|
poly_pool_list *poly_pool_head=NULL;
|
|
TEXRAMP *texture_ramps;
|
|
|
|
static MATERIAL *last_surf=NULL;
|
|
|
|
static float rendering_frame_rate=0.0f;
|
|
|
|
static int display_tile_base=0;
|
|
static int timing_frames=0;
|
|
static int rendered_frames=0;
|
|
static int very_first_frame=0;
|
|
|
|
extern int *opaque_endoftex_DMAptr;
|
|
|
|
/*}}} */
|
|
/*{{{ multiple i860 control*/
|
|
extern int _processorId,
|
|
_numProcessors;
|
|
|
|
concurrency_control *shared_cntl; /* =(concurrency_control *) 0xfffff880; */
|
|
|
|
VSTRIP longest_strip,
|
|
longest_verts,
|
|
longest_tris;
|
|
|
|
int prev_longest_strip=0,
|
|
prev_longest_verts=0,
|
|
prev_longest_tris=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 */
|
|
|
|
}
|
|
/*}}} */
|
|
|
|
/* some performance tracing */
|
|
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;
|
|
|
|
/*{{{ 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;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void init_HSP ( int link, char *string, int magic )*/
|
|
void init_HSP ( int link, char *string, int magic )
|
|
{
|
|
return;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ static void render_pxpl5_tristrip ( VERTEX *w0,*/
|
|
static void render_pxpl5_tristrip ( VERTEX *w0,
|
|
int tristrip,
|
|
int n_tris,
|
|
int front_face,
|
|
int opcode1,
|
|
float mtl_code,
|
|
pxpl5tri_fn tri_fn,
|
|
int clip_code,
|
|
float proj_clip )
|
|
{
|
|
int icoeff_p =(int) coefficient_ptr;
|
|
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
|
|
|
|
register VERTEX *v1, *v2, *v3;
|
|
|
|
v1=w0;
|
|
v2=w0+1;
|
|
v3=w0+2;
|
|
|
|
while (n_tris) {
|
|
int proceed=0;
|
|
|
|
if (clip_code) {
|
|
if (v1->position[2] > proj_clip) {
|
|
if (v2->position[2] > proj_clip) {
|
|
if (v3->position[2] > proj_clip) {
|
|
proceed=1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
proceed=1;
|
|
|
|
if (proceed) {
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=COEFF_FULL + (int) last_coeffchunk;
|
|
}
|
|
|
|
if (front_face) {
|
|
icoeff_p = (*tri_fn)( icoeff_p, mtl_code, opcode1,
|
|
v1,
|
|
v2,
|
|
v3 );
|
|
}
|
|
else
|
|
icoeff_p = (*tri_fn)( icoeff_p, mtl_code, opcode1,
|
|
v3,
|
|
v2,
|
|
v1 );
|
|
|
|
}
|
|
|
|
v3++;
|
|
v2++;
|
|
|
|
if (tristrip) {
|
|
v1++;
|
|
front_face^=1;
|
|
}
|
|
n_tris--;
|
|
}
|
|
|
|
coefficient_ptr=(float *) icoeff_p;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ void NULL_flip ( int me, int nodes )*/
|
|
void NULL_flip ( int me, int nodes )
|
|
{
|
|
return;
|
|
}
|
|
/*}}} */
|
|
|
|
static int first_add_opcode=1;
|
|
|
|
/*{{{ 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 (first_add_opcode) {
|
|
first_add_opcode=0;
|
|
/*
|
|
printf ("adding %d opcodes to bin 0x%x, address 0x%x\n",
|
|
n_opcodes, bin, &chunk->DMA_opcodes[index] );
|
|
*/
|
|
}
|
|
|
|
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 XP_flush()*/
|
|
void XP_flush()
|
|
{
|
|
manual_flush(shared_cntl->uncached_flush_location);
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ debug variables for XP*/
|
|
VSTRIP *__current_strip;
|
|
VERTEX *__current_head;
|
|
int __current_count;
|
|
int __render_count;
|
|
VERTEX *__render_head;
|
|
|
|
/*}}} */
|
|
|
|
#if 0
|
|
/* the C model for the hand-coded version */
|
|
/*{{{ static void xform_light_project ( )*/
|
|
static void xform_light_project ( VERTEX *v1,
|
|
int n_verts,
|
|
int strip_shade,
|
|
int front_face,
|
|
VIEW *eye,
|
|
LIGHTSOURCE *blondie,
|
|
MATRIX quad_aligned_m,
|
|
MATERIAL *surf,
|
|
int do_project,
|
|
float ks )
|
|
{
|
|
/*{{{ floating point registers*/
|
|
/*{{{ 12 matrix registers total 12*/
|
|
register float m00, m01, m02,
|
|
m10, m11, m12,
|
|
m20, m21, m22,
|
|
tx, ty, tz;
|
|
|
|
/*}}} */
|
|
/*{{{ 7 viewport scaling 18*/
|
|
register float wx, wy, wz,
|
|
eye_d,
|
|
zmax,
|
|
shx, shy;
|
|
|
|
/*}}} */
|
|
/*{{{ 2 lighting registers 20*/
|
|
|
|
/*
|
|
NB - kd is intrinsic colour, held in frame buffer. ks is now also
|
|
held in frame buffer as a 4-bit number, so we 6% control over specular
|
|
stuff.
|
|
*/
|
|
|
|
register float normfactor;
|
|
/*}}} */
|
|
|
|
/*{{{ 10 temporary registers 31 all used up and more ! ! !*/
|
|
|
|
register float fdot;
|
|
register float invz;
|
|
|
|
/* temporary registers, re-loaded per vertex */
|
|
register float px, py, pz;
|
|
#define nx px
|
|
#define ny py
|
|
#define nz pz
|
|
|
|
register float cdiff, cspec;
|
|
|
|
register float lx, ly, lz;
|
|
#define rx lx
|
|
#define ry ly
|
|
#define rz lz
|
|
|
|
|
|
/*}}} */
|
|
/*}}} */
|
|
/*{{{ integer registers*/
|
|
/* 8 register parameters in use */
|
|
|
|
/* if cooked, dolighting=0, lightbump = 0 */
|
|
/* if smooth, dolighting=1, lightbump = 1 */
|
|
/* if flat, dolighting=nv-2, lightbump = -1 */
|
|
/* per vertex, dolighting+=lightbump */
|
|
|
|
VERTEX *light_v;
|
|
LIGHTSOURCE *bulb;
|
|
int dolighting;
|
|
int lightbump;
|
|
float *light;
|
|
float *half;
|
|
float *norm;
|
|
float *phong_table;
|
|
int dot;
|
|
|
|
/*}}} */
|
|
|
|
/*{{{ initialize*/
|
|
/*{{{ cache matrix ...use fld.q if possible*/
|
|
m00=quad_aligned_m[0][0];
|
|
m01=quad_aligned_m[0][1];
|
|
m02=quad_aligned_m[0][2];
|
|
|
|
m10=quad_aligned_m[1][0];
|
|
m11=quad_aligned_m[1][1];
|
|
m12=quad_aligned_m[1][2];
|
|
|
|
m20=quad_aligned_m[2][0];
|
|
m21=quad_aligned_m[2][1];
|
|
m22=quad_aligned_m[2][2];
|
|
|
|
tx =quad_aligned_m[3][0];
|
|
ty =quad_aligned_m[3][1];
|
|
tz =quad_aligned_m[3][2];
|
|
/*}}} */
|
|
|
|
phong_table=surf->specular_table;
|
|
|
|
wx =eye->screen_half_width;
|
|
wy =eye->screen_half_height;
|
|
wz =eye->zscale;
|
|
|
|
eye_d=eye->d;
|
|
zmax =1.0f;
|
|
|
|
shx=wx*(eye->shift_x + 1.0f);
|
|
shy=wy*(eye->shift_y + 1.0f);
|
|
|
|
if (strip_shade & strip_shade_coloured) {
|
|
dolighting = 0;
|
|
lightbump = 0;
|
|
}
|
|
else if (strip_shade & strip_shade_smooth) {
|
|
dolighting = 1;
|
|
lightbump = 0;
|
|
light_v = v1;
|
|
}
|
|
else {
|
|
dolighting = n_verts-2;
|
|
lightbump = -1;
|
|
light_v = v1+1;
|
|
}
|
|
/*}}} */
|
|
/*{{{ which surface ?*/
|
|
if (front_face)
|
|
normfactor = 1.0f;
|
|
else
|
|
normfactor =-1.0f;
|
|
/*}}} */
|
|
|
|
while (n_verts) {
|
|
/*{{{ transform 18 flops*/
|
|
/* ****************
|
|
transform this point
|
|
*/
|
|
px=v1->position[0];
|
|
py=v1->position[1];
|
|
pz=v1->position[2];
|
|
|
|
rx=(px*m00)+(py*m10)+(pz*m20)+tx;
|
|
ry=(px*m01)+(py*m11)+(pz*m21)+ty;
|
|
rz=(px*m02)+(py*m12)+(pz*m22)+tz;
|
|
|
|
/*}}} */
|
|
/*{{{ project 18 flops*/
|
|
if (do_project) {
|
|
/* **************
|
|
project it to screen-space
|
|
*/
|
|
invz=eye_d/rz;
|
|
|
|
px=(rx*wx*invz)+shx;
|
|
py=(ry*wy*invz)+shy;
|
|
pz=wz*invz;
|
|
|
|
v1->position[0] = px;
|
|
v1->position[1] = py;
|
|
v1->position[2] = pz;
|
|
|
|
}
|
|
else {
|
|
v1->position[0] = rx;
|
|
v1->position[1] = ry;
|
|
v1->position[2] = rz;
|
|
}
|
|
/*}}} */
|
|
/*{{{ light 16 flops*/
|
|
if (dolighting) {
|
|
norm=light_v->normcol;
|
|
/* ********************
|
|
light this point
|
|
*/
|
|
/* NOTE - force into adjacent registers for f0 and fst.d */
|
|
cdiff=0.0f;
|
|
cspec=0.0f;
|
|
|
|
nx=normfactor*norm[0];
|
|
ny=normfactor*norm[1];
|
|
nz=normfactor*norm[2];
|
|
|
|
for (bulb=blondie; bulb; bulb=bulb->next ) {
|
|
/*{{{ light up this vertex according to bulb type*/
|
|
light=&bulb->xformpos[0];
|
|
|
|
/* do diffuse shading */
|
|
lx=light[0];
|
|
ly=light[1];
|
|
lz=light[2];
|
|
|
|
fdot=(nx*lx) + (ny*ly) + (nz*lz);
|
|
|
|
/* the multiply by light colour happens at end-of-frame */
|
|
if (fdot > 0.0f)
|
|
cdiff+=fdot;
|
|
|
|
/* do specular shading - NOTE power factor has gone */
|
|
half=(float *) *(int *) &(bulb->xformpos[3]);
|
|
|
|
lx=half[0];
|
|
ly=half[1];
|
|
lz=half[2];
|
|
|
|
dot=(int) ((nx*lx) + (ny*ly) + (nz*lz));
|
|
|
|
if (dot > 0) {
|
|
if (dot > (phong_precision - 1))
|
|
dot = phong_precision-1;
|
|
|
|
/* the multiply by light colour happens at end-of-frame */
|
|
/* ditto ks */
|
|
cspec +=phong_table[dot];
|
|
}
|
|
/*}}} */
|
|
}
|
|
/* fst.d .. */
|
|
norm[0]=cdiff*255.0;
|
|
norm[1]=cspec*255.0;
|
|
}
|
|
/*}}} */
|
|
|
|
v1++;
|
|
light_v++;
|
|
|
|
dolighting+=lightbump;
|
|
n_verts--;
|
|
}
|
|
}
|
|
/*}}} */
|
|
#endif
|
|
|
|
/*{{{ declare fn_xform_light_project*/
|
|
extern void fn_xform_light_project ( VERTEX *v1,
|
|
int n_verts,
|
|
int strip_shade,
|
|
int front_face,
|
|
VIEW *eye,
|
|
LIGHTSOURCE *blondie,
|
|
MATRIX quad_aligned_m,
|
|
MATERIAL *surf,
|
|
int do_project,
|
|
float ks,
|
|
int pmesh );
|
|
/*}}} */
|
|
|
|
#if 0
|
|
/*{{{ frustum clipping*/
|
|
extern void smintersect(SMOOTHPOINT pi, SMOOTHPOINT p1, SMOOTHPOINT p2, int axis,
|
|
float edge);
|
|
extern void copy_spoint( SMOOTHPOINT s, SMOOTHPOINT d );
|
|
|
|
/*{{{ static int smooth_clip (SMOOTHPOINT *out, SMOOTHPOINT *in,int inn, int axis, int sign, float edge)*/
|
|
static int smooth_clip ( SMOOTHPOINT *out, SMOOTHPOINT *in,
|
|
int inn, int axis, int sign, float edge)
|
|
{
|
|
register int outn=0, b1, b2;
|
|
SMOOTHPOINT *p1=in+inn-1, *p2=in;
|
|
register float v1, v2, vv1, vv2;
|
|
|
|
vv1=(*p1)[axis];
|
|
|
|
if (sign!=0) v1=vv1-edge;
|
|
else v1=edge-vv1;
|
|
|
|
b1=(v1>=0);
|
|
|
|
for (; inn>0; inn--) {
|
|
|
|
vv2=(*p2)[axis];
|
|
if (sign!=0) v2=vv2-edge;
|
|
else v2=edge-vv2;
|
|
b2=(v2>=0);
|
|
if (b1 && b2) {
|
|
copy_spoint (*p2,*out);
|
|
out++; outn++;
|
|
}
|
|
else {
|
|
if (b2||b1) {
|
|
smintersect (*out, *p2, *p1, axis, edge);
|
|
out++; outn++;
|
|
}
|
|
if (b2) {
|
|
copy_spoint (*p2,*out);
|
|
out++; outn++;
|
|
}
|
|
}
|
|
vv1=vv2; v1=v2; p1=p2; b1=b2; p2++;
|
|
}
|
|
return (outn);
|
|
}
|
|
|
|
/*}}} */
|
|
|
|
/*{{{ static void clip_smooth_triangle ( VERTEX *aa, VERTEX *bb, VERTEX *cc,*/
|
|
static void clip_smooth_triangle ( VERTEX *aa,
|
|
VERTEX *bb,
|
|
VERTEX *cc,
|
|
VIEW *eye,
|
|
int front_face, int clip_planes,
|
|
int smooth )
|
|
{
|
|
SMOOTHPOINT *tmp;
|
|
SMOOTHPOINT clip_poly [9],
|
|
bounce_poly [9];
|
|
SMOOTHPOINT *q,*p=&clip_poly[0], *b=&bounce_poly[0];
|
|
register int nv=3;
|
|
float *pp;
|
|
|
|
#define swap_ptrs(a,b) tmp=a;a=b;b=tmp
|
|
|
|
/* printf ("copy tri into poly\n" ); */
|
|
if (smooth) {
|
|
/*{{{ copy triangle into poly*/
|
|
q=p;
|
|
pp=(float *) q;
|
|
|
|
pp[0]=aa->position[0];
|
|
pp[1]=aa->position[1];
|
|
pp[2]=aa->position[2];
|
|
|
|
if (texture) {
|
|
pp[R] =aa->normcol[0];
|
|
pp[R+1]=aa->normcol[1];
|
|
pp[R+2]=aa->normcol[2];
|
|
}
|
|
else {
|
|
pp[R] =aa->normcol[0];
|
|
pp[R+1]=aa->normcol[1];
|
|
pp[R+2]=aa->normcol[2];
|
|
}
|
|
q++;
|
|
pp=(float *) q;
|
|
|
|
pp[0]=bb->position[0];
|
|
pp[1]=bb->position[1];
|
|
pp[2]=bb->position[2];
|
|
|
|
if (texture) {
|
|
#ifdef TEXHSP
|
|
hsp_tex_colour ( &pp[R], bb->normcol, bb->texcoords );
|
|
#else
|
|
pp[R] =bb->normcol[0];
|
|
pp[R+1]=bb->normcol[1];
|
|
pp[R+2]=bb->normcol[2];
|
|
#endif
|
|
}
|
|
else {
|
|
pp[R]=bb->normcol[0];
|
|
pp[R+1]=bb->normcol[1];
|
|
pp[R+2]=bb->normcol[2];
|
|
}
|
|
|
|
q++;
|
|
pp=(float *) q;
|
|
|
|
pp[0]=cc->position[0];
|
|
pp[1]=cc->position[1];
|
|
pp[2]=cc->position[2];
|
|
if (texture) {
|
|
/*{{{ */
|
|
#ifdef TEXHSP
|
|
hsp_tex_colour ( &pp[R], cc->normcol, cc->texcoords );
|
|
#else
|
|
pp[R] =cc->normcol[0];
|
|
pp[R+1]=cc->normcol[1];
|
|
pp[R+2]=cc->normcol[2];
|
|
#endif
|
|
/*}}} */
|
|
}
|
|
else {
|
|
pp[R]=cc->normcol[0];
|
|
pp[R+1]=cc->normcol[1];
|
|
pp[R+2]=cc->normcol[2];
|
|
}
|
|
|
|
/*}}} */
|
|
}
|
|
else {
|
|
/*{{{ copy triangle into poly USE VERTEX 1 FOR COLOUR*/
|
|
q=p;
|
|
pp=(float *) q;
|
|
|
|
pp[0]=aa->position[0];
|
|
pp[1]=aa->position[1];
|
|
pp[2]=aa->position[2];
|
|
|
|
if (texture) {
|
|
pp[R] =bb->normcol[0];
|
|
pp[R+1]=bb->normcol[1];
|
|
pp[R+2]=bb->normcol[2];
|
|
}
|
|
else {
|
|
pp[R]=bb->normcol[0];
|
|
pp[R+1]=bb->normcol[1];
|
|
pp[R+2]=bb->normcol[2];
|
|
}
|
|
|
|
q++;
|
|
pp=(float *) q;
|
|
|
|
pp[0]=bb->position[0];
|
|
pp[1]=bb->position[1];
|
|
pp[2]=bb->position[2];
|
|
|
|
if (texture) {
|
|
pp[R] =bb->normcol[0];
|
|
pp[R+1]=bb->normcol[1];
|
|
pp[R+2]=bb->normcol[2];
|
|
}
|
|
else {
|
|
pp[R]=bb->normcol[0];
|
|
pp[R+1]=bb->normcol[1];
|
|
pp[R+2]=bb->normcol[2];
|
|
}
|
|
|
|
q++;
|
|
pp=(float *) q;
|
|
|
|
pp[0]=cc->position[0];
|
|
pp[1]=cc->position[1];
|
|
pp[2]=cc->position[2];
|
|
|
|
if (texture) {
|
|
pp[R] =bb->normcol[0];
|
|
pp[R+1]=bb->normcol[1];
|
|
pp[R+2]=bb->normcol[2];
|
|
}
|
|
else {
|
|
pp[R]=bb->normcol[0];
|
|
pp[R+1]=bb->normcol[1];
|
|
pp[R+2]=bb->normcol[2];
|
|
}
|
|
/*}}} */
|
|
}
|
|
/*{{{ if (clip_planes&clip_hither)*/
|
|
if (clip_planes&clip_hither)
|
|
{
|
|
nv=smooth_clip (b,p,nv,Z,1,eye->hither );
|
|
swap_ptrs(p,b);
|
|
}
|
|
/*}}} */
|
|
if (nv<3) return;
|
|
/*{{{ if (clip_planes&clip_yon)*/
|
|
if (clip_planes&clip_yon)
|
|
{
|
|
nv=smooth_clip (b,p,nv,Z,0,eye->yon );
|
|
swap_ptrs(p,b);
|
|
}
|
|
/*}}} */
|
|
/*{{{ do perspeccy stuff*/
|
|
|
|
/* normalize view volume */
|
|
/* do perspective */
|
|
/* scale viewport */
|
|
|
|
{
|
|
float z_offs;
|
|
|
|
if (front_face) {
|
|
z_offs=maxZbufVal+(realOne*2); /* front */
|
|
}
|
|
else {
|
|
z_offs = maxZbufVal+(realOne * 4);
|
|
}
|
|
|
|
project_points ( (float *) p, eye, nv, z_offs, 8 );
|
|
}
|
|
|
|
/*}}} */
|
|
if (nv<3) return;
|
|
/*{{{ if (clip_planes&clip_x0)*/
|
|
if (clip_planes&clip_x0)
|
|
{
|
|
nv=smooth_clip (b,p,nv,X,1,0);
|
|
swap_ptrs(p,b);
|
|
}
|
|
/*}}} */
|
|
if (nv<3) return;
|
|
/*{{{ if (clip_planes&clip_x1)*/
|
|
if (clip_planes&clip_x1)
|
|
{
|
|
nv=smooth_clip (b,p,nv,X,0,eye->screen_width);
|
|
swap_ptrs(p,b);
|
|
}
|
|
/*}}} */
|
|
if (nv<3) return;
|
|
/*{{{ if (clip_planes&clip_y0)*/
|
|
if (clip_planes&clip_y0)
|
|
{
|
|
nv=smooth_clip (b,p,nv,Y,1,0);
|
|
swap_ptrs(p,b);
|
|
}
|
|
/*}}} */
|
|
if (nv<3) return;
|
|
/*{{{ if (clip_planes&clip_y1)*/
|
|
if (clip_planes&clip_y1)
|
|
{
|
|
nv=smooth_clip (b,p,nv,Y,0,eye->screen_height);
|
|
swap_ptrs(p,b);
|
|
}
|
|
/*}}} */
|
|
if (nv<3) return;
|
|
|
|
/*{{{ render optimised triangles*/
|
|
{
|
|
int n;
|
|
VERTEX va, vb, vc;
|
|
float *pp= (float *) p;
|
|
int *buf0, *buf, words=(nv*3)+1;
|
|
|
|
__trianglesRendered+=(nv-2);
|
|
|
|
buf0=wait_for_room ( eye, words );
|
|
buf=buf0;
|
|
|
|
*buf++ = (words-1) | (1 << 8); /* its a POLYSTRIP */
|
|
|
|
for (n=0; n<nv; n++ ) {
|
|
pp=(float *) p;
|
|
|
|
/*
|
|
MUST call hsp_vert, not draw_vertex, since the texture coords
|
|
are already in the colour slots ! ! !
|
|
|
|
*/
|
|
buf=hsp_vert ( buf, pp, pp+R, (float *) aa->texcoords );
|
|
|
|
p++;
|
|
}
|
|
|
|
inform_driver ( eye, buf0, words );
|
|
}
|
|
/*}}} */
|
|
}
|
|
/*}}} */
|
|
/*}}} */
|
|
#endif
|
|
|
|
#define check_dbl(p,s) if (((int) (p)) & 0x4) printf("misaligned vertex 0x%x in %s\n", p, s)
|
|
|
|
/*{{{ static int hither_clip ( VERTEX *out, VERTEX *in,*/
|
|
static int hither_clip ( VERTEX *out,
|
|
VERTEX *in,
|
|
float edge,
|
|
int texture,
|
|
int smooth )
|
|
{
|
|
#define clip(f,ix,t) \
|
|
out->f[ix]=p1->f[ix]+(t*((p2->f[ix])-(p1->f[ix])))
|
|
|
|
register int i, outn=0, b1, b2;
|
|
VERTEX *p1=in+2, *p2=in;
|
|
register float v1, v2, vv1, vv2;
|
|
|
|
vv1=p1->position[Z];
|
|
|
|
v1=vv1-edge;
|
|
b1=(v1>=0);
|
|
|
|
for (i = 0; i<3; i++ ) {
|
|
|
|
vv2=p2->position[Z];
|
|
v2=vv2-edge;
|
|
b2=(v2>=0);
|
|
if (b1 && b2) {
|
|
/* check_dbl(out,"hither_clip"); */
|
|
vertex_copy ( out, p2, 1 );
|
|
out++; outn++;
|
|
}
|
|
else {
|
|
if (b2||b1) {
|
|
/*{{{ intersect*/
|
|
float t;
|
|
|
|
t = (edge - vv1) / (vv2 - vv1);
|
|
|
|
clip ( position, X, t );
|
|
clip ( position, Y, t );
|
|
|
|
if (texture) {
|
|
clip ( texcoords, 0, t );
|
|
clip ( texcoords, 1, t );
|
|
}
|
|
if (smooth) {
|
|
clip ( normcol, 0, t );
|
|
clip ( normcol, 1, t );
|
|
clip ( normcol, 2, t );
|
|
}
|
|
else {
|
|
out->normcol[0]=p1->normcol[0];
|
|
out->normcol[1]=p1->normcol[1];
|
|
out->normcol[2]=p1->normcol[2];
|
|
}
|
|
out->position[2]=edge;
|
|
/*}}} */
|
|
out++; outn++;
|
|
}
|
|
if (b2) {
|
|
/* check_dbl(out, "hither_clip"); */
|
|
vertex_copy ( out, p2, 1 );
|
|
out++; outn++;
|
|
}
|
|
}
|
|
vv1=vv2; v1=v2; p1=p2; b1=b2; p2++;
|
|
}
|
|
return (outn);
|
|
}
|
|
|
|
/*}}} */
|
|
#if 0
|
|
/*{{{ static int yon_clip ( VERTEX *out, VERTEX *in,*/
|
|
static int yon_clip ( VERTEX *out, VERTEX *in,
|
|
float edge, int texture, int smooth )
|
|
{
|
|
#define clip(f,ix,t) \
|
|
out->f[ix]=p1->f[ix]+(t*((p2->f[ix])-(p1->f[ix])))
|
|
|
|
register int i, outn=0, b1, b2;
|
|
VERTEX *p1=in+2, *p2=in;
|
|
register float v1, v2, vv1, vv2;
|
|
|
|
vv1=p1->position[Z];
|
|
|
|
v1=edge-vv1;
|
|
b1=(v1>=0);
|
|
|
|
for (i=0; i<3; i++ ) {
|
|
|
|
vv2=p2->position[Z];
|
|
v2=edge-vv2;
|
|
b2=(v2>=0);
|
|
if (b1 && b2) {
|
|
/* check_dbl(out, "hither_clip"); */
|
|
vertex_copy ( out, p2, 1 );
|
|
out++; outn++;
|
|
}
|
|
else {
|
|
if (b2||b1) {
|
|
/*{{{ intersect*/
|
|
float t;
|
|
|
|
t = (edge - vv1) / (vv2 - vv1);
|
|
|
|
clip ( position, X, t );
|
|
clip ( position, Y, t );
|
|
|
|
if (texture) {
|
|
clip ( texcoords, 0, t );
|
|
clip ( texcoords, 1, t );
|
|
}
|
|
if (smooth) {
|
|
clip ( normcol, 0, t );
|
|
clip ( normcol, 1, t );
|
|
clip ( normcol, 2, t );
|
|
}
|
|
else {
|
|
out->normcol[0]=p1->normcol[0];
|
|
out->normcol[1]=p1->normcol[1];
|
|
out->normcol[2]=p1->normcol[2];
|
|
}
|
|
out->position[2]=edge;
|
|
/*}}} */
|
|
out++; outn++;
|
|
}
|
|
if (b2) {
|
|
/* check_dbl(out); */
|
|
vertex_copy ( out, p2, 1 );
|
|
out++; outn++;
|
|
}
|
|
}
|
|
vv1=vv2; v1=v2; p1=p2; b1=b2; p2++;
|
|
}
|
|
return (outn);
|
|
}
|
|
|
|
/*}}} */
|
|
#endif
|
|
|
|
/*{{{ static void pp5_clip_triangle ( VSTRIP *v, VERTEX *va, VERTEX *vb, VERTEX *vc,*/
|
|
|
|
static void pp5_clip_triangle ( VSTRIP *v,
|
|
VERTEX *va, VERTEX *vb, VERTEX *vc,
|
|
VERTEX *vtec,
|
|
VIEW *eye,
|
|
int frontness,
|
|
MATERIAL *front_surf,
|
|
int texture, int clip_code )
|
|
{
|
|
VERTEX quad[8]; /* caters for 3 in, 4 out */
|
|
VERTEX *vt=&quad[0];
|
|
register float minz=eye->hither;
|
|
register int flat = ((v->strip_shade&strip_shade_flat_mask) == strip_shade_flat);
|
|
register int outv;
|
|
|
|
/* only clip triangle if any of its z coords straddle clipping plane */
|
|
|
|
if ((va->position[Z] < minz) ||
|
|
(vb->position[Z] < minz) ||
|
|
(vc->position[Z] < minz)) {
|
|
/*{{{ do clip*/
|
|
/* make copy of input triangle */
|
|
/* check_dbl(vt,"pp5_clip"); */
|
|
vertex_copy( vt, va, 1 );
|
|
vertex_copy( vt+1, vb, 1 );
|
|
vertex_copy( vt+2, vc, 1 );
|
|
|
|
/* first deal with flat shading - copy flat colour to all 3 vertices */
|
|
if (flat) {
|
|
VERTEX *v1=&quad[1], *v2=&quad[2];
|
|
register float r, g, b;
|
|
r=v1->normcol[0];
|
|
g=v1->normcol[1];
|
|
b=v1->normcol[2];
|
|
|
|
vt->normcol[0]=r;
|
|
v2->normcol[0]=r;
|
|
vt->normcol[1]=g;
|
|
v2->normcol[1]=g;
|
|
vt->normcol[2]=b;
|
|
v2->normcol[2]=b;
|
|
}
|
|
|
|
/* perform hither clipping */
|
|
outv = hither_clip ( &quad[3], vt, minz, texture, flat==0 );
|
|
|
|
/* skip input triangle */
|
|
vt=&quad[3];
|
|
|
|
/* remember stride in floats yechh?? */
|
|
|
|
if (outv > 2) {
|
|
project_points ( &vt->position[0], eye, outv, sizeof(VERTEX) >> 2 );
|
|
|
|
render_pxpl5_tristrip ( vt,
|
|
0, outv-2,
|
|
frontness>>1,
|
|
front_surf->pxpl5opcode,
|
|
*(float *) &(front_surf->pxpl5codeword),
|
|
front_surf->triangle_fn,
|
|
0, 0.0f );
|
|
}
|
|
|
|
/*}}} */
|
|
}
|
|
else {
|
|
/*{{{ tri on-screen, just project then draw*/
|
|
int icoeff_p =(int) coefficient_ptr;
|
|
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
|
|
|
|
if (icoeff_p > icoeff_base)
|
|
coefficient_ptr=(float *) next_coeffchunk ();
|
|
|
|
/* check_dbl(vt,"pp5_clip"); */
|
|
vertex_copy( vt, va, 1 );
|
|
vertex_copy( vt+1, vb, 1 );
|
|
vertex_copy( vt+2, vc, 1 );
|
|
|
|
/* remember stride in floats yechh?? */
|
|
project_points ( &vt->position[0], eye, 3, sizeof(VERTEX) >> 2 );
|
|
|
|
if (frontness & 2) {
|
|
coefficient_ptr = (*front_surf->triangle_fn)( coefficient_ptr,
|
|
*(float *) &(front_surf->pxpl5codeword),
|
|
front_surf->pxpl5opcode,
|
|
vt,
|
|
vt+1,
|
|
vt+2);
|
|
}
|
|
else {
|
|
coefficient_ptr = (*front_surf->triangle_fn)( coefficient_ptr,
|
|
*(float *) &(front_surf->pxpl5codeword),
|
|
front_surf->pxpl5opcode,
|
|
vt+2,
|
|
vt+1,
|
|
vt );
|
|
}
|
|
|
|
/*}}} */
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ static void render_triangles ( VSTRIP *v,*/
|
|
/* the big bad wolf version */
|
|
int veryFirst=1;
|
|
|
|
static void render_triangles ( VSTRIP *v,
|
|
MATERIAL *front_surf,
|
|
VERTEX *render_head,
|
|
int n_tris,
|
|
int frontness,
|
|
MATRIX total,
|
|
LIGHTSOURCE *blonde,
|
|
VIEW *eye,
|
|
int clip_code )
|
|
{
|
|
int i;
|
|
VERTEX *r_strip=render_strip;
|
|
int texture=(v->strip_shade&strip_shade_textured)!=0;
|
|
|
|
if (n_tris==0) return;
|
|
last_surf=front_surf;
|
|
|
|
/*{{{ copy verts to r_strip*/
|
|
if (v->strip_type==strip_type_tri) {
|
|
/* check_dbl(r_strip,"render_triangles"); */
|
|
vertex_copy ( r_strip, render_head, n_tris+2 );
|
|
}
|
|
else {
|
|
/* check_dbl(r_strip,"render_triangles"); */
|
|
vertex_copy ( r_strip, v->head, 1 );
|
|
vertex_copy ( r_strip+1, render_head, n_tris+1 );
|
|
}
|
|
/*}}} */
|
|
|
|
if ((clip_code & (clip_hither | clip_yon)) == 0) {
|
|
/*{{{ no z-clipping*/
|
|
unclipped_tris+=n_tris;
|
|
/* transform and light with projecting */
|
|
fn_xform_light_project ( r_strip,
|
|
n_tris+2,
|
|
v->strip_shade, frontness&1,
|
|
eye, blonde, total, front_surf, 1 | (texture<<1),
|
|
front_surf->ks*255.0f, 0 );
|
|
render_pxpl5_tristrip ( r_strip,
|
|
(v->strip_type == strip_type_tri),
|
|
n_tris,
|
|
frontness>>1,
|
|
front_surf->pxpl5opcode,
|
|
*(float *) &(front_surf->pxpl5codeword),
|
|
front_surf->triangle_fn,
|
|
0, 0.0f );
|
|
|
|
/*}}} */
|
|
}
|
|
else if ((clip_code & clip_hither) == 0) {
|
|
/*{{{ just far-clip, easy*/
|
|
/* transform and light with projecting */
|
|
float proj_clip=eye->zscale*eye->d*1.04857588E+6 / eye->yon;
|
|
|
|
unclipped_tris+=n_tris;
|
|
fn_xform_light_project ( r_strip,
|
|
n_tris+2,
|
|
v->strip_shade, frontness&1,
|
|
eye, blonde, total, front_surf, 1 | (texture<<1),
|
|
front_surf->ks*255.0f, 0 );
|
|
render_pxpl5_tristrip ( r_strip,
|
|
(v->strip_type == strip_type_tri),
|
|
n_tris,
|
|
frontness>>1,
|
|
front_surf->pxpl5opcode,
|
|
*(float *) &(front_surf->pxpl5codeword),
|
|
front_surf->triangle_fn,
|
|
clip_code, proj_clip );
|
|
|
|
/*}}} */
|
|
}
|
|
else {
|
|
/*{{{ nasty, near clip*/
|
|
VERTEX *va, *vb, *vc, *vtec;
|
|
|
|
/* hard case, do fully general clipping */
|
|
/* transform and light without projecting */
|
|
fn_xform_light_project ( r_strip,
|
|
n_tris+2,
|
|
v->strip_shade, frontness&1,
|
|
eye, blonde, total, front_surf, 0,
|
|
front_surf->ks*255.0f, 0 );
|
|
|
|
|
|
va=render_strip;
|
|
vtec=va;
|
|
vb=va+1;
|
|
vc=vb+1;
|
|
|
|
for (i=0; i<n_tris; i++ ) {
|
|
clipped_tris++;
|
|
pp5_clip_triangle ( v, va,vb,vc, vtec, eye, frontness, front_surf, texture, clip_code );
|
|
if (v->strip_type == strip_type_tri) {
|
|
va++;
|
|
frontness^=2;
|
|
}
|
|
vb++;
|
|
vc++;
|
|
vtec++;
|
|
}
|
|
/*}}} */
|
|
}
|
|
|
|
__trianglesRendered+=n_tris;
|
|
__verticesRendered+=(n_tris+2);
|
|
|
|
veryFirst=0;
|
|
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ static VSTRIP *strip_copy ( VSTRIP *v )*/
|
|
static VSTRIP *strip_copy ( VSTRIP *v )
|
|
{
|
|
if (v==NULL)
|
|
return NULL;
|
|
else {
|
|
VSTRIP *stripcopy=&longest_strip;
|
|
VERTEX *vert=v->head,
|
|
*copy=stripcopy->head;
|
|
|
|
stripcopy->normals = v->normals;
|
|
stripcopy->strip_type = v->strip_type;
|
|
stripcopy->strip_render = v->strip_render;
|
|
stripcopy->strip_shade = v->strip_shade;
|
|
stripcopy->vertex_count = v->vertex_count;
|
|
|
|
/* check_dbl(copy,"strip_copy"); */
|
|
vertex_copy ( copy, vert, v->vertex_count );
|
|
|
|
return stripcopy;
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ static VSTRIP *copy_pmesh_verts ( VSTRIP *v )*/
|
|
static VSTRIP *copy_pmesh_verts ( VSTRIP *v )
|
|
{
|
|
if (v==NULL) return NULL;
|
|
else {
|
|
VSTRIP *stripcopy=&longest_verts;
|
|
VERTEX *vert=v->head,
|
|
*copy=stripcopy->head;
|
|
|
|
stripcopy->next = v->next;
|
|
stripcopy->normals = v->normals;
|
|
stripcopy->strip_type = v->strip_type;
|
|
stripcopy->strip_render = v->strip_render;
|
|
stripcopy->strip_shade = v->strip_shade;
|
|
stripcopy->vertex_count = v->vertex_count;
|
|
|
|
/* check_dbl(copy,"copy_pmesh_verts"); */
|
|
vertex_copy ( copy, vert, v->vertex_count );
|
|
|
|
return stripcopy;
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ static VSTRIP *copy_pmesh_tris ( VSTRIP *tris, VSTRIP *verts )*/
|
|
static VSTRIP *copy_pmesh_tris ( VSTRIP *tris, VERTEX *first_vert )
|
|
{
|
|
#if 0
|
|
/*{{{ */
|
|
VSTRIP *stripcopy=&longest_tris;
|
|
VERTEX *tri =tris->head,
|
|
*copy=stripcopy->head;
|
|
int delta;
|
|
int *itri=(int *) tri;
|
|
int *icop=(int *) copy;
|
|
int n, a, b, c, d;
|
|
double da, db;
|
|
|
|
stripcopy->vertex_count = tris->vertex_count;
|
|
|
|
/*
|
|
the trick here is, we copy the triangle pointers and add a
|
|
delta, which is new_address-old_address, and thus end up with
|
|
a sound data structure
|
|
*/
|
|
|
|
delta=((int) (longest_verts.head)) - ((int) first_vert);
|
|
|
|
for (n=tris->vertex_count; n; n--) {
|
|
a=itri[0];
|
|
b=itri[1];
|
|
c=itri[2];
|
|
|
|
icop[0]=a+delta;
|
|
icop[1]=b+delta;
|
|
icop[2]=c+delta;
|
|
icop[3]=0;
|
|
|
|
/* do plane eqn */
|
|
da=((double *) itri)[2];
|
|
db=((double *) itri)[3];
|
|
((double *) icop)[2]=da;
|
|
((double *) icop)[3]=db;
|
|
|
|
itri +=(sizeof(VERTEX)>>2);
|
|
icop +=(sizeof(VERTEX)>>2);
|
|
}
|
|
|
|
return stripcopy;
|
|
|
|
/*}}} */
|
|
#else
|
|
/*{{{ */
|
|
extern void pmesh_tri_copy ( VERTEX *, VERTEX *, int, int );
|
|
|
|
VSTRIP *stripcopy=&longest_tris;
|
|
|
|
stripcopy->vertex_count = tris->vertex_count;
|
|
|
|
pmesh_tri_copy ( stripcopy->head, tris->head, tris->vertex_count,
|
|
((int) (longest_verts.head)) - ((int) first_vert));
|
|
|
|
return stripcopy;
|
|
|
|
/*}}} */
|
|
#endif
|
|
}
|
|
/*}}} */
|
|
|
|
static float sphere_scale;
|
|
|
|
extern float* sphere_zb_rgb ( float *coeffs,
|
|
float material,
|
|
int opcode1,
|
|
VERTEX *v1,
|
|
VERTEX *v2,
|
|
VERTEX *v3 );
|
|
#if 0
|
|
/*{{{ the C-coded sphere functions*/
|
|
|
|
/*{{{ float* sphere_zb_d ( float *coeffs,*/
|
|
float* sphere_zb_d ( float *coeffs,
|
|
float material,
|
|
int opcode1,
|
|
VERTEX *v1,
|
|
VERTEX *v2,
|
|
VERTEX *v3 )
|
|
{
|
|
float x =v1->position[0], /* 0 */
|
|
y =v1->position[1], /* 4 */
|
|
z =v1->position[2], /* 8 */
|
|
r =v1->position[3], /* 12 */
|
|
rz=v1->planeEqn[3], /* 28 */
|
|
lx=v2->planeEqn[0], /* 16 */
|
|
ly=v2->planeEqn[1], /* 20 */
|
|
lz=v2->planeEqn[2]; /* 24 */
|
|
|
|
float two=2.0f, fA, fB, fC, fD;
|
|
float r2=r*r,
|
|
x2y2=(x*x)+(y*y),
|
|
r12=1.0f/r2;
|
|
float K, r_invlz;
|
|
|
|
int *coeffptr=(int *) coeffs;
|
|
/*
|
|
scan-convert - g(x,y) = Ax + By + C - Q
|
|
A = 2a, B = 2b C = r2 - a2 - b2, Q = x2 + y2
|
|
|
|
Note that r is screen-space radius,
|
|
rz is radius in z-buffer space
|
|
d SAME AS f FOR SQUARE PIXEL DISPLAYS
|
|
*/
|
|
|
|
r2-=x2y2;
|
|
|
|
fA=x*two;
|
|
fB=y*two;
|
|
fC=r2;
|
|
fD=-1.0f;
|
|
|
|
/* *****************************
|
|
switch on pixels inside circle
|
|
*/
|
|
|
|
*coeffptr++=opcode1;
|
|
IGC_FBITS ( coeffptr, 22 );
|
|
|
|
IGC_TREEgeZERO_Q6 ( coeffptr, fA, fB, fC, fD, 0.0f, fD );
|
|
|
|
/* **************
|
|
z-buffer pixels
|
|
*/
|
|
|
|
K=rz*r12;
|
|
fA*=K;
|
|
fB*=K;
|
|
fC=(z+rz)-(x2y2*K);
|
|
fD=-K;
|
|
|
|
IGC_MEMltTREE_Q6 ( coeffptr, dvpx_zbuf, dvpx_zbufbits,
|
|
fA, fB, fC, fD, 0.0f, fD );
|
|
IGC_TREEclmpintoMEM_Q0 ( coeffptr, dvpx_zbuf, dvpx_zbufbits );
|
|
|
|
/* **********************
|
|
shade pixels
|
|
|
|
*/
|
|
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_scalar, dvpx_scalarbits,
|
|
*(int *)&material );
|
|
IGC_CLEAR ( coeffptr, dvpx_specular, 8 );
|
|
|
|
r_invlz=r/lz;
|
|
K=-255.99f*lz*r12;
|
|
lx*=r_invlz;
|
|
ly*=r_invlz;
|
|
|
|
fA=K*((x*two) - lx);
|
|
fB=K*((y*two) - ly);
|
|
fC=K*(r2 + (lx*x + ly*y));
|
|
fD=-K;
|
|
|
|
IGC_TREEclmpintoMEM_Q6 ( coeffptr, dvpx_diffuse, 8,
|
|
fA, fB, fC, fD, 0.0f, fD );
|
|
IGC_FBITS ( coeffptr, 15 );
|
|
|
|
/* *****************
|
|
binitize it
|
|
|
|
*/
|
|
|
|
{
|
|
int ic =(int) coeffptr;
|
|
int ic0=(int) coeffs;
|
|
int words;
|
|
|
|
if (ic&7) {
|
|
ic+=4;
|
|
*coeffptr++=0;
|
|
}
|
|
words=ic-ic0;
|
|
|
|
binitize ( ic0, DMA_SEND(words>>3),
|
|
x-r, y-r,
|
|
x+r, y+r,
|
|
1023, 767, 16 );
|
|
|
|
ic+= 31;
|
|
ic&=~31;
|
|
|
|
return (float *) ic;
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ float* sphere_zb_d_s ( float *coeffs,*/
|
|
float* sphere_zb_d_s ( float *coeffs,
|
|
float material,
|
|
int opcode1,
|
|
VERTEX *v1,
|
|
VERTEX *v2,
|
|
VERTEX *v3 )
|
|
{
|
|
float x =v1->position[0],
|
|
y =v1->position[1],
|
|
z =v1->position[2],
|
|
r =v1->position[3],
|
|
rz=v1->planeEqn[3],
|
|
lx=v2->planeEqn[0],
|
|
ly=v2->planeEqn[1],
|
|
lz=v2->planeEqn[2];
|
|
|
|
float two=2.0f, fA, fB, fC, fD;
|
|
float r2=r*r,
|
|
x2y2=(x*x)+(y*y),
|
|
r12=1.0f/r2;
|
|
float K, r_invlz;
|
|
|
|
int *coeffptr=(int *) coeffs;
|
|
/*
|
|
scan-convert - g(x,y) = Ax + By + C - Q
|
|
A = 2a, B = 2b C = r2 - a2 - b2, Q = x2 + y2
|
|
|
|
Note that r is screen-space radius,
|
|
rz is radius in z-buffer space
|
|
d SAME AS f FOR SQUARE PIXEL DISPLAYS
|
|
*/
|
|
|
|
r2-=x2y2;
|
|
|
|
fA=x*two;
|
|
fB=y*two;
|
|
fC=r2;
|
|
fD=-1.0f;
|
|
|
|
/* *****************************
|
|
switch on pixels inside circle
|
|
*/
|
|
|
|
*coeffptr++=opcode1;
|
|
IGC_FBITS ( coeffptr, 22 );
|
|
|
|
IGC_TREEgeZERO_Q6 ( coeffptr, fA, fB, fC, fD, 0.0f, fD );
|
|
|
|
/* **************
|
|
z-buffer pixels
|
|
*/
|
|
|
|
K=rz*r12;
|
|
fA*=K;
|
|
fB*=K;
|
|
fC=(z+rz)-(x2y2*K);
|
|
fD=-K;
|
|
|
|
IGC_MEMltTREE_Q6 ( coeffptr, dvpx_zbuf, dvpx_zbufbits,
|
|
fA, fB, fC, fD, 0.0f, fD );
|
|
IGC_TREEclmpintoMEM_Q0 ( coeffptr, dvpx_zbuf, dvpx_zbufbits );
|
|
|
|
/* **********************
|
|
shade pixels
|
|
|
|
*/
|
|
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_scalar, dvpx_scalarbits,
|
|
*(int *)&material );
|
|
IGC_CLEAR ( coeffptr, dvpx_diffuse, 16 );
|
|
|
|
/* do diffuse bit */
|
|
r_invlz=r/lz;
|
|
K=-255.99f*lz*r12;
|
|
lx*=r_invlz;
|
|
ly*=r_invlz;
|
|
|
|
fA=K*((x*two) - lx);
|
|
fB=K*((y*two) - ly);
|
|
fC=K*(r2 + (lx*x + ly*y));
|
|
fD=-K;
|
|
|
|
IGC_TREEclmpintoMEM_Q6 ( coeffptr, dvpx_diffuse, 8, fA, fB, fC, fD, 0.0f, fD );
|
|
|
|
lx=v2->normcol[0];
|
|
ly=v2->normcol[1];
|
|
lz=v2->normcol[2];
|
|
|
|
r_invlz=r/lz;
|
|
K=-127.9f*lz*r12;
|
|
lx*=r_invlz;
|
|
ly*=r_invlz;
|
|
|
|
fA=K*((x*two) - lx);
|
|
fB=K*((y*two) - ly);
|
|
fC=K*(r2 + (lx*x + ly*y));
|
|
fD=-K;
|
|
|
|
IGC_TREEclmpintoMEM_Q6 ( coeffptr, dvpx_specular, 7, fA, fB, fC, fD, 0.0f, fD );
|
|
IGC_CLEAR ( coeffptr, dvpx_specular+7, 1 );
|
|
IGC_FBITS ( coeffptr, 15 );
|
|
|
|
/* *****************
|
|
binitize it
|
|
|
|
*/
|
|
|
|
{
|
|
int ic =(int) coeffptr;
|
|
int ic0=(int) coeffs;
|
|
int words;
|
|
|
|
if (ic&7) {
|
|
ic+=4;
|
|
*coeffptr++=0;
|
|
}
|
|
words=ic-ic0;
|
|
|
|
binitize ( ic0, DMA_SEND(words>>3),
|
|
x-r, y-r,
|
|
x+r, y+r,
|
|
1023, 767, 16 );
|
|
|
|
ic+= 31;
|
|
ic&=~31;
|
|
|
|
return (float *) ic;
|
|
}
|
|
}
|
|
/*}}} */
|
|
|
|
/*}}} */
|
|
/*{{{ float* sphere_zb_rgb_a ( float *coeffs,*/
|
|
float* sphere_zb_rgb_a ( float *coeffs,
|
|
float material,
|
|
int opcode1,
|
|
dpl_CONNECTION *conn )
|
|
{
|
|
dpl_VERTEX *v1=conn->indices[0];
|
|
dpl_VERTEX *v2=conn->indices[1];
|
|
float x =v1->xform_posn[0],
|
|
y =v1->xform_posn[1],
|
|
z =v1->xform_posn[2],
|
|
r =v1->xform_posn[3],
|
|
rz=v2->xform_posn[3],
|
|
lx=v2->xform_posn[0],
|
|
ly=v2->xform_posn[1],
|
|
lz=v2->xform_posn[2];
|
|
|
|
float two=2.0f, fA, fB, fC, fD;
|
|
float r2=r*r,
|
|
x2y2=(x*x)+(y*y),
|
|
r12=1.0f/r2;
|
|
float K, r_invlz;
|
|
|
|
int *coeffptr=(int *) coeffs;
|
|
/*
|
|
scan-convert - g(x,y) = Ax + By + C - Q
|
|
A = 2a, B = 2b C = r2 - a2 - b2, Q = x2 + y2
|
|
|
|
Note that r is screen-space radius,
|
|
rz is radius in z-buffer space
|
|
d SAME AS f FOR SQUARE PIXEL DISPLAYS
|
|
*/
|
|
|
|
r2-=x2y2;
|
|
|
|
fA=x*two;
|
|
fB=y*two;
|
|
fC=r2;
|
|
fD=-1.0f;
|
|
|
|
/* *****************************
|
|
switch on pixels inside circle
|
|
*/
|
|
|
|
*coeffptr++=opcode1;
|
|
IGC_FBITS ( coeffptr, 22 );
|
|
|
|
IGC_TREEgeZERO_Q6 ( coeffptr, fA, fB, fC, fD, 0.0f, fD );
|
|
|
|
/* **************
|
|
z-buffer pixels
|
|
*/
|
|
|
|
K=rz*r12;
|
|
fA*=K;
|
|
fB*=K;
|
|
fC=(z+rz)-(x2y2*K);
|
|
fD=-K;
|
|
|
|
IGC_MEMltTREE_Q6 ( coeffptr, dvpx_zbuf, dvpx_zbufbits,
|
|
fA, fB, fC, fD, 0.0f, fD );
|
|
IGC_TREEclmpintoMEM_Q0 ( coeffptr, dvpx_zbuf, dvpx_zbufbits );
|
|
|
|
/* **********************
|
|
shade pixels
|
|
|
|
*/
|
|
|
|
IGC_SCAintoMEM_S1 ( coeffptr, dvpx_scalar, dvpx_scalarbits,
|
|
*(int *)&material );
|
|
IGC_CLEAR ( coeffptr, dvpx_diffuse, 16 );
|
|
|
|
/* do diffuse bit */
|
|
r_invlz=r/lz;
|
|
K=-255.99f*lz*r12;
|
|
lx*=r_invlz;
|
|
ly*=r_invlz;
|
|
|
|
fA=K*((x*two) - lx);
|
|
fB=K*((y*two) - ly);
|
|
fC=K*(r2 + (lx*x + ly*y));
|
|
fD=-K;
|
|
|
|
IGC_TREEclmpintoMEM_Q6 ( coeffptr, dvpx_diffuse, 8, fA, fB, fC, fD, 0.0f, fD );
|
|
|
|
lx=v2->normcol[0];
|
|
ly=v2->normcol[1];
|
|
lz=v2->normcol[2];
|
|
|
|
r_invlz=r/lz;
|
|
K=-127.9f*lz*r12;
|
|
lx*=r_invlz;
|
|
ly*=r_invlz;
|
|
|
|
fA=K*((x*two) - lx);
|
|
fB=K*((y*two) - ly);
|
|
fC=K*(r2 + (lx*x + ly*y));
|
|
fD=-K;
|
|
|
|
IGC_TREEclmpintoMEM_Q6 ( coeffptr, dvpx_specular, 7, fA, fB, fC, fD, 0.0f, fD );
|
|
IGC_CLEAR ( coeffptr, dvpx_specular+7, 1 );
|
|
IGC_FBITS ( coeffptr, 15 );
|
|
|
|
/* *****************
|
|
binitize it
|
|
|
|
*/
|
|
|
|
{
|
|
int ic =(int) coeffptr;
|
|
int ic0=(int) coeffs;
|
|
int words;
|
|
|
|
if (ic&7) {
|
|
ic+=4;
|
|
*coeffptr++=0;
|
|
}
|
|
words=ic-ic0;
|
|
|
|
binitize ( ic0, DMA_SEND(words>>3),
|
|
x-r, y-r,
|
|
x+r, y+r,
|
|
1023, 767, 16 );
|
|
|
|
ic+= 31;
|
|
ic&=~31;
|
|
|
|
return (float *) ic;
|
|
}
|
|
}
|
|
/*}}} */
|
|
#endif
|
|
|
|
float shading_frame=0.0f;
|
|
|
|
|
|
/*{{{ static int alpha_texture ( MATERIAL *front_surf, MATERIAL *back_surf)*/
|
|
static int alpha_texture ( MATERIAL *front_surf, MATERIAL *back_surf)
|
|
{
|
|
int alpha=0;
|
|
|
|
if (front_surf) {
|
|
if (front_surf->tex) {
|
|
if (front_surf->tex->texture_type == TEXTURE_TYPE_24_ALPHA) {
|
|
alpha=1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (back_surf) {
|
|
if (back_surf->tex) {
|
|
if (back_surf->tex->texture_type == TEXTURE_TYPE_24_ALPHA) {
|
|
alpha=1;
|
|
}
|
|
}
|
|
}
|
|
return alpha;
|
|
}
|
|
/*}}} */
|
|
/*{{{ static int mtl_traced=0;*/
|
|
static int mtl_traced=0;
|
|
|
|
static void no_surface ( PATCH *p )
|
|
{
|
|
char *s;
|
|
|
|
s=(p->patch_type==patch_type_patch) ? "patch" : "pmesh";
|
|
|
|
printf ("not rendering %s, no surface for %s\n",
|
|
s, p->fmaterial_name );
|
|
|
|
if (mtl_traced==0) trace_materials();
|
|
|
|
mtl_traced=1;
|
|
}
|
|
/*}}} */
|
|
|
|
|
|
/*{{{ void renderPatch ( PATCH *p,*/
|
|
void renderPatch ( PATCH *p,
|
|
MATRIX forward,
|
|
MATRIX back,
|
|
LIGHTSOURCE *blonde,
|
|
VIEW *eye,
|
|
MATERIAL *front_surf,
|
|
MATERIAL *back_surf,
|
|
int clip_code )
|
|
{
|
|
VSTRIP *v, *viva;
|
|
register float *xform_eye=((float *) back)+12;
|
|
register int twosided=(back_surf != NULL);
|
|
register int bb;
|
|
screenbin *pushscreenbins=screenbins;
|
|
|
|
if (front_surf==NULL) {
|
|
no_surface(p);
|
|
return;
|
|
}
|
|
|
|
if (clip_code == 0) unclipped_patches++;
|
|
else clipped_patches++;
|
|
|
|
/* printf ("renderPatch\n" ); */
|
|
|
|
pxpl5izePatch ( p, front_surf, back_surf );
|
|
|
|
if (alpha_texture(front_surf, back_surf))
|
|
screenbins=trans_screenbins;
|
|
|
|
for (viva=p->head; viva!=NULL; viva=viva->next ) {
|
|
VERTEX *w, *a, *b, *render_head;
|
|
register int last, this, n=1, front=3;
|
|
|
|
v=strip_copy(viva);
|
|
|
|
n=1;
|
|
|
|
w=v->head;
|
|
bb=v->vertex_count-2;
|
|
|
|
fn_solve_strip ( xform_eye, (float *) w, bb, twosided,
|
|
eye->hither * 1.048e6 );
|
|
|
|
last=1&(*(int *) (&v->head->position[3]));
|
|
|
|
render_head=w;
|
|
w++;
|
|
a=w+1;
|
|
b=a+1;
|
|
bb--;
|
|
|
|
if (v->strip_type == strip_type_tri) {
|
|
/*{{{ render triangle strip*/
|
|
|
|
while (bb) {
|
|
this=1&(*(int *) (&w->position[3]));
|
|
|
|
if (this!=last) {
|
|
if (last) {
|
|
/* transition, prev were front, new is back-facing */
|
|
render_triangles ( v, front_surf, render_head,n, front,
|
|
forward, blonde, eye, clip_code );
|
|
}
|
|
else if (twosided) {
|
|
/* transition, prev were back, new is front-facing */
|
|
render_triangles ( v, back_surf, render_head, n, front^3,
|
|
forward, blonde, eye, clip_code );
|
|
}
|
|
render_head=w;
|
|
/*
|
|
now be careful with tristrips and front-backness - since every
|
|
other triangle alternates direction, we must force a direction
|
|
change in the drawer (NOT the shader) if an odd number of
|
|
triangles pops out of this
|
|
|
|
and remember that 'front' is bit-packed, and 2 indicates that
|
|
the polygons should be DRAWN forwards, 1 that they should be
|
|
SHADED forwards
|
|
*/
|
|
front^=((n&1)<<1);
|
|
n=0;
|
|
}
|
|
else if (n==14) {
|
|
if (last)
|
|
render_triangles ( v, front_surf, render_head,n, front,
|
|
forward, blonde, eye, clip_code );
|
|
else if (twosided)
|
|
render_triangles ( v, back_surf, render_head, n, front^3,
|
|
forward, blonde, eye, clip_code );
|
|
render_head=w;
|
|
n=0;
|
|
/* retain old value of front */
|
|
}
|
|
else {
|
|
n++;
|
|
w++;
|
|
b++;
|
|
bb--;
|
|
}
|
|
last=this;
|
|
}
|
|
|
|
if (last)
|
|
render_triangles ( v, front_surf,render_head, n, front,
|
|
forward, blonde, eye, clip_code );
|
|
else if (twosided)
|
|
render_triangles ( v, back_surf,render_head, n, front^3,
|
|
forward, blonde, eye, clip_code );
|
|
/*}}} */
|
|
}
|
|
else {
|
|
/*{{{ render polystrip*/
|
|
render_head=w;
|
|
|
|
while (bb) {
|
|
this=1&(*(int *) (&w->position[3]));
|
|
|
|
if (this!=last) {
|
|
if (last)
|
|
/* draw AND shade forwards */
|
|
render_triangles ( v, front_surf, render_head,n, 3,
|
|
forward, blonde, eye, clip_code );
|
|
else if (twosided)
|
|
/* draw AND shade backwards */
|
|
render_triangles ( v, back_surf, render_head, n, 0,
|
|
forward, blonde, eye, clip_code );
|
|
render_head=a;
|
|
n=0;
|
|
}
|
|
else if (n==14) {
|
|
if (last)
|
|
/* draw AND shade forwards */
|
|
render_triangles ( v,front_surf,render_head,n, 3,
|
|
forward, blonde, eye, clip_code );
|
|
else if (twosided)
|
|
/* draw AND shade backwards */
|
|
render_triangles ( v,back_surf,render_head,n, 0,
|
|
forward, blonde, eye, clip_code );
|
|
render_head=a;
|
|
n=0;
|
|
}
|
|
else {
|
|
n++;
|
|
w=a;
|
|
a=b;
|
|
b++;
|
|
bb--;
|
|
}
|
|
last=this;
|
|
}
|
|
|
|
if (last)
|
|
render_triangles ( v, front_surf,render_head, n, 3,
|
|
forward, blonde, eye, clip_code );
|
|
else if (twosided)
|
|
render_triangles ( v, back_surf,render_head, n, 0,
|
|
forward, blonde, eye, clip_code );
|
|
/*}}} */
|
|
}
|
|
}
|
|
screenbins=pushscreenbins;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void renderPmesh ( PATCH *p,*/
|
|
static int debug_pfs=0;
|
|
|
|
void renderPmesh ( PATCH *p,
|
|
MATRIX forward,
|
|
MATRIX back,
|
|
LIGHTSOURCE *blonde,
|
|
VIEW *eye,
|
|
MATERIAL *front_surf,
|
|
MATERIAL *back_surf,
|
|
int clip_code )
|
|
|
|
/*
|
|
pmesh rendering - a pmesh is stored as 2 VSTRIPs,
|
|
VSTRIP *head is the original, untransformed set of vertices
|
|
VSTRIP *tail is frigged as the connectivity list. The list contains
|
|
one VERTEX per triangle in the PMESH, and the X,Y,Z coordinates
|
|
are typecast into VERTEX pointers. Yes, this is wretched, but
|
|
*/
|
|
|
|
{
|
|
/*{{{ variables*/
|
|
VSTRIP *verts, *triangles;
|
|
register int opcode, bopcode;
|
|
register pxpl5tri_fn funky, bfunky;
|
|
register float material, bmaterial;
|
|
screenbin *pushscreenbins=screenbins;
|
|
|
|
/* VERTEX *vt; */
|
|
int *vti;
|
|
int i, texture;
|
|
register int twosided=(back_surf != NULL);
|
|
/*}}} */
|
|
|
|
/*{{{ init*/
|
|
verts=p->head;
|
|
texture=(verts->strip_shade&strip_shade_textured)!=0;
|
|
|
|
if (front_surf==NULL) {
|
|
no_surface(p);
|
|
return;
|
|
}
|
|
|
|
pxpl5izePatch ( p, front_surf, back_surf );
|
|
|
|
if (alpha_texture(front_surf, back_surf))
|
|
screenbins=trans_screenbins;
|
|
|
|
verts=p->head;
|
|
triangles=verts->next;
|
|
|
|
triangles=copy_pmesh_tris ( triangles, verts->head );
|
|
verts =copy_pmesh_verts ( verts );
|
|
/*}}} */
|
|
|
|
if (clip_code == 0) unclipped_patches++;
|
|
else clipped_patches++;
|
|
|
|
/* printf ("renderPmesh\n" ); */
|
|
|
|
fn_solve_pmesh ( &back[3][0], (float *) (triangles->head),
|
|
triangles->vertex_count, twosided,
|
|
eye->hither * 1.048e6 );
|
|
|
|
/*{{{ set up funky, bfunky etc*/
|
|
funky =front_surf->triangle_fn;
|
|
material=*(float *) &(front_surf->pxpl5codeword),
|
|
opcode =front_surf->pxpl5opcode;
|
|
|
|
if (twosided) {
|
|
bfunky =back_surf->triangle_fn;
|
|
bmaterial=*(float *) &(back_surf->pxpl5codeword),
|
|
bopcode =back_surf->pxpl5opcode;
|
|
}
|
|
/*}}} */
|
|
|
|
if ((clip_code & (clip_yon|clip_hither)) == 0) {
|
|
/*{{{ no z-clipping*/
|
|
/*{{{ */
|
|
int icoeff_p =(int) coefficient_ptr;
|
|
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
|
|
/*}}} */
|
|
|
|
unclipped_tris+=triangles->vertex_count;
|
|
|
|
fn_xform_light_project ( verts->head,
|
|
verts->vertex_count,
|
|
verts->strip_shade, 1,
|
|
eye, blonde, forward,
|
|
front_surf, 1 | (texture<<1),
|
|
front_surf->ks*255.0f, twosided==0 );
|
|
|
|
|
|
vti=(int *) triangles->head->position;
|
|
|
|
for (i=triangles->vertex_count; i; i--, vti+=(sizeof(VERTEX)>>2)) {
|
|
if (vti[3]&1) {
|
|
/*
|
|
if (debug_pfs<8) {
|
|
VERTEX *vt=(VERTEX *) vti[0];
|
|
|
|
printf ("vertex rgb=%f, %f, %f\n",
|
|
vt->normcol[0],
|
|
vt->normcol[1],
|
|
vt->normcol[2] );
|
|
debug_pfs++;
|
|
}
|
|
*/
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=icoeff_p + COEFF_FULL;
|
|
}
|
|
|
|
icoeff_p = funky ( icoeff_p,
|
|
material,
|
|
opcode,
|
|
vti[0],
|
|
vti[1],
|
|
vti[2] );
|
|
}
|
|
else if (twosided) {
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=icoeff_p + COEFF_FULL;
|
|
}
|
|
|
|
icoeff_p = bfunky ( icoeff_p,
|
|
bmaterial,
|
|
bopcode,
|
|
vti[2],
|
|
vti[1],
|
|
vti[0] );
|
|
}
|
|
}
|
|
coefficient_ptr=(float *) icoeff_p;
|
|
/*}}} */
|
|
}
|
|
else if ((clip_code & clip_hither) == 0) {
|
|
/*{{{ far clip only*/
|
|
int icoeff_p =(int) coefficient_ptr;
|
|
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
|
|
float proj_clip=eye->hither * 1.048576E+6 / eye->yon;
|
|
/* float proj_clip=eye->zscale*eye->d*1.04857588E+6 / eye->yon; */
|
|
|
|
fn_xform_light_project ( verts->head,
|
|
verts->vertex_count,
|
|
verts->strip_shade, 1,
|
|
eye, blonde, forward,
|
|
front_surf, 1 | (texture<<1),
|
|
front_surf->ks*255.0f, twosided==0 );
|
|
|
|
|
|
/* vt=triangles->head; */
|
|
vti=(int *) triangles->head->position;
|
|
|
|
for (i=triangles->vertex_count; i; i--, vti+=(sizeof(VERTEX)>>2)) {
|
|
int proceed=0;
|
|
|
|
VERTEX *va=(VERTEX *)(vti[0]);
|
|
VERTEX *vb=(VERTEX *)(vti[1]);
|
|
VERTEX *vc=(VERTEX *)(vti[2]);
|
|
|
|
if (va->position[2] > proj_clip) proceed=1;
|
|
if (vb->position[2] > proj_clip) proceed=1;
|
|
if (vc->position[2] > proj_clip) proceed=1;
|
|
|
|
|
|
if (proceed) {
|
|
farz_drawn_tris++;
|
|
|
|
/*{{{ do the triangle*/
|
|
if (vti[3]&1) {
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=icoeff_p + COEFF_FULL;
|
|
}
|
|
|
|
|
|
icoeff_p = funky ( icoeff_p,
|
|
material,
|
|
opcode,
|
|
vti[0],
|
|
vti[1],
|
|
vti[2] );
|
|
}
|
|
else if (twosided) {
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=icoeff_p + COEFF_FULL;
|
|
}
|
|
|
|
icoeff_p = bfunky ( icoeff_p,
|
|
bmaterial,
|
|
bopcode,
|
|
vti[2],
|
|
vti[1],
|
|
vti[0] );
|
|
}
|
|
/*}}} */
|
|
}
|
|
else {
|
|
farz_rejected_tris++;
|
|
}
|
|
}
|
|
coefficient_ptr=(float *) icoeff_p;
|
|
/*}}} */
|
|
}
|
|
else {
|
|
/*{{{ nasty, near clip*/
|
|
VERTEX *vt;
|
|
|
|
fn_xform_light_project ( verts->head,
|
|
verts->vertex_count,
|
|
verts->strip_shade, 1,
|
|
eye, blonde, forward, front_surf, 0,
|
|
front_surf->ks*255.0f, twosided==0 );
|
|
|
|
vt=triangles->head;
|
|
|
|
for (i=triangles->vertex_count; i; i--, vt++ ) {
|
|
int *ipos=(int *) vt->position;
|
|
if (ipos[3]&1) {
|
|
clipped_tris++;
|
|
pp5_clip_triangle ( verts,
|
|
(VERTEX *) (ipos[0]),
|
|
(VERTEX *) (ipos[1]),
|
|
(VERTEX *) (ipos[2]),
|
|
vt,
|
|
eye, 2, front_surf, texture, clip_code );
|
|
}
|
|
else if (twosided) {
|
|
clipped_tris++;
|
|
pp5_clip_triangle ( verts,
|
|
(VERTEX *) (ipos[2]),
|
|
(VERTEX *) (ipos[1]),
|
|
(VERTEX *) (ipos[0]),
|
|
vt,
|
|
eye, 2, back_surf, texture, clip_code );
|
|
}
|
|
}
|
|
/*}}} */
|
|
}
|
|
screenbins=pushscreenbins;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void renderSmesh ( PATCH *p,*/
|
|
void renderSmesh ( PATCH *p,
|
|
MATRIX forward,
|
|
MATRIX back,
|
|
LIGHTSOURCE *blonde,
|
|
VIEW *eye,
|
|
MATERIAL *front_surf,
|
|
MATERIAL *back_surf,
|
|
int clip_code )
|
|
|
|
{
|
|
/*{{{ variables*/
|
|
VSTRIP *verts;
|
|
register int opcode;
|
|
register pxpl5tri_fn funky;
|
|
register float material;
|
|
|
|
int icoeff_p =(int) coefficient_ptr;
|
|
int icoeff_base=COEFF_FULL + (int) last_coeffchunk;
|
|
|
|
VERTEX *vti, *vti0;
|
|
int i;
|
|
float scale_fac= sphere_scale;
|
|
/*}}} */
|
|
|
|
/*{{{ init*/
|
|
verts=p->head;
|
|
|
|
if (front_surf==NULL)
|
|
return;
|
|
|
|
pxpl5izeSpheres ( p, front_surf, back_surf );
|
|
|
|
verts=p->head;
|
|
verts =copy_pmesh_verts ( verts );
|
|
|
|
/*}}} */
|
|
/*{{{ set up funky, bfunky etc*/
|
|
funky = &sphere_zb_rgb;
|
|
material=*(float *) &(front_surf->pxpl5codeword);
|
|
opcode =front_surf->pxpl5opcode;
|
|
/*}}} */
|
|
|
|
/* printf ("renderSmesh\n" ); */
|
|
|
|
fn_xform_strip ( verts->head, forward, verts->vertex_count );
|
|
|
|
/*{{{ do lighting*/
|
|
/* drop diffuse component in */
|
|
verts->head->planeEqn[0]= 0.0f; /* sin(shading_frame/11.0f); */
|
|
verts->head->planeEqn[1]= 0.0f; /* 0.577f; */
|
|
verts->head->planeEqn[2]= -1.0f; /* cos(shading_frame/11.0f); */
|
|
|
|
{
|
|
float hyp, dx, dy, dz;
|
|
|
|
dx=verts->head->planeEqn[0];
|
|
dy=verts->head->planeEqn[1];
|
|
dz=verts->head->planeEqn[2];
|
|
|
|
hyp=1.0f/ sqrt(dx*dx + dy*dy + dz*dz );
|
|
|
|
verts->head->planeEqn[0]=dx*hyp;
|
|
verts->head->planeEqn[1]=dy*hyp;
|
|
verts->head->planeEqn[2]=dz*hyp;
|
|
}
|
|
|
|
/* drop specular component in */
|
|
verts->head->normcol[0]= sin(shading_frame/140.0f);
|
|
verts->head->normcol[1]=-0.577f;
|
|
verts->head->normcol[2]= cos(shading_frame/140.0f);
|
|
/*}}} */
|
|
|
|
vti=verts->head;
|
|
vti0=vti;
|
|
|
|
if ((clip_code & (clip_yon|clip_hither)) == 0) {
|
|
/*{{{ do all-in-one*/
|
|
project_spheres ( verts->head->position, eye,
|
|
verts->vertex_count,
|
|
sizeof(VERTEX) >> 2,
|
|
scale_fac );
|
|
|
|
for (i=verts->vertex_count; i; i--, vti++ ) {
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=icoeff_p + COEFF_FULL;
|
|
}
|
|
icoeff_p = funky ( icoeff_p,
|
|
material,
|
|
opcode,
|
|
vti,
|
|
vti0, /* this for lighting */
|
|
vti ); /* this not used */
|
|
}
|
|
/*}}} */
|
|
}
|
|
else {
|
|
for ( i=verts->vertex_count; i; i--, vti++ ) {
|
|
/*{{{ project + draw one sphere*/
|
|
if ((vti->position[2] - vti->position[3]) > eye->hither) {
|
|
project_spheres ( vti->position, eye,
|
|
1, sizeof(VERTEX) >> 2,
|
|
scale_fac );
|
|
|
|
if (icoeff_p > icoeff_base) {
|
|
icoeff_p=(int) next_coeffchunk ();
|
|
icoeff_base=icoeff_p + COEFF_FULL;
|
|
}
|
|
|
|
icoeff_p = funky ( icoeff_p,
|
|
material,
|
|
opcode,
|
|
vti,
|
|
vti0, /* this for lighting */
|
|
vti ); /* this not used */
|
|
}
|
|
/*}}} */
|
|
}
|
|
}
|
|
|
|
coefficient_ptr=(float *) icoeff_p;
|
|
}
|
|
/*}}} */
|
|
|
|
/*{{{ static void render_all_patches ( patch_render_chunk *patch_head )*/
|
|
static void render_all_patches ( patch_render_chunk *patch_head )
|
|
{
|
|
MATERIAL stack_f, *pf,
|
|
stack_b, *pb;
|
|
|
|
register int my_id=_processorId;
|
|
|
|
/* printf ("render_all_patches, patch_head=0x%x\n", patch_head ); */
|
|
|
|
for (; patch_head; patch_head=patch_head->next ) {
|
|
register int pcount =patch_head->patch_count;
|
|
register char *pchar=patch_head->patch_data;
|
|
|
|
if (pcount==0)
|
|
return;
|
|
|
|
while (pcount) {
|
|
register patch_render_rec *p=(patch_render_rec *) pchar;
|
|
#if 0
|
|
/*{{{ */
|
|
SemWait (&p->sem, my_id);
|
|
|
|
if (p->rendered)
|
|
SemSignal(&p->sem, my_id);
|
|
else {
|
|
p->rendered=1;
|
|
SemSignal(&p->sem, my_id);
|
|
|
|
}
|
|
|
|
/*}}} */
|
|
#endif
|
|
/*{{{ deal with materials*/
|
|
|
|
if (p->front_mtl) {
|
|
memcpy ( &stack_f, p->front_mtl, sizeof(MATERIAL));
|
|
pf=&stack_f;
|
|
}
|
|
else
|
|
pf=NULL;
|
|
|
|
if (p->back_mtl) {
|
|
memcpy ( &stack_b, p->back_mtl, sizeof(MATERIAL));
|
|
pb=&stack_b;
|
|
}
|
|
else
|
|
pb=NULL;
|
|
|
|
stack_f.tex=p->front_tex;
|
|
stack_b.tex=p->back_tex;
|
|
/*}}} */
|
|
|
|
sphere_scale=p->sphere_scale;
|
|
|
|
/* printf ("pcount=%d, render patch 0x%x\n", pcount, p->p ); */
|
|
|
|
p->render_me( p->p,
|
|
p->forward, p->back,
|
|
p->blonde, p->eye,
|
|
pf, pb,
|
|
p->clip_code );
|
|
|
|
pcount--;
|
|
pchar+=patch_bump_val;
|
|
}
|
|
}
|
|
}
|
|
/*}}} */
|
|
/*{{{ int render_displaylist ( int left_eye )*/
|
|
static int renders=0;
|
|
|
|
int render_displaylist ( int left_eye )
|
|
{
|
|
int pthen, pnow;
|
|
screenbin *pushscreen =screenbins;
|
|
screenbin *pushtscreen=trans_screenbins;
|
|
|
|
/* printf ("render_displaylist\n" ); */
|
|
|
|
renders++;
|
|
|
|
if (left_eye==0) {
|
|
/* printf ("left_eye==0, doing right eye bin stuff\n" ); */
|
|
screenbins=screenrbins;
|
|
trans_screenbins=trans_screenrbins;
|
|
}
|
|
|
|
dN_timer(&pthen);
|
|
|
|
if (shared_cntl->patch_list_active) {
|
|
/* printf ("shared_cntl patch_list_active, sorting out patch list\n" ); */
|
|
/*{{{ sort out patch list*/
|
|
/*
|
|
the patch traverser stops on a NULL next, OR on a zero
|
|
patch count, so plonk a zero into next->patch_count
|
|
*/
|
|
|
|
shared_cntl->patch_list_active->patch_count=shared_cntl->patch_count;
|
|
|
|
if (shared_cntl->patch_count) {
|
|
patch_render_chunk *next=shared_cntl->patch_list_active->next;
|
|
if (next)
|
|
next->patch_count=0;
|
|
}
|
|
/*}}} */
|
|
|
|
/* printf ("render_all_patches\n" ); */
|
|
render_all_patches( shared_cntl->patch_list_head );
|
|
/* printf ("rendered_all_patches, unsort patch list\n" ); */
|
|
|
|
/*{{{ unsort out patch list*/
|
|
shared_cntl->patch_list_active=shared_cntl->patch_list_head;
|
|
shared_cntl->patch_count=0;
|
|
shared_cntl->patch_usage=0;
|
|
shared_cntl->free_patch_rec=&shared_cntl->patch_list_active->patch_data[0];
|
|
/*}}} */
|
|
|
|
/* printf ("rendered_all_patches, unsort light list\n" ); */
|
|
|
|
/*{{{ unsort out light list*/
|
|
shared_cntl->light_list_active=shared_cntl->light_list_head;
|
|
shared_cntl->light_count=0;
|
|
shared_cntl->light_usage=0;
|
|
shared_cntl->free_light_rec=&shared_cntl->light_list_active->light_data[0];
|
|
/*}}} */
|
|
}
|
|
|
|
dN_timer(&pnow);
|
|
|
|
if (left_eye==0) {
|
|
screenbins=pushscreen;
|
|
trans_screenbins=pushtscreen;
|
|
}
|
|
|
|
return (pnow-pthen);
|
|
}
|
|
/*}}} */
|
|
|
|
static int first_framebuf_y = 0,
|
|
framebuf_flip = 4,
|
|
second_screen_flip=16;
|
|
|
|
static screenbin *prevBin=NULL;
|
|
static int prevX,
|
|
prevY;
|
|
|
|
/*{{{ 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=0;
|
|
|
|
/*{{{ 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;
|
|
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_TEX_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,
|
|
renders == 1 );
|
|
|
|
if (renders > 1) {
|
|
stereo=1;
|
|
strap_up_transptiles ( x_display_tiles, y_display_tiles,
|
|
screenrbins, trans_screenrbins,
|
|
first_framebuf_y^second_screen_flip,
|
|
1 );
|
|
}
|
|
|
|
renders=0;
|
|
/*}}} */
|
|
|
|
/*{{{ 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;
|
|
|
|
#if 1
|
|
/*{{{ print rendering speed*/
|
|
if ((then == 0) && (now == 0)) {
|
|
dN_timer (&then);
|
|
}
|
|
else {
|
|
int usecs;
|
|
extern int _dN_transactions;
|
|
|
|
timing_frames++;
|
|
|
|
if (replying && (timing_frames==40)) {
|
|
dN_timer (&now);
|
|
|
|
usecs=((now - then) / timing_frames);
|
|
then=now;
|
|
|
|
printf ("%f (cull %d stereo=%d)\n",
|
|
rendering_frame_rate=(1.0e6f / (float) usecs),
|
|
cull_pass_microsex,
|
|
stereo );
|
|
printf ("%d unclp_p %d clp_p %d unclp_t %d clp_t %d zrej_t %d zacpt\n",
|
|
unclipped_patches,
|
|
clipped_patches,
|
|
unclipped_tris,
|
|
clipped_tris,
|
|
farz_rejected_tris,
|
|
farz_drawn_tris );
|
|
|
|
timing_frames=0;
|
|
}
|
|
rendered_frames++;
|
|
}
|
|
/*}}} */
|
|
#endif
|
|
|
|
multisync();
|
|
}
|
|
else {
|
|
multisync();
|
|
}
|
|
|
|
/*}}} */
|
|
start_frame_stats();
|
|
/*{{{ flip all buffer space*/
|
|
|
|
if (screenbins == screen0bins) {
|
|
screenbins =screen1bins;
|
|
screenrbins=screenr1bins;
|
|
trans_screenbins =trans_screen1bins;
|
|
trans_screenrbins=trans_screenr1bins;
|
|
}
|
|
else if (screenbins == screen1bins) {
|
|
screenbins =screen0bins;
|
|
screenrbins=screenr0bins;
|
|
trans_screenbins =trans_screen0bins;
|
|
trans_screenrbins=trans_screenr0bins;
|
|
}
|
|
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 (stereo) {
|
|
liberate_screenbins ( screenrbins, 1024, 768 );
|
|
liberate_screenbins ( trans_screenrbins, 1024, 768 );
|
|
}
|
|
|
|
if (lastcoeffptr == 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;
|
|
|
|
/*}}} */
|
|
|
|
debug_pfs=0;
|
|
}
|
|
/*}}} */
|
|
/*{{{ void flip_screens( int me, int nodes )*/
|
|
|
|
void flip_screens( int me, int nodes )
|
|
{
|
|
int xd, yd, back_c;
|
|
|
|
shading_frame+=1.0f;
|
|
|
|
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++=cptr;
|
|
*ptr++=DMA_FLUSH_VAL;
|
|
|
|
*ptr++=cptr;
|
|
*ptr++=DMA_FLUSH_VAL;
|
|
|
|
*ptr++=cptr0;
|
|
*ptr++=DMA_SEND_VAL | 16;
|
|
|
|
*ptr++=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()*/
|
|
|
|
extern int getFsr ( void );
|
|
extern void setFsr ( int fsr );
|
|
extern float second_ ( void);
|
|
extern int give_fp ( void );
|
|
extern float fn_inv ( float p );
|
|
|
|
MATERIAL *mdefault;
|
|
|
|
int inited=0;
|
|
texcell *fx_cell;
|
|
|
|
void render_init( int x_size, int y_size )
|
|
{
|
|
int i, j;
|
|
int *p;
|
|
float then, now;
|
|
int *time_end_of_frame;
|
|
|
|
multisync();
|
|
|
|
if (inited == 0) {
|
|
int fsr;
|
|
inited=1;
|
|
|
|
longest_strip.head=NULL;
|
|
longest_verts.head=NULL;
|
|
longest_tris.head=NULL;
|
|
|
|
texture_ramps=(TEXRAMP *) malloc(MAX_TEX_RAMPS*sizeof(TEXRAMP));
|
|
|
|
ambient_value=120;
|
|
|
|
setRampEntry ( 0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0 );
|
|
setRampEntry ( 1, 0.3, 0.0, 0.0, 1.0, 1.0, 0.9 );
|
|
setRampEntry ( 2, 0.0, 0.5, 0.0, 1.0, 1.0, 1.0 );
|
|
setRampEntry ( 3, 0.0, 0.0, 0.4, 0.9, 0.9, 1.0 );
|
|
|
|
texInit ();
|
|
|
|
/* grab 1st 64x64 texture as flame holding thing */
|
|
/* fx_cell=allocateHSPtexture( 64, 64 ); */
|
|
|
|
|
|
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 ();
|
|
|
|
sceneGeometry.head=NULL;
|
|
sceneGeometry.tail=NULL;
|
|
|
|
mdefault = create_material ();
|
|
add_material(mdefault);
|
|
|
|
mdefault=newName ( mdefault, viz_createMaterial );
|
|
|
|
if (_processorId==0) {
|
|
/* printf ("render_init shared_cntl at 0x%x\n", shared_cntl ); */
|
|
|
|
shared_cntl->patch_list_head=NULL;
|
|
shared_cntl->light_list_head=NULL;
|
|
|
|
shared_cntl->length_longest_strip=0;
|
|
shared_cntl->length_longest_verts=0;
|
|
shared_cntl->length_longest_tris =0;
|
|
|
|
shared_cntl->patch_list_active=NULL;
|
|
shared_cntl->light_list_active=NULL;
|
|
|
|
shared_cntl->patch_usage=0;
|
|
shared_cntl->light_usage=0;
|
|
|
|
shared_cntl->patch_count=0;
|
|
shared_cntl->light_count=0;
|
|
|
|
shared_cntl->free_patch_rec=NULL;
|
|
shared_cntl->free_light_rec=NULL;
|
|
|
|
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 );
|
|
|
|
/* patch list startup */
|
|
shared_cntl->patch_list_head =(patch_render_chunk *) newBytes(4096);
|
|
shared_cntl->patch_list_active=shared_cntl->patch_list_head;
|
|
shared_cntl->patch_list_active->next=NULL;
|
|
shared_cntl->patch_count=0;
|
|
shared_cntl->patch_usage=0;
|
|
shared_cntl->free_patch_rec=shared_cntl->patch_list_active->patch_data;
|
|
|
|
/* light list startup */
|
|
shared_cntl->light_list_head =(light_render_chunk *) newBytes(4096);
|
|
shared_cntl->light_list_active=shared_cntl->light_list_head;
|
|
shared_cntl->light_list_active->next=NULL;
|
|
shared_cntl->light_count=0;
|
|
shared_cntl->light_usage=0;
|
|
shared_cntl->free_light_rec=shared_cntl->light_list_active->light_data;
|
|
|
|
multisync();
|
|
}
|
|
else
|
|
multisync();
|
|
|
|
/*
|
|
if ((_processorId==0) && (output_device!=pxpl5_device))
|
|
printf ( "Warning : device type not pxpl5_device (0x%x 0x%x)\n",
|
|
output_device, pxpl5_device );
|
|
*/
|
|
|
|
flipper = &pxpl5_flip;
|
|
|
|
#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 ("screenr0bins=0x%x\n", screenr0bins );
|
|
printf ("screenr1bins=0x%x\n", screenr1bins );
|
|
printf ("and screenbins=0x%x\n", screenbins );
|
|
*/
|
|
|
|
multisync();
|
|
|
|
}
|
|
}
|
|
/*}}} */
|