brender-1997/softrend/genrend.c
2022-05-03 14:31:40 -07:00

517 lines
15 KiB
C

/*
* Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved.
*
* $Id: genrend.c 2.6 1996/11/20 14:11:48 sam Exp JOHNG $
* $Locker: JOHNG $
*
* Geometry operations that are used for several different formats
*/
#include <stddef.h>
#include <string.h>
#include "drv.h"
#include "shortcut.h"
#include "brassert.h"
#include "blockops.h"
#include "vecifns.h"
/*
* Transform, project, outcode and update screen bounds of visible vertices
*/
#ifndef Vertex_TransformProjectOutcodeBounds
static void GEOMETRY_CALL Vertex_TransformProjectOutcodeBounds(struct br_geometry *self, struct br_renderer *renderer)
{
int v;
brp_vertex *tvp = rend.temp_vertices;
for(v=0; v < rend.nvertices; v++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX((br_vector4 *)(tvp->comp+C_X),&rend.vertices[v].p, &scache.model_to_screen);
OUTCODE_POINT(tvp->flags, (br_vector4 *)(tvp->comp+C_X));
if(!(tvp->flags & OUTCODES_ALL)) {
PROJECT_VERTEX_WRITE_Q(tvp,tvp->comp[C_X],tvp->comp[C_Y],tvp->comp[C_Z],tvp->comp[C_W]);
UPDATE_BOUNDS(tvp);
}
}
}
#endif
/*
* Transform, project and outcode of visible vertices
*/
void GEOMETRY_CALL Vertex_TransformProjectOutcode_CMOV(struct br_geometry *self, struct br_renderer *renderer);
#ifndef Vertex_TransformProjectOutcode
#if 1
void GEOMETRY_CALL Vertex_TransformProjectOutcode(struct br_geometry *self, struct br_renderer *renderer);
#else
static void GEOMETRY_CALL Vertex_TransformProjectOutcode(struct br_geometry *self, struct br_renderer *renderer)
{
int v;
int temp0,temp1;
brp_vertex *tvp = rend.temp_vertices;
for(v=0; v < rend.nvertices; v++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX((br_vector4 *)(tvp->comp+C_X),&rend.vertices[v].p, &scache.model_to_screen);
OUTCODE_POINT(tvp->flags, (br_vector4 *)(tvp->comp+C_X));
if(!(tvp->flags & OUTCODES_ALL)) {
PROJECT_VERTEX_WRITE_Q(tvp,tvp->comp[C_X],tvp->comp[C_Y],tvp->comp[C_Z],tvp->comp[C_W]);
}
}
}
#endif
#endif
/*
* Transform, project and update screen bounds of visible vertices
*/
#ifndef Vertex_OS_TransformProjectBounds
static void GEOMETRY_CALL Vertex_OS_TransformProjectBounds(struct br_geometry *self, struct br_renderer *renderer)
{
int v;
brp_vertex *tvp = rend.temp_vertices;
for(v=0; v < rend.nvertices; v++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX((br_vector4 *)(tvp->comp+C_X),&rend.vertices[v].p, &scache.model_to_screen);
PROJECT_VERTEX_WRITE_Q(tvp,tvp->comp[C_X],tvp->comp[C_Y],tvp->comp[C_Z],tvp->comp[C_W]);
UPDATE_BOUNDS(tvp);
}
}
#endif
/*
* Transform and project visible vertices
*/
#ifndef Vertex_OS_TransformProject
#if 1
void GEOMETRY_CALL Vertex_OS_TransformProject(struct br_geometry *self, struct br_renderer *renderer);
#else
static void GEOMETRY_CALL Vertex_OS_TransformProject(struct br_geometry *self, struct br_renderer *renderer)
{
int v;
brp_vertex *tvp = rend.temp_vertices;
for(v=0; v < rend.nvertices; v++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX((br_vector4 *)(tvp->comp+C_X),&rend.vertices[v].p, &scache.model_to_screen);
PROJECT_VERTEX_WRITE_Q(tvp,tvp->comp[C_X],tvp->comp[C_Y],tvp->comp[C_Z],tvp->comp[C_W]);
}
}
#endif
#endif
/*
* Transform, project, light and update screen bounds of visible vertices
*/
#ifndef Vertex_OS_TransformProjectBoundsSurf
static void GEOMETRY_CALL Vertex_OS_TransformProjectBoundsSurf(struct br_geometry *self, struct br_renderer *renderer)
{
int v,i;
brp_vertex *tvp = rend.temp_vertices;
struct fmt_vertex *vp = rend.vertices;
for(v=0; v < rend.nvertices; v++, vp++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX((br_vector4 *)(tvp->comp+C_X),&vp->p, &scache.model_to_screen);
PROJECT_VERTEX_WRITE_Q(tvp,tvp->comp[C_X],tvp->comp[C_Y],tvp->comp[C_Z],tvp->comp[C_W]);
UPDATE_BOUNDS(tvp);
for(i=0; i < renderer->state.cache.nvertex_fns; i++)
renderer->state.cache.vertex_fns[i](renderer, &vp->p, &vp->map, &vp->n, scache.colour, tvp->comp);
}
}
#endif
/*
* Transform, project and light visible vertices
*/
//void GEOMETRY_CALL Vertex_OS_TransformProjectSurf(struct br_geometry *self, struct br_renderer *renderer);
//#if 1
//#ifndef Vertex_OS_TransformProjectSurf
void cdecl Vertex_OS_TransformProjectSurf(struct br_geometry *self, struct br_renderer *renderer)
{
int v,i;
brp_vertex *tvp = rend.temp_vertices;
struct fmt_vertex *vp = rend.vertices;
Vertex_OS_TransformProject(self,renderer);
for(v=0; v < rend.nvertices; v++, vp++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
for(i=0; i < renderer->state.cache.nvertex_fns; i++)
renderer->state.cache.vertex_fns[i](renderer, &vp->p, &vp->map, &vp->n, scache.colour, tvp->comp);
}
#if 0
int v,i;
brp_vertex *tvp = rend.temp_vertices;
struct fmt_vertex *vp = rend.vertices;
for(v=0; v < rend.nvertices; v++, vp++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX((br_vector4 *)(tvp->comp+C_X),&vp->p, &scache.model_to_screen);
PROJECT_VERTEX_WRITE_Q(tvp,tvp->comp[C_X],tvp->comp[C_Y],tvp->comp[C_Z],tvp->comp[C_W]);
for(i=0; i < renderer->state.cache.nvertex_fns; i++)
renderer->state.cache.vertex_fns[i](renderer, &vp->p, &vp->map, &vp->n, scache.colour, tvp->comp);
}
#endif
}
//#endif
//#endif
/*
* Transform, project, light and update screen bounds of visible vertices
*/
#ifndef Vertex_OS_TransformProjectBoundsGeom
static void GEOMETRY_CALL Vertex_OS_TransformProjectBoundsGeom(struct br_geometry *self, struct br_renderer *renderer)
{
int v,i;
brp_vertex *tvp = rend.temp_vertices;
struct fmt_vertex *vp = rend.vertices;
for(v=0; v < rend.nvertices; v++, vp++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX((br_vector4 *)(tvp->comp+C_X),&vp->p, &scache.model_to_screen);
PROJECT_VERTEX_WRITE_Q(tvp,tvp->comp[C_X],tvp->comp[C_Y],tvp->comp[C_Z],tvp->comp[C_W]);
UPDATE_BOUNDS(tvp);
for(i=0; i < renderer->state.cache.nvertex_fns; i++)
renderer->state.cache.vertex_fns[i](renderer, &vp->p, &vp->map, &vp->n, rend.vertex_colours[v], tvp->comp);
}
}
#endif
/*
* Transform, project and light visible vertices
*/
#ifndef Vertex_OS_TransformProjectGeom
static void GEOMETRY_CALL Vertex_OS_TransformProjectGeom(struct br_geometry *self, struct br_renderer *renderer)
{
int v,i;
brp_vertex *tvp = rend.temp_vertices;
struct fmt_vertex *vp = rend.vertices;
for(v=0; v < rend.nvertices; v++, vp++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
TRANSFORM_VERTEX((br_vector4 *)(tvp->comp+C_X),&vp->p, &scache.model_to_screen);
PROJECT_VERTEX_WRITE_Q(tvp,tvp->comp[C_X],tvp->comp[C_Y],tvp->comp[C_Z],tvp->comp[C_W]);
for(i=0; i < renderer->state.cache.nvertex_fns; i++)
renderer->state.cache.vertex_fns[i](renderer, &vp->p, &vp->map, &vp->n, rend.vertex_colours[v], tvp->comp);
}
}
#endif
#if 1
/*
* Transform, project and update screen bounds of all vertives
*/
#ifndef Vertex_OSV_TransformProjectBounds
static void GEOMETRY_CALL Vertex_OSV_TransformProjectBounds(struct br_geometry *self, struct br_renderer *renderer)
{
int v;
brp_vertex *tvp = rend.temp_vertices;
for(v=0; v < rend.nvertices; v++, tvp++) {
TRANSFORM_VERTEX((br_vector4 *)(tvp->comp+C_X),&rend.vertices[v].p, &scache.model_to_screen);
PROJECT_VERTEX_WRITE_Q(tvp,tvp->comp[C_X],tvp->comp[C_Y],tvp->comp[C_Z],tvp->comp[C_W]);
UPDATE_BOUNDS(tvp);
}
}
#endif
/*
* Transform and project all vertives
*/
#ifndef Vertex_OSV_TransformProject
static void GEOMETRY_CALL Vertex_OSV_TransformProject(struct br_geometry *self, struct br_renderer *renderer)
{
int v;
brp_vertex *tvp = rend.temp_vertices;
for(v=0; v < rend.nvertices; v++, tvp++) {
TRANSFORM_VERTEX((br_vector4 *)(tvp->comp+C_X),&rend.vertices[v].p, &scache.model_to_screen);
PROJECT_VERTEX_WRITE_Q(tvp,tvp->comp[C_X],tvp->comp[C_Y],tvp->comp[C_Z],tvp->comp[C_W]);
}
}
#endif
#endif
/*
* Generate per-vertex surface parmeters, colour from surface
*/
#ifndef Vertex_SurfaceComponentsSurf
static void GEOMETRY_CALL Vertex_SurfaceComponentsSurf(struct br_geometry *self, struct br_renderer *renderer)
{
union brp_vertex *tvp = rend.temp_vertices;
struct fmt_vertex *vp = rend.vertices;
int v,i;
/*
* Simple hack for mapping
*/
for(v=0; v < rend.nvertices; v++, vp++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
for(i=0; i < renderer->state.cache.nvertex_fns; i++)
renderer->state.cache.vertex_fns[i](renderer, &vp->p, &vp->map, &vp->n, scache.colour, tvp->comp);
}
}
#endif
#ifndef Vertex_SurfaceComponentsTwoSidedSurf
static void GEOMETRY_CALL Vertex_SurfaceComponentsTwoSidedSurf(struct br_geometry *self, struct br_renderer *renderer)
{
union brp_vertex *tvp = rend.temp_vertices;
struct fmt_vertex *vp = rend.vertices;
int v,i;
br_vector3 rev_normal;
for(v=0; v < rend.nvertices; v++, vp++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
#if 0 // Removed two-sided relighting for <REDACTEDGAME>
if(tvp->flags & TVDIR_FRONT) {
#endif
for(i=0; i < renderer->state.cache.nvertex_fns; i++)
renderer->state.cache.vertex_fns[i](renderer, &vp->p, &vp->map, &vp->n, scache.colour, tvp->comp);
#if 0 // Removed two-sided relighting for <REDACTEDGAME>
} else {
BrVector3Negate(&rev_normal, &vp->n);
for(i=0; i < renderer->state.cache.nvertex_fns; i++)
renderer->state.cache.vertex_fns[i](renderer, &vp->p, &vp->map, &rev_normal, scache.colour, tvp->comp);
}
#endif
}
}
#endif
/*
* Generate per-vertex surface parmeters, colour from geometry
*/
#ifndef Vertex_SurfaceComponentsGeom
static void GEOMETRY_CALL Vertex_SurfaceComponentsGeom(struct br_geometry *self, struct br_renderer *renderer)
{
union brp_vertex *tvp = rend.temp_vertices;
struct fmt_vertex *vp = rend.vertices;
int v,i;
for(v=0; v < rend.nvertices; v++, vp++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
for(i=0; i < renderer->state.cache.nvertex_fns; i++)
renderer->state.cache.vertex_fns[i](renderer, &vp->p, &vp->map, &vp->n, rend.vertex_colours[v], tvp->comp);
}
}
#endif
#ifndef Vertex_SurfaceComponentsTwoSidedGeom
static void GEOMETRY_CALL Vertex_SurfaceComponentsTwoSidedGeom(struct br_geometry *self, struct br_renderer *renderer)
{
union brp_vertex *tvp = rend.temp_vertices;
struct fmt_vertex *vp = rend.vertices;
br_vector3 rev_normal;
int v,i;
for(v=0; v < rend.nvertices; v++, vp++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
#if 0 // Removed two-sided relighting for <REDACTEDGAME>
if(tvp->flags & TVDIR_FRONT) {
#endif
for(i=0; i < renderer->state.cache.nvertex_fns; i++)
renderer->state.cache.vertex_fns[i](renderer, &vp->p, &vp->map, &vp->n, rend.vertex_colours[v], tvp->comp);
#if 0 // Removed two-sided relighting for <REDACTEDGAME>
} else {
BrVector3Negate(&rev_normal, &vp->n);
for(i=0; i < renderer->state.cache.nvertex_fns; i++)
renderer->state.cache.vertex_fns[i](renderer, &vp->p, &vp->map, &rev_normal, rend.vertex_colours[v], tvp->comp);
}
#endif
}
}
#endif
/*
* Handles force front by fixing up C_Z and C_SZ
*/
#ifndef Vertex_ForceFront
static void GEOMETRY_CALL Vertex_ForceFront(struct br_geometry *self, struct br_renderer *renderer)
{
union brp_vertex *tvp = rend.temp_vertices;
struct fmt_vertex *vp = rend.vertices;
int v;
for(v=0; v < rend.nvertices; v++, vp++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
tvp->comp[C_SZ] = renderer->state.cache.comp_offsets[C_SZ]+renderer->state.cache.comp_scales[C_SZ];
tvp->comp[C_Z] = tvp->comp[C_W] - BR_SCALAR_EPSILON;
}
}
#endif
#ifndef Vertex_ForceBack
static void GEOMETRY_CALL Vertex_ForceBack(struct br_geometry *self, struct br_renderer *renderer)
{
union brp_vertex *tvp = rend.temp_vertices;
struct fmt_vertex *vp = rend.vertices;
int v;
for(v=0; v < rend.nvertices; v++, vp++, tvp++) {
if(rend.vertex_counts[v] == 0)
continue;
tvp->comp[C_SZ] = renderer->state.cache.comp_offsets[C_SZ]-renderer->state.cache.comp_scales[C_SZ];
tvp->comp[C_Z] = BR_SCALAR_EPSILON-tvp->comp[C_W];
}
}
#endif
#ifndef ScratchFree
void GEOMETRY_CALL ScratchFree(struct br_geometry *self, struct br_renderer *renderer)
{
BrScratchFree(rend.scratch);
rend.scratch = NULL;
}
#endif
/*
* Clear vertex flags
*/
#ifndef Vertex_ClearFlags
void GEOMETRY_CALL Vertex_ClearFlags(struct br_geometry *self, struct br_renderer *renderer)
{
int v;
for(v=0; v< rend.nvertices; v++)
rend.temp_vertices[v].flags = OUTCODES_NOT;
}
#endif
/*
* Select per vertex geometry operations
*/
void VertexGeometryFns(struct br_renderer *renderer, geometry_fn *prim_outcode)
{
/**
** Partially on screen geometry
**/
if(renderer->state.enable.flags & ENBL_BOUNDS)
GeometryFunctionAdd(renderer, Vertex_TransformProjectOutcodeBounds);
else
#if 1
if(renderer->device->hostInfo.capabilities&HOST_CAPS_CMOV)
GeometryFunctionAdd(renderer, Vertex_TransformProjectOutcode_CMOV);
else
#endif
GeometryFunctionAdd(renderer, Vertex_TransformProjectOutcode);
/*
* Apply any per-primitive outcoding to further reduce the visible primitives
* and vertices
*/
if(prim_outcode)
GeometryFunctionAdd(renderer, prim_outcode);
if(renderer->state.cache.nvertex_fns) {
if(renderer->state.cull.type == BRT_TWO_SIDED) {
if(renderer->state.surface.colour_source == BRT_GEOMETRY)
GeometryFunctionAdd(renderer, Vertex_SurfaceComponentsTwoSidedGeom);
else
GeometryFunctionAdd(renderer, Vertex_SurfaceComponentsTwoSidedSurf);
} else {
if(renderer->state.surface.colour_source == BRT_GEOMETRY)
GeometryFunctionAdd(renderer, Vertex_SurfaceComponentsGeom);
else
GeometryFunctionAdd(renderer, Vertex_SurfaceComponentsSurf);
}
}
/**
** Fully on screen geometry
**/
if(renderer->state.cache.nvertex_fns) {
if(renderer->state.cull.type == BRT_TWO_SIDED) {
if(renderer->state.enable.flags & ENBL_BOUNDS)
GeometryFunctionOnScreenAdd(renderer, Vertex_OS_TransformProjectBounds);
else
GeometryFunctionOnScreenAdd(renderer, Vertex_OS_TransformProject);
if(renderer->state.surface.colour_source == BRT_GEOMETRY)
GeometryFunctionOnScreenAdd(renderer, Vertex_SurfaceComponentsTwoSidedGeom);
else
GeometryFunctionOnScreenAdd(renderer, Vertex_SurfaceComponentsTwoSidedSurf);
} else {
if(renderer->state.enable.flags & ENBL_BOUNDS) {
if(renderer->state.surface.colour_source == BRT_GEOMETRY)
GeometryFunctionOnScreenAdd(renderer, Vertex_OS_TransformProjectBoundsGeom);
else
GeometryFunctionOnScreenAdd(renderer, Vertex_OS_TransformProjectBoundsSurf);
} else {
if(renderer->state.surface.colour_source == BRT_GEOMETRY)
GeometryFunctionOnScreenAdd(renderer, Vertex_OS_TransformProjectGeom);
else
GeometryFunctionOnScreenAdd(renderer, Vertex_OS_TransformProjectSurf);
}
}
} else {
if(renderer->state.enable.flags & ENBL_BOUNDS)
GeometryFunctionOnScreenAdd(renderer, Vertex_OS_TransformProjectBounds);
else
GeometryFunctionOnScreenAdd(renderer, Vertex_OS_TransformProject);
}
/*
* Tweak for FORCE_FRONT style
*/
if(renderer->state.surface.force_front)
GeometryFunctionBothAdd(renderer, Vertex_ForceFront);
if(renderer->state.surface.force_back)
GeometryFunctionBothAdd(renderer, Vertex_ForceBack);
}