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

309 lines
6.8 KiB
C

/*
* Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved.
*
* $Id: zbmeshp.c 1.20 1995/08/31 16:48:00 sam Exp $
* $Locker: $
*
* Mesh rendering to produce points
*/
#include "zb.h"
#include "shortcut.h"
#include "blockops.h"
static char rscid[] = "$Id: zbmeshp.c 1.20 1995/08/31 16:48:00 sam Exp $";
/*
* Render visible points
*/
STATIC void ZbPointsRender(void)
{
int g,v,gv;
br_vertex_group *gp = zb.model->vertex_groups;
struct temp_vertex *tvp;
struct temp_vertex_fixed tv[1];
struct zb_material_type *zbmt;
br_material *group_material;
tvp = zb.temp_vertices;
for(v=0, g=0; g < zb.model->nvertex_groups; g++, gp++) {
if((zb.model->prep_flags & MODUF_VERTEX_GROUPS_MATCH) && (zb.face_group_counts[g] == 0)) {
tvp += gp->nvertices;
v += gp->nvertices;
continue;
}
zb.material = group_material = (gp->material?gp->material:zb.default_material);
if(group_material->colour_map)
zb.texture_buffer = group_material->colour_map->pixels;
if(group_material->index_shade)
zb.shade_table = group_material->index_shade->pixels;
zbmt = group_material->rptr;
for(gv=0; gv < gp->nvertices; gv++,tvp++, v++) {
if((zb.vertex_counts[v] <= 0) || tvp->outcode != OUTCODES_NOT)
continue;
#if !BASED_FIXED
tv[0].v[X]=tvp->v[X];
tv[0].v[Y]=tvp->v[Y];
tv[0].v[Z]=tvp->v[Z];
ZbConvertComponents(tv[0].comp,tvp->comp,zbmt->convert_mask);
zbmt->point(tv);
#else
zbmt->point((struct temp_vertex_fixed *)tvp);
#endif
}
}
}
/*
* Do per-vertex parameter calculations (intensity, u & v)
*/
STATIC void ZbPointFindVertexParameters(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.model->prep_flags & MODUF_VERTEX_GROUPS_MATCH) && (zb.face_group_counts[g] == 0)) {
avp += gp->nvertices;
v += gp->nvertices;
} else {
SurfacePerMaterial(zb.material);
for(gv=0, vp = gp->vertices ; gv < gp->nvertices; gv++,v++,avp++,vp++) {
/*
* Ignore if not visible
*/
if(zb.vertex_counts[v] == 0)
continue;
fw.surface_fn(vp,&vp->n,avp->comp);
}
}
/*
* 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);
}
}
}
}
/*
* Do per face work - find all the faces that are on screen and
* allocate temp_vertex structures
*/
STATIC void ZbPointFindFacesAndVertices(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;
br_material *group_material;
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;
}
group_material = gp->material?gp->material:zb.default_material;
for(f=0; f < gp->nfaces; f++,fp++,tfp++) {
if(tfp->flag == 0)
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;
}
/*
* Face is a least partially visible
*/
}
}
}
/*
* Render a models points to the screen through the current transform
*/
void ZbMeshRenderPoints(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;
int inside_out;
/*
* Remember model and material in renderer info.
*/
zb.model = model;
zb.default_material = material;
/*
* 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->nface_groups * sizeof(*zb.face_group_counts));
scratch_size += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.vertex_counts));
scratch_size += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.temp_vertices));
/*
* 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_counts = (void *)sp;
sp += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_counts));
clear_end = sp;
zb.temp_faces = (void *)sp;
sp += SCRATCH_ALIGN(model->nprepared_faces * sizeof(*zb.temp_faces));
zb.temp_vertices = (void *)sp;
/*
* Clear vertex counts
*/
BrBlockFill(scratch,0,((clear_end - (char *)scratch) + 3) / 4);
/*
* Build view_to_model
*
* Record a flag to say if model is inside out (det of Xfrm is < 0)
*/
inside_out = BrMatrix34Inverse(&fw.view_to_model,&fw.model_to_view) < S0;
/*
* Transform eye point into model space
*/
BrVector3EyeInModel(&fw.eye_m);
/*
* Process lighting for this model
*/
SurfacePerModel();
/*
* Process this model
*/
/*
* 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
switch(fw.vtos_type) {
case BR_VTOS_PERSPECTIVE:
ZbFindVisibleFaces();
break;
case BR_VTOS_PARALLEL:
ZbFindVisibleFacesPar();
break;
}
ZbTransformVertices();
ZbPointFindFacesAndVertices();
ZbPointFindVertexParameters();
ZbPointsRender();
/*
* Release scratch
*/
BrScratchFree(scratch);
#if BOUNDING_RECTANGLE_CALL
/*
* Invoke a callback for bounding rectangle
*/
if(zb.bounds_call) {
br_int_32 int_bounds[4];
zb.bounds[0]-=BR_SCALAR(0.5);
zb.bounds[1]-=BR_SCALAR(0.5);
zb.bounds[2]+=BR_SCALAR(0.5);
zb.bounds[3]+=BR_SCALAR(0.5);
CLAMP_POINT_MIN(zb.bounds[0],zb.bounds[1]);
CLAMP_POINT_MAX(zb.bounds[2],zb.bounds[3]);
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
}