brender-1997/v1db/render.c

1099 lines
28 KiB
C
Raw Normal View History

2022-05-03 16:30:35 -05:00
/*
* Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved.
*
* $Id: render.c 2.17 1997/04/30 15:57:49 jon Exp $
* $Locker: $
*
* Traversal of hierachy for rendering
*/
// NB CHANGED FOR <REDACTEDGAME> SPECIFICALLY (uses actor->user)
#include "v1db.h"
#include "shortcut.h"
#include "brassert.h"
#include "datafile.h"
#include "formats.h"
#include "math_ip.h"
#include "..\..\csource\strat.h"
#define MarkStratAsDrawn(a) \
if ((a) > (void *)1024) ((STRAT *)(a))->flag_2|=ST_2_ONSCREEN;
#define MarkStratAsNotDrawn(a) \
if ((a) > (void *)1024) ((STRAT *)(a))->flag_2&=~ST_2_ONSCREEN;
BR_RCS_ID("$Id: render.c 2.17 1997/04/30 15:57:49 jon Exp $")
#if DEBUG
extern int trianglesInHierarchyCount;
#endif
static void actorRenderOnScreen(br_actor *ap,
br_model *model,
br_material *material,
void *render_data,
br_uint_8 style,
br_uint_16 t);
void BR_PUBLIC_ENTRY BrDbModelRender(br_actor *actor,
br_model *model,
br_material *material,
void *render_data,
br_uint_8 style,
int on_screen,
int use_custom)
{
br_int_32 count;
br_token_value tv[] = {
{BRT_V1INSERT_FUNCTION_P, 0},
{BRT_V1INSERT_ARG1_P, 0},
{BRT_V1INSERT_ARG2_P, 0},
{BRT_V1INSERT_ARG3_P, 0},
{0},
};
UASSERT(v1db.rendering != 0);
UASSERT(model != NULL);
UASSERT(material != NULL);
UASSERT(actor != NULL);
/*
* Mark local copy of model_to_screen as invalid
*/
v1db.model_to_screen_valid = BR_FALSE;
/*
* If model has custom callback, keep following it until
* a model is reached
*/
if(use_custom && (model->flags & BR_MODF_CUSTOM)) {
/*
* XXX Fetch current transforms from renderer
*/
model->custom(actor, model, material, render_data, style, on_screen);
return;
}
if(model->prepared == NULL && model->stored == NULL)
BR_ERROR1("Tried to render un-prepared model %s",model->identifier?model->identifier:"<NULL>");
/*
* Optional preparation for Z-Sort
*/
if(render_data != NULL) {
br_order_table *ot = render_data;
SetOrderTableBounds(&model->bounds, ot);
if(ot->visits == 0) {
BrZsOrderTableClear(ot);
InsertOrderTableList(ot);
}
ot->visits++;
RendererPartSet(v1db.renderer, BRT_HIDDEN_SURFACE, 0,
BRT_V1ORDER_TABLE_P, (br_uint_32) ot);
/*
* See if a 'primitive insertion' function needs to be added
*/
if(v1db.primitive_call) {
tv[0].v.p = v1db.primitive_call;
tv[1].v.p = actor;
tv[2].v.p = model;
tv[3].v.p = material;
RendererPartSetMany(v1db.renderer, BRT_HIDDEN_SURFACE, 0, tv, &count);
}
}
if(v1db.bounds_call) {
br_int_32 c;
char buffer[sizeof(br_vector2)*2];
br_token_value tv[] = {
{BRT_AS_VECTOR2_SCALAR(MIN), 0},
{BRT_AS_VECTOR2_SCALAR(MAX), 0},
{0,},
};
br_int_32 int_bounds[4];
/*
* Clear bounds
*/
RendererStateDefault(v1db.renderer, BR_STATE_BOUNDS);
RenderStyleCalls[style](actor, model, material, render_data, style, on_screen);
/*
* Fetch bounds and call user op.
*/
RendererPartQueryMany(v1db.renderer, BRT_BOUNDS, 0, tv, buffer, sizeof(buffer), &c);
int_bounds[0] = BrScalarToInt(((br_vector3 *)tv[0].v.p)->v[0]);
int_bounds[1] = BrScalarToInt(((br_vector3 *)tv[0].v.p)->v[1]);
int_bounds[2] = BrScalarToInt(((br_vector3 *)tv[1].v.p)->v[0]);
int_bounds[3] = BrScalarToInt(((br_vector3 *)tv[1].v.p)->v[1]);
/*
* Clamp to screen boundary
*/
if(int_bounds[0] < 0)
int_bounds[0] = 0;
if(int_bounds[1] < 0)
int_bounds[1] = 0;
if(int_bounds[2] < 0)
int_bounds[2] = 0;
if(int_bounds[3] < 0)
int_bounds[3] = 0;
if(int_bounds[0] >= v1db.colour_buffer->width)
int_bounds[0] = v1db.colour_buffer->width-1;
if(int_bounds[1] >= v1db.colour_buffer->height)
int_bounds[1] = v1db.colour_buffer->height-1;
if(int_bounds[2] >= v1db.colour_buffer->width)
int_bounds[2] = v1db.colour_buffer->width-1;
if(int_bounds[3] >= v1db.colour_buffer->height)
int_bounds[3] = v1db.colour_buffer->height-1;
/*
* Make relative to screen origon
*/
int_bounds[0] -= v1db.colour_buffer->origin_x;
int_bounds[1] -= v1db.colour_buffer->origin_y;
int_bounds[2] -= v1db.colour_buffer->origin_x;
int_bounds[3] -= v1db.colour_buffer->origin_y;
if((int_bounds[0] <= int_bounds[2]) &&
(int_bounds[1] <= int_bounds[3]) ) {
/*
* XXX Must make sure model_to_screen is up to date
*/
v1db.bounds_call(actor, model, material, render_data, style, &v1db.model_to_screen, int_bounds);
}
} else {
RenderStyleCalls[style](actor, model, material, render_data, style, on_screen);
}
MarkStratAsDrawn (actor->user);
}
br_uint_32 BR_PUBLIC_ENTRY BrOnScreenCheck(br_bounds3 *bounds)
{
br_token r;
UASSERT_MESSAGE("Invalid BrOnScreenCheck pointer", bounds != NULL);
RendererBoundsTest(v1db.renderer, &r, (void *)bounds);
return r;
}
/*
* Prepend an actor's transform onto the model->view transform and return the new combined transform
* type
*/
static br_uint_16 prependActorTransform(br_actor *ap, br_uint_16 t)
{
br_matrix34 mt;
ASSERT_MESSAGE("Invalid prependActorTransform pointer", ap != NULL);
#if 0
/*
* See if this actor is on the camera path - if so, generate a new transform
*/
if(ap == v1db.camera_path[ap->depth].a) {
RendererPartSet(v1db.renderer, BRT_MATRIX, 0,
BRT_AS_MATRIX34_SCALAR(MODEL_TO_VIEW), (br_uint_32)&v1db.camera_path[ap->depth].m);
t = v1db.camera_path[ap->depth].transform_type;
RendererPartSet(v1db.renderer, BRT_MATRIX, 0,
BRT_MODEL_TO_VIEW_HINT_T, BrTransformTypeIsLP(t)?BRT_LENGTH_PRESERVING:BRT_NONE);
RendererModelInvert(v1db.renderer);
} else {
if(BrTransformTypeIsMatrix34(ap->t.type))
RendererModelMul(v1db.renderer, (void *)&ap->t.t.mat);
else {
BrTransformToMatrix34(&mt, &ap->t);
RendererModelMul(v1db.renderer, (void *)&mt);
}
t = BrTransformCombineTypes(t, ap->t.type);
RendererPartSet(v1db.renderer, BRT_MATRIX, 0,
BRT_MODEL_TO_VIEW_HINT_T, BrTransformTypeIsLP(t)?BRT_LENGTH_PRESERVING:BRT_NONE);
}
#else
if(BrTransformTypeIsMatrix34(ap->t.type)) {
RendererModelMul(v1db.renderer, (void *)&ap->t.t.mat);
} else {
BrTransformToMatrix34(&mt, &ap->t);
RendererModelMul(v1db.renderer, (void *)&mt);
}
t = BrTransformCombineTypes(t, ap->t.type);
RendererPartSet(v1db.renderer, BRT_MATRIX, 0,
BRT_MODEL_TO_VIEW_HINT_T, BrTransformTypeIsLP(t)?BRT_LENGTH_PRESERVING:BRT_NONE);
#endif
return t;
}
static br_uint_16 prependMatrix(br_matrix34 *mat, br_uint_16 mat_t, br_uint_16 t)
{
ASSERT_MESSAGE("Invalid prependMatrix pointer", mat != NULL);
RendererModelMul(v1db.renderer, (void *)mat);
t = BrTransformCombineTypes(t, mat_t);
RendererPartSet(v1db.renderer, BRT_MATRIX, 0,
BRT_MODEL_TO_VIEW_HINT_T,
BrTransformTypeIsLP(t)?BRT_LENGTH_PRESERVING:BRT_NONE);
return t;
}
/*
* Rendering traversal for the given actor
*/
static void actorRender(br_actor *ap,
br_model *model,
br_material *material,
void *render_data,
br_uint_8 style,
br_uint_16 t)
{
/*
* Saved state
*/
br_material *this_material;
br_model *this_model;
void *this_render_data;
br_actor *a;
br_token s;
ASSERT_MESSAGE("Invalid actorRender pointer", model != NULL);
ASSERT_MESSAGE("Invalid actorRender pointer", material != NULL);
MarkStratAsNotDrawn (ap->user);
/*
* Ignore actors with no children that are not models, and actors with renderstyle = NONE
*/
if(ap->children == NULL && ap->type != BR_ACTOR_MODEL)
return;
/*
* See if this actor overrides default material, model, render_data or style
*/
if(ap->render_style != BR_RSTYLE_DEFAULT)
style = ap->render_style;
if(style == BR_RSTYLE_NONE)
return;
#if DEBUG && defined(_DEBUG)
if((!ap->model)&&(ap->type==BR_ACTOR_MODEL))
printf("using default model\n");
#endif
this_material = ap->material?ap->material:material;
this_model = ap->model?ap->model:model;
this_render_data=ap->render_data?ap->render_data:render_data;
/*
* Catch special case of identity transforms
*/
if(ap->t.type == BR_TRANSFORM_IDENTITY) {
/**
** Actor has no transform
**/
switch(ap->type) {
case BR_ACTOR_MODEL:
/*
* This is a model - see if model's bounding box is on screen
*/
#if DEBUG
{
int a;
struct v11model *mdl=(struct v11model*)this_model->prepared;
for(a=0;a<mdl->ngroups;a++){
trianglesInHierarchyCount+=mdl->groups[a].nfaces;
}
}
#endif
if((s = BrOnScreenCheck(&this_model->bounds)) != OSC_REJECT) {
BrDbModelRender(ap, this_model, this_material, this_render_data, style, s, 1);
}
break;
case BR_ACTOR_BOUNDS:
/*
* A bounding box - truncate whole tree if rejected
*/
if(BrOnScreenCheck(ap->type_data) == OSC_REJECT)
/* DONT PROCESS CHILDREN */
return;
break;
case BR_ACTOR_BOUNDS_CORRECT:
/*
* A garuanteed bounding box - test to see if it is on screen
*/
switch(BrOnScreenCheck(ap->type_data)) {
case OSC_ACCEPT:
/*
* Bounding box is completely on screen - process children with special loop
*/
BR_FOR_SIMPLELIST(&ap->children, a)
actorRenderOnScreen(a,this_model,this_material,this_render_data, style, t);
/* FALL THROUGH */
case OSC_REJECT:
/* DONT PROCESS CHILDREN */
return;
}
}
/*
* Recurse for children
*/
BR_FOR_SIMPLELIST(&ap->children, a)
actorRender(a, this_model, this_material, this_render_data, style, t);
return;
}
/**
** Actor has a transform
**/
/*
* Save the current transforms
*/
RendererStatePush(v1db.renderer, BR_STATE_MATRIX);
t = prependActorTransform(ap, t);
switch(ap->type) {
case BR_ACTOR_MODEL:
#if DEBUG
{
int a;
struct v11model *mdl=(struct v11model*)this_model->prepared;
for(a=0;a<mdl->ngroups;a++){
trianglesInHierarchyCount+=mdl->groups[a].nfaces;
}
}
#endif
/*
* This is a model - see if model's bounding box is on screen
*/
if((s = BrOnScreenCheck(&this_model->bounds)) != OSC_REJECT) {
BrDbModelRender(ap, this_model, this_material, this_render_data, style, s, 1);
}
break;
case BR_ACTOR_BOUNDS:
/*
* A bounding box - truncate whole tree if rejected
*/
if(BrOnScreenCheck(ap->type_data) == OSC_REJECT) {
RendererStatePop(v1db.renderer, BR_STATE_MATRIX);
return;
}
break;
case BR_ACTOR_BOUNDS_CORRECT:
/*
* A garuanteed bounding box - test to see if it is on screen
*/
switch(BrOnScreenCheck(ap->type_data)) {
case OSC_ACCEPT:
/*
* Bounding box is completely on screen - process children with special loop
*/
BR_FOR_SIMPLELIST(&ap->children, a)
actorRenderOnScreen(a, this_model, this_material, this_render_data, style, t);
/* FALL THROUGH */
case OSC_REJECT:
/*
* Don't process children
*/
RendererStatePop(v1db.renderer, BR_STATE_MATRIX);
return;
}
}
/*
* Recurse for children
*/
BR_FOR_SIMPLELIST(&ap->children, a)
actorRender(a, this_model, this_material, this_render_data, style, t);
/*
* Restore transforms
*/
RendererStatePop(v1db.renderer, BR_STATE_MATRIX);
}
/*
* Rendering traversal for an actor that is completely on screen, along
* with any children
*/
static void actorRenderOnScreen(br_actor *ap,
br_model *model,
br_material *material,
void *render_data,
br_uint_8 style,
br_uint_16 t)
{
/*
* Saved state
*/
br_material *this_material;
br_model *this_model;
void *this_render_data;
br_actor *a;
ASSERT_MESSAGE("Invalid actorRenderOnScreen pointer", model != NULL);
ASSERT_MESSAGE("Invalid actorRenderOnScreen pointer", material != NULL);
/*
* See if this actor overrides default material, model or style
*/
if(ap->render_style != BR_RSTYLE_DEFAULT)
style = ap->render_style;
if(style == BR_RSTYLE_NONE)
return;
this_material = ap->material?ap->material:material;
this_model = ap->model?ap->model:model;
this_render_data=ap->render_data?ap->render_data:render_data;
/*
* Catch special case of identity transforms
*/
if(ap->t.type == BR_TRANSFORM_IDENTITY) {
/*
* This actor has no transform
*/
if(ap->type == BR_ACTOR_MODEL)
BrDbModelRender(ap, this_model, this_material, this_render_data, style, OSC_ACCEPT, 1);
BR_FOR_SIMPLELIST(&ap->children, a)
actorRenderOnScreen(a,this_model,this_material, this_render_data, style, t);
return;
}
/**
** Actor has a transform
**/
/*
* Save the current transforms
*/
RendererStatePush(v1db.renderer, BR_STATE_MATRIX);
t = prependActorTransform(ap, t);
if(ap->type == BR_ACTOR_MODEL)
BrDbModelRender(ap, this_model, this_material, this_render_data, style, OSC_ACCEPT, 1);
BR_FOR_SIMPLELIST(&ap->children, a)
actorRenderOnScreen(a, this_model, this_material, this_render_data, style, t);
/*
* Restore transforms
*/
RendererStatePop(v1db.renderer, BR_STATE_MATRIX);
}
/*
* Render all the children of root
*/
static void sceneRenderWorld(br_actor *world)
{
br_model *model = v1db.default_model;
br_material *material = v1db.default_material;
void *render_data = v1db.default_render_data;
br_uint_8 style = BR_RSTYLE_DEFAULT;
br_actor *a;
if(world->model)
model = world->model;
if(world->material)
material = world->material;
if(world->render_data)
render_data = world->render_data;
if(world->render_style != BR_RSTYLE_DEFAULT)
style = world->render_style;
BR_FOR_SIMPLELIST(&world->children, a)
actorRender(a, model, material, render_data, style, (br_uint_16)v1db.ttype);
}
/*
* Add a sub-tree to the current rendering pass -
*
* Walks up tree from provided actor to find the material, model and
* style to inherit
*/
static void sceneRenderAdd(br_actor *tree)
{
br_material *material = NULL;
br_model *model = NULL;
void *render_data = NULL;
br_uint_8 style = BR_RSTYLE_DEFAULT;
br_actor *a;
br_int_32 t;
br_matrix34 m;
if(tree->parent == NULL) {
/*
* Simple case for when added tree is unconnected
*/
actorRender(tree,
v1db.default_model,
v1db.default_material,
v1db.default_render_data, BR_RSTYLE_DEFAULT,
(br_uint_16)v1db.ttype);
return;
}
t = BR_TRANSFORM_IDENTITY;
BrMatrix34Identity(&m);
/*
* Walk back to current rendering root
*/
for(a = tree->parent; a ; a = a->parent) {
/*
* Closest material, model and render_data
*/
if(material == NULL && a->material)
material = a->material;
if(model == NULL && a->model)
model = a->model;
if(render_data == NULL && a->render_data)
render_data = a->render_data;
/*
* Furthest style
*/
if(a->render_style != BR_RSTYLE_DEFAULT)
style = a->render_style;
/*
* Quit if we have go the the root that is
* being used for the current rendering pass
* (before accumulating transform s.t. we do not
* include root's transform
*/
if(a == v1db.render_root)
break;
/*
* Accumulate transform
*/
if(a->t.type != BR_TRANSFORM_IDENTITY) {
BrMatrix34PostTransform(&m,&a->t);
t = BrTransformCombineTypes(t,a->t.type);
}
}
if(material == NULL)
material = v1db.default_material;
if(model == NULL)
model = v1db.default_model;
if(render_data == NULL)
render_data = v1db.default_render_data;
if(t == BR_TRANSFORM_IDENTITY) {
actorRender(tree, model, material, render_data, style,
(br_uint_16)v1db.ttype);
} else {
RendererStatePush(v1db.renderer, BR_STATE_MATRIX);
t = prependMatrix(&m, (unsigned short)t, (unsigned short)v1db.ttype);
actorRender(tree, model, material, render_data, style,
(br_uint_16)t);
RendererStatePop(v1db.renderer, BR_STATE_MATRIX);
}
}
/*
* BrDbSceneRenderBegin()
*
* Setup a new scene to be rendered - processes the camera, lights
* and environment
*/
void BR_PUBLIC_ENTRY BrDbSceneRenderBegin(br_actor *world,
br_actor *camera)
{
br_matrix34 tfm;
br_matrix4 vtos;
br_actor *a;
int i;
br_token vtos_type;
br_uint_32 dummy;
UASSERT_MESSAGE("No renderer present", v1db.renderer != NULL );
UASSERT_MESSAGE("Invalid BrDbSceneRenderBegin pointer", world != NULL);
UASSERT_MESSAGE("Invalid BrDbSceneRenderBegin pointer", camera != NULL);
/*
* Work out View Transform from info. in camera actor
*/
vtos_type = CameraToScreenMatrix4(&vtos, camera);
RendererPartSet(v1db.renderer, BRT_MATRIX, 0, BRT_AS_MATRIX4_SCALAR(VIEW_TO_SCREEN), (br_uint_32)&vtos);
RendererPartSet(v1db.renderer, BRT_MATRIX, 0, BRT_VIEW_TO_SCREEN_HINT_T, (br_uint_32)vtos_type);
RendererPartSet(v1db.renderer, BRT_MATRIX, 0, BRT_AS_SCALAR(HITHER_Z), *(br_uint_32 *)&((br_camera *)camera->type_data)->hither_z);
RendererPartSet(v1db.renderer, BRT_MATRIX, 0, BRT_AS_SCALAR(YON_Z), *(br_uint_32 *)&((br_camera *)camera->type_data)->yon_z);
/*
* Collect transforms from camera to root
*
* Make a stack of cumulative transforms for each level between
* the camera and the root - this is so that model->view
* transforms can use the shortest route, rather than via the root
*/
for(i=0; i< MAX_CAMERA_DEPTH; i++)
v1db.camera_path[i].a = NULL;
i = camera->depth;
a = camera;
BrMatrix34Identity(&v1db.camera_path[i].m);
v1db.camera_path[i].transform_type = BR_TRANSFORM_IDENTITY;
for( ; (i > 0) && (a != world) ; a = a->parent, i--) {
ASSERT(a != NULL);
BrMatrix34Transform(&tfm,&a->t);
BrMatrix34Mul(&v1db.camera_path[i-1].m,&v1db.camera_path[i].m,&tfm);
v1db.camera_path[i-1].transform_type = BrTransformCombineTypes(v1db.camera_path[i].transform_type, a->t.type);
v1db.camera_path[i].a = a;
}
if(world != a)
BR_ERROR0("camera is not in world hierachy");
/*
* Make world->view as initial model->view
*/
RendererPartSet(v1db.renderer, BRT_MATRIX, 0,
BRT_AS_MATRIX34_SCALAR(MODEL_TO_VIEW), (br_uint_32)&v1db.camera_path[i].m);
v1db.ttype = v1db.camera_path[i].transform_type;
RendererPartSet(v1db.renderer, BRT_MATRIX, 0,
BRT_MODEL_TO_VIEW_HINT_T, BrTransformTypeIsLP(v1db.ttype)?BRT_LENGTH_PRESERVING:BRT_NONE);
RendererModelInvert(v1db.renderer);
/*
* Setup active lights, clip planes, horizon and environment
*/
RendererPartQueryBuffer(v1db.renderer, BRT_MATRIX, 0, &dummy, (br_uint_32 *)&tfm, sizeof(tfm),
BRT_AS_MATRIX34_SCALAR(MODEL_TO_VIEW));
BrSetupLights(world, &tfm, v1db.ttype);
BrSetupClipPlanes(world, &tfm, v1db.ttype, &vtos);
BrSetupEnvironment(world, &tfm, v1db.ttype);
BrSetupHorizons(world, &tfm, v1db.ttype);
}
/*
* Set a callback function for bounding rectangles
*/
br_renderbounds_cbfn * BR_PUBLIC_ENTRY BrDbSetRenderBoundsCallback(br_renderbounds_cbfn *new_cbfn)
{
br_renderbounds_cbfn *old_cbfn = v1db.bounds_call;
UASSERT_MESSAGE("Invalid BrDbSetRenderBoundsCallback pointer", new_cbfn != NULL);
v1db.bounds_call = new_cbfn;
/*
* Enable or disable bounds in renderer
*/
if(v1db.renderer)
RendererPartSet(v1db.renderer, BRT_ENABLE, 0, BRT_BOUNDS_B, (v1db.bounds_call != NULL));
return old_cbfn;
}
/*
* Draw a sparse lattice of zero pixels into the output buffer
*/
#if EVAL
static void DrawLattice(br_pixelmap *pmap)
{
int sx,sy;
for(sy = -pmap->origin_y + 32; sy < pmap->height; sy += 64)
for(sx = -pmap->origin_x + 32; sx < pmap->width; sx += 64)
BrPixelmapPixelSet(pmap, sx, sy, 0);
}
#endif
/*
* Compatibility functions
*/
static void SetOrigin(br_pixelmap *buffer)
{
ASSERT( buffer != NULL);
ASSERT_MESSAGE("SetOrigin divide by zero error", BrIntToScalar(buffer->width/2) != 0);
ASSERT_MESSAGE("SetOrigin divide by zero error", BrIntToScalar(buffer->height/2) != 0);
v1db.origin.v[0] = BR_DIV(BrIntToScalar(buffer->origin_x - buffer->width/2),
BrIntToScalar(buffer->width/2));
v1db.origin.v[1] = -BR_DIV(BrIntToScalar(buffer->origin_y - buffer->height/2),
BrIntToScalar(buffer->height/2));
}
static void SetViewport(br_pixelmap *buffer)
{
ASSERT( buffer != NULL);
v1db.vp_ox = BR_SCALAR(buffer->base_x+buffer->width/2)+BR_SCALAR(0.5);
v1db.vp_width = BR_SCALAR(buffer->width/2);
v1db.vp_oy = BR_SCALAR(buffer->height/2)+BR_SCALAR(0.5);
v1db.vp_height = -BR_SCALAR(buffer->height/2);
};
void BR_PUBLIC_ENTRY BrZbSceneRenderBegin(br_actor *world,
br_actor *camera,
br_pixelmap *colour_buffer,
br_pixelmap *depth_buffer)
{
br_camera *camera_data;
UASSERT_MESSAGE("No renderer present", v1db.renderer != NULL );
UASSERT(v1db.rendering == RENDERING_NONE);
UASSERT_MESSAGE("Invalid BrZbSceneRenderBegin actor pointer", world != NULL);
UASSERT_MESSAGE("Invalid BrZbSceneRenderBegin actor pointer", camera != NULL);
UASSERT_MESSAGE("Invalid BrZbSceneRenderBegin pixelmap pointer", colour_buffer != NULL);
UASSERT_MESSAGE("Invalid BrZbSceneRenderBegin pixelmap pointer", depth_buffer != NULL);
v1db.rendering = RENDERING_ZB;
v1db.render_root = world;
v1db.colour_buffer = colour_buffer;
/*
* Setup output state for renderer
*/
SetOrigin(colour_buffer);
SetViewport(colour_buffer);
RendererPartSet(v1db.renderer, BRT_OUTPUT, 0, BRT_COLOUR_BUFFER_O, (br_uint_32) colour_buffer);
RendererPartSet(v1db.renderer, BRT_OUTPUT, 0, BRT_DEPTH_BUFFER_O, (br_uint_32) depth_buffer);
/*
* Setup primitives heap and order table for deferred primitives
*/
if(v1db.format_buckets != NULL) {
v1db.heap.current = v1db.heap.base;
camera_data=(br_camera *)camera->type_data;
v1db.default_order_table->max_z=camera_data->yon_z;
v1db.default_order_table->min_z=camera_data->hither_z;
v1db.default_order_table->visits = 0;
v1db.order_table_list = NULL;
RendererPartSet(v1db.renderer, BRT_HIDDEN_SURFACE, 0, BRT_V1ORDER_TABLE_P, (br_uint_32) v1db.default_order_table);
RendererPartSet(v1db.renderer, BRT_HIDDEN_SURFACE, 0, BRT_V1PRIMITIVE_HEAP_P, (br_uint_32) &v1db.heap);
RendererPartSet(v1db.renderer, BRT_HIDDEN_SURFACE, 0, BRT_TYPE_T, BRT_BUCKET_SORT_DEFERRED);
v1db.default_render_data = v1db.default_order_table;
} else {
RendererPartSet(v1db.renderer, BRT_HIDDEN_SURFACE, 0, BRT_TYPE_T, BRT_NONE);
v1db.default_render_data = NULL;
}
BrDbSceneRenderBegin(world, camera);
}
void BR_PUBLIC_ENTRY BrZbSceneRenderAdd(br_actor *tree)
{
UASSERT(v1db.rendering == RENDERING_ZB);
UASSERT_MESSAGE("Invalid BrZbSceneRenderAdd pointer", tree != NULL);
sceneRenderAdd(tree);
}
void BR_PUBLIC_ENTRY BrZbSceneRenderEnd(void)
{
UASSERT(v1db.rendering == RENDERING_ZB);
/*
* Draw any deferred primitives
*/
if(v1db.format_buckets != NULL)
if(v1db.primary_order_table) {
/*
* Render primitives in the primary order table
* and the list of order tables
*/
RenderPrimaryOrderTable();
} else {
/*
* Render primitives in the list of order table
*/
RenderOrderTableList();
}
/*
* Overlay lattice if evaluation version
*/
#if EVAL
DrawLattice(v1db.colour_buffer);
#endif
/*
* Tell the renderer to flush
*/
RendererFlush(v1db.renderer, BR_FALSE);
v1db.rendering = RENDERING_NONE;
v1db.render_root = NULL;
}
void BR_PUBLIC_ENTRY BrZbSceneRender(
br_actor *world,
br_actor *camera,
br_pixelmap *colour_buffer,
br_pixelmap *depth_buffer)
{
UASSERT_MESSAGE("No renderer present", v1db.renderer != NULL );
UASSERT_MESSAGE("Invalid BrZbSceneRender actor pointer", world != NULL);
UASSERT_MESSAGE("Invalid BrZbSceneRender actor pointer", camera != NULL);
UASSERT_MESSAGE("Invalid BrZbSceneRender pixelmap pointer", colour_buffer != NULL);
UASSERT_MESSAGE("Invalid BrZbSceneRender pixelmap pointer", depth_buffer != NULL);
// Stop BRender dying horribly when no renderer is loaded
if ( v1db.renderer )
{
BrZbSceneRenderBegin(world, camera, colour_buffer, depth_buffer);
sceneRenderWorld(world);
BrZbSceneRenderEnd();
}
}
void BR_PUBLIC_ENTRY BrZsSceneRenderBegin(br_actor *world,
br_actor *camera,
br_pixelmap *colour_buffer)
{
br_camera *camera_data;
UASSERT(v1db.renderer != NULL);
UASSERT(v1db.rendering == RENDERING_NONE);
UASSERT_MESSAGE("Invalid BrZsSceneRenderBegin actor pointer", world != NULL);
UASSERT_MESSAGE("Invalid BrZsSceneRenderBegin actor pointer", camera != NULL);
UASSERT_MESSAGE("Invalid BrZsSceneRenderBegin pixelmap pointer", colour_buffer != NULL);
v1db.rendering = RENDERING_ZS;
v1db.render_root = world;
v1db.colour_buffer = colour_buffer;
SetOrigin(colour_buffer);
SetViewport(colour_buffer);
RendererPartSet(v1db.renderer, BRT_OUTPUT, 0, BRT_COLOUR_BUFFER_O, (br_uint_32) colour_buffer);
RendererPartSet(v1db.renderer, BRT_OUTPUT, 0, BRT_DEPTH_BUFFER_O, 0);
/*
* Setup primitives heap and order table
*/
v1db.heap.current = v1db.heap.base;
camera_data=(br_camera *)camera->type_data;
v1db.default_order_table->max_z=camera_data->yon_z;
v1db.default_order_table->min_z=camera_data->hither_z;
v1db.default_order_table->visits = 0;
v1db.order_table_list = NULL;
RendererPartSet(v1db.renderer, BRT_HIDDEN_SURFACE, 0, BRT_V1ORDER_TABLE_P, (br_uint_32) v1db.default_order_table);
RendererPartSet(v1db.renderer, BRT_HIDDEN_SURFACE, 0, BRT_V1PRIMITIVE_HEAP_P, (br_uint_32) &v1db.heap);
RendererPartSet(v1db.renderer, BRT_HIDDEN_SURFACE, 0, BRT_TYPE_T, BRT_BUCKET_SORT);
v1db.default_render_data = v1db.default_order_table;
BrDbSceneRenderBegin(world, camera);
}
void BR_PUBLIC_ENTRY BrZsSceneRenderAdd(br_actor *tree)
{
UASSERT(v1db.rendering == RENDERING_ZS);
UASSERT_MESSAGE("Invalid BrZsSceneRenderAdd pointer", tree != NULL);
sceneRenderAdd(tree);
}
void BR_PUBLIC_ENTRY BrZsSceneRenderEnd(void)
{
UASSERT(v1db.rendering == RENDERING_ZS);
RendererPartSet(v1db.renderer, BRT_OUTPUT, 0, BRT_COLOUR_BUFFER_O, (br_uint_32) v1db.colour_buffer);
if(v1db.format_buckets == NULL)
BR_ERROR0("Renderer does not support buckets");
if(v1db.primary_order_table) {
/*
* Render primitives in the primary order table
* and the list of order tables
*/
RenderPrimaryOrderTable();
} else {
/*
* Render primitives in the list of order table
*/
RenderOrderTableList();
}
/*
* Overlay lattice if evaluation version
*/
#if EVAL
DrawLattice(v1db.colour_buffer);
#endif
/*
* Tell the renderer to flush
*/
RendererFlush(v1db.renderer, BR_FALSE);
v1db.rendering = RENDERING_NONE;
v1db.render_root = NULL;
}
/*
* Wrapper that invokes above three calls in order
*/
void BR_PUBLIC_ENTRY BrZsSceneRender(br_actor *world,
br_actor *camera,
br_pixelmap *colour_buffer)
{
UASSERT_MESSAGE("No renderer present", v1db.renderer != NULL );
UASSERT_MESSAGE("Invalid BrZsSceneRender actor pointer", world != NULL);
UASSERT_MESSAGE("Invalid BrZsSceneRender actor pointer", camera != NULL);
UASSERT_MESSAGE("Invalid BrZsSceneRender pixelmap pointer", colour_buffer != NULL);
// Stop BRender dying horribly when no renderer present.
if ( v1db.renderer )
{
BrZsSceneRenderBegin(world, camera, colour_buffer);
sceneRenderWorld(world);
BrZsSceneRenderEnd();
}
}
br_primitive_cbfn * BR_PUBLIC_ENTRY BrZsPrimitiveCallbackSet(br_primitive_cbfn *new_cbfn)
{
br_primitive_cbfn *old_cbfn = v1db.primitive_call;
v1db.primitive_call = new_cbfn;
return old_cbfn;
}
void BR_PUBLIC_ENTRY BrZbModelRender(br_actor *actor,
br_model *model,
br_material *material,
br_uint_8 style,
int on_screen,
int use_custom)
{
UASSERT_MESSAGE("Invalid BrZbModelRender model actor pointer", actor != NULL);
UASSERT_MESSAGE("Invalid BrZbModelRender model pointer", model != NULL);
UASSERT_MESSAGE("Invalid BrZbModelRender material pointer", material != NULL);
BrDbModelRender(actor, model, material, NULL, style, on_screen, use_custom);
}
void BR_PUBLIC_ENTRY BrZsModelRender(br_actor *actor,
br_model *model,
br_material *material,
br_order_table *order_table,
br_uint_8 style,
int on_screen,
int use_custom)
{
UASSERT_MESSAGE("Invalid BrZsModelRender model actor pointer", actor != NULL);
UASSERT_MESSAGE("Invalid BrZsModelRender model pointer", model != NULL);
UASSERT_MESSAGE("Invalid BrZsModelRender material pointer", material != NULL);
UASSERT_MESSAGE("Invalid BrZsModelRender order table pointer", order_table != NULL);
BrDbModelRender(actor, model, material, order_table, style, on_screen, use_custom);
}
br_renderbounds_cbfn * BR_PUBLIC_ENTRY BrZbRenderBoundsCallbackSet(br_renderbounds_cbfn *new_cbfn)
{
ASSERT(new_cbfn != NULL);
if ( !v1db.zb_active )
{
BR_ERROR0("BrZbSetRenderBoundsCallback called before BrZbBegin");
return NULL ;
}
else
return BrDbSetRenderBoundsCallback(new_cbfn);
}
br_renderbounds_cbfn * BR_PUBLIC_ENTRY BrZsRenderBoundsCallbackSet(br_renderbounds_cbfn *new_cbfn)
{
ASSERT(new_cbfn != NULL);
if ( !v1db.zs_active )
{
BR_ERROR0("BrZsSetRenderBoundsCallback called before BrZsBegin");
return NULL ;
}
else
return BrDbSetRenderBoundsCallback(new_cbfn);
}