brender-v1.1.2/ZB/ZBMESH.C
2022-05-04 18:14:23 -07:00

1695 lines
39 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved.
*
* $Id: zbmesh.c 1.67 1995/08/31 16:47:54 sam Exp $
* $Locker: $
*
* Mesh rendering to produce faces
*/
#include "zb.h"
#include "shortcut.h"
#include "blockops.h"
#include "brassert.h"
static char rscid[] = "$Id: zbmesh.c 1.67 1995/08/31 16:47:54 sam Exp $";
#define SHOW_REVERSED 0
#if BASED_FIXED
#define FAST_PROJECT 1
#define FAST_CULL 1
#endif
#if BASED_FLOAT
#define FAST_PROJECT 0
#define FAST_CULL 0
#endif
STATIC void ClearDirections(void)
{
int v;
for(v=0; v< zb.model->nprepared_vertices; v++) {
zb.temp_vertices[v].direction = 0;
}
zb.directions_cleared = 1;
}
/*
* Find out which faces in mesh are towards eye
*
* Accumulate a count of visible faces per group
*/
void ZbFindVisibleFaces(void)
{
int f,g,n,df;
br_face *fp = zb.model->prepared_faces;
br_face_group *gp = zb.model->face_groups;
struct temp_face *tfp = zb.temp_faces;
for(g=0; g < zb.model->nface_groups; g++, gp++) {
/*
* Record the material to use for each group
*/
zb.material = (gp->material?gp->material:zb.default_material);
if(zb.material->flags & BR_MATF_TWO_SIDED) {
/*
* Work out which side of face is visible
*/
if(!zb.directions_cleared)
ClearDirections();
for(f=0,n=0; f < gp->nfaces; f++, fp++, tfp++) {
tfp->flag = TFF_VISIBLE;
df = TVDIR_FRONT;
/*
* if Plane_Eqn . Eye <= 0, face is away from eye
*/
if(BrFVector3Dot(&fp->n,&fw.eye_m) < fp->d) {
tfp->flag |= TFF_REVERSED;
df = TVDIR_BACK;
}
zb.vertex_counts[fp->vertices[0]]++;
zb.vertex_counts[fp->vertices[1]]++;
zb.vertex_counts[fp->vertices[2]]++;
zb.temp_vertices[fp->vertices[0]].direction |= df;
zb.temp_vertices[fp->vertices[1]].direction |= df;
zb.temp_vertices[fp->vertices[2]].direction |= df;
}
zb.face_group_counts[g] = gp->nfaces;
} else if(zb.material->flags & BR_MATF_ALWAYS_VISIBLE) {
/*
* Don't check visibility of face
*/
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
tfp->flag = TFF_VISIBLE;
zb.vertex_counts[fp->vertices[0]]++;
zb.vertex_counts[fp->vertices[1]]++;
zb.vertex_counts[fp->vertices[2]]++;
}
zb.face_group_counts[g] = gp->nfaces;
} else {
/*
* Check plane eqn. of every face in group against the eye
*/
for(f=0,n=0; f < gp->nfaces; f++, fp++, tfp++) {
/*
* if Plane_Eqn . Eye <= 0, face is away from eye
*/
if(BrFVector3Dot(&fp->n,&fw.eye_m) < fp->d) {
tfp->flag = 0;
continue;
}
tfp->flag = TFF_VISIBLE;
zb.vertex_counts[fp->vertices[0]]++;
zb.vertex_counts[fp->vertices[1]]++;
zb.vertex_counts[fp->vertices[2]]++;
n++;
}
zb.face_group_counts[g] = n;
}
}
}
void ZbFindVisibleFacesPar(void)
{
int f,g,n,df;
br_face *fp = zb.model->prepared_faces;
br_face_group *gp = zb.model->face_groups;
struct temp_face *tfp = zb.temp_faces;
for(g=0; g < zb.model->nface_groups; g++, gp++) {
/*
* Recored the material to use for each group
*/
zb.material = (gp->material?gp->material:zb.default_material);
if(zb.material->flags & BR_MATF_TWO_SIDED) {
/*
* Work out which side of face is visible
*/
if(!zb.directions_cleared)
ClearDirections();
for(f=0,n=0; f < gp->nfaces; f++, fp++, tfp++) {
tfp->flag = TFF_VISIBLE;
df = TVDIR_FRONT;
/*
* if Plane_Eqn . Eye <= 0, face is away from eye
*/
if(BrFVector3Dot(&fp->n,&fw.eye_m) < S0) {
tfp->flag |= TFF_REVERSED;
df = TVDIR_BACK;
}
zb.vertex_counts[fp->vertices[0]]++;
zb.vertex_counts[fp->vertices[1]]++;
zb.vertex_counts[fp->vertices[2]]++;
zb.temp_vertices[fp->vertices[0]].direction |= df;
zb.temp_vertices[fp->vertices[1]].direction |= df;
zb.temp_vertices[fp->vertices[2]].direction |= df;
}
zb.face_group_counts[g] = gp->nfaces;
} else if(zb.material->flags & BR_MATF_ALWAYS_VISIBLE) {
/*
* Two sided faces always face the eye
*/
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
tfp->flag = TFF_VISIBLE;
zb.vertex_counts[fp->vertices[0]]++;
zb.vertex_counts[fp->vertices[1]]++;
zb.vertex_counts[fp->vertices[2]]++;
}
zb.face_group_counts[g] = gp->nfaces;
} else {
/*
* Check plane eqn. of every face in group against the eye
*/
for(f=0,n=0; f < gp->nfaces; f++, fp++, tfp++) {
/*
* if Plane_Eqn . Eye <= 0, face is away from eye
*/
if(BrFVector3Dot(&fp->n,&fw.eye_m) < S0) {
tfp->flag = 0;
continue;
}
tfp->flag = TFF_VISIBLE;
zb.vertex_counts[fp->vertices[0]]++;
zb.vertex_counts[fp->vertices[1]]++;
zb.vertex_counts[fp->vertices[2]]++;
n++;
}
zb.face_group_counts[g] = n;
}
}
}
/*
* Transform, project & outcode vertices
*
*/
void ZbTransformVertices(void)
{
int i,c;
struct temp_vertex *tvp;
br_vector4 screen;
tvp = zb.temp_vertices;
for(i=0; i < zb.model->nprepared_vertices; i++, tvp++) {
/*
* Ignore if not visible
*/
if(zb.vertex_counts[i] == 0)
continue;
/*
* Transform into screen space
*/
BrMatrix4ApplyP(&screen,&zb.model->prepared_vertices[i].p,&fw.model_to_screen);
tvp->comp[C_X] = screen.v[X];
tvp->comp[C_Y] = screen.v[Y];
tvp->comp[C_Z] = screen.v[Z];
tvp->comp[C_W] = screen.v[W];
OUTCODE_POINT(tvp->outcode, &screen);
/*
* Project if inside clip volume
*/
if(!(tvp->outcode & OUTCODES_ALL)) {
PROJECT_VERTEX(tvp,screen.v[X],screen.v[Y],screen.v[Z],screen.v[W]);
UPDATE_BOUNDS(*tvp);
}
}
}
/*
* Do per face work - find all the faces that are on screen
*/
STATIC void ZbFindFacesAndVertices(void)
{
int f,g,j;
br_face *fp = zb.model->prepared_faces;
br_face_group *gp = zb.model->face_groups;
struct temp_face *tfp = zb.temp_faces;
br_uint_32 combined_codes;
for(g=0; g < zb.model->nface_groups; g++, gp++) {
/*
* Skip group if it is not visible
*/
if(zb.face_group_counts[g] == 0) {
fp += gp->nfaces;
tfp += gp->nfaces;
continue;
}
zb.material = (gp->material?gp->material:zb.default_material);
if(zb.material->prep_flags & MATUF_SURFACE_FACES)
SurfacePerMaterial(zb.material);
for(f=0; f < gp->nfaces; f++,fp++,tfp++) {
if(!tfp->flag)
continue;
/*
* Work out AND/OR of outcodes
*/
combined_codes = zb.temp_vertices[fp->vertices[0]].outcode |
zb.temp_vertices[fp->vertices[1]].outcode |
zb.temp_vertices[fp->vertices[2]].outcode;
/*
* If completely of one edge of view volume (by outcodes)
* mark as not visible
* continue
*/
if((combined_codes & OUTCODES_NOT) != OUTCODES_NOT) {
zb.face_group_counts[g]--;
tfp->flag = 0;
zb.vertex_counts[fp->vertices[0]]--;
zb.vertex_counts[fp->vertices[1]]--;
zb.vertex_counts[fp->vertices[2]]--;
continue;
}
/*
* If any outcode is set - mark as needing clipping and remember combined codes
*/
if(combined_codes & OUTCODES_ALL) {
tfp->flag |= TFF_CLIPPED;
tfp->codes = combined_codes & OUTCODES_ALL;
zb.face_group_clipped[g] = 1;
}
/*
* Face will be rendered
*/
/*
* Do lighting for face if required
*/
if(zb.material->prep_flags & MATUF_SURFACE_FACES)
tfp->surface = fw.face_surface_fn(zb.model->prepared_vertices+fp->vertices[0],fp,tfp->flag & TFF_REVERSED);
}
}
}
/*
* Render a clipped face using the indiciated callback for triangle rendering
*/
STATIC void ZbFaceRender(struct clip_vertex *cp_in, int n)
{
int j;
struct temp_vertex tv[3],*tvp1,*tvp2,*tvpt;
/*
* Render face
*/
for(j=0; j < 2; j++, cp_in++) {
PROJECT_VERTEX(tv+j,cp_in->comp[C_X],cp_in->comp[C_Y],cp_in->comp[C_Z],cp_in->comp[C_W]);
UPDATE_BOUNDS(tv[j]);
#if !BASED_FIXED
ZbConvertComponents((br_fixed_ls *)tv[j].comp,cp_in->comp,zb.convert_mask);
#else
tv[j].comp[C_W] = cp_in->comp[C_W];
tv[j].comp[C_I] = cp_in->comp[C_I];
tv[j].comp[C_U] = cp_in->comp[C_U];
tv[j].comp[C_V] = cp_in->comp[C_V];
tv[j].comp[C_R] = cp_in->comp[C_R];
tv[j].comp[C_G] = cp_in->comp[C_G];
tv[j].comp[C_B] = cp_in->comp[C_B];
#endif
}
tvp1 = tv+1;
tvp2 = tv+2;
for(j = 2; j < n; j++, cp_in++) {
PROJECT_VERTEX(tvp2,cp_in->comp[C_X],cp_in->comp[C_Y],cp_in->comp[C_Z],cp_in->comp[C_W]);
UPDATE_BOUNDS(*tvp2);
#if !BASED_FIXED
ZbConvertComponents((br_fixed_ls *)tvp2->comp,cp_in->comp,zb.convert_mask);
#else
tvp2->comp[C_W] = cp_in->comp[C_W];
tvp2->comp[C_I] = cp_in->comp[C_I];
tvp2->comp[C_U] = cp_in->comp[C_U];
tvp2->comp[C_V] = cp_in->comp[C_V];
tvp2->comp[C_R] = cp_in->comp[C_R];
tvp2->comp[C_G] = cp_in->comp[C_G];
tvp2->comp[C_B] = cp_in->comp[C_B];
#endif
zb.triangle_render((struct temp_vertex_fixed *)tv,
(struct temp_vertex_fixed *)tvp1,
(struct temp_vertex_fixed *)tvp2);
tvpt = tvp1; tvp1 = tvp2; tvp2 = tvpt;
}
}
/*
* Render visible faces with clipping
*/
STATIC void ZbRenderFaces(void)
{
br_face_group *gp = zb.model->face_groups;
struct temp_face *tfp = zb.temp_faces;
struct clip_vertex *clipped;
int g;
struct zb_material_type *zbmt;
/*
* Loop for each group
*/
for(g=0; g < zb.model->nface_groups; g++, gp++) {
/*
* Skip group if it is not visible
*/
if(zb.face_group_counts[g] == 0) {
tfp += gp->nfaces;
continue;
}
zb.material = (gp->material?gp->material:zb.default_material);
/*
* Extract various bits of info from material type
*/
ASSERT(zb.material->rptr != NULL);
zbmt = zb.material->rptr;
zb.triangle_render = zbmt->triangle;
zb.clip_mask = zbmt->clip_mask;
#if !BASED_FIXED
zb.convert_mask = zbmt->convert_mask;
#endif
if(zb.material->colour_map)
zb.texture_buffer = zb.material->colour_map->pixels;
if(zb.material->index_shade)
zb.shade_table = zb.material->index_shade->pixels;
/*
* Call the face group render function
*/
zbmt->face_group(gp,tfp);
tfp += gp->nfaces;
}
}
/*
* Render a group of faces
*/
void BR_ASM_CALL ZbRenderFaceGroup(br_face_group *gp,struct temp_face *tfp)
{
br_face *fp;
struct clip_vertex *clipped;
int f,g,nclipped;
struct zb_material_type *zbmt;
int i;
struct temp_vertex *tvp,tv[3];
br_vertex *vp;
br_fvector3 rev_normal;
if((zb.material->flags & BR_MATF_TWO_SIDED) && (zb.material->prep_flags & MATUF_SURFACE_VERTICES)) {
SurfacePerMaterial(zb.material);
}
/*
* Go through each face in loop
*/
for(f=0, fp=gp->faces ; f < gp->nfaces; f++,fp++, tfp++) {
switch(tfp->flag) {
/*
* Face is not on screen at all
*/
case 0:
continue;
/*
* Back of face is visible
*/
case TFF_VISIBLE | TFF_REVERSED:
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES) {
/*
* If any ov the vertices are used in both directions -
* relight them with corect normal
*/
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i] = *tvp;
if(tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) {
vp = zb.model->vertices+fp->vertices[i];
BrFVector3Negate(&rev_normal, &vp->n);
fw.surface_fn(vp,&rev_normal,tv[i].comp);
}
#if !BASED_FIXED
ZbConvertComponents((br_fixed_ls *)tv[i].comp,tvp->comp,zb.convert_mask);
#endif
}
zb.triangle_render((struct temp_vertex_fixed *)tv+0,
(struct temp_vertex_fixed *)tv+1,
(struct temp_vertex_fixed *)tv+2);
break;
}
/* ELSE FALL THROUGH */
/*
* Face is fully on screen
*/
case TFF_VISIBLE:
/*
* Render face
*/
#if !BASED_FIXED
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i].v[X] = tvp->v[X];
tv[i].v[Y] = tvp->v[Y];
tv[i].v[Z] = tvp->v[Z];
ZbConvertComponents((br_fixed_ls *)tv[i].comp,tvp->comp,zb.convert_mask);
}
zb.triangle_render((struct temp_vertex_fixed *)tv+0,
(struct temp_vertex_fixed *)tv+1,
(struct temp_vertex_fixed *)tv+2);
#else
zb.triangle_render((struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[0],
(struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[1],
(struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[2]);
#endif
break;
case TFF_VISIBLE | TFF_CLIPPED | TFF_REVERSED:
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES) {
/*
* If any ov the vertices are used in both directions -
* relight them with corect normal
*/
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i] = *tvp;
if(tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) {
vp = zb.model->vertices+fp->vertices[i];
BrFVector3Negate(&rev_normal, &vp->n);
fw.surface_fn(vp,&rev_normal,tv[i].comp);
}
}
if((clipped = ZbTempClip(tv,tfp,zb.clip_mask,&nclipped))) {
ZbFaceRender(clipped,nclipped);
}
break;
}
/* ELSE FALL THROUGH */
/*
* Face is partially on screen
*/
case TFF_VISIBLE | TFF_CLIPPED:
if((clipped = ZbFaceClip(fp,tfp,zb.clip_mask,&nclipped))) {
ZbFaceRender(clipped,nclipped);
}
break;
}
}
}
/*
* Render a group of faces - Set the current I value from the face
*/
void BR_ASM_CALL ZbRenderFaceGroup_FaceI(br_face_group *gp, struct temp_face *tfp)
{
br_face *fp;
struct clip_vertex *clipped;
int f,g,nclipped;
struct zb_material_type *zbmt;
int i;
struct temp_vertex tv[3],*tvp;
br_vertex *vp;
br_fvector3 rev_normal;
if((zb.material->flags & BR_MATF_TWO_SIDED) && (zb.material->prep_flags & MATUF_SURFACE_VERTICES)) {
SurfacePerMaterial(zb.material);
}
/*
* Go through each face in loop
*/
for(f=0, fp=gp->faces ; f < gp->nfaces; f++,fp++, tfp++) {
switch(tfp->flag) {
/*
* Face is not on screen at all
*/
case 0:
continue;
case TFF_VISIBLE | TFF_REVERSED:
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES) {
zb.pi.current = BrIntToFixed(tfp->surface);
/*
* If any ov the vertices are used in both directions -
* relight them with corect normal
*/
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i] = *tvp;
if(tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) {
vp = zb.model->vertices+fp->vertices[i];
BrFVector3Negate(&rev_normal, &vp->n);
fw.surface_fn(vp,&rev_normal,tv[i].comp);
}
#if !BASED_FIXED
ZbConvertComponents((br_fixed_ls *)tv[i].comp,tvp->comp,zb.convert_mask);
#endif
}
zb.triangle_render((struct temp_vertex_fixed *)tv+0,
(struct temp_vertex_fixed *)tv+1,
(struct temp_vertex_fixed *)tv+2);
break;
}
/* ELSE FALL THROUGH */
/*
* Face is fully on screen
*/
case TFF_VISIBLE:
/*
* Render face
*/
zb.pi.current = BrIntToFixed(tfp->surface);
#if !BASED_FIXED
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i].v[X] = tvp->v[X];
tv[i].v[Y] = tvp->v[Y];
tv[i].v[Z] = tvp->v[Z];
ZbConvertComponents((br_fixed_ls *)tv[i].comp,tvp->comp,zb.convert_mask);
}
zb.triangle_render((struct temp_vertex_fixed *)tv+0,
(struct temp_vertex_fixed *)tv+1,
(struct temp_vertex_fixed *)tv+2);
#else
zb.triangle_render((struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[0],
(struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[1],
(struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[2]);
#endif
break;
case TFF_VISIBLE | TFF_CLIPPED | TFF_REVERSED:
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES) {
/*
* If any ov the vertices are used in both directions -
* relight them with corect normal
*/
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i] = *tvp;
if(tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) {
vp = zb.model->vertices+fp->vertices[i];
BrFVector3Negate(&rev_normal, &vp->n);
fw.surface_fn(vp,&rev_normal,tv[i].comp);
}
}
if((clipped = ZbTempClip(tv,tfp,zb.clip_mask,&nclipped))) {
zb.pi.current = BrIntToFixed(tfp->surface);
ZbFaceRender(clipped,nclipped);
}
break;
}
/* ELSE FALL THROUGH */
/*
* Face is partially on screen
*/
case TFF_VISIBLE | TFF_CLIPPED:
if((clipped = ZbFaceClip(fp,tfp,zb.clip_mask,&nclipped))) {
zb.pi.current = BrIntToFixed(tfp->surface);
ZbFaceRender(clipped,nclipped);
}
break;
}
}
}
/*
* Render a group of faces - Set the current I value for each
* vertex from the face
*/
void BR_ASM_CALL ZbRenderFaceGroup_FaceIV(br_face_group *gp, struct temp_face *tfp)
{
br_face *fp;
struct clip_vertex *clipped;
int f,g,nclipped;
struct zb_material_type *zbmt;
br_scalar ci;
int i;
struct temp_vertex tv[3],*tvp;
br_vertex *vp;
br_fvector3 rev_normal;
/*
* Go through each face in loop
*/
for(f=0, fp=gp->faces ; f < gp->nfaces; f++,fp++, tfp++) {
switch(tfp->flag) {
/*
* Face is not on screen at all
*/
case 0:
continue;
case TFF_VISIBLE | TFF_REVERSED:
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES) {
ci = BrIntToScalar(tfp->surface);
zb.temp_vertices[fp->vertices[0]].comp[C_I] = ci;
zb.temp_vertices[fp->vertices[1]].comp[C_I] = ci;
zb.temp_vertices[fp->vertices[2]].comp[C_I] = ci;
/*
* If any ov the vertices are used in both directions -
* relight them with corect normal
*/
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i] = *tvp;
if(tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) {
vp = zb.model->vertices+fp->vertices[i];
BrFVector3Negate(&rev_normal, &vp->n);
fw.surface_fn(vp,&rev_normal,tv[i].comp);
}
#if !BASED_FIXED
ZbConvertComponents((br_fixed_ls *)tv[i].comp,tvp->comp,zb.convert_mask);
#endif
}
zb.triangle_render((struct temp_vertex_fixed *)tv+0,
(struct temp_vertex_fixed *)tv+1,
(struct temp_vertex_fixed *)tv+2);
break;
}
/* ELSE FALL THROUGH */
/*
* Face is fully on screen
*/
case TFF_VISIBLE:
/*
* Render face
*/
ci = BrIntToScalar(tfp->surface);
zb.temp_vertices[fp->vertices[0]].comp[C_I] = ci;
zb.temp_vertices[fp->vertices[1]].comp[C_I] = ci;
zb.temp_vertices[fp->vertices[2]].comp[C_I] = ci;
#if !BASED_FIXED
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i].v[X] = tvp->v[X];
tv[i].v[Y] = tvp->v[Y];
tv[i].v[Z] = tvp->v[Z];
ZbConvertComponents((br_fixed_ls *)tv[i].comp,tvp->comp,zb.convert_mask);
}
zb.triangle_render((struct temp_vertex_fixed *)tv+0,
(struct temp_vertex_fixed *)tv+1,
(struct temp_vertex_fixed *)tv+2);
#else
zb.triangle_render((struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[0],
(struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[1],
(struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[2]);
#endif
break;
case TFF_VISIBLE | TFF_CLIPPED | TFF_REVERSED:
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES) {
ci = BrIntToScalar(tfp->surface);
zb.temp_vertices[fp->vertices[0]].comp[C_I] = ci;
zb.temp_vertices[fp->vertices[1]].comp[C_I] = ci;
zb.temp_vertices[fp->vertices[2]].comp[C_I] = ci;
/*
* If any ov the vertices are used in both directions -
* relight them with corect normal
*/
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i] = *tvp;
if(tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) {
vp = zb.model->vertices+fp->vertices[i];
BrFVector3Negate(&rev_normal, &vp->n);
fw.surface_fn(vp,&rev_normal,tv[i].comp);
}
}
if((clipped = ZbTempClip(tv,tfp,zb.clip_mask,&nclipped))) {
ZbFaceRender(clipped,nclipped);
}
break;
}
/* ELSE FALL THROUGH */
/*
* Face is partially on screen
*/
case TFF_VISIBLE | TFF_CLIPPED:
ci = BrIntToScalar(tfp->surface);
zb.temp_vertices[fp->vertices[0]].comp[C_I] = ci;
zb.temp_vertices[fp->vertices[1]].comp[C_I] = ci;
zb.temp_vertices[fp->vertices[2]].comp[C_I] = ci;
if((clipped = ZbFaceClip(fp,tfp,zb.clip_mask,&nclipped))) {
ZbFaceRender(clipped,nclipped);
}
break;
}
}
}
/*
* Render a group of faces - get the current R,G,B values from the face
*/
void BR_ASM_CALL ZbRenderFaceGroup_FaceRGB(br_face_group *gp, struct temp_face *tfp)
{
br_face *fp;
struct clip_vertex *clipped;
int f,g,nclipped;
struct zb_material_type *zbmt;
int i;
struct temp_vertex tv[3],*tvp;
br_vertex *vp;
br_fvector3 rev_normal;
/*
* Go through each face in loop
*/
for(f=0, fp=gp->faces ; f < gp->nfaces; f++,fp++, tfp++) {
switch(tfp->flag) {
/*
* Face is not on screen at all
*/
case 0:
continue;
case TFF_VISIBLE | TFF_REVERSED:
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES) {
zb.pr.current = BrIntToFixed(BR_RED(tfp->surface));
zb.pg.current = BrIntToFixed(BR_GRN(tfp->surface));
zb.pb.current = BrIntToFixed(BR_BLU(tfp->surface));
/*
* If any ov the vertices are used in both directions -
* relight them with corect normal
*/
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i] = *tvp;
if(tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) {
vp = zb.model->vertices+fp->vertices[i];
BrFVector3Negate(&rev_normal, &vp->n);
fw.surface_fn(vp,&rev_normal,tv[i].comp);
}
#if !BASED_FIXED
ZbConvertComponents((br_fixed_ls *)tv[i].comp,tvp->comp,zb.convert_mask);
#endif
}
zb.triangle_render((struct temp_vertex_fixed *)tv+0,
(struct temp_vertex_fixed *)tv+1,
(struct temp_vertex_fixed *)tv+2);
break;
}
/* ELSE FALL THROUGH */
/*
* Face is fully on screen
*/
case TFF_VISIBLE:
/*
* Render face
*/
zb.pr.current = BrIntToFixed(BR_RED(tfp->surface));
zb.pg.current = BrIntToFixed(BR_GRN(tfp->surface));
zb.pb.current = BrIntToFixed(BR_BLU(tfp->surface));
#if !BASED_FIXED
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i].v[X] = tvp->v[X];
tv[i].v[Y] = tvp->v[Y];
tv[i].v[Z] = tvp->v[Z];
ZbConvertComponents((br_fixed_ls *)tv[i].comp,tvp->comp,zb.convert_mask);
}
zb.triangle_render((struct temp_vertex_fixed *)tv+0,
(struct temp_vertex_fixed *)tv+1,
(struct temp_vertex_fixed *)tv+2);
#else
zb.triangle_render((struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[0],
(struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[1],
(struct temp_vertex_fixed *)zb.temp_vertices+fp->vertices[2]);
#endif
break;
case TFF_VISIBLE | TFF_CLIPPED | TFF_REVERSED:
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES) {
/*
* If any ov the vertices are used in both directions -
* relight them with corect normal
*/
for(i=0; i<3; i++) {
tvp = zb.temp_vertices+fp->vertices[i];
tv[i] = *tvp;
if(tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) {
vp = zb.model->vertices+fp->vertices[i];
BrFVector3Negate(&rev_normal, &vp->n);
fw.surface_fn(vp,&rev_normal,tv[i].comp);
}
}
if((clipped = ZbTempClip(tv,tfp,zb.clip_mask,&nclipped))) {
zb.pr.current = BrIntToFixed(BR_RED(tfp->surface));
zb.pg.current = BrIntToFixed(BR_GRN(tfp->surface));
zb.pb.current = BrIntToFixed(BR_BLU(tfp->surface));
ZbFaceRender(clipped,nclipped);
}
break;
}
/* ELSE FALL THROUGH */
/*
* Face is partially on screen
*/
case TFF_VISIBLE | TFF_CLIPPED:
if((clipped = ZbFaceClip(fp,tfp,zb.clip_mask,&nclipped))) {
zb.pr.current = BrIntToFixed(BR_RED(tfp->surface));
zb.pg.current = BrIntToFixed(BR_GRN(tfp->surface));
zb.pb.current = BrIntToFixed(BR_BLU(tfp->surface));
ZbFaceRender(clipped,nclipped);
}
break;
}
}
}
/*
* Do per-vertex paramter calculations (intensity, u & v)
*/
STATIC void ZbFindVertexParameters(void)
{
int gv,g,v;
struct temp_vertex *avp;
br_vertex *vp;
br_vertex_group *gp = zb.model->vertex_groups;
/*
* Base vertices
*/
avp = zb.temp_vertices;
v = 0;
for(g=0; g < zb.model->nvertex_groups; g++, gp++) {
zb.material = (gp->material?gp->material:zb.default_material);
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES &&
!((zb.model->prep_flags & MODUF_VERTEX_GROUPS_MATCH) && zb.face_group_counts[g] == 0)) {
SurfacePerMaterial(zb.material);
if(zb.material->flags & BR_MATF_TWO_SIDED) {
/*
* Two sided material - do lighting calculations
* with forward facing normals unless the vertex
* is only used reversed, then use the negated
* normal
*/
for(gv=0, vp = gp->vertices ; gv < gp->nvertices; gv++,v++,avp++,vp++) {
if(zb.vertex_counts[v]) {
if(avp->direction & TVDIR_FRONT)
fw.surface_fn(vp,&vp->n,avp->comp);
else {
br_fvector3 rev_normal;
BrFVector3Negate(&rev_normal, &vp->n);
fw.surface_fn(vp,&rev_normal,avp->comp);
}
}
}
} else {
for(gv=0, vp = gp->vertices ; gv < gp->nvertices; gv++,v++,avp++,vp++)
if(zb.vertex_counts[v])
fw.surface_fn(vp,&vp->n,avp->comp);
}
} else {
avp += gp->nvertices;
v += gp->nvertices;
}
/*
* Handle FORCE_Z_0
*/
if(zb.material->flags & BR_MATF_FORCE_Z_0) {
avp -= gp->nvertices;
for(gv=0; gv < gp->nvertices; gv++,avp++) {
avp->v[Z] = 0;
avp->comp[C_Z] = BR_SCALAR(0.0);
}
}
}
}
/*
* On Screen version of geometry
*/
/*
* Go through model's face list - find forward facing faces and light them
*/
STATIC void ZbOnScreenFindFacesVerts(void)
{
int f,g,j,v,vt,df;
br_face *fp = zb.model->prepared_faces;
br_face_group *gp = zb.model->face_groups;
struct temp_face *tfp = zb.temp_faces;
/*
* Go through each group
*/
for(g=0; g < zb.model->nface_groups; g++, gp++) {
zb.material = (gp->material?gp->material:zb.default_material);
if(zb.material->prep_flags & MATUF_SURFACE_FACES)
SurfacePerMaterial(zb.material);
zb.face_group_counts[g] = 0;
if(zb.material->flags & BR_MATF_TWO_SIDED) {
if(!zb.directions_cleared)
ClearDirections();
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
tfp->flag = TFF_VISIBLE;
df = TVDIR_FRONT;
if(BrFVector3Dot(&fp->n,&fw.eye_m) < fp->d) {
tfp->flag |= TFF_REVERSED;
df = TVDIR_BACK;
}
zb.vertex_counts[fp->vertices[0]] = 1;
zb.vertex_counts[fp->vertices[1]] = 1;
zb.vertex_counts[fp->vertices[2]] = 1;
zb.temp_vertices[fp->vertices[0]].direction |= df;
zb.temp_vertices[fp->vertices[1]].direction |= df;
zb.temp_vertices[fp->vertices[2]].direction |= df;
if(zb.material->prep_flags & MATUF_SURFACE_FACES)
tfp->surface = fw.face_surface_fn(
zb.model->prepared_vertices + fp->vertices[0],fp, tfp->flag & TFF_REVERSED);
}
zb.face_group_counts[g] = gp->nfaces;
} else if(zb.material->flags & BR_MATF_ALWAYS_VISIBLE) {
if(zb.material->prep_flags & MATUF_SURFACE_FACES) {
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
tfp->flag = TFF_VISIBLE;
tfp->surface = fw.face_surface_fn(
zb.model->prepared_vertices + fp->vertices[0],fp,0);
zb.vertex_counts[fp->vertices[0]] = 1;
zb.vertex_counts[fp->vertices[1]] = 1;
zb.vertex_counts[fp->vertices[2]] = 1;
}
} else {
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
tfp->flag = TFF_VISIBLE;
zb.vertex_counts[fp->vertices[0]] = 1;
zb.vertex_counts[fp->vertices[1]] = 1;
zb.vertex_counts[fp->vertices[2]] = 1;
}
}
zb.face_group_counts[g] = gp->nfaces;
} else {
/*
* Single sided faces
*/
if(zb.material->prep_flags & MATUF_SURFACE_FACES) {
#if FAST_CULL
zb.face_group_counts[g] = ZbOSFFVGroupCulledLit_A(fp,tfp,gp->nfaces);
tfp += gp->nfaces;
fp += gp->nfaces;
#else
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
if(BrFVector3Dot(&fp->n,&fw.eye_m) < fp->d) {
tfp->flag = 0;
} else {
tfp->flag = TFF_VISIBLE;
zb.face_group_counts[g]++;
zb.vertex_counts[fp->vertices[0]] = 1;
zb.vertex_counts[fp->vertices[1]] = 1;
zb.vertex_counts[fp->vertices[2]] = 1;
tfp->surface = fw.face_surface_fn(
zb.model->prepared_vertices + fp->vertices[0],fp,0);
}
}
#endif
} else {
#if FAST_CULL
zb.face_group_counts[g] = ZbOSFFVGroupCulled_A(fp,tfp,gp->nfaces);
tfp += gp->nfaces;
fp += gp->nfaces;
#else
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
if(BrFVector3Dot(&fp->n,&fw.eye_m) < fp->d) {
tfp->flag = 0;
} else {
tfp->flag = TFF_VISIBLE;
zb.face_group_counts[g]++;
zb.vertex_counts[fp->vertices[0]] = 1;
zb.vertex_counts[fp->vertices[1]] = 1;
zb.vertex_counts[fp->vertices[2]] = 1;
}
}
#endif
}
}
}
}
STATIC void ZbOnScreenFindFacesVertsPar(void)
{
int f,g,j,v,vt,df;
br_face *fp = zb.model->prepared_faces;
br_face_group *gp = zb.model->face_groups;
struct temp_face *tfp = zb.temp_faces;
/*
* Go through each group
*/
for(g=0; g < zb.model->nface_groups; g++, gp++) {
zb.material = (gp->material?gp->material:zb.default_material);
if(zb.material->prep_flags & MATUF_SURFACE_FACES)
SurfacePerMaterial(zb.material);
zb.face_group_counts[g] = 0;
if(zb.material->flags & BR_MATF_TWO_SIDED) {
if(!zb.directions_cleared)
ClearDirections();
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
tfp->flag = TFF_VISIBLE;
df = TVDIR_FRONT;
if(BrFVector3Dot(&fp->n,&fw.eye_m) < S0) {
tfp->flag |= TFF_REVERSED;
df = TVDIR_BACK;
}
zb.face_group_counts[g]++;
zb.vertex_counts[fp->vertices[0]] = 1;
zb.vertex_counts[fp->vertices[1]] = 1;
zb.vertex_counts[fp->vertices[2]] = 1;
zb.temp_vertices[fp->vertices[0]].direction |= df;
zb.temp_vertices[fp->vertices[1]].direction |= df;
zb.temp_vertices[fp->vertices[2]].direction |= df;
if(zb.material->prep_flags & MATUF_SURFACE_FACES)
tfp->surface = fw.face_surface_fn(
zb.model->prepared_vertices + fp->vertices[0],fp,tfp->flag & TFF_REVERSED);
}
} else if(zb.material->flags & BR_MATF_ALWAYS_VISIBLE) {
/*
* Two sided faces are always visible
*/
if(zb.material->prep_flags & MATUF_SURFACE_FACES) {
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
tfp->flag = TFF_VISIBLE;
tfp->surface = fw.face_surface_fn(
zb.model->prepared_vertices + fp->vertices[0],fp,0);
zb.vertex_counts[fp->vertices[0]] = 1;
zb.vertex_counts[fp->vertices[1]] = 1;
zb.vertex_counts[fp->vertices[2]] = 1;
}
} else {
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
tfp->flag = TFF_VISIBLE;
zb.vertex_counts[fp->vertices[0]] = 1;
zb.vertex_counts[fp->vertices[1]] = 1;
zb.vertex_counts[fp->vertices[2]] = 1;
}
}
zb.face_group_counts[g] = gp->nfaces;
} else {
/*
* Single sided faces
*/
if(zb.material->prep_flags & MATUF_SURFACE_FACES) {
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
if(BrFVector3Dot(&fp->n,&fw.eye_m) < S0) {
tfp->flag = 0;
} else {
tfp->flag = TFF_VISIBLE;
zb.face_group_counts[g]++;
zb.vertex_counts[fp->vertices[0]] = 1;
zb.vertex_counts[fp->vertices[1]] = 1;
zb.vertex_counts[fp->vertices[2]] = 1;
tfp->surface = fw.face_surface_fn(
zb.model->prepared_vertices + fp->vertices[0],fp,0);
}
}
} else {
for(f=0; f < gp->nfaces; f++, fp++, tfp++) {
if(BrFVector3Dot(&fp->n,&fw.eye_m) <= S0) {
tfp->flag = 0;
} else {
tfp->flag = TFF_VISIBLE;
zb.face_group_counts[g]++;
zb.vertex_counts[fp->vertices[0]] = 1;
zb.vertex_counts[fp->vertices[1]] = 1;
zb.vertex_counts[fp->vertices[2]] = 1;
}
}
}
}
}
}
/*
* For all the active vertices, transform them and work out
* the per vertex parameters
*/
STATIC void ZbOnScreenTransformVertices(void)
{
int v,g,gv;
struct temp_vertex *avp;
br_vertex *vp;
br_vertex_group *gp = zb.model->vertex_groups;
br_vector4 screen;
/*
* Base vertices
*/
v = 0;
avp = zb.temp_vertices;
for(g=0; g < zb.model->nvertex_groups; g++, gp++) {
zb.material = (gp->material?gp->material:zb.default_material);
/*
* Skip if group is not visible
*/
if((zb.model->prep_flags & MODUF_VERTEX_GROUPS_MATCH) && zb.face_group_counts[g] == 0) {
avp += gp->nvertices;
v += gp->nvertices;
continue;
}
/*
* Select a transform according to current situation
*/
if(zb.material->flags & BR_MATF_TWO_SIDED) {
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES)
SurfacePerMaterial(zb.material);
/*
* Do surface function and bounds update per vertex
*/
for(gv=0, vp = gp->vertices ; gv < gp->nvertices; gv++,v++,avp++,vp++) {
if(zb.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX_OS();
avp->comp[C_W] = screen.v[W];
PROJECT_VERTEX(avp,screen.v[X],screen.v[Y],screen.v[Z],screen.v[W]);
UPDATE_BOUNDS(*avp);
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES) {
if(avp->direction & TVDIR_FRONT)
fw.surface_fn(vp,&vp->n,avp->comp);
else {
br_fvector3 rev_normal;
BrFVector3Negate(&rev_normal, &vp->n);
fw.surface_fn(vp,&rev_normal,avp->comp);
}
}
}
continue;
}
if(zb.material->prep_flags & MATUF_SURFACE_VERTICES) {
SurfacePerMaterial(zb.material);
if(zb.bounds_call) {
#if FAST_PROJECT
ZbOSTVGroupLitBC_A(gp->vertices,avp,gp->nvertices,(br_uint_8 *)zb.vertex_counts+v);
avp += gp->nvertices;
v += gp->nvertices;
#else
/*
* Do surface function and bounds update per vertex
*/
for(gv=0, vp = gp->vertices ; gv < gp->nvertices; gv++,v++,avp++,vp++) {
if(zb.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX_OS();
avp->comp[C_W] = screen.v[W];
PROJECT_VERTEX(avp,screen.v[X],screen.v[Y],screen.v[Z],screen.v[W]);
UPDATE_BOUNDS(*avp);
fw.surface_fn(vp, &vp->n, avp->comp);
}
#endif
} else {
/*
* Do surface function per vertex
*/
#if FAST_PROJECT
ZbOSTVGroupLit_A(gp->vertices,avp,gp->nvertices,(br_uint_8 *)zb.vertex_counts+v);
avp += gp->nvertices;
v += gp->nvertices;
#else
for(gv=0, vp = gp->vertices ; gv < gp->nvertices; gv++,v++,avp++,vp++) {
if(zb.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX_OS();
avp->comp[C_W] = screen.v[W];
PROJECT_VERTEX(avp,screen.v[X],screen.v[Y],screen.v[Z],screen.v[W]);
fw.surface_fn(vp, &vp->n, avp->comp);
}
#endif
}
} else {
if(zb.bounds_call) {
/*
* Do bounds update per vertex
*/
#if FAST_PROJECT
ZbOSTVGroupBC_A(gp->vertices,avp,gp->nvertices,(br_uint_8 *)zb.vertex_counts+v);
avp += gp->nvertices;
v += gp->nvertices;
#else
for(gv=0, vp = gp->vertices ; gv < gp->nvertices; gv++,v++,avp++,vp++) {
if(zb.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX_OS();
avp->comp[C_W] = screen.v[W];
PROJECT_VERTEX(avp,screen.v[X],screen.v[Y],screen.v[Z],screen.v[W]);
UPDATE_BOUNDS(*avp);
}
#endif
} else {
/*
* Just transform
*/
#if FAST_PROJECT
ZbOSTVGroup_A(gp->vertices,avp,gp->nvertices,(br_uint_8 *)zb.vertex_counts+v);
avp += gp->nvertices;
v += gp->nvertices;
#else
for(gv=0, vp = gp->vertices ; gv < gp->nvertices; gv++,v++,avp++,vp++) {
if(zb.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX_OS();
avp->comp[C_W] = screen.v[W];
PROJECT_VERTEX(avp,screen.v[X],screen.v[Y],screen.v[Z],screen.v[W]);
}
#endif
}
}
/*
* Handle FORCE_Z_0
*/
if(zb.material->flags & BR_MATF_FORCE_Z_0) {
avp -= gp->nvertices;
for(gv=0; gv < gp->nvertices; gv++,avp++) {
avp->v[Z] = 0;
avp->comp[C_Z] = BR_SCALAR(0.0);
}
}
}
}
/*
* Render a model to the screen through the current transform
*/
void ZbMeshRender(br_actor *actor,
br_model *model,
br_material *material,
br_uint_8 style,
int on_screen)
{
void *scratch;
int scratch_size;
char *sp,*clear_end;
/*
* Remember model and material in renderer info.
*/
zb.model = model;
zb.default_material = material;
#if 0
{
extern br_material test_materials[];
if(on_screen == OSC_ACCEPT)
zb.default_material = test_materials+2;
}
#endif
#if 0
on_screen = OSC_PARTIAL;
#endif
zb.directions_cleared = 0;
/*
* Work out amount of scratch space needed for this model
*/
scratch_size = SCRATCH_ALIGN(model->nprepared_faces * sizeof(*zb.temp_faces));
scratch_size += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.vertex_counts));
scratch_size += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.temp_vertices));
scratch_size += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_counts));
scratch_size += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_clipped));
/*
* Make sure current scratch buffer is big enough
*/
scratch = BrScratchAllocate(scratch_size+SCRATCH_BOUNDARY);
/*
* Allocate scratch areas
*/
sp = scratch;
zb.vertex_counts = (void *)sp;
sp += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.vertex_counts));
zb.face_group_clipped = (void *)sp;
sp += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_clipped));
clear_end = sp;
zb.face_group_counts = (void *)sp;
sp += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_counts));
zb.temp_faces = (void *)sp;
sp += SCRATCH_ALIGN(model->nprepared_faces * sizeof(*zb.temp_faces));
zb.temp_vertices = (void *)sp;
/*
* Clear vertex counts and vertex materials
*/
BrBlockFill(scratch,0,((clear_end - (char *)scratch) + 3) / 4);
#if FAST_PROJECT
/*
* If on_screen, then let the fast project code pre process the model->screen
* matrix
*
* If there was an overflow, revert back to OSC_PARTIAL
*/
if(on_screen == OSC_ACCEPT)
if(ZbOSCopyModelToScreen_A())
on_screen = OSC_PARTIAL;
#endif
/*
* Build view_to_model
*
* Record a flag to say if model is inside out (det of Xfrm is < 0)
*/
BrMatrix34Inverse(&fw.view_to_model,&fw.model_to_view);
/*
* Transform eye point into model space
*/
BrVector3EyeInModel(&fw.eye_m);
/*
* Normalised version for environment mapping
*/
BrVector3Normalise(&fw.eye_m_normalised,&fw.eye_m);
/*
* Process lighting for this model
*/
SurfacePerModel();
/*
* Initialise bounds
*/
#if BOUNDING_RECTANGLE_CALL
zb.bounds[BR_BOUNDS_MIN_X] = zb.bounds[BR_BOUNDS_MIN_Y] = 0x7fffffff;
zb.bounds[BR_BOUNDS_MAX_X] = zb.bounds[BR_BOUNDS_MAX_Y] = 0x80000001;
#endif
/*
* Process this model
*/
if(on_screen == OSC_ACCEPT) {
switch(fw.vtos_type) {
case BR_VTOS_PERSPECTIVE:
ZbOnScreenFindFacesVerts();
break;
case BR_VTOS_PARALLEL:
ZbOnScreenFindFacesVertsPar();
break;
}
ZbOnScreenTransformVertices();
ZbRenderFaces();
} else {
switch(fw.vtos_type) {
case BR_VTOS_PERSPECTIVE:
ZbFindVisibleFaces();
break;
case BR_VTOS_PARALLEL:
ZbFindVisibleFacesPar();
break;
}
ZbTransformVertices();
ZbFindFacesAndVertices();
ZbFindVertexParameters();
ZbRenderFaces();
}
/*
* Release scratch
*/
BrScratchFree(scratch);
#if BOUNDING_RECTANGLE_CALL
/*
* Invoke a callback for bounding rectangle
*/
if(zb.bounds_call) {
br_int_32 int_bounds[4];
int_bounds[0] = ScreenToInt(zb.bounds[0]);
int_bounds[1] = ScreenToInt(zb.bounds[1])+fw.output->base_y;
int_bounds[2] = ScreenToInt(zb.bounds[2])-1;
int_bounds[3] = ScreenToInt(zb.bounds[3])+fw.output->base_y-1;
if((int_bounds[0] <= int_bounds[2]) &&
(int_bounds[1] <= int_bounds[3]) ) {
zb.bounds_call(actor, model, material, NULL, style, &fw.model_to_screen,
int_bounds);
}
}
#endif
}
/*
* Attempt to shrink scratch space if current usage is well
* bellow that allocated
*
* If max usage is l.t. 1/2 allocated space for 50 tests, then
* resize buffer
*/
void ZbScratchShrink(void)
{
/* XXX Add Water */
}
#if !BASED_FIXED
/*
* Convert component from scalar to fixed
*/
void ZbConvertComponents(br_fixed_ls *dest,br_scalar *src,br_uint_32 mask)
{
for( ;mask ; mask >>= 1, dest++, src++)
if(mask & 1)
*dest = BrScalarToFixed(*src);
}
#endif
/*
* Local Variables:
* tab-width: 4
* End:
*/