Files
RP412/MUNGA_L4/L4VIDEO.cpp
T
CydandClaude Fable 5 b97dcce3a2 Pilot callsigns on the Winners Circle plates
The plates beside each spot came out blank. They ask for textures called
player1..player8, which are not files - the renderer draws each pilot's
callsign into a texture at run time - so the load failed and left them
untextured. Nothing bound the two together.

SortAndReloadNameBitmaps already builds those textures indexed by
finishing place, which is exactly how the plates are numbered, so the
plate beside each spot wants mNameTextures[place]. Binding them is the
whole fix, but it takes two steps rather than one.

The plates have to survive mesh consolidation first. Static geometry is
merged with D3DXConcatenateMeshes and its draw ops deduped by material -
and eight failed texture loads leave eight identical untextured ops, so
all eight plates collapse into one that could only ever carry a single
name. Each plate now gets a distinct 1x1 marker texture as it loads,
which keeps it a subset of its own. The marker is never seen.

Then the binding runs against the consolidated mesh, not the objects the
plates were loaded from - by podium time those have been merged away and
are no longer drawn, which is why re-pointing them changed nothing.

Verified on a race: 8 plates found in the consolidated mesh, 1 bound,
and the winner's plate reads their callsign under their vehicle. One
bound of eight is right for a single-pod race - the rest of the places
have nobody in them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 14:40:53 -05:00

7843 lines
256 KiB
C++

#include "mungal4.h"
#pragma hdrstop
#include "..\munga\door.h"
#include "..\munga\doorfram.h"
#include "..\munga\eyecandy.h"
#include "l4vidrnd.h"
#include "l4video.h"
#include "..\munga\matrix.h"
#include "..\munga\mover.h"
#include "..\munga\jmover.h"
#include "..\munga\player.h"
#include "..\munga\camship.h"
#include "..\munga\director.h"
#include "..\munga\mission.h"
#include "..\munga\cultural.h"
#include "..\munga\nttmgr.h"
#include "..\munga\app.h"
#include "l4particles.h"
#include "DXUtils.h"
using namespace std;
#include <conio.h>
#include <vector>
#include <hash_map>
#include <map>
LPDIRECT3D9 gD3D = NULL;
// Single-window cockpit: viewscreen child window the scene presents into
// (NULL = present to the device window as always).
HWND gMainPresentWindow = NULL;
//STUBBED: DPL RB 1/14/07
// when this is resolved it can be removed
#include "..\DPLSTUB.h"
#include <d3dx9.h>
#define char8 unsigned char
#define uint32 unsigned __int32
// basic macro to help with releasing things
#define SAFE_RELEASE(handle) if (handle) { handle->Release(); handle = NULL; }
#define PILL_COUNT 20
#define PILL_SIZE (y_size*0.03125) // 32 @ 1280x1024
#define PILL_SPACING (PILL_SIZE*0.625) // 20 @ 1280x1024
#define LOAD_COLOR 0xFF6565FF
#define FADE_IN 0.05f
#define PILL_ON 0.05f
#define FADE_OUT 0.5f
#define LOAD_TEXT_HEIGHT PILL_SIZE // 32 @ 1280x1024
#define LOAD_TEXT_WIDTH (LOAD_TEXT_HEIGHT*12.125) // 388 @ 1280x1024
#define PS_OFF 0
#define PS_FADINGIN 1
#define PS_ON 2
#define PS_FADINGOUT 3
#define LOAD_TEXT_VERT (PILL_SIZE/2.0)
#ifdef LOGFRAMERATE
FILE *FRAMERATE_LOG;
#endif
//
// Includes for the DPL libraries
//
// RB 1/15/07
//#include <dpl\dpl.h>
//#include <dpl\dpl_2d.h>
//#include <dpl\dpl_vpx.h>
//#include <dpl\dplutils.h>
//#include <dpl\matrix.h>
//
// You can enable or disable these traces here for quicker rebuilding during
// profile testing, but for production they should be all turned off!
//
//#define TRACE_VIDEO_CULL_SETUP
//#define TRACE_VIDEO_VEHICLE_RENDERABLES
// #define TRACE_VIDEO_ALL_RENDERABLES
//
// These are other traces you can use to extract data
//
#if defined(TRACE_VIDEO_LOAD_OBJECT)
static BitTrace Video_Load_Object("Video Load Object");
#define SET_VIDEO_LOAD_OBJECT() Video_Load_Object.Set()
#define CLEAR_VIDEO_LOAD_OBJECT() Video_Load_Object.Clear()
#else
#define SET_VIDEO_LOAD_OBJECT()
#define CLEAR_VIDEO_LOAD_OBJECT()
#endif
#if defined(TRACE_VIDEO_CONSTRUCT_ROOT)
static BitTrace Video_Construct_Root("Video Construct Root");
#define SET_VIDEO_CONSTRUCT_ROOT() Video_Construct_Root.Set()
#define CLEAR_VIDEO_CONSTRUCT_ROOT() Video_Construct_Root.Clear()
#else
#define SET_VIDEO_CONSTRUCT_ROOT()
#define CLEAR_VIDEO_CONSTRUCT_ROOT()
#endif
//
// This is the time spent fetching and processing the pickpoint information
// from the DPL renderer.
//
#if defined(TRACE_VIDEO_PICKPOINT)
static BitTrace Video_Pickpoint("Video Pickpoint");
#define SET_VIDEO_PICKPOINT() Video_Pickpoint.Set()
#define CLEAR_VIDEO_PICKPOINT() Video_Pickpoint.Clear()
#else
#define SET_VIDEO_PICKPOINT()
#define CLEAR_VIDEO_PICKPOINT()
#endif
//
// Traces the time spent setting up the video culling parameters
//
#if defined(TRACE_VIDEO_CULL_SETUP)
static BitTrace Video_Cull_Setup("Video Cull Setup");
# define SET_VIDEO_CULL_SETUP() Video_Cull_Setup.Set()
# define CLEAR_VIDEO_CULL_SETUP() Video_Cull_Setup.Clear()
#else
# define SET_VIDEO_CULL_SETUP()
# define CLEAR_VIDEO_CULL_SETUP()
#endif
//
// This trace covers the entire time spent executing renderables as one
// transition. It goes up when the execute implimentation starts running
// over the all iterator and goes down when it's done.
//
#if defined(TRACE_VIDEO_RENDERABLES)
static BitTrace Video_Renderables("Video Renderables");
#define SET_VIDEO_RENDERABLES() Video_Renderables.Set()
#define CLEAR_VIDEO_RENDERABLES() Video_Renderables.Clear()
#else
#define SET_VIDEO_RENDERABLES()
#define CLEAR_VIDEO_RENDERABLES()
#endif
//
// Traces time spent executing renderables that belong to a vehicle entity
// (currently Mech, VTV or BTPlayer)
//
#if defined(TRACE_VIDEO_VEHICLE_RENDERABLES)
static BitTrace Video_Vehicle_Renderables("Video Vehicle Renderables");
# define SET_VIDEO_VEHICLE_RENDERABLES() Video_Vehicle_Renderables.Set()
# define CLEAR_VIDEO_VEHICLE_RENDERABLES() Video_Vehicle_Renderables.Clear()
#else
# define SET_VIDEO_VEHICLE_RENDERABLES()
# define CLEAR_VIDEO_VEHICLE_RENDERABLES()
#endif
//
// This trace will transition as each individual renderable is executed.
// It will buzz and cause serious impact to the accuracy of the trace but is
// good for identifying time-eating individual renderables
//
#if defined(TRACE_VIDEO_ALL_RENDERABLES)
static BitTrace Video_All_Renderables("Video All Renderables");
# define SET_VIDEO_ALL_RENDERABLES() Video_All_Renderables.Set()
# define CLEAR_VIDEO_ALL_RENDERABLES() Video_All_Renderables.Clear()
#else
# define SET_VIDEO_ALL_RENDERABLES()
# define CLEAR_VIDEO_ALL_RENDERABLES()
#endif
//
// This is the routine that does a DPL_FlushArticulations on the batch of
// DCS's that we've been holding during rendering, std::flushing them all to
// the card in a big batch
//
#if defined(TRACE_VIDEO_BATCH_FLUSH)
static BitTrace Video_Batch_Flush("Video Batch Flush");
# define SET_VIDEO_BATCH_FLUSH() Video_Batch_Flush.Set()
# define CLEAR_VIDEO_BATCH_FLUSH() Video_Batch_Flush.Clear()
#else
# define SET_VIDEO_BATCH_FLUSH()
# define CLEAR_VIDEO_BATCH_FLUSH()
#endif
//
// This trace shows the time spent doing the "frame done" processing where the
// renderer waits for the DPL card to become ready and then issues a command
// to start the scene drawing. An additional batch std::flush can happen here.
// If USE_ONE_VIDEO_TRACE is turned on, data from this trace will show up as
// part of the Video_Renderer trace.
//
#if defined(TRACE_VIDEO_RENDERER_FRAME_DONE)
# if defined(USE_ONE_VIDEO_TRACE)
# define SET_VIDEO_RENDERER_FRAME_DONE() Video_Renderer.Set()
# define CLEAR_VIDEO_RENDERER_FRAME_DONE() Video_Renderer.Clear()
# else
static BitTrace Video_Renderer_Frame_Done("Video Renderer Frame Done");
# define SET_VIDEO_RENDERER_FRAME_DONE() Video_Renderer_Frame_Done.Set()
# define CLEAR_VIDEO_RENDERER_FRAME_DONE() Video_Renderer_Frame_Done.Clear()
# endif
#else
# define SET_VIDEO_RENDERER_FRAME_DONE()
# define CLEAR_VIDEO_RENDERER_FRAME_DONE()
#endif
//
// The following traces are specifically designed for profileing the low level
// DPL routines in Division's libraries. You need to link to a special "profile"
// version of the division libraries for these to work. If you enable them
// with a production libdpl you will get NO traces. If you disable them and
// try to link to a profile version of libdpl you will get link errors. Sorry
// but this is the most efficient way of connecting the c++ trace routines to
// the C code of division's libraries.
//
// There are switches in the DPL libraries that handle turning these functions
// on and off in the profile version.
//
//#define TRACE_DPL_LOAD_OBJECT
//#define TRACE_DPL_TRANSPUTER_LINK // will buzz
//#define TRACE_DPL_DO_OUTSW // will buzz
//#define TRACE_DPL_OUTINT32 // will buzz
#if defined(TRACE_DPL_LOAD_OBJECT)
static BitTrace DPL_Load_Object("DPL Load Object");
extern "C"
{
void Set_DPL_Load_Object();
void Clear_DPL_Load_Object();
}
void
Set_DPL_Load_Object()
{
DPL_Load_Object.Set();
}
void
Clear_DPL_Load_Object()
{
DPL_Load_Object.Clear();
}
#endif
#if defined(TRACE_DPL_TRANSPUTER_LINK)
static BitTrace DPL_Transputer_Link("DPL Transputer Link");
extern "C"
{
void Set_DPL_Transputer_Link();
void Clear_DPL_Transputer_Link();
}
void
Set_DPL_Transputer_Link()
{
DPL_Transputer_Link.Set();
}
void
Clear_DPL_Transputer_Link()
{
DPL_Transputer_Link.Clear();
}
#endif
#if defined(TRACE_DPL_DO_OUTSW)
static BitTrace DPL_do_outsw("DPL do_outsw");
extern "C"
{
void Set_DPL_do_outsw();
void Clear_DPL_do_outsw();
}
void
Set_DPL_do_outsw()
{
DPL_do_outsw.Set();
}
void
Clear_DPL_do_outsw()
{
DPL_do_outsw.Clear();
}
#endif
#if defined(TRACE_DPL_OUTINT32)
static BitTrace DPL_outint32("DPL outint32");
extern "C"
{
void Set_DPL_outint32();
void Clear_DPL_outint32();
}
void
Set_DPL_outint32()
{
DPL_outint32.Set();
}
void
Clear_DPL_outint32()
{
DPL_outint32.Clear();
}
#endif
//
// The following trace will probably be obsolete soon
//
#if 0
#if defined(TRACE_VIDEO_FIRST_FRAME_DONE)
static BitTrace Video_First_Frame_Done("Video First Frame Done");
# define SET_VIDEO_FIRST_FRAME_DONE() Video_First_Frame_Done.Set()
# define CLEAR_VIDEO_FIRST_FRAME_DONE() Video_First_Frame_Done.Clear()
#else
# define SET_VIDEO_FIRST_FRAME_DONE()
# define CLEAR_VIDEO_FIRST_FRAME_DONE()
#endif
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Definitions of various debugging switches
//
#define DEBUG_SPECIAL_CALLBACK 0 // 0 = none, 1 = print special, 2 = real noisy
#define DEBUG_CREATE_CALLBACK 0 // 0 = none,
#define PRINT_THE_PFX False // Set to true and the pfx definition will print when it is read in.
#define RAPID_SECT_PIXEL True // True if you want to use the rapidsectpixel call for intersections
#define PARTICLE_TEST False // True to issue a stream of particles at the detected intersect point
#define PRINT_PICKPOINT_TEST False // True to print data whenever the intersect changes
#define NOISY_RENDERER False // True enables a lot of printouts as the renderer makes/kills object
#define USE_TRACKER_STRUCTURE False // True to enable the full tracker structure that holds damage zone names & such
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Definitions of system constants used only in this file
//
#define MAX_SPECIAL_ARGUMENTS 25 // Maximum number of arguments a "special" callback can handle
#define MAX_SPECIAL_SIZE 512 // Maximum size (characters) of a "special"
#define dpl_arg_sep '~' // seperator used when parsing dpl argument string
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Entity
*Entity_Being_Created = 0; // !!! temp, till callback handlers become a class
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// These extern "c" routines and constants are from startdpl or from dpl
// itself and need to be here.
//
extern "C" {
//STUBBED: DPL RB 1/15/07
//extern const int
// x_size, // x size of the screen (from startdpl)
// y_size; // y size of the screen (startdpl)
void
dpl_TexmapTexels2D ( // A routine from DPL we normally couldn't access
dpl_TEXMAP *tm,
uint32 *texels,
int32 u_size,
int32 v_size,
int32 bytes_per_texel);
int
screen_resolution( // Sets up the screen resolution (startdpl)
char *dpl_argv ),
explode_args( // Parses DPLARG system environmental (startdpl)
char **argv,
char *dpl_args,
char sep );
char
*dpl_TypeToString( // Converts a DPL type code into a string (libdpl)
dpl_TYPE t);
int32
dpl_DrawSceneComplete(void); // missing definition (libdpl)
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// see DPLReportPerfStats()
//STUBBED: VIDEO RB 1/15/07
//extern "C" const int32 __sect_time;
//extern "C" const int32 __last_cull_time;
//extern "C" const int32 __last_draw_time;
//extern "C" const int32 __last_frame_time;
//extern "C" const int32 __last_pxpl_time;
//extern "C" const int32 __last_frame_prims;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// dump_frame_buffer() std::declaration
void dump_frame_buffer(
dpl_VIEW *eye,
int32 x_size,
int32 y_size,
Logical antialias);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The following are definitions of DPL callback functions. These are called
// by the dpl file loader as it is loading graphics files so we can do material
// substitution and set special attributes on geometry & such.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The "special" callback is called whenever a "special" field is processed in
// incomming geometry.
// dPL special callback function type.
// typedef void (dpl_SPECIAL_CALLBACK)(dpl_TYPE type, void *handle,
// char8 *special, uint32 special_len);
static void
TestSpecialCallBack(
dpl_TYPE type,
void *handle,
char8 *special,
uint32 special_len)
{
//STUBBED: DPL RB 1/14/07
// char
// *args[MAX_SPECIAL_ARGUMENTS],
// **argptr,
// *argstring;
// int
// argcount;
// float
// u0,
// v0,
// du,
// dv;
// int32
// immunity;
// char
//// NameBuff[80],
// TempBuff[MAX_SPECIAL_SIZE + 1];
// #if USE_TRACKER_STRUCTURE
// dpl_tracker
// *this_tracker;
// #endif
//
// if(special_len > MAX_SPECIAL_SIZE)
// {
// DEBUG_STREAM<<"SPECIAL was bigger than "<<MAX_SPECIAL_SIZE<<"\n" << std::flush;
// Verify(special_len > MAX_SPECIAL_SIZE);
// }
// strncpy(TempBuff, (const char*)special, special_len);
// TempBuff[special_len] = 0;
// if(TempBuff[special_len-1] != 0)
// {
// DEBUG_STREAM<<"Caution, the following SPECIAL was not null terminated\n" << std::flush;
// printf("SPECIAL->%08x: %s, %s\n", handle, dpl_TypeToString(type), TempBuff);
// }
// #if DEBUG_SPECIAL_CALLBACK >= 1
// printf("SPECIAL->%08x: %s, %s\n", handle, dpl_TypeToString(type), TempBuff);
// #endif
////
//// Scan all the argument start points into an array for easier processing.
//// also avoids non-reentrand problem with strtok
////
// argstring = TempBuff;
// for(argcount = 0; argcount<MAX_SPECIAL_ARGUMENTS; argcount++)
// {
// args[argcount] = strtok(argstring," ");
// if(!args[argcount])
// break;
// argstring = NULL;
// }
// args[MAX_SPECIAL_ARGUMENTS-1] = 0;
////
//// Decode the dpl_type the special was found in, all I know of are listed here
//// though some we may never see.
////
// switch(type)
// {
// case dpl_type_error:
// break;
// case dpl_type_scene:
// break;
// case dpl_type_zones:
// break;
// case dpl_type_view:
// break;
// case dpl_type_instance:
// break;
// case dpl_type_dcs:
// break;
// case dpl_type_light:
// break;
// case dpl_type_object:
// for(argptr = args;
// *argptr;
// argptr++)
// {
// if (strcmp(*argptr, "ADDITIVE_LODS") == 0)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("Calling SetObjectAdditiveLODs on an object\n");
// #endif
// // REMOVE dpl_SetObjectAdditiveLODs to run with older renderers
// dpl_SetObjectAdditiveLODs ( (dpl_OBJECT *)handle);
// }
// }
// break;
// case dpl_type_lod:
// break;
// case dpl_type_geogroup:
// #if USE_TRACKER_STRUCTURE
// this_tracker = (dpl_tracker *)dpl_GetAppSpecific(handle);
// #endif
// for(argptr = args;
// *argptr;
// argptr++)
// {
// if (strncmp(*argptr, "dz_", 3) == 0)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("Doing SPECIAL GEOGROUP Damage zone ");
// #endif
//
// #if USE_TRACKER_STRUCTURE
// if (this_tracker)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("marked\n");
// #endif
// strncpy(this_tracker->dz_name, *argptr, MAX_DZ_NAME_LENGTH);
// this_tracker->dz_name[MAX_DZ_NAME_LENGTH - 1] = 0;
// #endif
// //---------------------------------------------
// // lookup damage zone index in global namelist
// //---------------------------------------------
// if (Entity_Being_Created->damageZones)
// {
// Check_Pointer(Entity_Being_Created->damageZones);
//
// int
// damage_zone_index;
//
// damage_zone_index =
// Entity_Being_Created->GetDamageZoneIndex(*argptr);
//
// if (damage_zone_index != -1)
// {
// #if USE_TRACKER_STRUCTURE
// this_tracker->Damage_Zone_Number = damage_zone_index;
// #else
// if(dpl_GetAppSpecific(handle))
// Fail("AppSpecific already set\n");
// dpl_PutAppSpecific(handle, (void *)(damage_zone_index+1));
// #endif
// }
// else
// {
// DEBUG_STREAM << std::endl << "Damage zone '" <<
// *argptr << "' not in table." << std::endl;
// }
// }
// #if USE_TRACKER_STRUCTURE
// }
// else
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("NOT marked\n");
// #endif
// }
// #endif
// }
// else if(strcmp(*argptr,"PUNCH") == 0)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("Doing SPECIAL GEOGROUP Punchize\n");
// #endif
// dpl_Punchize((dpl_GEOGROUP *)handle);
// }
// else if(strcmp(*argptr,"DAMAGE") == 0)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("Doing SPECIAL GEOGROUP damagize\n");
// #endif
// if(*(++argptr))
// {
// int
// status;
// dpl_MATERIAL *damagize_material = dpl_LookupMaterial ( *argptr, dpl_lookup_normal, &status );
// if(damagize_material)
// {
// dpl_Damagize((dpl_GEOGROUP *)handle, damagize_material);
// }
// else
// {
// DEBUG_STREAM<<"SPECIAL GEOGROUP DAMAGE couldn't find material "<<*argptr<<"\n" << std::flush;
// Verify(damagize_material);
// }
// }
// else
// {
// DEBUG_STREAM<<"SPECIAL GEOGROUP DAMAGE no material name \n" << std::flush;
// Verify(*argptr);
// }
// }
// else if(strcmp(*argptr,"WIREFRAME") == 0)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("Doing SPECIAL GEOGROUP WIREFRAME\n");
// #endif
// dpl_SetGeogroupWireframe((dpl_GEOGROUP *)handle, True);
// }
// else if(strcmp(*argptr,"GEOMETRIZE") == 0)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("Doing SPECIAL GEOGROUP geometrize\n");
// #endif
// if(*(++argptr))
// {
// dpl_GEOMETRY
// *geometry_ptr;
// long
// geometrize_code;
// int
// geometry_id = 0;
// sscanf(
// *argptr,
// "%lx",
// &geometrize_code);
// do
// {
// geometry_ptr = dpl_GetGeogroupGeometry((dpl_GEOGROUP *)handle,geometry_id);
// if(geometry_ptr)
// {
// dpl_Geometrize(geometry_ptr,geometrize_code);
// }
// geometry_id++;
// } while(geometry_ptr);
// }
// else
// {
// DEBUG_STREAM<<"SPECIAL GEOGROUP GEOMETRIZE has no geometrize code\n" << std::flush;
// Verify(*argptr);
// }
// }
// else if(strcmp(*argptr,"DRAWLAST") == 0)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("Doing SPECIAL GEOGROUP DRAWLAST\n");
// #endif
// dpl_SetGeogroupDrawLast((dpl_GEOGROUP *)handle, True);
// dpl_FlushGeogroup((dpl_GEOGROUP *)handle);
// }
// else if(strcmp(*argptr,"BLINK") == 0)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("SPECIAL GEOGROUP BLINK is not supported\n");
// #endif
// }
// else
// {
// DEBUG_STREAM<<"SPECIAL GEOGROUP "<<*argptr<<" is not a geogroup modifier\n" << std::flush;
// }
// }
// break;
// case dpl_type_geometry:
// break;
// case dpl_type_material:
// for(argptr = args;
// *argptr;
// argptr++)
// {
// if(strcmp(*argptr,"IMMUNE") == 0)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("Doing SPECIAL MATERIAL IMMUNE\n");
// #endif
// if(*(++argptr))
// {
// immunity = atol(*argptr);
// dpl_SetMaterialFogImmunity ( (dpl_MATERIAL *)handle, immunity );
// dpl_FlushMaterial((dpl_MATERIAL *)handle);
// }
// else
// {
// DEBUG_STREAM<<"SPECIAL MATERIAL IMMUNE has no immune code\n" << std::flush;
// Verify(*argptr);
// }
// }
// else
// {
// DEBUG_STREAM<<"SPECIAL MATERIAL "<<*argptr<<" is not a material modifier\n" << std::flush;
// }
// }
// break;
// case dpl_type_texture:
// for(argptr = args;
// *argptr;
// argptr++)
// {
// if(strcmp(*argptr,"SCROLL") == 0)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("Doing SCROLL\n");
// #endif
// u0 = v0 = du = dv = 0.0;
// if(*(++argptr))
// u0 = atof(*argptr);
// else
// {
// DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing u0\n" << std::flush;
// Verify(*argptr);
// }
// if(*(++argptr))
// v0 = atof(*argptr);
// else
// {
// DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing v0\n" << std::flush;
// Verify(*argptr);
// }
// if(*(++argptr))
// du = atof(*argptr);
// else
// {
// DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing du\n" << std::flush;
// Verify(*argptr);
// }
// if(*(++argptr))
// dv = atof(*argptr);
// else
// {
// DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing dv\n" << std::flush;
// Verify(*argptr);
// }
// dpl_SetTextureScroll (
// (dpl_TEXTURE *)handle,
// u0,
// v0,
// du,
// dv);
// dpl_FlushTexture((dpl_TEXTURE *)handle);
// }
// else if(strcmp(*argptr,"FAKESIZE") == 0)
// {
// #if DEBUG_SPECIAL_CALLBACK >= 2
// Tell("Doing SPECIAL TEXURE FAKESIZE\n");
// #endif
// int
// size, offset;
// if(*(++argptr))
// size = atoi(*argptr);
// else
// {
// DEBUG_STREAM<<"SPECIAL TEXTURE FAKESIZE missing size\n" << std::flush;
// Verify(*argptr);
// }
// if(*(++argptr))
// offset = atoi(*argptr);
// else
// {
// DEBUG_STREAM<<"SPECIAL TEXTURE FAKESIZE missing offset\n" << std::flush;
// Verify(*argptr);
// }
// dpl_FakeTextureSize((dpl_TEXTURE *)handle,size,offset);
// dpl_FlushTexture((dpl_TEXTURE *)handle);
// }
// else
// {
// DEBUG_STREAM<<"SPECIAL TEXTURE "<<*argptr<<" is not a texture modifier\n" << std::flush;
// }
// }
// break;
// case dpl_type_texmap:
// break;
// case dpl_type_ramp:
// break;
// }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The TestCreateCallBack callback is called whenever a dpl node of the indicated
// type is created while loading a DPL graphics file.
/* dPL create/delete callback function type. */
//typedef void (dpl_CREATE_DELETE_CALLBACK)(dpl_TYPE type, void *handle);
static void
TestCreateCallBack(
dpl_TYPE type,
#if DEBUG_CREATE_CALLBACK>=1
void *handle
#else
void *
#endif
)
{
//
// get a pointer to the node structure (first part of most dpl types)
//
#if DEBUG_CREATE_CALLBACK >=1
printf("CREATE->%08x: %s\n", handle, dpl_TypeToString(type));
#endif
switch(type)
{
case dpl_type_error:
break;
case dpl_type_scene:
break;
case dpl_type_zones:
break;
case dpl_type_view:
break;
case dpl_type_instance:
break;
case dpl_type_dcs:
break;
case dpl_type_light:
break;
case dpl_type_object:
break;
case dpl_type_lod:
break;
case dpl_type_geogroup:
#if USE_TRACKER_STRUCTURE
{
dpl_tracker *this_tracker = new dpl_tracker;
this_tracker->This_Entity = Entity_Being_Created;
this_tracker->dz_name[0] = 0;
this_tracker->Damage_Zone_Number = -1; // no damage zone (default)
if(dpl_GetAppSpecific(handle))
DEBUG_STREAM<<"app_specific hook already set!\n" << std::flush;
dpl_PutAppSpecific(handle, this_tracker);
break;
}
#endif
case dpl_type_geometry:
break;
case dpl_type_material:
break;
case dpl_type_texture:
break;
case dpl_type_texmap:
break;
case dpl_type_ramp:
break;
}
}
//#############################################################################
// Code to setup and handle material substitutions.
//#############################################################################
//
NameList
*materialSubstitutionList = NULL;
const char *opMaterialName(const char *fileName, int opId)
{
hash_map<string, hash_map<int, string>>::const_iterator fileIter = gOpNames->find(string(fileName));
if (fileIter != gOpNames->end())
{
hash_map<int, string>::const_iterator matIter = (*fileIter).second.find(opId);
if (matIter != (*fileIter).second.end())
{
return (*matIter).second.c_str();
}
}
return NULL;
}
void loadTables()
{
gOpNames = new hash_map<string, hash_map<int, string>>();
gReplacementData = new hash_map<string, ReplacementMaterialData>();
FILE * opNames = fopen("VIDEO\\REPLACEMATS.tbl", "rb");
size_t numMats;
fread(&numMats, sizeof(size_t), 1, opNames);
for (int i = 0; i < (int)numMats; i++)
{
int opNum, fileNameLen, matNameLen;
fread(&opNum, sizeof(int), 1, opNames);
fread(&fileNameLen, sizeof(int), 1, opNames);
char *fileName = new char[fileNameLen];
fread(fileName, sizeof(char), fileNameLen, opNames);
fread(&matNameLen, sizeof(int), 1, opNames);
char *matName = new char[matNameLen];
fread(matName, sizeof(char), matNameLen, opNames);
hash_map<string, hash_map<int, string>>::const_iterator fileIter = gOpNames->find(string(fileName));
if (fileIter != gOpNames->end())
{
hash_map<int, string>::const_iterator matIter = (*fileIter).second.find(opNum);
if (matIter != (*fileIter).second.end())
{
(*gOpNames)[string(fileName)][opNum] = string(matName);
} else
{
(*gOpNames)[string(fileName)].insert(pair<int, string>(opNum, string(matName)));
}
} else
{
hash_map<int, string> fileMap;
fileMap.insert(pair<int, string>(opNum, string(matName)));
gOpNames->insert(pair<string, hash_map<int, string>>(string(fileName), fileMap));
}
delete [] fileName;
delete [] matName;
}
fclose(opNames);
FILE *replacementData = fopen("VIDEO\\MATREPLACETABLE.tbl", "rb");
fread(&numMats, sizeof(size_t), 1, replacementData);
for (int i = 0; i < (int)numMats; i++)
{
int matNameLen, texNameLen;
fread(&matNameLen, sizeof(int), 1, replacementData);
char *matName = new char[matNameLen];
fread(matName, sizeof(char), matNameLen, replacementData);
fread(&texNameLen, sizeof(int), 1, replacementData);
char *texName = new char[texNameLen];
fread(texName, sizeof(char), texNameLen, replacementData);
ReplacementMaterialData data;
data.texName = string(texName);
fread(&data, sizeof(float), 3, replacementData);
gReplacementData->insert(pair<string, ReplacementMaterialData>(string(matName), data));
delete [] matName;
delete [] texName;
}
fclose(replacementData);
}
/* dPL material name callback function type. */
//typedef char8 *(dpl_MATERIAL_NAME_CALLBACK)(char8 *mat_name);
char*
substituteMaterial(
char *source
)
{
static char
buffer[MATERIAL_NAME_BUFFER_LENGTH];
NameList::Entry
*entry;
const char
*search,
*replace,
*pc;
int
len;
//----------------------------------------------
// perform text substitution
// first match in the sub list gets substituted
// materialSubstitutionList is a pre-prepared global namelist.
//----------------------------------------------
if (materialSubstitutionList == NULL)
{
return source;
}
entry = materialSubstitutionList->GetFirstEntry();
while (entry)
{
search = entry->GetName();
if (search && *search && (pc = strstr((char*)source, search)) != NULL)
{
replace = entry->GetChar();
*buffer = '\0';
len = (char*)pc - source;
while (*replace == '<')
{
++replace;
--len;
}
if (len > 0)
{
strncat(buffer, (const char*)source, len);
}
pc += strlen(search);
len = strlen(replace);
while (len && *(replace+len-1) == '>')
{
--len;
if (*pc) { ++pc; }
}
if (len > 0)
{
strncat(buffer, replace, len);
}
Str_Cat(buffer, pc, MATERIAL_NAME_BUFFER_LENGTH);
delete [] source;
source = new char[strlen(buffer) + 1];
Str_Copy((char*)source, buffer, MATERIAL_NAME_BUFFER_LENGTH);
break;
}
entry = entry->GetNextEntry();
}
return source;
}
vector<MONITORINFO> DPLRenderer::MonitorsCreateAll(int &monitorCount)
{
monitorCount = gD3D->GetAdapterCount();
vector<MONITORINFO> allMonitors(monitorCount);
for(UINT i = 0; i < monitorCount; i++)
{
HMONITOR monitorHandle = gD3D->GetAdapterMonitor(i);
MONITORINFO info;
info.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(monitorHandle, &info);
allMonitors[i] = info;
}
return allMonitors;
}
void DPLRenderer::SetCoreRenderStates()
{
mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_USEW);
float size = 1.0f;
mDevice->SetRenderState(D3DRS_POINTSIZE, *(DWORD*)(&size));
mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
D3DXMATRIX view_matrix, proj_matrix;
D3DXMatrixIdentity(&view_matrix);
D3DXMatrixOrthoLH(&proj_matrix, x_size, y_size, 1.0f, 1000.0f);
mDevice->SetTransform(D3DTS_VIEW, &view_matrix);
mDevice->SetTransform(D3DTS_PROJECTION, &proj_matrix);
mDevice->SetRenderState(D3DRS_LIGHTING, false);
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
mDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
mDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
mDevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
mDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
mDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
mDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
mDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}
//-----------------------------------------------------------------------------
//--------------------------DPL video resource object--------------------------
//-----------------------------------------------------------------------------
//#############################################################################
//############################ L4VideoObject ############################
//#############################################################################
L4VideoObject::L4VideoObject(
const char *filename,
ResourceType resource_type,
Enumeration renderer_modes, // RendererModes
float blink_period,
float percent_time_on
)
{
Check_Pointer(filename);
Str_Copy(objectFilename, filename, sizeof(objectFilename));
//---------------------------------------------------------------
// pad objectFilename with nulls so all .res files are identical
//---------------------------------------------------------------
char
*p = objectFilename + strlen(filename) + 1,
*c = objectFilename + sizeof(objectFilename);
for (; p < c; ++p)
{ *p = '\0'; }
resourceType = resource_type;
rendererModes = renderer_modes;
blinkPeriod = blink_period;
percentTimeOn = percent_time_on;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
L4VideoObject::~L4VideoObject()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
L4VideoObject::TestInstance() const
{
Verify( strlen(objectFilename) < sizeof(objectFilename) );
return True;
}
//#############################################################################
//######################## L4VideoObjectWrapper #########################
//#############################################################################
L4VideoObjectWrapper::L4VideoObjectWrapper(
L4VideoObject *video_object,
Logical delete_object
)
{
Check_Pointer(video_object); // do not use Check()
videoObject = video_object;
deleteObject = delete_object;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
L4VideoObjectWrapper::~L4VideoObjectWrapper()
{
if (deleteObject)
{
Unregister_Pointer(videoObject);
delete videoObject;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
L4VideoObjectWrapper::TestInstance() const
{
if (videoObject)
{
Check_Pointer(videoObject); // do not use Check()
}
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// static
int L4VideoObjectWrapper::BuildVideoObjectChainFromResource(ChainOf<L4VideoObjectWrapper*> *video_chain, ResourceDescription *video_resource)
{
//do not Check(this) - static
Check(video_chain);
Check(video_resource);
const char *video_pointer;
int object_count, index;
long object_size;
L4VideoObject *video_object;
L4VideoObjectWrapper *video_wrapper;
//----------------------------------------------------
// convert video resource into chain of video objects
//----------------------------------------------------
video_pointer = (char *)video_resource->resourceAddress;
Check_Pointer(video_pointer);
object_count = *((int *)video_pointer);
video_pointer += sizeof(int);
object_size = sizeof(L4VideoObject);
Verify(video_resource->resourceSize == sizeof(int) + object_count * object_size);
//Tell("video chain: ("<<object_count<<")");
for (index = 0; index < object_count; ++index)
{
video_object = (L4VideoObject *)video_pointer;
//do not register (done through resource)
video_pointer += object_size;
//Tell(" '"<<video_object->GetObjectFilename()<<"' 0x"<<std::hex<<video_object->GetRendererModes());
video_wrapper = new L4VideoObjectWrapper(video_object, False);
Register_Object(video_wrapper);
video_chain->Add(video_wrapper);
}
//Tell(std::dec<<"\n");
return object_count;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// static
void
L4VideoObjectWrapper::DeleteVideoObjectChain(
ChainOf<L4VideoObjectWrapper*> *video_chain
)
{
//do not Check(this) - static
Check(video_chain);
ChainIteratorOf<L4VideoObjectWrapper*>
video_iterator(video_chain);
L4VideoObjectWrapper
*video_wrapper;
while ((video_wrapper = video_iterator.ReadAndNext()) != NULL)
{
Check(video_wrapper);
Unregister_Object(video_wrapper);
delete video_wrapper;
}
return;
}
void DPLRenderer::FindBestAdapterIndices(bool isWindowed)
{
bool spanDisable = false;
bool *spanDisablePtr = NULL;
//Get all available monitor indices & stats
int monitorCount = 0;
std::vector<MONITORINFO> monitors = this->MonitorsCreateAll(monitorCount);
int monitorReserved = 0x10000000;
//Test for primary gauge override
char* gaugeAdapterString = getenv("PRIMGAUGE");
if (gaugeAdapterString != NULL)
{
mPrimaryIndex = new int;
*mPrimaryIndex = atoi(gaugeAdapterString);
DEBUG_STREAM << "Primary gauge override- adapter " << *mPrimaryIndex << std::endl;
}
//Test for secondary gauge override
gaugeAdapterString = getenv("SECGAUGE");
if (gaugeAdapterString != NULL)
{
mSecondaryIndex = new int;
*mSecondaryIndex = atoi(gaugeAdapterString);
DEBUG_STREAM << "Secondary gauge override- adapter " << *mSecondaryIndex << std::endl;
}
//Only do gauge overrides if we're using gauges during this execution
if (!Application::DoSuppressGauges())
{
//Test for gauge1 override
gaugeAdapterString = getenv("MFDGAUGE");
if (gaugeAdapterString != NULL)
{
mAux1Index = new int;
*mAux1Index = atoi(gaugeAdapterString);
DEBUG_STREAM << "MFD Gauge Override- adapter " << *mAux1Index << std::endl;
}
//Test for span disable override
spanDisablePtr = NULL;
gaugeAdapterString = getenv("SPANDISABLE");
if (gaugeAdapterString != NULL)
{
spanDisable = atoi(gaugeAdapterString);
spanDisablePtr = &spanDisable;
DEBUG_STREAM << "Spanning Override: Span ";
if (*spanDisablePtr)
{
DEBUG_STREAM << "Disabled";
} else
{
DEBUG_STREAM << "Enabled";
}
DEBUG_STREAM << std::endl;
}
if (spanDisablePtr == NULL || *spanDisablePtr)
{
//Test for gauge2 override
gaugeAdapterString = getenv("MFDGAUGE2");
if (gaugeAdapterString != NULL)
{
mAux2Index = new int;
*mAux2Index = atoi(gaugeAdapterString);
DEBUG_STREAM << "MFD Gauge #2 Override- adapter " << *mAux2Index << std::endl;
}
}
//Disable spanning if they overrode the 2nd gauge
if (spanDisablePtr == NULL && mAux2Index != NULL)
{
DEBUG_STREAM << "MFD Gauge #2 was overridden... forcing spanning disabled." << std::endl;
spanDisable = true;
spanDisablePtr = &spanDisable;
}
}
//Remove all monitors explicitly assigned somewhere from the list of available monitors
if (mPrimaryIndex != NULL && (*mPrimaryIndex) >= 0 && (*mPrimaryIndex) < monitorCount)
{
monitors[*mPrimaryIndex].dwFlags |= monitorReserved;
}
if (mSecondaryIndex != NULL && (*mSecondaryIndex) >= 0 && (*mSecondaryIndex) < monitorCount)
{
monitors[*mSecondaryIndex].dwFlags |= monitorReserved;
}
if (mAux1Index != NULL && (*mAux1Index) >= 0 && (*mAux1Index) < monitorCount)
{
monitors[*mAux1Index].dwFlags |= monitorReserved;
}
if (mAux2Index != NULL && (*mAux2Index) >= 0 && (*mAux2Index) < monitorCount)
{
monitors[*mAux2Index].dwFlags |= monitorReserved;
}
if (mPrimaryIndex == NULL)
{
DEBUG_STREAM << "Trying to find the monitor marked as active in Windows..." << std::endl;
//Set up the monitor so marked as the primary (unless none are marked)
for (int i = 0; i < monitorCount; i++)
{
int flags = monitors[i].dwFlags;
if ((flags & (MONITORINFOF_PRIMARY | monitorReserved)) == MONITORINFOF_PRIMARY)
{
DEBUG_STREAM << "Monitor " << i << " was set as active in Windows... setting it as the primary monitor." << endl;
mPrimaryIndex = new int;
*mPrimaryIndex = i;
monitors[i].dwFlags |= monitorReserved;
break;
}
}
}
//Do gauges next, since they're the easiest to pick out
if (!Application::DoSuppressGauges() && !isWindowed && monitorCount > 2)
{
DEBUG_STREAM << "Gauges are on, we are not in windowed mode, and we have " << monitorCount << " available monitors, so will try to find MFDs..." << std::endl;
if (mAux1Index == NULL && (spanDisablePtr == NULL || !(*spanDisablePtr)))
{
DEBUG_STREAM << "Don't have a MFD #1 monitor yet, and spanning is not explicitly disabled, so will try to find a really wide monitor for both MFDs..." << std::endl;
//try to find a really wide monitor to use as gauge1
for (int i = 0; i < monitorCount; i++)
{
if ((monitors[i].dwFlags & monitorReserved) == 0)
{
RECT size = monitors[i].rcMonitor;
float aspect = ( (double)(size.right - size.left) / (double)(size.bottom - size.top));
if (aspect > 2.5f)
{
//Really wide! Probably a spanning monitor
DEBUG_STREAM << "Monitor " << i << " is really wide, so will try to use it as the MFDs." << std::endl;
mAux1Index = new int;
*mAux1Index = i;
monitors[i].dwFlags |= monitorReserved;
if (spanDisablePtr == NULL)
{
DEBUG_STREAM << "Explicitly setting spanning to enabled..." << std::endl;
spanDisable = FALSE;
spanDisablePtr = &(spanDisable);
}
break;
}
}
}
}
int possibleAux2Index = -1;
if (mAux1Index == NULL && (spanDisablePtr == NULL || *spanDisablePtr))
{
DEBUG_STREAM << "MFDs not found yet, and spanning isn't explicitly enabled. Will try to find two same-size monitors to use as MFDs..." << std::endl;
map<pair<int,int>,vector<int>> sameSizeMonitors;
//Group the unclaimed monitors by resolution
for (int i = 0; i < monitorCount; i++)
{
if ((monitors[i].dwFlags & monitorReserved) == 0)
{
int width = monitors[i].rcMonitor.right - monitors[i].rcMonitor.left;
int height = monitors[i].rcMonitor.bottom - monitors[i].rcMonitor.top;
pair<int, int> resolution(width, height);
if (sameSizeMonitors.find(resolution) == sameSizeMonitors.end())
{
sameSizeMonitors[resolution] = vector<int>();
}
sameSizeMonitors[resolution].insert(sameSizeMonitors[resolution].begin(), i);
}
}
//Retrieve the bucket of monitors with at least two monitors and the smallest resolution (y res counts more than x res)
vector<int> bestMonitors;
int smallestYRes = -1;
int bestXRes = -1;
for (map<pair<int,int>,vector<int>>::iterator it = sameSizeMonitors.begin(); it != sameSizeMonitors.end(); it++)
{
if ((*it).second.size() >= 2)
{
int yRes = (*it).first.second;
int xRes = (*it).first.first;
if (smallestYRes >= 0)
{
DEBUG_STREAM << "Multiple sets of identically-sized monitors are available. Will use smallest set..." << std::endl;
}
if (smallestYRes < 0 || yRes < smallestYRes || (yRes == smallestYRes && xRes < bestXRes))
{
smallestYRes = yRes;
bestXRes = xRes;
bestMonitors = (*it).second;
}
}
}
int aux1Candidate = -1;
int aux2Candidate = -1;
int aux1Right = 0;
int aux2Right = 0;
if (bestMonitors.size() > 2)
{
DEBUG_STREAM << "More than 2 monitors in the set of smallest, identically-sized monitors... Will use the furthest right as right MFD, one just to the left of that as left MFD..." << std::endl;
}
//The second aux screen is the one furthest to the right
//the first aux screen is the one just to the left of that one
for (vector<int>::iterator it = bestMonitors.begin(); it != bestMonitors.end(); it++)
{
int i = (*it);
if ((monitors[i].dwFlags & monitorReserved) == 0)
{
int right = monitors[i].rcMonitor.right;
if (aux2Candidate < 0 || aux2Right < right)
{
aux1Candidate = aux2Candidate;
aux1Right = aux2Right;
aux2Candidate = i;
aux2Right = right;
} else if (aux1Candidate < 0 || aux1Right < right)
{
aux1Candidate = i;
aux1Right = right;
}
}
}
if (aux1Candidate >= 0 && aux2Candidate >= 0)
{
DEBUG_STREAM << "Got two decent same-size monitors, will use as MFDs... Left is " << aux1Candidate << " and right is " << aux2Candidate << "." << std::endl;
mAux1Index = new int;
*mAux1Index = aux1Candidate;
monitors[aux1Candidate].dwFlags |= monitorReserved;
mAux2Index = new int;
*mAux2Index = aux2Candidate;
monitors[aux2Candidate].dwFlags |= monitorReserved;
spanDisable = true;
spanDisablePtr = &spanDisable;
} else
{
DEBUG_STREAM << "Could not find two identical monitors to use for MFDs." << std::endl;
}
}
if (mAux2Index == NULL && mAux1Index != NULL && (spanDisablePtr == NULL || *spanDisablePtr))
{
DEBUG_STREAM << "We have a left MFD and no right MFD, and spanning is not explicitly enabled. Will try to find identically-sized right MFD." << std::endl;
//find a monitor that is identical to the first gauge monitor
//if multiple, use the furthest to the right
int bestMonitorIndex = -1;
int bestMonitorRight = 0;
int aux1Width = (monitors[*mAux1Index].rcMonitor.right - monitors[*mAux1Index].rcMonitor.left);
int aux1Height = (monitors[*mAux1Index].rcMonitor.bottom - monitors[*mAux1Index].rcMonitor.top);
for (int i = 0; i < monitorCount; i++)
{
if ((monitors[i].dwFlags & monitorReserved) == 0)
{
int monitorWidth = (monitors[i].rcMonitor.right - monitors[i].rcMonitor.left);
int monitorHeight = (monitors[i].rcMonitor.bottom - monitors[i].rcMonitor.top);
if (monitorWidth == aux1Width && monitorHeight == aux1Height)
{
if (bestMonitorIndex >= 0)
{
DEBUG_STREAM << "Found more than one monitor identically sized to the left MFD. Will use furthest-right monitor." << std::endl;
}
if (bestMonitorIndex < 0 || bestMonitorRight < monitors[i].rcMonitor.right)
{
bestMonitorIndex = i;
bestMonitorRight = monitors[i].rcMonitor.right;
}
}
}
}
if (bestMonitorIndex >= 0)
{
DEBUG_STREAM << "Using monitor " << bestMonitorIndex << "as right MFD monitor." << std::endl;
mAux2Index = new int;
*mAux2Index = bestMonitorIndex;
monitors[bestMonitorIndex].dwFlags |= monitorReserved;
} else
{
DEBUG_STREAM << "Could not find decent monitor for right MFD." << std::endl;
}
}
} else
{
DEBUG_STREAM << "Either MFDs are explicitly disabled, we're running in windowed mode, or we don't have enough monitors attached to this machine. MFD monitors will not be detected." << std::endl;
}
if (mPrimaryIndex == NULL)
{
DEBUG_STREAM << "Still no appropriate primary monitor- will find tallest monitor to use." << std::endl;
//Pick the monitor with the highest y resolution (leftmost if there's a tie)
int bestMonitorIndex = -1;
int bestMonitorHeight = 0;
int bestMonitorX = 0;
for (int i = 0; i < monitorCount; i++)
{
if ((monitors[i].dwFlags & monitorReserved) == 0)
{
int height = (monitors[i].rcMonitor.bottom - monitors[i].rcMonitor.top);
if (bestMonitorIndex < 0 || height > bestMonitorHeight || (height == bestMonitorHeight && monitors[i].rcMonitor.left < bestMonitorX))
{
bestMonitorIndex = i;
bestMonitorHeight = height;
bestMonitorX = monitors[i].rcMonitor.left;
}
}
}
if (bestMonitorIndex >= 0)
{
DEBUG_STREAM << "Using monitor " << bestMonitorIndex << " as primary monitor." << std::endl;
mPrimaryIndex = new int;
*mPrimaryIndex = bestMonitorIndex;
monitors[bestMonitorIndex].dwFlags |= monitorReserved;
} else
{
DEBUG_STREAM << "Could not find decent primary monitor. Likely no unclaimed monitors." << std::endl;
}
}
if (mPrimaryIndex != NULL && isWindowed)
{
DEBUG_STREAM << "Game is currently running windowed mode- will set all remaining undefined monitors to be the same as the primary monitor." << std::endl;
if (mSecondaryIndex == NULL)
{
mSecondaryIndex = new int;
*mSecondaryIndex = *mPrimaryIndex;
}
if (mAux1Index == NULL && mAux2Index == NULL)
{
mAux1Index = new int;
*mAux1Index = *mPrimaryIndex;
mAux2Index = new int;
*mAux2Index = *mPrimaryIndex;
}
} else if (!isWindowed && mSecondaryIndex == NULL)
{
DEBUG_STREAM << "Detecting secondary monitor- will attempt to use furthest-left remaining monitor." << std::endl;
//Pick the leftmost remaining monitor
int leftmostIndex = -1;
int leftmostX = 0;
for (int i = 0; i < monitorCount; i++)
{
if ((monitors[i].dwFlags & monitorReserved) == 0)
{
if (leftmostIndex < 0 || monitors[i].rcMonitor.left < leftmostX)
{
leftmostIndex = i;
leftmostX = monitors[i].rcMonitor.left;
}
}
}
if (leftmostIndex >= 0)
{
DEBUG_STREAM << "Using monitor " << leftmostIndex << " as secondary monitor." << std::endl;
mSecondaryIndex = new int;
*mSecondaryIndex = leftmostIndex;
} else
{
DEBUG_STREAM << "Could not find appropriate secondary monitor. Likely no unclaimed monitors remain." << std::endl;
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Constructor for DPLRenderer
//
DPLRenderer::DPLRenderer(
HWND hWnd,
unsigned int screenWidth,
unsigned int screenHeight,
bool fullscreen,
InterestType interest_type,
InterestDepth depth_calibration
):
VideoRenderer(
1.0f,
1.0f,
RendererPriority::DefaultRendererPriority,
interest_type,
depth_calibration
),
projectile_list(NULL),
dplObjectCacheSocket(NULL, False),
dplJointToDCSTranslatorSocket(NULL,False),
dplRenderableSocket(NULL),
mRenderables(NULL),
x_size(screenWidth),
y_size(screenHeight),
mReticle(NULL),
mCamShipHUD(NULL),
mStaticObjectsHead(NULL),
mStaticObjectsCount(0),
mPrimaryIndex(NULL),
mSecondaryIndex(NULL),
mAux1Index(NULL),
mAux2Index(NULL)
{
__int64 frequency = HiResCounterFreq();
#ifdef LOGFRAMERATE
FRAMERATE_LOG = fopen("framerate.log", "wb");
fwrite(&frequency, sizeof(__int64), 1, FRAMERATE_LOG);
#endif
mCamera = NULL;
loadTables();
// clear out our render lists
memset(mRenderLists, 0, sizeof(mRenderLists));
memset(mNameTextures, 0, sizeof(mNameTextures));
memset(mOrdinalTextures, 0, sizeof(mOrdinalTextures));
D3DXCreateMatrixStack(0, &m_MatrixStack);
m_MatrixStack->LoadIdentity();
gD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (!gD3D)
{
DEBUG_STREAM<<"Couldn't create Direct3D interface!"<<std::endl<<std::flush << std::flush;
PostQuitMessage(1);
}
this->FindBestAdapterIndices(!fullscreen);
memset(&mPresentParams, 0, sizeof(D3DPRESENT_PARAMETERS));
mPresentParams.BackBufferCount = 1;
mPresentParams.MultiSampleType = (D3DMULTISAMPLE_TYPE)atol(getenv("MULTISAMPLE"));
if (mPresentParams.MultiSampleType > 0)
{
gD3D->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, !fullscreen, mPresentParams.MultiSampleType, &mPresentParams.MultiSampleQuality);
mPresentParams.MultiSampleQuality--;
}
mPresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
mPresentParams.hDeviceWindow = hWnd;
mPresentParams.Flags = 0;
mPresentParams.FullScreen_RefreshRateInHz = (fullscreen)?60:D3DPRESENT_RATE_DEFAULT;
mPresentParams.PresentationInterval = D3DPRESENT_RATE_DEFAULT;
mPresentParams.BackBufferFormat = D3DFMT_X8R8G8B8;
mPresentParams.EnableAutoDepthStencil = TRUE;
mPresentParams.AutoDepthStencilFormat = D3DFMT_D24X8;
mPresentParams.Windowed = !fullscreen;
if (fullscreen)
{
mPresentParams.BackBufferWidth = screenWidth;
mPresentParams.BackBufferHeight = screenHeight;
}
HRESULT hr;
//DEBUG_STREAM<<"**************************"<<std::endl<<"**************************"<<std::endl;
//for (UINT adapter = 0; adapter<=3; adapter++)
//{
// DEBUG_STREAM<<"\tAdapter "<<adapter<<": ";
// D3DFORMAT format = (adapter == 0 ? D3DFMT_X8R8G8B8 : D3DFMT_R5G6B5);
// UINT modes = gD3D->GetAdapterModeCount(adapter, format);
// DEBUG_STREAM<<modes<<" display modes"<<std::endl;
// for (UINT mode=0; mode<modes; mode++)
// {
// D3DDISPLAYMODE displayMode;
// hr = gD3D->EnumAdapterModes(adapter, format, mode, &displayMode);
// if (FAILED(hr))
// {
// DEBUG_STREAM<<"\t\tFailed to retrieve display mode "<<mode<<"."<<std::endl;
// continue;
// }
// DEBUG_STREAM<<"\t\t"<<displayMode.Format<<": "<<displayMode.Width<<" x "<<displayMode.Height<<" @ "<<displayMode.RefreshRate<<" Hz"<<std::endl;
// }
// DEBUG_STREAM<<std::endl;
//}
//DEBUG_STREAM<<"**************************"<<std::endl<<"**************************"<<std::endl<<std::flush;
if (mPrimaryIndex == NULL)
{
DEBUG_STREAM<<"Unable to locate a suitable primary device index."<<std::endl<<std::flush;
PostQuitMessage(1);
return;
}
V(gD3D->CreateDevice(*mPrimaryIndex, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &mPresentParams, &mDevice));
if (FAILED(hr))
{
DEBUG_STREAM<<"Couldn't create HARDWARE_VERTEXPROCESSING device."<<std::endl<<std::flush;
V(gD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &mPresentParams, &mDevice));
if (FAILED(hr))
{
PostQuitMessage(1);
}
}
mDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 0.0f, 0);
mDevice->Present(NULL, NULL, NULL, NULL);
ParticleEngine::Initialize(mDevice);
SetCoreRenderStates();
//STUBBED: DPL RB 1/14/07
char
Eye_Type[50],
*Eye_Arg, // Controls generation of the eye point
*DPL_Arg; // Points to DPLARG environment pointer once we get it
int
psfx_number;
// int
// i; // Temporary loop counter
float
eye_x,
eye_y,
eye_z,
eye_x_rot,
eye_y_rot,
eye_z_rot;
//
// Initialize a bunch of the variables to their starting values
//
eyeRelative = False;
completeCycleNeeded = False;
lastAppState = 0;
fogUpdating = True;
fogRed = 0.0f;
fogBlue = 0.0f;
fogGreen = 0.0f;
fogNear = 0.0f;
fogFar = 0.0f;
currentFogFar = 0.0f;
currentFogNear = 0.0f;
searchLightFogRed = 0.0f;
searchLightFogGreen = 0.0f;
searchLightFogBlue = 0.0f;
searchLightFogNear = 0.0f;
searchLightFogFar = 0.0f;
noSearchLightFogRed = 0.0f;
noSearchLightFogGreen = 0.0f;
noSearchLightFogBlue = 0.0f;
noSearchLightFogNear = 0.0f;
noSearchLightFogFar = 0.0f;
clipNear = 0.0f;
clipFar = 0.0f;
backgroundRed = 0.0f;
backgroundGreen = 0.0f;
backgroundBlue = 0.0f;
viewAngle = 30.0f;
// the Winners Circle camera is off until the podium asks for it. No
// restore path is needed: a fresh DPLRenderer is built per mission, so
// the next race re-reads viewangle from RPDPL.INI.
mPresentationCamera = False;
mPresentationFog = False;
mPresentationAspect = 0.0f;
mPresentationFadeTime = 0.0f;
mPresentationFogRed = 0.0f;
mPresentationFogGreen = 0.0f;
mPresentationFogBlue = 0.0f;
mPresentationFogNear = 0.0f;
mPresentationFogFar = 0.0f;
D3DXMatrixIdentity(&mPresentationView);
dplMainView = NULL;
dplDeathZone = NULL;
dplMainZone = NULL;
vehicleReticle = NULL;
dplHitInstance = NULL;
dplHitDCS = NULL;
dplHitGeoGroup = NULL;
dplHitGeometry = NULL;
delayedDCSCount = 0;
myUniqueID = 0;
sceneLightDCS = NULL;
sceneLight = NULL;
sceneLightCount = 0;
worldToEyeMatrix = LinearMatrix::Identity; // the current world to eye transform for our linked entity
currentFrameTime = Now(); // the time at the start of renderable execution
Verify(!DPLHeap);
// DPLHeap = new UserHeap("DPL Heap", 2000000);
Register_Object(DPLHeap);
//
// Clear the myPSFXDescriptons array to all zeros so we can detect attempts
// to use uninitialized items.
//
memset(myPSFXDescriptons, 0, sizeof(myPSFXDescriptons));
//
// These guys will come out of a world environment variable eventually
//
eye_x = 0.0f;
eye_y = 10.0f;
eye_z = 0.0f;
eye_x_rot = 0.0f;
eye_y_rot = 0.0f;
eye_z_rot = 0.0f;
//
// Get pointers to environmentals containing DPL startup arguments and
// eye positioning information. If L4EYES is present set the renderer
// variable that controls the hooking up of the eye position.
//
Eye_Type[0] = 0;
DPL_Arg = getenv("DPLARG");
Eye_Arg = getenv("L4EYES");
if(Eye_Arg)
{
sscanf(
Eye_Arg,
"%f %f %f %f %f %f %s",
&eye_x,
&eye_y,
&eye_z,
&eye_x_rot,
&eye_y_rot,
&eye_z_rot,
Eye_Type);
printf("%f, %f, %f %f, %f, %f\n",
eye_x,
eye_y,
eye_z,
eye_x_rot,
eye_y_rot,
eye_z_rot);
Disconnected_Eye = True; // tells vidrend:: to request outside view of linked entity
if(*Eye_Type == 'r')
{
DEBUG_STREAM<<"DPLRenderer::DPLRenderer Eye will be offset relative to vehicle\n" << std::flush;
eyeRelative = True;
}
}
//
// If the argument was empty, we can't render !!! should exit sensiblly
//
if(!DPL_Arg)
{
DEBUG_STREAM << "DPLARG must be set for the Division card to come up\n" << std::flush;
Verify(DPL_Arg);
}
//
// If we're still here, try to interpret and setup the screen resolution
// requested by DPLARG. The screen_resolution function is Phil's routine
// in startdpl.
//
// if (screen_resolution ( DPL_Arg ) == 0)
// {
// DEBUG_STREAM << "DPLARG is bad, I couldn't understand video format\n" << std::flush;
// Verify(DPL_Arg);
// }
//
// Breakdown the DPLARGS string using expload_args from startdpl, then feed
// the results to the dpl_Init routine to get DPL up and running.
//
char *argv[32];
// int argc = explode_args ( argv, DPL_Arg, dpl_arg_sep );
// dpl_Init ( argc, argv );
//
// Setup the file paths for geometry and texture loading
//
// dpl_SetObjectFilePath ( ".\\video", "\\video", "..\\video" );
// dpl_SetTexmapFilePath ( ".\\video", "\\video", "..\\video" );
// dpl_SetMaterialFilePath ( ".\\video", "\\video", "..\\video" );
// dpl_SetObjectFilePath ( ".\\video", "", "" );
// std::cout<<dpl_GetObjectFilePath()<<"\n";
// dpl_SetTexmapFilePath ( ".\\video", "", "" );
// std::cout<<dpl_GetTexmapFilePath()<<"\n";
// dpl_SetMaterialFilePath ( ".\\video", "", "" );
// std::cout<<dpl_GetMaterialFilePath()<<"\n";
//
// Set the extensions and the DPL routines that will load them
//
// dpl_SetExtnObjectLoadFunc (".bgf", dpl_bgfRead);
// dpl_SetExtnTexmapLoadFunc (".vtx", dpl_vtxRead);
// dpl_SetExtnTexmapLoadFunc (".tga", dpl_tgaRead);
// dpl_SetExtnTexmapLoadFunc (".int", dpl_sgiRead);
// dpl_SetExtnTexmapLoadFunc (".inta", dpl_sgiRead);
// dpl_SetExtnTexmapLoadFunc (".rgb", dpl_sgiRead);
// dpl_SetExtnTexmapLoadFunc (".rgba", dpl_sgiRead);
//
// Setup the dpl callback routines for handling specials, object creation and
// material name munging.
//
// dpl_SetSpecialCallback(TestSpecialCallBack);
// dpl_SetCreateNodeCallback(TestCreateCallBack);
// dpl_SetMaterialNameCallback(TestMaterialCallBack);
//
// Create the one zone everything will live in !!!! more zones later for smart culling
//
// dplMainZone = dpl_NewZone();
Check_Pointer(dplMainZone);
// dplDeathZone = dpl_NewZone();
Check_Pointer(dplDeathZone);
//
// Create the view we will use for our eyepoint
//
// dplMainView = dpl_NewView();
Check_Pointer(dplMainView);
//
// This creates a DCS and links it to the view, I probably should just let the
// eye renderable do this but it's convenient since it can be used as the
// eye point for testing.
//
// dplTestEyeDCS = dpl_NewDCS();
Check_Pointer ( dplTestEyeDCS);
// dpl_RotateDCS ( dplTestEyeDCS, eye_z_rot, dpl_Z );
// dpl_RotateDCS ( dplTestEyeDCS, eye_x_rot, dpl_X );
// dpl_RotateDCS ( dplTestEyeDCS, eye_y_rot, dpl_Y );
// dpl_TranslateDCS ( dplTestEyeDCS, eye_x, eye_y, eye_z);
// dpl_SetDCSZone ( dplTestEyeDCS, dplMainZone );
// dpl_SetViewDCS ( dplMainView, dplTestEyeDCS);
//
// Do some setup work on the zone
//
// dpl_SetZoneAllViewsOn ( dplMainZone );
// dpl_SetZoneAllViewsOn ( dplDeathZone );
//
// Setup some defaults so we can safely render a blank screen now
//
//
// dpl_SetViewClipPlanes ( dplMainView, 1.0f, 2.0f );
// dpl_SetViewBackGround ( dplMainView, 0.0f, 0.0f, 0.0f);
// dpl_SetPipeWindow (0, 0, 0, x_size, y_size);
// dpl_SetViewProjection ( dplMainView, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f/(tan( 0.5235987666667f)));
// dpl_SetViewPipe ( dplMainView, 0);
// dpl_AddViewToScene ( dplMainView );
// dpl_SetViewFog (dplMainView, dpl_fog_type_pixel_lin, 0.0, 0.0, 0.0, 0.01, 0.05 );
//
// DPLReadEnvironment();
//
// dpl_FlushDCS ( dplTestEyeDCS);
// dpl_FlushView ( dplMainView);
// dpl_FlushZone ( dplMainZone);
// dpl_FlushZone ( dplDeathZone);
//
// Call DrawScene to force the system do draw a blank screen
//
// dpl_DrawScene();
//
// Start a clock used to keep track of the frame rate
//
StartSample = Now();
FrameCount = 0;
ResetStatistics();
statistics_started = False;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dpl_ZONE*
DPLRenderer::MakeNewZone()
{
//STUBBED: DPL RB 1/14/07
dpl_ZONE *temp_zone;
////
//// Make a new zone for use by someone constructing an object, switch it on
//// and std::flush it out to the card.
////
//temp_zone = dpl_NewZone();
//Check_Pointer(temp_zone);
//dpl_SetZoneAllViewsOn (temp_zone);
//dpl_FlushZone (temp_zone);
////
//// HACK !!! at this point we should put the zone into a chain so we can
//// find it to switch it on and off later.
////
return(temp_zone);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AddDynamicRenderable puts a renderable into this renderer's dynamic execution
// socket so it will be run every frame.
//
void DPLRenderer::AddDynamicRenderable(Component *my_renderable)
{
Check(my_renderable);
Check(&dplRenderableSocket);
dplRenderableSocket.Add(my_renderable);
}
void DPLRenderer::AddToPassList(d3d_OBJECT *object, int pass)
{
if (pass >= PASS_TOTAL_COUNT)
return;
for (d3d_OBJECT *iter = mRenderLists[pass]; iter; iter = iter->GetNext(pass))
if ((void*)iter == (void*)object)
return;
object->SetPrevious(NULL, pass);
object->SetNext(mRenderLists[pass], pass);
if (mRenderLists[pass] != NULL)
mRenderLists[pass]->SetPrevious(object, pass);
mRenderLists[pass] = object;
}
hyper DPLRenderer::HashAdd(hyper input, char data)
{
const hyper multiplier = 37;
return (input * multiplier) + data;
}
hyper DPLRenderer::HashDrawOp(L4DRAWOP *op)
{
char diffR = (char)(op->material.Diffuse.r * 255);
char diffG = (char)(op->material.Diffuse.g * 255);
char diffB = (char)(op->material.Diffuse.b * 255);
char diffA = (char)(op->material.Diffuse.a * 255);
char ambA = (char)(op->material.Ambient.a * 255);
char ambR = (char)(op->material.Ambient.r * 255);
char ambG = (char)(op->material.Ambient.g * 255);
char ambB = (char)(op->material.Ambient.b * 255);
char spcA = (char)(op->material.Specular.a * 255);
char spcR = (char)(op->material.Specular.r * 255);
char spcG = (char)(op->material.Specular.g * 255);
char spcB = (char)(op->material.Specular.b * 255);
char spcP = (char)(op->material.Power * 255);
char emiA = (char)(op->material.Emissive.a * 255);
char emiR = (char)(op->material.Emissive.r * 255);
char emiG = (char)(op->material.Emissive.g * 255);
char emiB = (char)(op->material.Emissive.b * 255);
const hyper startValue = 37;
hyper hash = startValue;
hash = HashAdd(hash, diffA);
hash = HashAdd(hash, diffR);
hash = HashAdd(hash, diffG);
hash = HashAdd(hash, diffB);
hash = HashAdd(hash, ambA);
hash = HashAdd(hash, ambR);
hash = HashAdd(hash, ambG);
hash = HashAdd(hash, ambB);
hash = HashAdd(hash, spcA);
hash = HashAdd(hash, spcR);
hash = HashAdd(hash, spcG);
hash = HashAdd(hash, spcB);
hash = HashAdd(hash, spcP);
hash = HashAdd(hash, emiA);
hash = HashAdd(hash, emiR);
hash = HashAdd(hash, emiG);
hash = HashAdd(hash, emiB);
hash = HashAdd(hash, (char)op->drawAsDecal);
hash = HashAdd(hash, (char)op->alphaTest);
hash = HashAdd(hash, (char)op->drawAsSky);
char *pointerPointer = (char*)(&(op->texture.texture));
for (int i = 0; i < 4; i++)
{
hash = HashAdd(hash, pointerPointer[i]);
}
return hash;
}
void DPLRenderer::AddStaticObject(d3d_OBJECT *object)
{
object->SetPrevious(NULL, -1);
object->SetNext(mStaticObjectsHead, -1);
if (mStaticObjectsHead != NULL)
mStaticObjectsHead->SetPrevious(object, -1);
mStaticObjectsHead = object;
mStaticObjectsCount++;
}
void DPLRenderer::RecurseStaticObject(HierarchicalDrawComponent *obj)
{
if (obj->IsStatic())
{
if (obj->GetDrawObj() != NULL && obj->GetDrawObj()->GetMesh() != NULL)
{
//Only load it for a static object if it has a valid mesh-
//we'll handle valid sphere lists later
this->AddStaticObject(obj->GetDrawObj());
obj->ResetDrawObj();
}
std::vector<HierarchicalDrawComponent *>::const_iterator child_it = obj->Enumerate();
while (child_it != obj->End())
{
RecurseStaticObject(*child_it);
++child_it;
}
}
}
d3d_OBJECT * DPLRenderer::ConsolidateSingleObject(LPD3DXMESH *meshes, D3DXMATRIX *transforms, UINT startingMesh, UINT meshCount, hash_map<DWORD, hyper> subsetHash, hash_map<hyper, DWORD> hashToOp, vector<L4DRAWOP*> finalOps)
{
HRESULT hr;
LPD3DXMESH outMesh;
V( D3DXConcatenateMeshes(meshes + startingMesh, meshCount, D3DXMESH_MANAGED, transforms + startingMesh, NULL, NULL, mDevice, &outMesh) );
DWORD *adjacency = new DWORD[outMesh->GetNumFaces() * 3];
V( outMesh->GenerateAdjacency(0.05f, adjacency) );
DWORD *attributes;
int numFaces = outMesh->GetNumFaces();
V( outMesh->LockAttributeBuffer(0, &attributes) );
for (int i = 0; i < numFaces; i++)
{
stdext::hash_map<DWORD, hyper>::const_iterator face_it = subsetHash.find(attributes[i]);
if (face_it == subsetHash.end())
{
//Freak out
}
stdext::hash_map<hyper, DWORD>::const_iterator subset_it = hashToOp.find((*face_it).second);
if (subset_it == hashToOp.end())
{
//Freak out
}
attributes[i] = (*subset_it).second;
}
V( outMesh->UnlockAttributeBuffer() );
V( outMesh->OptimizeInplace(D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT, adjacency, adjacency, NULL, NULL) );
d3d_OBJECT *consolObj = new d3d_OBJECT(mDevice, outMesh, adjacency, finalOps.size());
for (int drawOpInd = 0; drawOpInd < consolObj->GetDrawOpCount(); drawOpInd++)
{
L4DRAWOP *op = consolObj->GetDrawOp(drawOpInd);
L4DRAWOP *source = finalOps[drawOpInd];
op->material = source->material;
op->texture = source->texture;
op->drawAsDecal = source->drawAsDecal;
op->alphaTest = source->alphaTest;
op->drawAsSky = source->drawAsSky;
if (op->texture.texture != NULL)
{
op->texture.texture->AddRef();
}
}
delete [] adjacency;
return consolObj;
}
void DPLRenderer::ConsolidateStaticObjects()
{
HRESULT hr;
HierarchicalDrawComponent *drawComp;
SChainIteratorOf<HierarchicalDrawComponent*> iterator(&mRenderables);
while ((drawComp = iterator.ReadAndNext()) != NULL)
{
if (drawComp->IsStatic())
{
drawComp->Execute();
this->RecurseStaticObject(drawComp);
}
}
LPD3DXMESH *meshes = new LPD3DXMESH[mStaticObjectsCount];
D3DXMATRIX *transforms = new D3DXMATRIX[mStaticObjectsCount];
int i = 0;
int opCount = 0;
std::vector<L4DRAWOP*> finalOps;
stdext::hash_map<hyper, DWORD> hashToOp;
stdext::hash_map<DWORD, hyper> subsetHash;
int vertCount = 0;
int startMesh = 0;
int meshCount = 0;
for (d3d_OBJECT *obj = mStaticObjectsHead; obj; obj = obj->GetNext(-1), i++)
{
if (vertCount + obj->GetMesh()->GetNumVertices() > 65535)
{
this->mConsolidatedStaticObjects.push_back(this->ConsolidateSingleObject(meshes, transforms, startMesh, meshCount, subsetHash, hashToOp, finalOps));
vertCount = 0;
startMesh = meshCount;
meshCount = 0;
opCount = 0;
//Clear the draw ops lists
finalOps.clear();
hashToOp.clear();
subsetHash.clear();
}
meshes[i] = obj->GetMesh();
transforms[i] = obj->GetLocalToWorld();
vertCount += meshes[i]->GetNumVertices();
meshCount++;
for (int opNum = 0; opNum < obj->GetDrawOpCount(); opNum++)
{
hyper hash = this->HashDrawOp(obj->GetDrawOp(opNum));
stdext::hash_map<hyper, DWORD>::const_iterator hash_it = hashToOp.find(hash);
if (hash_it == hashToOp.end())
{
finalOps.insert(finalOps.end(), obj->GetDrawOp(opNum));
hashToOp.insert(std::pair<hyper, DWORD>(hash, (DWORD)(finalOps.size() - 1)));
hash_it = hashToOp.find(hash);
}
subsetHash.insert(std::pair<DWORD, hyper>((DWORD)opCount, hash));
opCount++;
}
}
if (meshCount > 0)
{
this->mConsolidatedStaticObjects.push_back(this->ConsolidateSingleObject(meshes, transforms, startMesh, meshCount, subsetHash, hashToOp, finalOps));
}
d3d_OBJECT *obj = mStaticObjectsHead;
while (obj != NULL)
{
d3d_OBJECT *next = obj->GetNext(-1);
delete obj;
obj = next;
}
mStaticObjectsHead = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// RemoveDynamicRenderable removes a renderable from the dynamic execution
// socket.
//
void
DPLRenderer::RemoveDynamicRenderable(Component *my_renderable)
{
Check(my_renderable);
Check(&dplRenderableSocket);
PlugIterator remover(my_renderable);
remover.RemoveSocket(&dplRenderableSocket);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
DPLRenderer::SetFogStyle(FogStyle my_fog)
{
//STUBBED: DPL RB 1/14/07
switch(my_fog)
{
case updateFogSetting:
fogUpdating = True;
break;
case noUpdateFogSetting:
fogUpdating = False;
break;
case searchLightOnFogStyle:
fogRed = searchLightFogRed;
fogGreen = searchLightFogGreen;
fogBlue = searchLightFogBlue;
fogNear = searchLightFogNear;
fogFar = searchLightFogFar;
if(fogUpdating)
{
mDevice->SetRenderState(D3DRS_FOGCOLOR, D3DCOLOR_XRGB((int)(255 * fogRed), (int)(255 * fogGreen), (int)(255 * fogBlue)));
// dpl_SetViewFog(
// dplMainView,
// dpl_fog_type_pixel_lin,
// fogRed,
// fogGreen,
// fogBlue,
// fogNear,
// fogFar );
// dpl_FlushView(dplMainView);
}
break;
case searchLightOffFogStyle:
fogRed = noSearchLightFogRed;
fogGreen = noSearchLightFogGreen;
fogBlue = noSearchLightFogBlue;
fogNear = noSearchLightFogNear;
fogFar = noSearchLightFogFar;
if(fogUpdating)
{
mDevice->SetRenderState(D3DRS_FOGCOLOR, D3DCOLOR_XRGB((int)(255 * fogRed), (int)(255 * fogGreen), (int)(255 * fogBlue)));
// dpl_SetViewFog(
// dplMainView,
// dpl_fog_type_pixel_lin,
// fogRed,
// fogGreen,
// fogBlue,
// fogNear,
// fogFar );
// dpl_FlushView(dplMainView);
}
break;
case winnersCircleFogStyle:
//
// The presentation shot, restored from the DPL body below. The
// stand sits far off the track in open ground, so the track's own
// fog leaves it in the dark - this is the lighter blue-violet the
// original used to lift it, with the fog pushed back to 100/1050.
//
// HACK!! This really shouldn't reset the clip planes, but since
// it only happens at the end of the review, it should be safe for now.
//
fogRed = 0.32f;
fogGreen = 0.30f;
fogBlue = 0.65f;
fogNear = 100.0f;
fogFar = 1050.0f;
// the per-frame FOGSTART/FOGEND come from these
currentFogNear = fogNear;
currentFogFar = fogFar;
clipNear = 0.25f;
clipFar = 1100.0f;
// tells the end-of-mission fade to stand down
mPresentationFog = True;
//
// Crop to the shape the stand was composed for. 4:3 unless
// RP412PODIUMASPECT says otherwise; 0 turns it off and lets
// the podium run full width.
//
mPresentationAspect = 4.0f / 3.0f;
{
const char *aspect = getenv("RP412PODIUMASPECT");
if (aspect != NULL)
{
mPresentationAspect = (float) atof(aspect);
}
}
// unconditional: fogUpdating is off while a vehicle drives its own
// headlight fog, and the podium overrides all of that
if (mDevice != NULL)
{
mDevice->SetRenderState(D3DRS_FOGCOLOR,
D3DCOLOR_XRGB((int)(255 * fogRed), (int)(255 * fogGreen),
(int)(255 * fogBlue)));
}
// dpl_SetViewClipPlanes ( dplMainView, 0.25f, 1100.0f );
// dpl_SetViewFog(
// dplMainView,
// dpl_fog_type_pixel_lin,
// 0.32,
// 0.3,
// 0.65,
// 100.0f,
// 1050.0f );
// dpl_FlushView(dplMainView);
break;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
DPLRenderer::GetCurrentFogSettings(
float *fog_Red,
float *fog_Green,
float *fog_Blue,
float *fog_Near,
float *fog_Far)
{
*fog_Red = fogRed;
*fog_Green = fogGreen;
*fog_Blue = fogBlue;
*fog_Near = fogNear;
*fog_Far = fogFar;
}
void DPLRenderer::SetCurrentFogLimits(
float fog_Near,
float fog_Far)
{
currentFogNear = fog_Near;
currentFogFar = fog_Far;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// MarkDCSHiearchy This will std::decend a DCS tree and set the appSpecific hook
// in every DCS equal to the entity pointer "entity", it calls itself recursively
// to do this.
//
void
DPLRenderer::MarkDCSHiearchy(
dpl_DCS *root_DCS, // Root of the hiearchy to mark
Entity *entity) // Entity pointer to mark it with
{
//STUBBED: DPL RB 1/14/07
//int
// dcs_counter;
//dpl_DCS
// *child_DCS;
////
//// First, mark this DCS
////
//if(dpl_GetAppSpecific(root_DCS))
// Fail("DPLRenderer::MarkDCSHiearchy tried to mark a DCS that was already marked!\n");
//dpl_PutAppSpecific(root_DCS,entity);
////
//// Now call this routine on all this dcs's children
////
//dcs_counter = 0;
//while((child_DCS=dpl_GetDCSChildDCS(root_DCS,dcs_counter)) != NULL)
//{
// MarkDCSHiearchy(child_DCS, entity);
// dcs_counter++;
//}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ReadPSFX
// reads a pfx file into a supplied array
// Most of this routine was a direct copy of phil's code and as such is a bit
// on the messy side.
//
dpl_PARTICLESTART_EFFECT_INFO*
DPLRenderer::ReadPSFX(
const char *file_name) // Name of the file containing the PSFX description
{
//STUBBED: DPL RB 1/14/07
// FILE
// *fp;
// int
// i,
// status;
// char
// line[256],
// *cp;
// //
// // Open the file containing the psfx, fail if it doesn't exist
// //
// strcpy(line,"video\\");
// strcat(line,file_name);
// fp = fopen ( line, "rt" );
// if(!fp)
// {
// DEBUG_STREAM<<"Could not open pfx file "<<line<<" effects using it will fail\n" << std::flush;
// return(NULL);
//// Fail("Required PFX file not found\n");
// }
// //
// // Allocate the memory for the pfx to be stored in.
// //
dpl_PARTICLESTART_EFFECT_INFO *psfx_info = new dpl_PARTICLESTART_EFFECT_INFO;
// if(!psfx_info)
// {
// Fail("ran out of RAM trying to read a pfx file\n");
// }
// //
// // This is the format of the psfx file we are going to read
// //
// #if 0
// format of psfx file is (NO BLANK LINES UNTIL END!)
// %s texture
// %d identifier %d maximum_issue %f release_period %f rate
// %f px %f py %f pz %f pv
// %f velx %f vely %f velz %f velxv %f velyv %f velzv
// %f rad %f radv %f exp %f expv %f dexp %f dexpv
// %f accelx %f accely %f accelz %f accelxv %f accelyv %f accelzv
// %f atten %f attenv
// %f sRi %f sGi %f sBi %f sAi %f sRiv %f sGiv %f sBiv %f sAiv
// %f sRo %f sGo %f sBo %f sAo %f sRov %f sGov %f sBov %f sAov
// %f eRi %f eGi %f eBi %f eAi %f eRiv %f eGiv %f eBiv %f eAiv
// %f eRo %f eGo %f eBo %f eAo %f eRov %f eGov %f eBov %f eAov
// %f color_warp %f alpha_warp
// %f duration %f durationv
// #endif
// //
// // Read in the texture name, null terminate it and look it up,
// // we don't complain if it fails since it is possible to do one of these
// // effects with no texture on it.
// //
// cp = fgets ( line, 255, fp );
// for (i=0; i<255; i++ )
// {
// if (cp[i] == '\n')
// cp[i]=0x0;
// }
// psfx_info->tex = dpl_LookupTexture ( cp, dpl_lookup_normal, &status );
// #if PRINT_THE_PFX
// printf ( "texture => %s\n", cp );
// #endif
// //
// // The remander of these statements get the rest of the PFX data
// //
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp,
// "%x %d %f %f\n",
// &psfx_info->identifier, &psfx_info->maximum_issue, &psfx_info->release_period, &psfx_info->rate );
// if(status < 4)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp, "%f %f %f %f\n", &psfx_info->px, &psfx_info->py, &psfx_info->pz, &psfx_info->pv );
// if(status < 4)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp, "%f %f %f %f %f %f\n",
// &psfx_info->velx, &psfx_info->vely, &psfx_info->velz,
// &psfx_info->velxv, &psfx_info->velyv, &psfx_info->velzv );
// if(status < 6)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp, "%f %f %f %f %f %f\n",
// &psfx_info->rad, &psfx_info->radv, &psfx_info->exp, &psfx_info->expv, &psfx_info->dexp, &psfx_info->dexpv );
// if(status < 6)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp, "%f %f %f %f %f %f\n",
// &psfx_info->accelx, &psfx_info->accely, &psfx_info->accelz,
// &psfx_info->accelxv, &psfx_info->accelyv, &psfx_info->accelzv );
// if(status < 6)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp, "%f %f\n", &psfx_info->atten, &psfx_info->attenv );
// if(status < 2)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp, "%f %f %f %f %f %f %f %f\n",
// &psfx_info->sRi,&psfx_info->sGi,&psfx_info->sBi,&psfx_info->sAi,&psfx_info->sRiv,&psfx_info->sGiv,&psfx_info->sBiv,&psfx_info->sAiv );
// if(status < 8)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp, "%f %f %f %f %f %f %f %f\n",
// &psfx_info->sRo,&psfx_info->sGo,&psfx_info->sBo,&psfx_info->sAo,&psfx_info->sRov,&psfx_info->sGov,&psfx_info->sBov,&psfx_info->sAov );
// if(status < 8)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp, "%f %f %f %f %f %f %f %f\n",
// &psfx_info->eRi,&psfx_info->eGi,&psfx_info->eBi,&psfx_info->eAi,&psfx_info->eRiv,&psfx_info->eGiv,&psfx_info->eBiv,&psfx_info->eAiv );
// if(status < 8)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp, "%f %f %f %f %f %f %f %f\n",
// &psfx_info->eRo,&psfx_info->eGo,&psfx_info->eBo,&psfx_info->eAo,&psfx_info->eRov,&psfx_info->eGov,&psfx_info->eBov,&psfx_info->eAov );
// if(status < 8)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp, "%f %f\n", &psfx_info->colour_warp, &psfx_info->alpha_warp );
// if(status < 2)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// cp = fgets ( line, 255, fp );
// status = sscanf ( cp, "%f %f\n", &psfx_info->dur, &psfx_info->durv );
// if(status < 2)
// {
// std::cout<<"pfx file "<<file_name<<" did not read correctly\n";
// return(NULL);
// }
//
// fclose (fp);
// #if PRINT_THE_PFX
// printf ( "Read psfx ->\n" );
// /*{{{ trace the psfx*/
// printf ( "psfx_info->tex = 0x%x\n",
// psfx_info->tex );
// printf ( "identifier = 0x%x ",
// psfx_info->identifier );
// printf ( "maximum_issue = %d ",
// psfx_info->maximum_issue );
// printf ( "release_period = %f\n",
// psfx_info->release_period );
// printf ( "rate = %f ",
// psfx_info->rate );
// printf ( "px = %f ",
// psfx_info->px );
// printf ( "py = %f ",
// psfx_info->py );
// printf ( "pz = %f ",
// psfx_info->pz );
// printf ( "pv = %f\n",
// psfx_info->pv );
// printf ( "velx = %f ",
// psfx_info->velx );
// printf ( "vely = %f ",
// psfx_info->vely );
// printf ( "velz = %f\n",
// psfx_info->velz );
// printf ( "velxv = %f ",
// psfx_info->velxv );
// printf ( "velyv = %f ",
// psfx_info->velyv );
// printf ( "velzv = %f\n",
// psfx_info->velzv );
// printf ( "rad = %f ",
// psfx_info->rad );
// printf ( "radv = %f\n",
// psfx_info->radv );
// printf ( "exp = %f ",
// psfx_info->exp );
// printf ( "expv = %f ",
// psfx_info->expv );
// printf ( "dexp = %f ",
// psfx_info->dexp );
// printf ( "dexpv = %f\n",
// psfx_info->dexpv );
// printf ( "accelx = %f ",
// psfx_info->accelx );
// printf ( "accely = %f ",
// psfx_info->accely );
// printf ( "accelz = %f ",
// psfx_info->accelz );
// printf ( "accelxv = %f ",
// psfx_info->accelxv );
// printf ( "accelyv = %f ",
// psfx_info->accelyv );
// printf ( "accelzv = %f\n",
// psfx_info->accelzv );
// printf ( "atten = %f ",
// psfx_info->atten );
// printf ( "attenv = %f\n",
// psfx_info->attenv );
// printf ( "sRi = %f ",
// psfx_info->sRi );
// printf ( "sGi = %f ",
// psfx_info->sGi );
// printf ( "sBi = %f ",
// psfx_info->sBi );
// printf ( "sAi = %f\n",
// psfx_info->sAi );
// printf ( "sRiv = %f ",
// psfx_info->sRiv );
// printf ( "sGiv = %f ",
// psfx_info->sGiv );
// printf ( "sBiv = %f ",
// psfx_info->sBiv );
// printf ( "sAiv = %f\n",
// psfx_info->sAiv );
// printf ( "sRo = %f ",
// psfx_info->sRo );
// printf ( "sGo = %f ",
// psfx_info->sGo );
// printf ( "sBo = %f ",
// psfx_info->sBo );
// printf ( "sAo = %f\n",
// psfx_info->sAo );
// printf ( "sRov = %f ",
// psfx_info->sRov );
// printf ( "sGov = %f ",
// psfx_info->sGov );
// printf ( "sBov = %f ",
// psfx_info->sBov );
// printf ( "sAov = %f\n",
// psfx_info->sAov );
// printf ( "eRi = %f ",
// psfx_info->eRi );
// printf ( "eGi = %f ",
// psfx_info->eGi );
// printf ( "eBi = %f ",
// psfx_info->eBi );
// printf ( "eAi = %f\n",
// psfx_info->eAi );
// printf ( "eRiv = %f ",
// psfx_info->eRiv );
// printf ( "eGiv = %f ",
// psfx_info->eGiv );
// printf ( "eBiv = %f ",
// psfx_info->eBiv );
// printf ( "eAiv = %f\n",
// psfx_info->eAiv );
// printf ( "eRo = %f ",
// psfx_info->eRo );
// printf ( "eGo = %f ",
// psfx_info->eGo );
// printf ( "eBo = %f ",
// psfx_info->eBo );
// printf ( "eAo = %f\n",
// psfx_info->eAo );
// printf ( "eRov = %f ",
// psfx_info->eRov );
// printf ( "eGov = %f ",
// psfx_info->eGov );
// printf ( "eBov = %f ",
// psfx_info->eBov );
// printf ( "eAov = %f\n",
// psfx_info->eAov );
// printf ( "colour_warp = %f ",
// psfx_info->colour_warp );
// printf ( "alpha_warp = %f ",
// psfx_info->alpha_warp );
// printf ( "dur = %f ",
// psfx_info->dur );
// printf ( "durv = %f\n",
// psfx_info->durv );
// #endif
return(psfx_info);
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// New INI file handler
// routine to read in an environment from a notation file and setup lights,
// spfx and such...
//
void
DPLRenderer::DPLReadINIPage(
NotationFile *master_notation_file,
const char *starting_page_name,
Mission *mission,
Logical debug_printing)
{
//STUBBED: DPL RB 1/14/07
float
red,
green,
blue,
x_rotate,
y_rotate,
z_rotate;
NameList
*cache_namelist,
*light_namelist,
*psfx_namelist,
*specialfx_namelist,
*include_pages,
*path_pages;
NameList::Entry
*entry;
const char
*next_include_page_name,
*TempStringPtr,
*compare_source;
if (debug_printing)
std::cout<<"DPLReadINIPage processing "<<starting_page_name<<"\n";
//
//---------------------------------------------------
// Process all the DPL gunk found on this page first
//---------------------------------------------------
//
if ((path_pages = master_notation_file->MakeEntryList(starting_page_name, "objectpath")) != NULL)
{
Register_Object(path_pages);
//
// Recursively process all the include pages
//
for( entry = path_pages->GetFirstEntry();
entry;
entry = entry->GetNextEntry())
{
// dpl_AddToObjectFilePath((char *)entry->dataReference, dpl_path_user);
if (debug_printing)
{
// DEBUG_STREAM << "objectpath '" << dpl_GetObjectFilePath() << "'" << std::endl << std::flush;
}
}
Unregister_Object(path_pages);
delete path_pages;
}
if ((path_pages = master_notation_file->MakeEntryList(starting_page_name, "texmappath")) != NULL)
{
Register_Object(path_pages);
//
// Recursively process all the include pages
//
for( entry = path_pages->GetFirstEntry();
entry;
entry = entry->GetNextEntry())
{
// dpl_AddToTexmapFilePath((char *)entry->dataReference, dpl_path_user);
if (debug_printing)
{
// DEBUG_STREAM << "texmappath '" << dpl_GetTexmapFilePath() << "'" << std::endl << std::flush;
}
}
Unregister_Object(path_pages);
delete path_pages;
}
if ((path_pages = master_notation_file->MakeEntryList(starting_page_name, "materialpath")) != NULL)
{
Register_Object(path_pages);
//
// Recursively process all the include pages
//
for( entry = path_pages->GetFirstEntry();
entry;
entry = entry->GetNextEntry())
{
// dpl_AddToMaterialFilePath((char *)entry->dataReference, dpl_path_user);
if (debug_printing)
{
// DEBUG_STREAM << "materialpath '" << dpl_GetMaterialFilePath() << "'" << std::endl << std::flush;
}
}
Unregister_Object(path_pages);
delete path_pages;
}
if (master_notation_file->GetEntry(starting_page_name, "priorityobjectpath", &TempStringPtr))
{
// dpl_AddToObjectFilePath((char *)TempStringPtr, dpl_path_system);
if (debug_printing)
{ DEBUG_STREAM << "priorityobjectpath '" << TempStringPtr << "'" << std::endl << std::flush; }
}
if (master_notation_file->GetEntry(starting_page_name, "prioritytexmappath", &TempStringPtr))
{
// dpl_AddToTexmapFilePath((char *)TempStringPtr, dpl_path_system);
if (debug_printing)
{ DEBUG_STREAM << "prioritytexmappath '" << TempStringPtr << "'" << std::endl << std::flush; }
}
if (master_notation_file->GetEntry(starting_page_name, "prioritymaterialpath", &TempStringPtr))
{
// dpl_AddToMaterialFilePath((char *)TempStringPtr, dpl_path_system);
if (debug_printing)
{ DEBUG_STREAM << "prioritymaterialpath '" << TempStringPtr << "'" << std::endl << std::flush; }
}
//
// Get a the list of dpl objects that should be loaded into cache and load them
//
if ((cache_namelist = master_notation_file->MakeEntryList(starting_page_name, "cache")) != NULL)
{
d3d_OBJECT *d3d_a_object;
Register_Object(cache_namelist);
for(entry = cache_namelist->GetFirstEntry(); entry; entry = entry->GetNextEntry())
{
d3d_a_object = d3d_OBJECT::LoadObject(mDevice, (char *)entry->dataReference);
if(!d3d_a_object)
DEBUG_STREAM<<"Unable to cache "<<(char *)entry->dataReference<<"\n" << std::flush;
else
{
if(debug_printing)
std::cout<<"Caching "<<(char *)entry->dataReference<<"\n";
}
}
Unregister_Object(cache_namelist);
delete cache_namelist;
}
//
// Get the clip range
//
if(master_notation_file->GetEntry(starting_page_name, "clip" ,&TempStringPtr))
{
sscanf(TempStringPtr, "%f %f", &clipNear, &clipFar);
if(debug_printing)
std::cout<<"Clip Range "<<TempStringPtr<<"\n";
}
//
// Background color
//
if(master_notation_file->GetEntry(starting_page_name, "backgnd" ,&TempStringPtr))
{
sscanf(TempStringPtr, "%f %f %f", &backgroundRed, &backgroundGreen, &backgroundBlue);
if(debug_printing)
std::cout<<"Background Color "<<TempStringPtr<<"\n";
}
//
// Get the projection, pipe and other view related junk
//
if(master_notation_file->GetEntry(starting_page_name, "viewangle" ,&TempStringPtr))
{
sscanf(TempStringPtr, "%f", &viewAngle);
if(debug_printing)
std::cout<<"View Angle "<<TempStringPtr<<"\n";
}
//
// now that we have the viewing angle, screen size, and clip ranges, setup the projection matrix
//
D3DXMatrixIdentity(&mProjectionMatrix);
D3DXMatrixPerspectiveFovLH(&mProjectionMatrix, viewAngle * (PI/180.0f), (float)x_size / (float)y_size, clipNear, clipFar);
mProjectionMatrix(0, 0) *= -1;
mDecalEpsilon = 0.0000005f;
mDecalProjectionMatrix = mProjectionMatrix;
mDecalProjectionMatrix._33 -= mDecalEpsilon;
//
// setup the fog
//
if(master_notation_file->GetEntry(starting_page_name, "fog" ,&TempStringPtr))
{
sscanf(TempStringPtr, "%f %f %f %f %f", &fogNear, &fogFar, &fogRed, &fogGreen, &fogBlue);
searchLightFogRed = fogRed;
searchLightFogGreen = fogGreen;
searchLightFogBlue = fogBlue;
searchLightFogNear = fogNear;
searchLightFogFar = fogFar;
noSearchLightFogRed = fogRed;
noSearchLightFogGreen = fogGreen;
noSearchLightFogBlue = fogBlue;
noSearchLightFogNear = fogNear;
noSearchLightFogFar = fogFar;
currentFogNear = fogNear;
currentFogFar = fogFar;
// Force a 0-0 black fog on startup
// dpl_SetViewFog(dplMainView, dpl_fog_type_pixel_lin, 0.0, 0.0, 0.0, 0.01, 0.05);
//TODO: for fog testing, just set the values here
mDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
mDevice->SetRenderState(D3DRS_FOGCOLOR, D3DCOLOR_XRGB((int)(255 * fogRed), (int)(255 * fogGreen), (int)(255 * fogBlue)));
mDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
if(debug_printing)
std::cout<<"Fog "<<TempStringPtr<<"\n";
}
//
// setup the no searchlight fog if any
//
if(master_notation_file->GetEntry(starting_page_name, "nosearchlightfog" ,&TempStringPtr))
{
sscanf(TempStringPtr, "%f %f %f %f %f", &noSearchLightFogNear, &noSearchLightFogFar, &noSearchLightFogRed, &noSearchLightFogGreen, &noSearchLightFogBlue);
if(debug_printing)
std::cout<<"nosearchlightfog "<<TempStringPtr<<"\n";
}
//
// setup the ambient light
//
if(master_notation_file->GetEntry(starting_page_name, "ambient" ,&TempStringPtr))
{
sscanf(TempStringPtr, "%f %f %f ", &red, &green, &blue);
mDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB((int)(255 * red), (int)(255 * green), (int)(255 * blue)));
if(debug_printing)
std::cout<<"Ambient Light "<<TempStringPtr<<"\n";
}
//
// Set up the day/night cloud color
//
if (master_notation_file->GetEntry(starting_page_name, "clouds", &TempStringPtr))
{
sscanf(TempStringPtr, "%f %f %f ", &this->mCloudRed, &this->mCloudGreen, &this->mCloudBlue);
}
if (master_notation_file->GetEntry(starting_page_name, "cloudemit", &TempStringPtr))
{
sscanf(TempStringPtr, "%f %f %f ", &this->mCloudEmitRed, &this->mCloudEmitGreen, &this->mCloudEmitBlue);
}
//
// Get a the list of lights from this page
//
if ((light_namelist = master_notation_file->MakeEntryList(starting_page_name, "light")) != NULL)
{
Register_Object(light_namelist);
//
// HACK !!! All the lights must (temporarily) be defined on a single page.
// The lights and their DCS's should really be stored in a light object on
// a chain, or as an actual entity in the simulation. This line will throw
// an exception if this rule is violated
//
if(light_namelist->EntryCount() != 0)
{
if(sceneLightCount != 0)
{
Fail("All lights must be defined on a single INI file page!\n");
}
//
// Create storage space for the dpl_LIGHT and dpl_DCS structures
//
sceneLightCount = light_namelist->EntryCount();
if (sceneLightCount)
{
sceneLight = new D3DLIGHT9[sceneLightCount];
memset(sceneLight, 0, sizeof(D3DLIGHT9) * sceneLightCount);
}
int current_entry = 0;
for(entry = light_namelist->GetFirstEntry(); entry; entry = entry->GetNextEntry(), ++current_entry)
{
//
// Read the parameters for the light
//
sscanf(
(char *)entry->dataReference,
"%f %f %f %f %f %f",
&red,
&green,
&blue,
&x_rotate,
&y_rotate,
&z_rotate);
if(debug_printing)
std::cout<<"Light "<<(char *)entry->dataReference<<"\n";
//
// Create and rotate a dcs to hold the light, and the light itself
//
sceneLight[current_entry].Type = D3DLIGHT_DIRECTIONAL;
sceneLight[current_entry].Diffuse.r = red;
sceneLight[current_entry].Diffuse.g = green;
sceneLight[current_entry].Diffuse.b = blue;
sceneLight[current_entry].Diffuse.a = 1.0f;
D3DXMATRIX rot, rotX, rotY, rotZ;
D3DXMatrixRotationX(&rotX, x_rotate * (PI/180.0f));
D3DXMatrixRotationY(&rotY, y_rotate * (PI/180.0f));
D3DXMatrixRotationZ(&rotZ, z_rotate * (PI/180.0f));
rot = rotZ * rotX * rotY;
D3DXVECTOR3 dir(0, 0, -1);
D3DXVECTOR4 vec;
D3DXVec3Transform(&vec, &dir, &rot);
dir = D3DXVECTOR3(vec.x, vec.y, vec.z);
D3DXVec3Normalize(&dir, &dir);
sceneLight[current_entry].Direction.x = dir.x;
sceneLight[current_entry].Direction.y = dir.y;
sceneLight[current_entry].Direction.z = dir.z;
mDevice->SetLight(current_entry, &sceneLight[current_entry]);
mDevice->LightEnable(current_entry, TRUE);
// sceneLight[current_entry] = dpl_NewLight();
// sceneLightDCS[current_entry] = dpl_NewDCS();
// dpl_AddDCSToScene ( sceneLightDCS[current_entry] );
// dpl_SetLightType ( sceneLight[current_entry], dpl_light_type_directional );
// dpl_SetLightColor ( sceneLight[current_entry], red, green, blue);
// dpl_SetLightDCS ( sceneLight[current_entry], sceneLightDCS[current_entry] );
// dpl_RotateDCS ( sceneLightDCS[current_entry], z_rotate, dpl_Z );
// dpl_RotateDCS ( sceneLightDCS[current_entry], x_rotate, dpl_X );
// dpl_RotateDCS ( sceneLightDCS[current_entry], y_rotate, dpl_Y );
// dpl_FlushLight ( sceneLight[current_entry] );
// dpl_FlushDCS ( sceneLightDCS[current_entry] );
}
}
//
// Get rid of the light entry list
//
Unregister_Object(light_namelist);
delete light_namelist;
}
////
//// Get a the list of PSFX effects we should load into RAM
////
//if ((psfx_namelist = master_notation_file->MakeEntryList(starting_page_name, "psfx")) != NULL)
//{
// const char *psfx_file_name;
// int psfx_number;
// //
// // create all the PSFX on the current page
// //
// for( entry = psfx_namelist->GetFirstEntry();
// entry;
// entry = entry->GetNextEntry())
// {
// psfx_number = atoi(entry->GetName()+4);
// psfx_file_name = entry->GetChar();
// if(debug_printing)
// std::cout<<"psfx"<<psfx_number<<" "<<psfx_file_name<<"\n";
// if(psfx_number < 0 || psfx_number > MAX_PSFX_COUNT-1)
// {
// Fail("PSFX id number was not in the allowed range");
// }
// //
// // See if we are overwriting an existing psfx
// //
// if(myPSFXDescriptons[psfx_number])
// {
// std::cout<<"psfx#"<<psfx_number<<" already existed from an earlier page, redefining it\n";
// delete myPSFXDescriptons[psfx_number];
// Unregister_Pointer(myPSFXDescriptons[psfx_number]);
// }
//// DEBUG_STREAM<<"Loading PSFX# "<<psfx_number<<" from file "<<psfx_file_name<<"\n" << std::flush;
// myPSFXDescriptons[psfx_number] = ReadPSFX(psfx_file_name);
// Register_Pointer(myPSFXDescriptons[psfx_number]);
// }
// //
// // Get rid of the PSFX entry list
// //
// delete psfx_namelist;
//}
//
// Get a the list of special effects
//
if ((specialfx_namelist = master_notation_file->MakeEntryList(starting_page_name, "effect")) != NULL)
{
const char *effect_page_name;
int status, spfx_number, version;
INDIE_EFFECT spfx;
memset(&spfx, 0, sizeof(PARTICLE_EFFECT));
Register_Object(specialfx_namelist);
//
// create all the effects on the current page
//
for( entry = specialfx_namelist->GetFirstEntry();
entry;
entry = entry->GetNextEntry())
{
//
// Get the page with this effect on it
//
effect_page_name = entry->GetChar();
if(debug_printing)
std::cout<<"specialfx"<<spfx_number<<" "<<effect_page_name<<"\n";
master_notation_file->GetEntry(effect_page_name, "id", &spfx_number);
version = 1;
master_notation_file->GetEntry(effect_page_name, "version", &version);
if (version < 2)
continue;
master_notation_file->GetEntry(effect_page_name, "texbounds", &TempStringPtr);
sscanf(TempStringPtr, "%f %f %f %f", &spfx.textureBounds.left, &spfx.textureBounds.top, &spfx.textureBounds.right, &spfx.textureBounds.bottom);
master_notation_file->GetEntry(effect_page_name, "rotate", (int*)&spfx.rotate);
master_notation_file->GetEntry(effect_page_name, "size", &spfx.fragSize);
master_notation_file->GetEntry(effect_page_name, "velocity", &spfx.velocity);
master_notation_file->GetEntry(effect_page_name, "varianceX", &spfx.varianceX);
master_notation_file->GetEntry(effect_page_name, "varianceY", &spfx.varianceY);
master_notation_file->GetEntry(effect_page_name, "varianceZ", &spfx.varianceZ);
master_notation_file->GetEntry(effect_page_name, "gravity", &spfx.gravity);
master_notation_file->GetEntry(effect_page_name, "count", &spfx.fragCount);
master_notation_file->GetEntry(effect_page_name, "life", &spfx.fragLifetime);
if (!master_notation_file->GetEntry(effect_page_name, "max_repeat", &spfx.maxRepeat))
spfx.maxRepeat = 30.0;
NameList *color_list = master_notation_file->MakeEntryList(effect_page_name, "color");
int i = 0;
for (NameList::Entry *color_entry = color_list->GetFirstEntry(); color_entry; color_entry = color_entry->GetNextEntry())
{
memset(&spfx.colors[i], 0, sizeof(COLOR_POINT));
spfx.colors[i].active = true;
int a, r, g, b;
sscanf(color_entry->GetChar(), "%f %d %d %d %d", &spfx.colors[i].time, &a, &r, &g, &b);
spfx.colors[i].color.argb = D3DCOLOR_ARGB(a, r, g, b);
i++;
}
for (;i < COLOR_POINT_COUNT; i++)
{
memset(&spfx.colors[i], 0, sizeof(COLOR_POINT));
}
//
// install the effect
//
int isIndie = 0;
master_notation_file->GetEntry(effect_page_name, "independent", &isIndie);
if (isIndie)
{
master_notation_file->GetEntry(effect_page_name, "maxIssue", &spfx.maxIssue);
master_notation_file->GetEntry(effect_page_name, "releasePeriod", &spfx.releasePeriod);
master_notation_file->GetEntry(effect_page_name, "duration", &spfx.duration);
spfx.id = 1000 + spfx_number;
myPSFXDescriptons[spfx_number] = spfx;
}
else
ParticleEngine::InstallEffect(spfx_number, *((PARTICLE_EFFECT*)&spfx));
}
//
// Get rid of the effect entry list
//
Unregister_Object(specialfx_namelist);
delete specialfx_namelist;
}
//--------------------------------------------------
// Make a list of all the include pages on this page
//--------------------------------------------------
if ((include_pages = master_notation_file->MakeEntryList(starting_page_name, "include")) != NULL)
{
Register_Object(include_pages);
//
// Recursively process all the include pages
//
for( entry = include_pages->GetFirstEntry();
entry;
entry = entry->GetNextEntry())
{
// Get the name of the next include page
next_include_page_name = (char *)entry->dataReference;
// Process the next page recursively through this routine
DPLReadINIPage(
master_notation_file,
next_include_page_name,
mission,
debug_printing);
if(debug_printing)
std::cout<<"DPLReadINIPage returned to "<<starting_page_name<<"\n";
}
Unregister_Object(include_pages);
delete include_pages;
}
//
// Process a compare and branch if there is one on this page
//
if(master_notation_file->GetEntry(starting_page_name, "compare" ,&compare_source))
{
Logical
match;
NameList
*branch_pages;
CString
compare_strings[10],
wild_card("*"),
token_string,
target_string,
master_compare_string(compare_source);
int
token_count;
ResourceFile
*this_resource_file;
//
// Get a pointer to our resource file so we can find the name of the map
// resource later in this process.
//
Check(application);
this_resource_file = application->GetResourceFile();
Check(this_resource_file);
//
// Print the compare string
//
if(debug_printing)
std::cout<<"compare = "<<master_compare_string<<"\n";
//
// Break the compare string apart, fetch the mission variables for each
// item in it and store them in the compare_strings array for later.
//
token_count = 0;
while(target_string = master_compare_string.GetNthToken(token_count,","))
{
// std::cout<<"Mission variable "<<token_count<<": ";
if(strcmp(target_string,"location") == 0)
{
compare_strings[token_count] = (this_resource_file->FindResourceDescription(mission->GetMapID()))->resourceName;
// std::cout<<target_string<<" = "<<compare_strings[token_count]<<"\n";
}
else if(strcmp(target_string,"time") == 0)
{
compare_strings[token_count] = mission->GetMissionTime();
// std::cout<<target_string<<" = "<<compare_strings[token_count]<<"\n";
}
else if(strcmp(target_string,"weather") == 0)
{
compare_strings[token_count] = mission->GetMissionWeather();
// std::cout<<target_string<<" = "<<compare_strings[token_count]<<"\n";
}
else if(strcmp(target_string,"scenario") == 0)
{
compare_strings[token_count] = mission->GetScenarioName();
// std::cout<<target_string<<" = "<<compare_strings[token_count]<<"\n";
}
else
{
std::cout<<"Mission variable "<<token_count<<": "<<target_string<<" IS AN UNKNOWN MISSION VARIABLE\n";
}
token_count++;
}
//
// Print the version of the compare string with the actual mission variables
// in it
//
int i;
if(debug_printing)
{
std::cout<<"comparing to: ";
for(i = 0; i<token_count; i++)
{
std::cout<<compare_strings[i]<<", ";
}
std::cout<<"\n";
}
//
// Now compare all the branch pages till we have done them all or found a match
//
branch_pages = master_notation_file->MakeEntryList(starting_page_name,"branch");
Register_Object(branch_pages);
for( entry = branch_pages->GetFirstEntry();
entry;
entry = entry->GetNextEntry())
{
CString
branch_command,
match_string;
int
compare_token;
//
// Get the text of the branch command and print it
//
branch_command = (char *)entry->dataReference;
if(debug_printing)
std::cout<<"branch = "<<branch_command<<"\n";
//
// Grab each token out of the branch string and compare it to the
// corrisponding item in compare_strings. This also checks for the
// wildcard cararcter. Any failure to match skips this branch string.
//
match = True;
for(compare_token = 0; compare_token<token_count; compare_token++)
{
match_string = branch_command.GetNthToken(compare_token,",");
if(match_string != compare_strings[compare_token] && match_string != wild_card)
{
match = False;
// std::cout<<match_string<<"!="<<compare_strings[compare_token]<<"\n";
break;
}
else
{
// std::cout<<match_string<<"=="<<compare_strings[compare_token]<<"\n";
}
}
//
// See if we had a successful match
//
if(match)
{
// Match! Get the name of the page to branch to and do it.
match_string = branch_command.GetNthToken(compare_token,",");
DPLReadINIPage(
master_notation_file,
match_string,
mission,
debug_printing);
if(debug_printing)
std::cout<<"DPLReadINIPage returned to "<<starting_page_name<<"\n";
// now break out of the loop because we only allow one page to match
break;
}
}
Unregister_Object(branch_pages);
delete branch_pages;
//
// If we found no match, yell about it
//
if(!match)
{
DEBUG_STREAM << "BRANCH ERROR IN '" <<
master_notation_file->GetFileName() <<
"' NO MATCH FOUND!!" << std::endl;
}
}
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Read environment
// routine to read in an environment from a notation file and setup lights,
// spfx and such...
//
void
DPLRenderer::DPLReadEnvironment(Mission *mission)
{
//STUBBED: DPL RB 1/14/07
char *L4DPLcfg;
// const char
// *cc;
NotationFile *renderer_environment;
Logical debug_printing;
//
// Get the name of the notation file from an environmental
//
L4DPLcfg = getenv("L4DPLCFG");
if (!L4DPLcfg)
{
DEBUG_STREAM<<"L4DPLCFG not defined, using dpldflt.ini!\n" << std::flush;
L4DPLcfg = "dpldflt.ini";
}
//
// Read the environment out of a notation file
//
renderer_environment = new NotationFile(L4DPLcfg);
Register_Object(renderer_environment);
if (renderer_environment->PageCount() == 0)
{
DEBUG_STREAM<<"Renderer config notation file "<<L4DPLcfg<<"was empty, can't continue\n" << std::flush;
Verify(renderer_environment->PageCount() == 0);
}
//
// Register the notation file and check it
//
Check(renderer_environment);
if (renderer_environment->PageExists("main"))
{
if (!(renderer_environment->GetLogicalEntry("main", "debug", &debug_printing)))
{
debug_printing=False;
}
DPLReadINIPage(renderer_environment, "main", mission, debug_printing);
#if 0
if ((cc = dpl_GetObjectFilePath()) == NULL || *cc == NULL)
{
dpl_SetObjectFilePath ( ".\\video", NULL, NULL );
}
if ((cc = dpl_GetTexmapFilePath()) == NULL || *cc == NULL)
{
dpl_SetTexmapFilePath ( ".\\video", NULL, NULL );
}
if ((cc = dpl_GetMaterialFilePath()) == NULL || *cc == NULL)
{
dpl_SetMaterialFilePath ( ".\\video", NULL, NULL );
}
#endif
}
else
{
if (!(renderer_environment->GetLogicalEntry("dpl_config", "debug", &debug_printing)))
{
debug_printing=False;
}
std::cout<<"READING OLD FORMAT INI FILE '"<<renderer_environment->GetFileName()<<"'---hope this works\n";
// dpl_SetObjectFilePath ( ".\\video", NULL, NULL );
// dpl_SetTexmapFilePath ( ".\\video", NULL, NULL );
// dpl_SetMaterialFilePath ( ".\\video", NULL, NULL );
DPLReadINIPage(renderer_environment, "dpl_config", mission, debug_printing);
}
if (debug_printing)
{
// DEBUG_STREAM << "ObjectFilePath '" << dpl_GetObjectFilePath() << "'" << std::endl << std::flush;
// DEBUG_STREAM << "TexmapFilePath '" << dpl_GetTexmapFilePath() << "'" << std::endl << std::flush;
// DEBUG_STREAM << "MaterialFilePath '" << dpl_GetMaterialFilePath() << "'" << std::endl << std::flush;
}
//
// Close the notation file
//
Verify( !renderer_environment->IsDirty() );
Unregister_Object(renderer_environment);
delete renderer_environment;
//
// Flush all the things we've set/changed here
//
// dpl_FlushView(dplMainView);
return;
}
//
//#############################################################################
// Destructor for the video renderer
//#############################################################################
//
DPLRenderer::~DPLRenderer()
{
delete gOpNames;
delete gReplacementData;
if (mPrimaryIndex != NULL)
{
delete mPrimaryIndex;
}
if (mSecondaryIndex != NULL)
{
delete mSecondaryIndex;
}
if (mAux1Index != NULL)
{
delete mAux1Index;
}
if (mAux2Index != NULL)
{
delete mAux2Index;
}
// device-bound resources living in static caches would dangle into
// the next race of the single-binary loop - drop them with the device
d3d_OBJECT::FlushTextureCache();
SAFE_RELEASE(mDevice);
SAFE_RELEASE(gD3D);
//STUBBED: DPL RB 1/14/07
//int
// psfx_number;
////------------------------------------------------------
//// release allocated memory used by dump_frame_buffer()
////------------------------------------------------------
//dump_frame_buffer(NULL, NULL, NULL, NULL);
////
//// Delete any memory allocated to hold psfx effect descriptions
////
//for( psfx_number = 0; psfx_number < MAX_PSFX_COUNT; psfx_number++)
//{
// if(myPSFXDescriptons[psfx_number])
// {
// delete myPSFXDescriptons[psfx_number];
// Unregister_Pointer(myPSFXDescriptons[psfx_number]);
// myPSFXDescriptons[psfx_number] = NULL;
// }
//}
////
////~~~~~~~~~~~~~~~~~~
//// Delete all Lights
////~~~~~~~~~~~~~~~~~~
////
//if (ambientLight)
//{
// Check_Pointer(ambientLight);
// Unregister_Pointer(ambientLight);
// dpl_DeleteLight(ambientLight);
//}
//if (sceneLightDCS && sceneLight)
//{
// Check_Pointer(sceneLightDCS);
// for(int ii=0;ii<sceneLightCount;++ii)
// {
// Check_Pointer(sceneLight[ii]);
// Check_Pointer(sceneLightDCS[ii]);
// dpl_RemoveDCSFromScene(sceneLightDCS[ii]);
// dpl_DeleteDCS(sceneLightDCS[ii]);
// Unregister_Pointer(sceneLight[ii]);
// Unregister_Pointer(sceneLightDCS[ii]);
// }
// Unregister_Pointer(sceneLight);
// delete[] sceneLight;
// Unregister_Pointer(sceneLightDCS);
// delete[] sceneLightDCS;
//}
//Unregister_Object(DPLHeap);
//delete DPLHeap;
// DPLHeap = NULL;
}
//
//#############################################################################
// TestInstance
//#############################################################################
//
Logical
DPLRenderer::TestInstance() const
{
VideoRenderer::TestInstance();
Verify(dplMainView != NULL);
Verify(dplMainZone != NULL);
return True;
}
//
//#############################################################################
// FlushBitSliceTexture
// Sends the bitslice texture to the division card.
// LoadBitSliceTexture
// Handles building of a bitmap into a texture map for the Division card, this
// specifically deals with merging a 1 bit bitmap into a 4 bit bitslice texmap.
//#############################################################################
//
void
DPLRenderer::FlushBitSliceTexture(
unsigned int *local_storage)
{
//STUBBED: DPL RB 1/14/07
//int
// status;
//dpl_TEXTURE *temp_texture =
// dpl_LookupTexture("bmap:bmap1_tex", dpl_lookup_normal, &status);
//if(temp_texture == NULL)
//{
// DEBUG_STREAM<<"WARNING, textures for player names not defined\n" << std::flush;
//}
//else
//{
// dpl_TEXMAP *temp_texmap =
// dpl_GetTextureTexmap(temp_texture);
// if(temp_texmap != NULL)
// {
// dpl_TexmapTexels2D ( temp_texmap, local_storage,
// 128,
// 64,
// 4 );
// dpl_FlushTexmap(temp_texmap);
// }
// else
// {
// DEBUG_STREAM<<"WARNING, texmap for player names not defined\n" << std::flush;
// }
//}
}
void DPLRenderer::LoadBitSliceTexture(BitMap *bitmap_to_load, LPDIRECT3DTEXTURE9 local_storage)
{
// lock the texture and grab a pointer to the data
D3DLOCKED_RECT lockedRect;
local_storage->LockRect(0, &lockedRect, NULL, D3DLOCK_DISCARD);
//
// Figure out the position to start copying the data at
//
Word *word_pointer = bitmap_to_load->Data.MapPointer;
__int16 *pixel_pointer = (__int16*)lockedRect.pBits;
//
// Actually process the texels
//
int bit_mask = 0x8000;
for(int y = 0; y < 32; y++)
{
for(int x = 0; x < 128; x++)
{
if (*word_pointer & bit_mask)
*(pixel_pointer++) = 0xFFFF;
else
*(pixel_pointer++) = 0x0000;
bit_mask >>= 1;
if (bit_mask == 0)
{
bit_mask = 0x8000;
word_pointer++;
}
}
}
// unlock the texture now that we're done updating it
local_storage->UnlockRect(0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CacheExplosionScripts
// Handles code to preload the morph and other caches with things needed by
// explosion scripts. Should be called at startup, once for each.
//
void
DPLRenderer::CacheExplosionScripts(
int script_select) // The script to be cached
{
//STUBBED: DPL RB 1/14/07
// dpl_OBJECT
// *object;
// //
// // Load the morph targets into the MUNGA object cache
// //
// switch(script_select)
// {
// case 104: // Thor death explosion
// case 106: // Thor death explosion
// {
// dpl_LoadObject("flamebig.bgf", dpl_load_normal);
// dpl_LoadObject("thrdbr.bgf" , dpl_load_normal);
// dpl_LoadObject("ldbr.bgf" , dpl_load_normal);
// dpl_LoadObject("flamesml.bgf", dpl_load_normal);
//// DEBUG_STREAM << "explosion "<< script_select<<" cached\n" << std::flush;
// break;
// }
// }
}
//
//#############################################################################
// ExplosionScripts
// Contains several scripts for running various types of explosion effects.
//#############################################################################
//
void
DPLRenderer::ExplosionScripts(
Entity *entity, // The entity we are dealing with
ResourceDescription* ,//model_resource, // Pointer to the video resource
ViewFrom ,//view_type, // Type of reference (inside/outside...etc.)
int script_select)
{
//STUBBED: DPL RB 1/14/07
// dpl_OBJECT
// *object_1;
// //
// // Construct a root renderable to hang the explosion effects on
// //
// RootRenderable *this_root =
// new RootRenderable(
// entity, // Entity to attach the renderable to
// RootRenderable::Dynamic, // How/when to execute the renderable
// NULL, // object to hang on the DCS, may be a list later <NULL>
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL); // intersection mask for the object
// Register_Object(this_root);
// //
// // Select which script to construct
// //
// switch(script_select)
// {
// case 0: // Shock wave
// {
// //
// // Load object(s) we will be using for the explosions
// //
// object_1 = dpl_LoadObject("shock.bgf", dpl_load_normal);
// //
// // Setup control variables and transforms we need
// //
// Vector3D scaling_velocity_1(3.5, 3.5, 3.5);
// Vector3D velocity_accel_1(0.0, 0.0, 0.0);
// LinearMatrix explosion_1_offset(True);
// //
// // Create the scaling explosion renderables
// //
// ScalingExplosionRenderable *explosion_1 =
// new ScalingExplosionRenderable(
// entity, // Entity to attach the renderable to
// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable
// object_1, // This will be the scaling explosion object
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL, // intersection mask for the object
// this_root->GetDCS(), // the parent DCS we will be offsetting from
// &explosion_1_offset, // offset matrix to be applied prior to joint DCS
// &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity
// &velocity_accel_1,
// 0.0f,
// NULL); // -.25 gravity is normal
// Register_Object(explosion_1);
// //
// // Create a sweep renderable to drive the material morph
// //
// SweepRenderable *sweep_1 =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 0.5f, // How long to take to sweep from 0 to 1
// 1, // number of times to cycle before stopping
// NULL);
// Register_Object(sweep_1);
// //
// // Lookup a texture that we can use for the morphing materials
// //
// int
// status;
// dpl_TEXTURE *effect_texture =
// dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status );
// if (effect_texture == NULL)
// DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n" << std::flush;
// //
// // Setup a morph material renderable for each explosion shape
// //
// MorphMaterialRenderable *morph_material_1 =
// new MorphMaterialRenderable(
// entity, // Entity to attach the renderable to
// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable
// 1.0f,1.0f,1.0f, // Material's ambient component
// 1.0f,1.0f,1.0f, // Material's emissive component
// 1.0f,1.0f,1.0f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 4.0f,0.2f,-0.05f, // Material's opacity
// effect_texture, // Material's texture pointer
// 0.0f, // Material's Z dither value
// 0, // Material's Fog Imunity value
// 0.5f,0.5f,0.5f, // Material's ambient component
// 0.5f,0.5f,0.5f, // Material's emissive component
// 0.5f,0.5f,0.5f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
//// 0.25f,0.25f,-0.05f, // Material's opacity
// 0.1f,0.1f,-0.05f, // Material's opacity
// 0.0f, // Material's Z dither value
// sweep_1->GetSweepAttribute());
// Register_Object(morph_material_1);
// dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1);
// if(!explosion_1_instance)
// Fail("explosion_1_instance came back null\n");
// dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial());
// dpl_FlushInstance(explosion_1_instance);
// break;
// }
// case 1: // Big explosion
// {
// //
// // Load object(s) we will be using for the explosions
// //
// object_1 = dpl_LoadObject("exp.bgf", dpl_load_normal);
// //
// // Setup control variables and transforms we need
// //
// Vector3D scaling_velocity_1(0.15, 0.15, 0.15);
// Vector3D scaling_velocity_2(0.18, 0.22, 0.18);
// Vector3D velocity_accel_1(0.0, 0.0, 0.0);
// Vector3D velocity_accel_2(0.0, 0.0, 0.0);
// LinearMatrix explosion_1_offset(True);
// LinearMatrix explosion_2_offset(True);
// Point3D explosion_2_translate(0.0f, 0.0f, 0.0f);
// EulerAngles explosion_2_rotate(0.0f, 1.0f, 0.0f);
// explosion_2_offset = explosion_2_rotate;
// explosion_2_offset = explosion_2_translate;
// //
// // Create the scaling explosion renderables
// //
// ScalingExplosionRenderable *explosion_1 =
// new ScalingExplosionRenderable(
// entity, // Entity to attach the renderable to
// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable
// object_1, // This will be the scaling explosion object
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL, // intersection mask for the object
// this_root->GetDCS(), // the parent DCS we will be offsetting from
// &explosion_1_offset, // offset matrix to be applied prior to joint DCS
// &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity
// &velocity_accel_1,
// 0.0f,
// NULL); // -.25 gravity is normal
// Register_Object(explosion_1);
// ScalingExplosionRenderable *explosion_2 =
// new ScalingExplosionRenderable(
// entity, // Entity to attach the renderable to
// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable
// object_1, // This will be the scaling explosion object
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL, // intersection mask for the object
// this_root->GetDCS(), // the parent DCS we will be offsetting from
// &explosion_2_offset, // offset matrix to be applied prior to joint DCS
// &scaling_velocity_2, // Effect control vector, Y is acceleration, X, Z are velocity
// &velocity_accel_2,
// 0.0f,
// NULL);
// Register_Object(explosion_2);
// //
// // Create a sweep renderable to drive the material morph
// //
// SweepRenderable *sweep_1 =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 3.0f,
// 1, // number of times to cycle before stopping
// NULL); // How long to take to sweep from 0 to 1
// Register_Object(sweep_1);
// SweepRenderable *sweep_2 =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 2.0f,
// 1, // number of times to cycle before stopping
// NULL); // How long to take to sweep from 0 to 1
// Register_Object(sweep_2);
// //
// // Lookup a texture that we can use for the morphing materials
// //
// int
// status;
// dpl_TEXTURE *effect_texture =
// dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status );
// if (effect_texture == NULL)
// DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n" << std::flush;
// //
// // Setup a morph material renderable for each explosion shape
// //
// #if 0
// 0.9f,0.0f,0.0f, // Material's ambient component
// 1.0f,1.0f,0.0f, // Material's emissive component
// 1.0f,0.7f,0.2f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 8.0f,0.2f,-0.05f, // Material's opacity
// #endif
// MorphMaterialRenderable *morph_material_1 =
// new MorphMaterialRenderable(
// entity, // Entity to attach the renderable to
// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable
// 0.9f,0.0f,0.0f, // Material's ambient component
// 1.0f,0.2f,0.0f, // Material's emissive component
// 1.0f,0.2f,0.0f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 10.0f,0.6f,-0.05f, // Material's opacity
// effect_texture, // Material's texture pointer
// 0.0f, // Material's Z dither value
// 0, // Material's Fog Imunity value
// 0.3f,0.0f,0.0f, // Material's ambient component
// 0.5f,0.0f,0.0f, // Material's emissive component
// 0.2f,0.0f,0.0f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 0.25f,0.25f,-0.05f, // Material's opacity
// 15.0f, // Material's Z dither value
// sweep_1->GetSweepAttribute());
// Register_Object(morph_material_1);
// MorphMaterialRenderable *morph_material_2 =
// new MorphMaterialRenderable(
// entity, // Entity to attach the renderable to
// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable
// 0.9f,0.0f,0.0f, // Material's ambient component
// 1.0f,0.6f,0.3f, // Material's emissive component
// 1.0f,0.4f,0.2f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 8.0f,0.2f,-0.05f, // Material's opacity
// effect_texture, // Material's texture pointer
// 0.0f, // Material's Z dither value
// 0, // Material's Fog Imunity value
// 0.1f,0.0f,0.0f, // Material's ambient component
// 0.0f,0.0f,0.0f, // Material's emissive component
// 0.1f,0.0f,0.0f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 0.25f,0.25f,-0.05f, // Material's opacity
// 15.0f, // Material's Z dither value
// sweep_2->GetSweepAttribute());
// Register_Object(morph_material_2);
// //
// // Override the materials in the two explosion shapes using these morph materials
// //
// dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1);
// dpl_INSTANCE *explosion_2_instance = dpl_GetDCSInstance(explosion_2->GetDCS(), 1);
//
// if(!explosion_1_instance)
// Fail("explosion_1_instance came back null\n");
// if(!explosion_2_instance)
// Fail("explosion_2_instance came back null\n");
//
// dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial());
// dpl_SetInstanceFrontMaterial(explosion_2_instance, morph_material_2->GetMaterial());
//
// dpl_FlushInstance(explosion_1_instance);
// dpl_FlushInstance(explosion_2_instance);
// break;
// }
// case 2: // Big explosion
// {
// //
// // Load object(s) we will be using for the explosions
// //
// object_1 = dpl_LoadObject("exp.bgf", dpl_load_normal);
// //
// // Setup control variables and transforms we need
// //
// Vector3D scaling_velocity_1(1.0, 0.2, 1.0);
// Vector3D scaling_velocity_2(0.75, 0.75, 0.75);
// Vector3D velocity_accel_1(-0.00725, -0.004, -0.00725);
//// Vector3D velocity_accel_1(-0.00925, -0.00925, -0.00925);
// Vector3D velocity_accel_2(-0.01388, -0.01388, -0.01388);
// LinearMatrix explosion_1_offset(True);
// LinearMatrix explosion_2_offset(True);
// Point3D explosion_2_translate(0.0f, 0.0f, 0.0f);
// EulerAngles explosion_2_rotate(0.0f, 1.0f, 0.0f);
// explosion_2_offset = explosion_2_rotate;
// explosion_2_offset = explosion_2_translate;
// //
// // Create the scaling explosion renderables
// //
// ScalingExplosionRenderable *explosion_1 =
// new ScalingExplosionRenderable(
// entity, // Entity to attach the renderable to
// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable
// object_1, // This will be the scaling explosion object
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL, // intersection mask for the object
// this_root->GetDCS(), // the parent DCS we will be offsetting from
// &explosion_1_offset, // offset matrix to be applied prior to joint DCS
// &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity
// &velocity_accel_1,
// 0.0f,
// NULL); // -.25 gravity is normal
// Register_Object(explosion_1);
// ScalingExplosionRenderable *explosion_2 =
// new ScalingExplosionRenderable(
// entity, // Entity to attach the renderable to
// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable
// object_1, // This will be the scaling explosion object
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL, // intersection mask for the object
// this_root->GetDCS(), // the parent DCS we will be offsetting from
// &explosion_2_offset, // offset matrix to be applied prior to joint DCS
// &scaling_velocity_2, // Effect control vector, Y is acceleration, X, Z are velocity
// &velocity_accel_2,
// 0.0f,
// NULL);
// Register_Object(explosion_2);
// //
// // Create a sweep renderable to drive the material morph
// //
// SweepRenderable *sweep_1 =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 3.0f, // How long to take to sweep from 0 to 1
// 1, // number of times to cycle before stopping
// NULL);
// Register_Object(sweep_1);
// SweepRenderable *sweep_2 =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 2.0f, // How long to take to sweep from 0 to 1
// 1, // number of times to cycle before stopping
// NULL);
// Register_Object(sweep_2);
// //
// // Lookup a texture that we can use for the morphing materials
// //
// int
// status;
// dpl_TEXTURE *effect_texture =
// dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status );
// if (effect_texture == NULL)
// DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n" << std::flush;
// //
// // Setup a morph material renderable for each explosion shape
// //
// #if 0
// 0.9f,0.0f,0.0f, // Material's ambient component
// 1.0f,1.0f,0.0f, // Material's emissive component
// 1.0f,0.7f,0.2f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 8.0f,0.2f,-0.05f, // Material's opacity
// #endif
// MorphMaterialRenderable *morph_material_1 =
// new MorphMaterialRenderable(
// entity, // Entity to attach the renderable to
// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable
// 0.9f,0.0f,0.0f, // Material's ambient component
// 1.0f,0.2f,0.0f, // Material's emissive component
// 1.0f,0.2f,0.0f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 8.0f,0.2f,-0.05f, // Material's opacity
// effect_texture, // Material's texture pointer
// 0.0f, // Material's Z dither value
// 0, // Material's Fog Imunity value
// 0.3f,0.0f,0.0f, // Material's ambient component
// 0.5f,0.0f,0.0f, // Material's emissive component
// 0.2f,0.0f,0.0f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 0.25f,0.25f,-0.05f, // Material's opacity
// 15.0f, // Material's Z dither value
// sweep_1->GetSweepAttribute());
// Register_Object(morph_material_1);
// MorphMaterialRenderable *morph_material_2 =
// new MorphMaterialRenderable(
// entity, // Entity to attach the renderable to
// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable
// 0.9f,0.0f,0.0f, // Material's ambient component
// 1.0f,0.6f,0.4f, // Material's emissive component
// 1.0f,0.3f,0.2f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 8.0f,0.2f,-0.05f, // Material's opacity
// effect_texture, // Material's texture pointer
// 0.0f, // Material's Z dither value
// 0, // Material's Fog Imunity value
// 0.1f,0.0f,0.0f, // Material's ambient component
// 0.0f,0.0f,0.0f, // Material's emissive component
// 0.0f,0.0f,0.0f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 0.25f,0.25f,-0.05f, // Material's opacity
// 15.0f, // Material's Z dither value
// sweep_2->GetSweepAttribute());
// Register_Object(morph_material_2);
// //
// // Override the materials in the two explosion shapes using these morph materials
// //
// dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1);
// dpl_INSTANCE *explosion_2_instance = dpl_GetDCSInstance(explosion_2->GetDCS(), 1);
//
// if(!explosion_1_instance)
// Fail("explosion_1_instance came back null\n");
// if(!explosion_2_instance)
// Fail("explosion_2_instance came back null\n");
//
// dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial());
// dpl_SetInstanceFrontMaterial(explosion_2_instance, morph_material_2->GetMaterial());
//
// dpl_FlushInstance(explosion_1_instance);
// dpl_FlushInstance(explosion_2_instance);
// break;
// }
// case 3: // Sparks
// {
// //
// // Load object(s) we will be using for the explosions
// //
// object_1 = dpl_LoadObject("spk1.bgf", dpl_load_normal);
// //
// // Setup control variables and transforms we need
// //
// Vector3D scaling_velocity_1(0.1, 0.1, 0.1);
// Vector3D velocity_accel_1(0.0, 0.0, 0.0);
// LinearMatrix explosion_1_offset(True);
// //
// // Create the scaling explosion renderables
// //
// ScalingExplosionRenderable *explosion_1 =
// new ScalingExplosionRenderable(
// entity, // Entity to attach the renderable to
// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable
// object_1, // This will be the scaling explosion object
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL, // intersection mask for the object
// this_root->GetDCS(), // the parent DCS we will be offsetting from
// &explosion_1_offset, // offset matrix to be applied prior to joint DCS
// &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity
// &velocity_accel_1,
// -0.15f,
// NULL); // -.25 gravity is normal
// Register_Object(explosion_1);
// //
// // Create a sweep renderable to drive the material morph
// //
// SweepRenderable *sweep_1 =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 0.5f, // How long to take to sweep from 0 to 1
// 1, // number of times to cycle before stopping
// NULL);
// Register_Object(sweep_1);
// //
// // Lookup a texture that we can use for the morphing materials
// //
// int
// status;
// dpl_TEXTURE *effect_texture =
// dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status );
// if (effect_texture == NULL)
// DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n" << std::flush;
// //
// // Setup a morph material renderable for each explosion shape
// //
// MorphMaterialRenderable *morph_material_1 =
// new MorphMaterialRenderable(
// entity, // Entity to attach the renderable to
// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable
// 1.0f,1.0f,0.0f, // Material's ambient component
// 1.0f,1.0f,0.0f, // Material's emissive component
// 1.0f,1.0f,0.0f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 1.0f,1.0f,1.0f, // Material's opacity
// effect_texture, // Material's texture pointer
// 0.0f, // Material's Z dither value
// 2, // Material's Fog Imunity value
// 0.9f,0.0f,0.0f, // Material's ambient component
// 0.9f,0.0f,0.0f, // Material's emissive component
// 0.9f,0.0f,0.0f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0, // Material's specular component
// 1.0f,1.0f,1.0f, // Material's opacity
// 0.0f, // Material's Z dither value
// sweep_1->GetSweepAttribute());
// Register_Object(morph_material_1);
// dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1);
// if(!explosion_1_instance)
// Fail("explosion_1_instance came back null\n");
// dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial());
// dpl_FlushInstance(explosion_1_instance);
// break;
// }
// case 4: // A huge mech explodes (yawn)
// {
// Point3D null_offset(0.0f, 0.0f, 0.0f);
// LinearMatrix null_offset_matrix(True);
// Point3D local_height(0.0f, 6.2f, 0.0f); // height of Thor
// LinearMatrix local_offset(True);
// local_offset = local_height;
// DPLStaticChildRenderable *local_root =
// new DPLStaticChildRenderable(
// entity,
// false,
// NULL,
// dpl_isect_mode_obj,
// NULL,
// local_offset,
// this_root->GetDCS());
// Register_Object(local_root);
// //
// // Load morph sources we need for the effect
// //
// dpl_OBJECT *thor_debris_object = dpl_LoadObject("thrdbr.bgf", dpl_load_normal);
// dpl_OBJECT *large_debris_object = dpl_LoadObject("ldbr.bgf", dpl_load_normal);
// dpl_OBJECT *small_flames_object = dpl_LoadObject("flamesml.bgf", dpl_load_normal);
// //
// // Load morph targets we need for the effect
// //
// //------------------------------------------------
// // Renderables to handle the chunks and fireballs
// //------------------------------------------------
//#if 0
// OneShotDelayRenderable *fireball_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.25f); // How long to wait before raising the trigger
// Register_Object(fireball_delay);
// Point3D my_offset(0.0, 4.0, 0.0);
// #if DEBUG_LEVEL > 0
// DPLPSFXRenderable* initial_boom =
// #endif
// new DPLPSFXRenderable(
// entity, // Entity to attach the renderable to
// DPLPSFXRenderable::Dynamic, // How/when to execute the renderable
// fireball_delay->GetTriggerAttribute(), // address containing the trigger
// myPSFXDescriptons[7], // pointer to the PFX description
// this_root->GetDCS(), // DCS the effect is relative to (may be NULL)
// &my_offset); // Offset (or world coordinants if DCS is NULL)
// Register_Object(initial_boom);
// #if DEBUG_LEVEL > 0
// DPLEffectRenderable *chunks_effect =
// #endif
// new DPLEffectRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// fireball_delay->GetTriggerAttribute(), // address containing the trigger
// 3, // Chunks // DPL effect number to trigger
// local_root->GetDCS(), // DCS the effect is relative to (may be NULL)
// &null_offset); // Offset (or world coordinants if DCS is NULL)
// Register_Object(chunks_effect);
// Point3D fireball_offset(1.0f, 5.0f, 1.0f);
// #if DEBUG_LEVEL > 0
// DPLEffectRenderable *fireball_effect =
// #endif
// new DPLEffectRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// fireball_delay->GetTriggerAttribute(), // address containing the trigger
// 15, // Fireball // DPL effect number to trigger
// local_root->GetDCS(), // DCS the effect is relative to (may be NULL)
// &fireball_offset); // Offset (or world coordinants if DCS is NULL)
// Register_Object(fireball_effect);
//#endif
// OneShotDelayRenderable *fireball_delay_2 =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.55f); // How long to wait before raising the trigger
// Register_Object(fireball_delay_2);
// Point3D fireball_offset_2(-1.0f, 5.0f, -1.0f);
// #if DEBUG_LEVEL > 0
// DPLEffectRenderable *fireball_effect_2 =
// #endif
// new DPLEffectRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// fireball_delay_2->GetTriggerAttribute(), // address containing the trigger
// 15, // Fireball // DPL effect number to trigger
// local_root->GetDCS(), // DCS the effect is relative to (may be NULL)
// &fireball_offset_2); // Offset (or world coordinants if DCS is NULL)
// Register_Object(fireball_effect_2);
// //-----------------------------------------------
// // Renderables to handle static debris
// //-----------------------------------------------
// OneShotDelayRenderable *static_debris_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.25f); // How long to wait before raising the trigger
// Register_Object(static_debris_delay);
// DPLStaticChildRenderable *mech_debris =
// new DPLStaticChildRenderable(
// entity,
// false,
// thor_debris_object,
// dpl_isect_mode_obj,
// NULL,
// null_offset_matrix,
// this_root->GetDCS());
// Register_Object(mech_debris);
// #if DEBUG_LEVEL > 0
// MakeDCSFall *mech_debris_fall =
// #endif
// new MakeDCSFall(
// entity, // Entity to attach the renderable to
// MakeDCSFall::Dynamic, // How/when to execute the renderable
// mech_debris->GetDCS(), // the DCS to control
// -0.025f, // Gravity in meters/sec squared
// static_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off
// Register_Object(mech_debris_fall);
// // Find the instance with the static_thr in it and hook up the instance switch
// dpl_INSTANCE *mech_debris_instance = dpl_GetDCSInstance(mech_debris->GetDCS(), 1);
// #if DEBUG_LEVEL > 0
// InstanceSwitchRenderable *mech_debris_instance_switch =
// #endif
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// mech_debris_instance, // the instance to control
// True, // Instance is on when trigger is...
// static_debris_delay->GetTriggerAttribute());
// Register_Object(mech_debris_instance_switch);
//
// DPLStaticChildRenderable *large_debris =
// new DPLStaticChildRenderable(
// entity,
// false,
// large_debris_object,
// dpl_isect_mode_obj,
// NULL,
// null_offset_matrix,
// mech_debris->GetDCS());
// Register_Object(large_debris);
// // Find the instance with the static_thr in it and hook up the instance switch
// dpl_INSTANCE *large_debris_instance = dpl_GetDCSInstance(large_debris->GetDCS(), 1);
// #if DEBUG_LEVEL > 0
// InstanceSwitchRenderable *large_debris_instance_switch =
// #endif
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// large_debris_instance, // the instance to control
// True, // Instance is on when trigger is...
// static_debris_delay->GetTriggerAttribute());
// Register_Object(large_debris_instance_switch);
// //-----------------------------------------------
// // Renderables to handle fires
// //-----------------------------------------------
// OneShotDelayRenderable *fires_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.25f); // How long to wait before raising the trigger
// Register_Object(fires_delay);
// DPLStaticChildRenderable *fires =
// new DPLStaticChildRenderable(
// entity,
// false,
// NULL,
// dpl_isect_mode_obj,
// NULL,
// null_offset_matrix,
// this_root->GetDCS());
// Register_Object(fires);
// #if DEBUG_LEVEL > 0
// MakeDCSFall *fires_fall =
// #endif
// new MakeDCSFall(
// entity, // Entity to attach the renderable to
// MakeDCSFall::Dynamic, // How/when to execute the renderable
// fires->GetDCS(), // the DCS to control
// -0.01f, // Gravity in meters/sec squared
// fires_delay->GetTriggerAttribute()); // true if the instance is on, false if off
// Register_Object(fires_fall);
// DPLStaticChildRenderable *small_flames =
// new DPLStaticChildRenderable(
// entity,
// false,
// small_flames_object,
// dpl_isect_mode_obj,
// NULL,
// null_offset_matrix,
// fires->GetDCS());
// Register_Object(small_flames);
// // Find the instance with the static_thr in it and hook up the instance switch
// dpl_INSTANCE *small_flames_instance = dpl_GetDCSInstance(small_flames->GetDCS(), 1);
// #if DEBUG_LEVEL > 0
// InstanceSwitchRenderable *small_flames_instance_switch =
// #endif
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// small_flames_instance, // the instance to control
// True, // Instance is on when trigger is...
// fires_delay->GetTriggerAttribute());
// Register_Object(small_flames_instance_switch);
//
// dpl_OBJECT *big_flames_object = dpl_LoadObject("flamebig.bgf", dpl_load_normal);
// DPLStaticChildRenderable *big_flames =
// new DPLStaticChildRenderable(
// entity,
// false,
// big_flames_object,
// dpl_isect_mode_obj,
// NULL,
// null_offset_matrix,
// fires->GetDCS());
// Register_Object(big_flames);
// // Make big flames object billboard along y-axis
// dpl_SetDCSReorientAxes(big_flames->GetDCS(), dpl_reorient_axes_y);
// dpl_FlushDCS(big_flames->GetDCS());
// // Find the instance with the static_thr in it and hook up the instance switch
// dpl_INSTANCE *big_flames_instance = dpl_GetDCSInstance(big_flames->GetDCS(), 1);
// #if DEBUG_LEVEL > 0
// InstanceSwitchRenderable *big_flames_instance_switch =
// #endif
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// big_flames_instance, // the instance to control
// True, // Instance is on when trigger is...
// fires_delay->GetTriggerAttribute());
// Register_Object(big_flames_instance_switch);
// //
// // These renderables create the rising smoke column using a pfx effect.
// //
//#if 0
// Point3D my_offset2(0.0, 5.0, 0.0);
// #if DEBUG_LEVEL > 0
// OnePSFXRenderable *this_effect=
// #endif
// new OnePSFXRenderable(
// entity, // Entity to attach the renderable to
// OnePSFXRenderable::Static, // How/when to execute the renderable
// myPSFXDescriptons[1], // name of file with the PFX description in it
// this_root->GetDCS(), // DCS the effect is relative to (may be NULL)
// &my_offset2); // Offset (or world coordinants if DCS is NULL)
// Register_Object(this_effect);
//#endif
// break;
// }
// //----------------------------------------
// case 5: // Sfx #105 - Delayed ground hit
// //----------------------------------------
// {
// //
// // Create the delayed ground hit renderables
// //
// Point3D null_offset(0.0f, 0.0f, 0.0f);
// OneShotDelayRenderable *ground_hit_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.15f); // How long to wait before raising the trigger
// Register_Object(ground_hit_delay);
// #if DEBUG_LEVEL > 0
// DPLEffectRenderable *ground_hit_effect =
// #endif
// new DPLEffectRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// ground_hit_delay->GetTriggerAttribute(), // address containing the trigger
// 12, // GroundHit // DPL effect number to trigger
// this_root->GetDCS(), // DCS the effect is relative to (may be NULL)
// &null_offset); // Offset (or world coordinants if DCS is NULL)
// Register_Object(ground_hit_effect);
// break;
// }
// //------------------------------------------
// case 6: // Sfx #106 - Thor death explosion
// //------------------------------------------
// {
// #if 0
// int status; // used with dpl calls
// Point3D null_offset(0.0f, 0.0f, 0.0f);
// LinearMatrix null_offset_matrix(True);
// Point3D local_height(0.0f, 6.2f, 0.0f); // height of Thor
// LinearMatrix local_offset(True);
// local_offset = local_height;
// DPLStaticChildRenderable *local_root =
// new DPLStaticChildRenderable(
// entity,
// false,
// NULL,
// dpl_isect_mode_obj,
// NULL,
// local_offset,
// this_root->GetDCS());
// Register_Object(local_root);
//#if 0
// //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// //
// // Show static thor (TEMPORARY for testing)
// //
// dpl_OBJECT *static_thr_object = dpl_LoadObject("thr.bgf", dpl_load_normal);
// DPLStaticChildRenderable *static_thr =
// new DPLStaticChildRenderable(
// entity,
// false,
// static_thr_object,
// dpl_isect_mode_obj,
// NULL,
// null_offset_matrix,
// local_root->GetDCS());
// Register_Object(static_thr);
// // This defines how long the static_thr stays visible
// OneShotDelayRenderable *static_thr_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.5f); // How long to wait before raising the trigger
// // Find the instance with the static_thr in it and hook up the instance switch
// dpl_INSTANCE *static_thr_instance = dpl_GetDCSInstance(static_thr->GetDCS(), 1);
// InstanceSwitchRenderable *static_thr_instance_switch =
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// static_thr_instance, // the instance to control
// False, // Instance is on when trigger is...
// static_thr_delay->GetTriggerAttribute());
// //
// //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//#endif
// //
// // Load objects we will be using for the explosion effect
// //
// DPLObjectWrapper *flash_object_wrapper =
// new DPLObjectWrapper(
// entity, // Entity to attach the renderable to
// "exdisk_A.bgf", // Name of the DPL object to load into the wrapper
// dpl_load_nocache); // Type of loading to perform on this object
// Register_Object(flash_object_wrapper);
// dpl_OBJECT *flash_object_a = flash_object_wrapper->GetDPLObject();
// dpl_OBJECT *flash_object_b = dpl_LoadObject("exdisk_B.bgf", dpl_load_normal);
// dpl_OBJECT *flash_object_c = dpl_LoadObject("exdisk_C.bgf", dpl_load_normal);
// DPLObjectWrapper *debris_object_wrapper =
// new DPLObjectWrapper(
// entity, // Entity to attach the renderable to
// "thrtor_A.bgf", // Name of the DPL object to load into the wrapper
// dpl_load_nocache); // Type of loading to perform on this object
// Register_Object(debris_object_wrapper);
// dpl_OBJECT *morph_debris_a = debris_object_wrapper->GetDPLObject();
// dpl_OBJECT *morph_debris_b = dpl_LoadObject("thrtor_B.bgf", dpl_load_normal);
// dpl_OBJECT *morph_debris_c = dpl_LoadObject("thrtor_C.bgf", dpl_load_normal);
// DPLObjectWrapper *hips_object_wrapper =
// new DPLObjectWrapper(
// entity, // Entity to attach the renderable to
// "thrhip_A.bgf", // Name of the DPL object to load into the wrapper
// dpl_load_nocache); // Type of loading to perform on this object
// Register_Object(hips_object_wrapper);
// dpl_OBJECT *morph_hips_a = hips_object_wrapper->GetDPLObject();
// dpl_OBJECT *morph_hips_b = dpl_LoadObject("thrhip_B.bgf", dpl_load_normal);
// dpl_OBJECT *morph_hips_c = dpl_LoadObject("thrhip_C.bgf", dpl_load_normal);
// dpl_OBJECT *thor_debris_object = dpl_LoadObject("thrdbr.bgf", dpl_load_normal);
// dpl_OBJECT *large_debris_object = dpl_LoadObject("ldbr.bgf", dpl_load_normal);
// dpl_OBJECT *small_flames_object = dpl_LoadObject("flamesml.bgf", dpl_load_normal);
// dpl_OBJECT *big_flames_object = dpl_LoadObject("flamebig.bgf", dpl_load_normal);
// //----------------------------------------------
// // Renderables to perform morphing flash object
// //----------------------------------------------
// SweepRenderable *flash_morph_sweep =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 1.0f, // How long to take to sweep from 0 to 1
// 1, // number of times to cycle before stopping
// NULL, // trigger
// -0.5f, // Initial value
// 2.0f); // Final value
// ChildMorphRenderable *flash_morph =
// new ChildMorphRenderable(
// entity, // Entity to attach the renderable to
// ChildMorphRenderable::Dynamic, // How/when to execute the renderable
// flash_object_a, // destination
// flash_object_b, // start object
// flash_object_c, // end object
// flash_morph_sweep->GetSweepAttribute(), // pointer to control variable
// dpl_morph_vertices | dpl_morph_colors, // Defines type of morph to do
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL, // intersection mask for the object
// this_root->GetDCS()); // the parent DCS we will be offsetting from
// // Make flash object billboard along y-axis
// dpl_SetDCSReorientAxes(flash_morph->GetDCS(), dpl_reorient_axes_y);
// dpl_FlushDCS(flash_morph->GetDCS());
// // This defines how long the flash stays up
// OneShotDelayRenderable *flash_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 1.0f); // How long to wait before raising the trigger
// Register_Object(flash_delay);
// // Find the instance with the flash in it and hook up the instance switch
// dpl_INSTANCE *flash_morph_instance = dpl_GetDCSInstance(flash_morph->GetDCS(), 1);
// InstanceSwitchRenderable *flash_instance_switch =
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// flash_morph_instance, // the instance to control
// False, // Instance is on when trigger is...
// flash_delay->GetTriggerAttribute());
// //---------------------------------------------------
// // Create a material morph to fade flash object away
// //---------------------------------------------------
// OneShotDelayRenderable *flash_fade_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.5f); // How long to wait before raising the trigger
// SweepRenderable *flash_fade_sweep =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 0.4f, // How long to take to sweep from 0 to 1
// 1, // number of times to cycle before stopping
// flash_fade_delay->GetTriggerAttribute()); // trigger variable
// Register_Object(flash_fade_sweep);
// // Lookup texture for smoke column
// dpl_TEXTURE *flash_texture =
// dpl_LookupTexture("btfx:bexp9_tex", dpl_lookup_normal, &status);
// if (flash_texture == NULL)
// DEBUG_STREAM<<"couldn't find texture btfx:bexp9_tex for an effect\n" << std::flush;
// //
// MorphMaterialRenderable *flash_fade_material =
// new MorphMaterialRenderable(
// entity, // Entity to attach the renderable to
// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable
// 1.0f,1.0f,1.0f, // Material's ambient component
// 1.0f,1.0f,1.0f, // Material's emissive component
// 1.0f,1.0f,1.0f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0f, // Material's specular component
// 1.0f,1.0f,1.0f, // Material's opacity
// flash_texture, // Material's texture pointer
// 0.0f, // Material's Z dither value
// 1, // Material's Fog Imunity value
// 1.0f,1.0f,1.0f, // Material's ambient component
// 1.0f,1.0f,1.0f, // Material's emissive component
// 1.0f,1.0f,1.0f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0f, // Material's specular component
// 0.0f,0.0f,0.0f, // Material's opacity
// 0.0f, // Material's Z dither value
// flash_fade_sweep->GetSweepAttribute());
// Register_Object(flash_fade_material);
//// dpl_INSTANCE *flash_morph_instance = dpl_GetDCSInstance(flash_morph->GetDCS(), 1);
// if (!flash_morph_instance)
// Fail("flash_morph_instance came back null\n");
// dpl_SetInstanceFrontMaterial(flash_morph_instance, flash_fade_material->GetMaterial());
// dpl_FlushInstance(flash_morph_instance);
// //------------------------------------------------
// // Renderables to handle the chunks and fireballs
// //------------------------------------------------
// OneShotDelayRenderable *fireball_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.25f); // How long to wait before raising the trigger
// Register_Object(fireball_delay);
// DPLEffectRenderable *chunks_effect =
// new DPLEffectRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// fireball_delay->GetTriggerAttribute(), // address containing the trigger
// 3, // Chunks // DPL effect number to trigger
// local_root->GetDCS(), // DCS the effect is relative to (may be NULL)
// &null_offset); // Offset (or world coordinants if DCS is NULL)
// Register_Object(chunks_effect);
// Point3D fireball_offset(1.0f, 5.0f, 1.0f);
// DPLEffectRenderable *fireball_effect =
// new DPLEffectRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// fireball_delay->GetTriggerAttribute(), // address containing the trigger
// 15, // Fireball // DPL effect number to trigger
// local_root->GetDCS(), // DCS the effect is relative to (may be NULL)
// &fireball_offset); // Offset (or world coordinants if DCS is NULL)
// Register_Object(fireball_effect);
// OneShotDelayRenderable *fireball_delay_2 =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.55f); // How long to wait before raising the trigger
// Register_Object(fireball_delay_2);
// Point3D fireball_offset_2(-1.0f, 5.0f, -1.0f);
// DPLEffectRenderable *fireball_effect_2 =
// new DPLEffectRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// fireball_delay_2->GetTriggerAttribute(), // address containing the trigger
// 15, // Fireball // DPL effect number to trigger
// local_root->GetDCS(), // DCS the effect is relative to (may be NULL)
// &fireball_offset_2); // Offset (or world coordinants if DCS is NULL)
// Register_Object(fireball_effect_2);
// //------------------------------------------------------
// // Renderables to handle the torso debris explode morph
// //------------------------------------------------------
// OneShotDelayRenderable *morph_debris_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.25f, // How long to wait before raising the trigger
// 4.25f); // Duration of trigger
// SweepRenderable *debris_morph_sweep =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 4.0f, // How long to take to sweep from 0 to 1
// 1, // number of times to cycle before stopping
// morph_debris_delay->GetTriggerAttribute(), // trigger variable
// 0.0f, // initial value of sweep
// 9.0f, // final value of sweep
// SweepRenderable::Y_SQR_X); // function to apply
// ChildMorphRenderable *debris_morph =
// new ChildMorphRenderable(
// entity, // Entity to attach the renderable to
// ChildMorphRenderable::Dynamic, // How/when to execute the renderable
// morph_debris_a, // destination
// morph_debris_b, // start object
// morph_debris_c, // end object
// debris_morph_sweep->GetSweepAttribute(), // pointer to control variable
// dpl_morph_vertices, // Defines type of morph to do
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL, // intersection mask for the object
// local_root->GetDCS()); // the parent DCS we will be offsetting from
// MakeDCSFall *debris_make_fall =
// new MakeDCSFall(
// entity, // Entity to attach the renderable to
// MakeDCSFall::Dynamic, // How/when to execute the renderable
// debris_morph->GetDCS(), // the DCS to control
// -9.81f, // Gravity in meters/sec squared
// morph_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off
// // Find the instance with the debris in it and hook up the instance switch
// dpl_INSTANCE *debris_morph_instance = dpl_GetDCSInstance(debris_morph->GetDCS(), 1);
// InstanceSwitchRenderable *debris_morph_instance_switch =
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// debris_morph_instance, // the instance to control
// True, // Instance is on when trigger is...
// morph_debris_delay->GetTriggerAttribute());
// //-----------------------------------------------------
// // Renderables to handle the hips debris explode morph
// //-----------------------------------------------------
// ChildMorphRenderable *hips_morph =
// new ChildMorphRenderable(
// entity, // Entity to attach the renderable to
// ChildMorphRenderable::Dynamic, // How/when to execute the renderable
// morph_hips_a, // destination
// morph_hips_b, // start object
// morph_hips_c, // end object
// debris_morph_sweep->GetSweepAttribute(), // pointer to control variable
// dpl_morph_vertices, // Defines type of morph to do
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL, // intersection mask for the object
// local_root->GetDCS()); // the parent DCS we will be offsetting from
// MakeDCSFall *hips_make_fall =
// new MakeDCSFall(
// entity, // Entity to attach the renderable to
// MakeDCSFall::Dynamic, // How/when to execute the renderable
// hips_morph->GetDCS(), // the DCS to control
// -9.81f, // Gravity in meters/sec squared
// morph_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off
// // Find the instance with the debris in it and hook up the instance switch
// dpl_INSTANCE *hips_morph_instance = dpl_GetDCSInstance(hips_morph->GetDCS(), 1);
// InstanceSwitchRenderable *hips_morph_instance_switch =
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// hips_morph_instance, // the instance to control
// True, // Instance is on when trigger is...
// morph_debris_delay->GetTriggerAttribute());
// //-----------------------------------------------
// // Renderables to handle static debris and fires
// //-----------------------------------------------
// OneShotDelayRenderable *static_debris_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.25f); // How long to wait before raising the trigger
// DPLStaticChildRenderable *mech_debris =
// new DPLStaticChildRenderable(
// entity,
// false,
// thor_debris_object,
// dpl_isect_mode_obj,
// NULL,
// null_offset_matrix,
// this_root->GetDCS());
// Register_Object(mech_debris);
// MakeDCSFall *mech_debris_fall =
// new MakeDCSFall(
// entity, // Entity to attach the renderable to
// MakeDCSFall::Dynamic, // How/when to execute the renderable
// mech_debris->GetDCS(), // the DCS to control
// -0.01f, // Gravity in meters/sec squared
// static_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off
// // Find the instance with the static_thr in it and hook up the instance switch
// dpl_INSTANCE *mech_debris_instance = dpl_GetDCSInstance(mech_debris->GetDCS(), 1);
// InstanceSwitchRenderable *mech_debris_instance_switch =
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// mech_debris_instance, // the instance to control
// True, // Instance is on when trigger is...
// static_debris_delay->GetTriggerAttribute());
//
// DPLStaticChildRenderable *large_debris =
// new DPLStaticChildRenderable(
// entity,
// false,
// large_debris_object,
// dpl_isect_mode_obj,
// NULL,
// null_offset_matrix,
// mech_debris->GetDCS());
// Register_Object(large_debris);
// // Find the instance with the static_thr in it and hook up the instance switch
// dpl_INSTANCE *large_debris_instance = dpl_GetDCSInstance(large_debris->GetDCS(), 1);
// InstanceSwitchRenderable *large_debris_instance_switch =
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// large_debris_instance, // the instance to control
// True, // Instance is on when trigger is...
// static_debris_delay->GetTriggerAttribute());
//
// DPLStaticChildRenderable *small_flames =
// new DPLStaticChildRenderable(
// entity,
// false,
// small_flames_object,
// dpl_isect_mode_obj,
// NULL,
// null_offset_matrix,
// mech_debris->GetDCS());
// Register_Object(small_flames);
// // Find the instance with the static_thr in it and hook up the instance switch
// dpl_INSTANCE *small_flames_instance = dpl_GetDCSInstance(small_flames->GetDCS(), 1);
// InstanceSwitchRenderable *small_flames_instance_switch =
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// small_flames_instance, // the instance to control
// True, // Instance is on when trigger is...
// static_debris_delay->GetTriggerAttribute());
//
// DPLStaticChildRenderable *big_flames =
// new DPLStaticChildRenderable(
// entity,
// false,
// big_flames_object,
// dpl_isect_mode_obj,
// NULL,
// null_offset_matrix,
// mech_debris->GetDCS());
// Register_Object(big_flames);
// // Make big flames object billboard along y-axis
// dpl_SetDCSReorientAxes(big_flames->GetDCS(), dpl_reorient_axes_y);
// dpl_FlushDCS(big_flames->GetDCS());
// // Find the instance with the static_thr in it and hook up the instance switch
// dpl_INSTANCE *big_flames_instance = dpl_GetDCSInstance(big_flames->GetDCS(), 1);
// InstanceSwitchRenderable *big_flames_instance_switch =
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// big_flames_instance, // the instance to control
// True, // Instance is on when trigger is...
// static_debris_delay->GetTriggerAttribute());
// //-------------------------------------------------------------
// // Renderables to handle the rising smoke column (first shape)
// //-------------------------------------------------------------
//#if 1
// OneShotDelayRenderable *first_one_shot =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 0.0f); // How long to wait before raising the trigger
// Register_Object(first_one_shot);
// Point3D my_offset(0.0, 6.0, 0.0);
// #if DEBUG_LEVEL > 0
// DPLPSFXRenderable* this_effect =
// #endif
// new DPLPSFXRenderable(
// entity, // Entity to attach the renderable to
// DPLPSFXRenderable::Dynamic, // How/when to execute the renderable
// first_one_shot->GetTriggerAttribute(), // address containing the trigger
// myPSFXDescriptons[1], // pointer to the PFX description
// this_root->GetDCS(), // DCS the effect is relative to (may be NULL)
// &my_offset); // Offset (or world coordinants if DCS is NULL)
// Register_Object(this_effect);
//
//// the below code will be removed in favor of PFX effects once they are tested
//#else
//// OneShotDelayRenderable *smoke_1_morph_delay =
//// new OneShotDelayRenderable(
//// entity, // Entity to attach the renderable to
//// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
//// 0.25f); // How long to wait before raising the trigger
// SweepRenderable *smoke_1_sweep =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 40.0f, // How long to take to sweep from 0 to 1
// 1, // number of times to cycle before stopping
// static_debris_delay->GetTriggerAttribute(),
// 0.2f,
// 2.5f);
// ChildMorphRenderable *smoke_1_morph =
// new ChildMorphRenderable(
// entity, // Entity to attach the renderable to
// ChildMorphRenderable::Dynamic, // How/when to execute the renderable
// smoke_1_a, // destination
// smoke_b, // start object
// smoke_c, // end object
// smoke_1_sweep->GetSweepAttribute(), // pointer to control variable
// dpl_morph_vertices, // Defines type of morph to do
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL, // intersection mask for the object
// this_root->GetDCS()); // the parent DCS we will be offsetting from
// // Find the instance with the flash in it and hook up the instance switch
// dpl_INSTANCE *smoke_1_instance = dpl_GetDCSInstance(smoke_1_morph->GetDCS(), 1);
// InstanceSwitchRenderable *smoke_1_instance_switch =
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// smoke_1_instance, // the instance to control
// True, // Instance is on when trigger is...
// static_debris_delay->GetTriggerAttribute());
// //--------------------------------------------------------------
// // Renderables to handle the rising smoke column (second shape)
// //--------------------------------------------------------------
//#if 0
// OneShotDelayRenderable *smoke_2_morph_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 6.0f); // How long to wait before raising the trigger
// SweepRenderable *smoke_2_sweep =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 30.0f, // How long to take to sweep from 0 to 1
// 1, // number of times to cycle before stopping
// smoke_2_morph_delay->GetTriggerAttribute(),
// 0.1f,
// 1.0f);
// ChildMorphRenderable *smoke_2_morph =
// new ChildMorphRenderable(
// entity, // Entity to attach the renderable to
// ChildMorphRenderable::Dynamic, // How/when to execute the renderable
// smoke_2_a, // destination
// smoke_b, // start object
// smoke_c, // end object
// smoke_2_sweep->GetSweepAttribute(), // pointer to control variable
// dpl_morph_vertices, // Defines type of morph to do
// false, // DPL Zone this stuff will live in (for culling)
// dpl_isect_mode_obj, // type of intersections to do on this object
// NULL, // intersection mask for the object
// this_root->GetDCS()); // the parent DCS we will be offsetting from
// // Find the instance with the flash in it and hook up the instance switch
// dpl_INSTANCE *smoke_2_instance = dpl_GetDCSInstance(smoke_2_morph->GetDCS(), 1);
// InstanceSwitchRenderable *smoke_2_morph_instance_switch =
// new InstanceSwitchRenderable(
// entity, // Entity to attach the renderable to
// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable
// smoke_2_instance, // the instance to control
// True, // Instance is on when trigger is...
// smoke_2_morph_delay->GetTriggerAttribute());
//#endif
// //-------------------------------------------
// // Set dither Z on material for smoke column
// //-------------------------------------------
// dpl_MATERIAL *damage_material =
// dpl_LookupMaterial ("btfx:smoke1_mtl",
// dpl_lookup_normal,
// &status);
// if (damage_material == 0)
// {
// std::cout << "couldn't find material\n";
// }
// else
// {
// dpl_SetMaterialDitherZ(damage_material, 10.0f);
// dpl_FlushMaterial(damage_material);
// }
// //---------------------------------------------------
// // Create a material morph to fade smoke column away
// //---------------------------------------------------
// OneShotDelayRenderable *smoke_fade_delay =
// new OneShotDelayRenderable(
// entity, // Entity to attach the renderable to
// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable
// 25.0f); // How long to wait before raising the trigger
// SweepRenderable *smoke_fade_sweep =
// new SweepRenderable(
// entity, // Entity to attach the renderable to
// SweepRenderable::Dynamic, // How/when to execute the renderable
// 18.5f, // How long to take to sweep from 0 to 1
// 1, // number of times to cycle before stopping
// smoke_fade_delay->GetTriggerAttribute()); // trigger variable
// Register_Object(smoke_fade_sweep);
// // Lookup texture for smoke column
// dpl_TEXTURE *smoke_texture =
// dpl_LookupTexture("btfx:smoke1_scr_tex", dpl_lookup_normal, &status);
// if (smoke_texture == NULL)
// DEBUG_STREAM<<"couldn't find texture btfx:smoke1_scr_tex for an effect\n" << std::flush;
// //
// MorphMaterialRenderable *smoke_fade_material =
// new MorphMaterialRenderable(
// entity, // Entity to attach the renderable to
// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable
// 1.0f,1.0f,1.0f, // Material's ambient component
// 0.7f,0.4f,0.4f, // Material's emissive component
// 0.3714f,0.2899f,0.3714f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0f, // Material's specular component
// 0.7f,0.99f,0.0f, // Material's opacity
// smoke_texture, // Material's texture pointer
// 10.0f, // Material's Z dither value
// 3, // Material's Fog Imunity value
// 1.0f,1.0f,1.0f, // Material's ambient component
// 0.7f,0.4f,0.4f, // Material's emissive component
// 0.3714f,0.2899f,0.3714f, // Material's diffuse component
// 0.0f,0.0f,0.0f,0.0f, // Material's specular component
// 0.0f,0.99f,0.0f, // Material's opacity
// 10.0f, // Material's Z dither value
// smoke_fade_sweep->GetSweepAttribute());
// Register_Object(smoke_fade_material);
//// dpl_INSTANCE *smoke_1_instance = dpl_GetDCSInstance(smoke_1_morph->GetDCS(), 1);
// if (!smoke_1_instance)
// Fail("smoke_1_instance came back null\n");
// dpl_SetInstanceFrontMaterial(smoke_1_instance, smoke_fade_material->GetMaterial());
// dpl_FlushInstance(smoke_1_instance);
//#endif
// #else
// DEBUG_STREAM <<"Explosion effect 104 called, this is disabled and shouldn't be used!\n" << std::flush;
// #endif
// break;
// }
// default:
// {
// break;
// }
// }
}
//
//#############################################################################
// MakeEntityRenderables handles creating all the renderables necessary to
// display an object. This routine contains default behaviors for creating
// some types of simple objects. The idea is that if a higher level routine
// can't figure out how to make renderables for something this routine will be
// called and the default behavior will be used.
//#############################################################################
//
void
DPLRenderer::MakeEntityRenderables(
Entity *entity, // The entity we are dealing with
ResourceDescription *model_resource, // Pointer to the video resource
ViewFrom view_type) // Type of reference (inside/outside...etc.)
{
//STUBBED: DPL RB 1/14/07
char *object_filename;
#if DEBUG_LEVEL > 0
int object_count;
#endif
L4VideoObject *video_object;
L4VideoObjectWrapper *video_wrapper;
ChainOf<L4VideoObjectWrapper*> video_chain(NULL);
L4VideoObject::ResourceType resource_type;
// dpl_DCS *my_root_dcs;
Enumeration renderer_modes;
//
// Set the Entity_Being_Created global so the C language callback will
// be able to mark the geometry with damage zone values if necessary.
//
Entity_Being_Created = entity;
// my_root_dcs = NULL;
//
// convert video resource into chain of video objects and make an iterator
// for that chain
//
if (model_resource)
{
#if DEBUG_LEVEL > 0
object_count =
#endif
L4VideoObjectWrapper::BuildVideoObjectChainFromResource(&video_chain, model_resource);
}
ChainIteratorOf<L4VideoObjectWrapper*> video_iterator(video_chain);
//
// Switch to allow us to have scripts at this level for constructing certain
// types of video objects (whether or not they have a video resource)
//
switch (entity->GetClassID())
{
//
// Dropzones have no graphical appearance so we do nothing
//
case DropZoneClassID:
break;
//
// Player objects have no graphical appearance unless one is created
// at a higher (game specific) level, so we do nothing here.
//
case PlayerClassID:
break;
// this entity has no visual appearance
case AudioEntityClassID:
break;
//
// Cultural and landmark are the only ones with "destroyed" processing
// This is similar to the default case but does not allow us to be
// inside the entity, does not allow us to be a mover,
//
case CulturalIconClassID:
case LandmarkClassID:
{
dpl_INSTANCE *this_instance;
d3d_OBJECT *this_object;
dpl_ISECT_MODE intersect_mode;
HierarchicalDrawComponent *component = NULL;
uint32 intersect_mask;
LinearMatrix offset_matrix = LinearMatrix::Identity;
//dpl_DCS *root_DCS, *this_DCS;
//
// Make sure the object has a video resource
//
if (!model_resource)
{
VideoRenderer::MakeEntityRenderables(entity, model_resource, view_type);
Entity_Being_Created = NULL;
return;
}
// intersect_mode = dpl_isect_mode_geometry;
intersect_mask = INTERSECT_ALL;
Logical first_object = True;
video_iterator.First();
while ((video_wrapper = video_iterator.ReadAndNext()) != NULL)
{
video_object = video_wrapper->GetVideoObject();
object_filename = video_object->GetObjectFilename();
resource_type = video_object->GetResourceType();
renderer_modes = video_object->GetRendererModes();
#if NOISY_RENDERER
Tell("L4VIDEO.cpp loading object " << object_filename);
Tell(" type " << resource_type);
Tell(" mode 0x" <<std::hex<<renderer_modes<<std::dec<< "." << std::endl);
#endif
if ((resource_type != L4VideoObject::Object) &&
(resource_type != L4VideoObject::Rubble))
{
DEBUG_STREAM << "L4VIDEO.cpp wrong video resource type for object "<<object_filename<<"\n" << std::flush;
continue; // next object
}
SET_VIDEO_LOAD_OBJECT();
// HACK !!! load the object as uncached so entity identification will work right
// this_object = dpl_LoadObject(object_filename, dpl_load_normal);
this_object = d3d_OBJECT::LoadObject(mDevice, object_filename);
CLEAR_VIDEO_LOAD_OBJECT();
if (this_object == NULL)
{
DEBUG_STREAM << "L4VIDEO.cpp couldn't load object "<<object_filename<<"\n" << std::flush;
if (!first_object)
{
continue; // next object
}
}
if (first_object)
{
first_object = False;
component = new RootRenderable(
entity, // Entity to attach the renderable to
RootRenderable::Static, // How/when to execute the renderable
this_object, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
intersect_mode, // type of intersections to do on this object
intersect_mask); // intersection mask for the object
//root_DCS = this_static_root->GetDCS();
//------------------------------------------------------
// if root object billboards (all others billboard too)
//------------------------------------------------------
//this_DCS = root_DCS;
// this_instance = this_static_root->GetInstance();
//
// Set my_root_dcs because we want this guy's hiearchy to be marked
// with his entity pointer
//
// my_root_dcs = root_DCS;
}
else
{
if (renderer_modes | L4VideoObject::BillboardObject)
{
//------------------------------------------
// attach additional object to separate DCS
// because it is billboarded
//------------------------------------------
component = new DPLStaticChildRenderable(
entity,
false,
this_object,
intersect_mode,
intersect_mask,
offset_matrix,
NULL);
// this_DCS = this_child->GetDCS();
// this_instance = this_child->GetInstance();
}
else
{
//----------------------------------------
// attach additional objects to root_DCS
// (HACK) temporary implementation (HACK)
//----------------------------------------
component = new DCSInstanceRenderable(
entity, // Entity to attach the renderable to
DCSInstanceRenderable::Static, // How/when to execute the renderable
this_object, // object to connect to the instance
NULL, // the DCS to add the instance to
intersect_mode, // type of intersections to do on this object
intersect_mask, // intersection mask for the object
True); // initial visibility setting
//this_DCS = NULL;
// this_instance = another_instance->GetInstance();
}
}
// add the new object to our renderables list
if (component)
mRenderables.Add(component);
component = NULL;
//
// Hook up the object to an instance switch renderable responsive to state
//
StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState");
switch(resource_type)
{
case L4VideoObject::Object:
{
component = new StateInstanceSwitchRenderable(
entity, // Entity to attach the renderable to
StateInstanceSwitchRenderable::Watcher, // How/when to execute the renderable
this_instance, // the instance to control
False, // true to turn on in this state, false for off
simulation_state, // State dial we use to control the on/off
CulturalIcon::BurningState); // State that we look for
break;
}
case L4VideoObject::Rubble:
{
component = new StateInstanceSwitchRenderable(
entity, // Entity to attach the renderable to
StateInstanceSwitchRenderable::Watcher, // How/when to execute the renderable
this_instance, // the instance to control
True, // true to turn on in this state, false for off
simulation_state, // State dial we use to control the on/off
CulturalIcon::BurningState); // State that we look for
break;
}
}
if (component)
mRenderables.Add(component);
//----------------------------------
// billboard object if so indicated
//----------------------------------
// if (this_DCS && (renderer_modes & L4VideoObject::BillboardObject))
// {
// int axes = dpl_reorient_axes_none;
// if (renderer_modes & L4VideoObject::BillboardXAxis)
// {
// axes |= dpl_reorient_axes_x;
// }
// if (renderer_modes & L4VideoObject::BillboardYAxis)
// {
// axes |= dpl_reorient_axes_y;
// }
// if (renderer_modes & L4VideoObject::BillboardZAxis)
// {
// axes |= dpl_reorient_axes_z;
// }
// dpl_SetDCSReorientAxes(this_DCS, (dpl_REORIENT_AXES)axes);
// dpl_FlushDCS(this_DCS);
// }
}
break;
}
//
// Case to handle rivets using the fast projectile code
//
case RivetClassID:
{
d3d_OBJECT
*this_object;
video_iterator.First();
video_wrapper = video_iterator.ReadAndNext();
Check(video_wrapper);
video_object = video_wrapper->GetVideoObject();
Check_Pointer(video_object);
object_filename = video_object->GetObjectFilename();
this_object = d3d_OBJECT::LoadObject(GetDevice(), object_filename);
#if DEBUG_LEVEL > 0
ProjectileRootRenderable *projectile =
#endif
new ProjectileRootRenderable(
entity, // Entity to attach the renderable to
ProjectileRootRenderable::Dynamic, // How/when to execute the renderable
this_object, // object to hang on the DCS, may be a list later <NULL>
false); // DPL Zone this stuff will live in (for culling)
Register_Object(projectile);
break;
}
//
// Script for generating renderables for eyecandy
//
case EyeCandyClassID:
{
int effect_number;
dpl_ISECT_MODE dpl_isect_mode_obj;
RootRenderable *this_root =
new RootRenderable(
entity, // Entity to attach the renderable to
RootRenderable::Dynamic, // How/when to execute the renderable
NULL, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
dpl_isect_mode_obj, // type of intersections to do on this object
NULL); // intersection mask for the object
Register_Object(this_root);
StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState");
video_iterator.First();
while ((video_wrapper = video_iterator.ReadAndNext()) != NULL)
{
video_object = video_wrapper->GetVideoObject();
effect_number = atoi(video_object->GetObjectFilename());
#if DEBUG_LEVEL > 0
DPLSFXRenderable *this_effect =
#endif
new DPLSFXRenderable(
entity, // Entity to attach the effect to
false, // DPL zone everything will be in
Point3D::Identity, // Point offset from the parent DCS
this_root, // Parent DCS (can be NULL for world)
simulation_state, // Trigger effect when this state changes
EyeCandy::effectOn, // Trigger effect when in this state
effect_number, // Type of effect to trigger
.01); // Effect repeat speed.
Register_Object(this_effect);
}
break;
}
//
// Script for generating an explosion of type specified in the resource file
//
case ExplosionClassID:
{
DEBUG_STREAM << "Explosion Created in MakeEntityRenderables:" << std::endl << std::flush;
int effect_number;
video_iterator.First();
while ((video_wrapper = video_iterator.ReadAndNext()) != NULL)
{
video_object = video_wrapper->GetVideoObject();
effect_number = atoi(video_object->GetObjectFilename());
DEBUG_STREAM << " ** effect_number = " << effect_number << std::endl << std::flush;
if(effect_number < 100 || effect_number >= 1000)
{
DEBUG_STREAM << " ** DPLIndependantEffect(["
<< entity->localOrigin.linearPosition.x
<< ", " << entity->localOrigin.linearPosition.y
<< ", " << entity->localOrigin.linearPosition.z << "], " << effect_number << ");" << std::endl << std::flush;
DPLIndependantEffect(
entity->localOrigin.linearPosition,
effect_number);
}
else
{
DEBUG_STREAM << " ** ExplosionScripts(*entity*, RES["
<< model_resource->resourceID << " - " << model_resource->resourceName << "], "
<< "ViewFrom::" << (view_type == ViewFrom::insideEntity ? "insideEntity" : (view_type == ViewFrom::outsideEntity ? "outsideEntity" : "collisionEntity"))
<< ", " << (effect_number - 100) << ");" << std::endl << std::flush;
ExplosionScripts(
entity, // The entity we are dealing with
model_resource, // Pointer to the video resource
view_type, // Type of reference (inside/outside...etc.)
effect_number - 100);
}
}
break;
}
case CameraDirectorClassID:
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create the CameraDirector HUD Renderable if not a Replicant
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
if (entity->GetInstance() == CameraDirector::MasterInstance)
{
CameraDirector *camera_director = (CameraDirector*) entity;
Check_Pointer(camera_director);
int *player_index = &camera_director->goalPlayerIndex;
Check_Pointer(player_index);
Logical *display_rank_window = &camera_director->displayRankingWindow;
Check_Pointer(display_rank_window);
mCamShipHUD = new CameraShipHUDRenderable(entity, CameraShipHUDRenderable::Dynamic, player_index, display_rank_window);
}
break;
}
//
// Script for a drivable camera, the camera is invisible to other players
//
case CameraShipClassID:
{
if(view_type == insideEntity)
{
//
// Build an empty root renderable and an eye renderable
//
dpl_ISECT_MODE dpl_isect_mode_obj;
RootRenderable *this_root =
new RootRenderable(
entity, // Entity to attach the renderable to
RootRenderable::Dynamic, // How/when to execute the renderable
NULL, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
dpl_isect_mode_obj, // type of intersections to do on this object
NULL); // intersection mask for the object
Register_Object(this_root);
#if 0 //DEBUG_LEVEL > 0
DPLEyeRenderable* this_eye =
#endif
mCamera =
new DPLEyeRenderable(
entity,
LinearMatrix::Identity,
this_root,
NULL
);
Register_Object(this_eye);
}
break;
}
//
// Script for doorframe, so it can be used in any game
//
case DoorFrameClassID:
{
Verify( object_count == 6 );
//------------------------------------------------
// First video object is root shape for the door
// followed by left door shape, right door shape,
// door lights, left door lights, and right door
// lights.
//------------------------------------------------
d3d_OBJECT
*object,
*left,
*right,
*object_lights,
*left_lights,
*right_lights;
int object_number = 0;
video_iterator.First();
while ((video_wrapper = video_iterator.ReadAndNext()) != NULL)
{
video_object = video_wrapper->GetVideoObject();
object_filename = video_object->GetObjectFilename();
#if NOISY_RENDERER
Tell("L4VIDEO.cpp loading door object "<<object_filename<<"\n");
#endif
switch (object_number)
{
case 0:
// object = dpl_LoadObject(object_filename, dpl_load_normal);
object = d3d_OBJECT::LoadObject(mDevice, object_filename);
break;
case 1:
// left = dpl_LoadObject(object_filename, dpl_load_normal);
left = d3d_OBJECT::LoadObject(mDevice, object_filename);
break;
case 2:
// right = dpl_LoadObject(object_filename, dpl_load_normal);
right = d3d_OBJECT::LoadObject(mDevice, object_filename);
break;
case 3:
// object_lights = dpl_LoadObject(object_filename, dpl_load_normal);
object_lights = d3d_OBJECT::LoadObject(mDevice, object_filename);
break;
case 4:
// left_lights = dpl_LoadObject(object_filename, dpl_load_normal);
left_lights = d3d_OBJECT::LoadObject(mDevice, object_filename);
break;
case 5:
// right_lights = dpl_LoadObject(object_filename, dpl_load_normal);
right_lights = d3d_OBJECT::LoadObject(mDevice, object_filename);
break;
default:
// ignore any additional objects
break;
}
++object_number;
}
//
// HACK Hard Coded Doorframes SubsystemArray access
//
Door *left_door_sub = (Door*) entity->GetSubsystem(0);
Point3D* left_door_position = &left_door_sub->currentPosition;
Door *right_door_sub = (Door*) entity->GetSubsystem(1);
Point3D* right_door_position = &right_door_sub->currentPosition;
dpl_ISECT_MODE dpl_isect_mode_obj;
RootRenderable *door_sill =
new RootRenderable(
entity, // Entity to attach the renderable to
RootRenderable::Static, // How/when to execute the renderable
object, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
dpl_isect_mode_obj, // type of intersections to do on this object
NULL); // intersection mask for the object
Register_Object(door_sill);
//
// Set my_root_dcs because we want this guy's hiearchy to be marked
// with his entity pointer
//
// my_root_dcs = door_sill->GetDCS();
LinearMatrix my_ident(True);
DPLChildPointRenderable* left_door =
new DPLChildPointRenderable(
entity,
false,
left,
dpl_isect_mode_obj,
NULL,
my_ident,
door_sill,
left_door_position);
Register_Object(left_door);
DPLChildPointRenderable* right_door =
new DPLChildPointRenderable(
entity,
false,
right,
dpl_isect_mode_obj,
NULL,
my_ident,
door_sill,
right_door_position);
Register_Object(right_door);
#if DEBUG_LEVEL > 0
DCSInstanceRenderable *door_sill_lights_instance =
#endif
new DCSInstanceRenderable(
entity, // Entity to attach the renderable to
DCSInstanceRenderable::Static, // How/when to execute the renderable
object_lights, // object to connect to the instance
door_sill, // the DCS to add the instance to
dpl_isect_mode_obj, // type of intersections to do on this object
NULL, // intersection mask for the object
True); // initial visibility setting
Register_Object(door_sill_lights_instance);
#if DEBUG_LEVEL > 0
DCSInstanceRenderable *left_door_lights_instance =
#endif
new DCSInstanceRenderable(
entity, // Entity to attach the renderable to
DCSInstanceRenderable::Static, // How/when to execute the renderable
left_lights, // object to connect to the instance
left_door, // the DCS to add the instance to
dpl_isect_mode_obj, // type of intersections to do on this object
NULL, // intersection mask for the object
True); // initial visibility setting
Register_Object(left_door_lights_instance);
#if DEBUG_LEVEL > 0
DCSInstanceRenderable *right_door_lights_instance =
#endif
new DCSInstanceRenderable(
entity, // Entity to attach the renderable to
DCSInstanceRenderable::Static, // How/when to execute the renderable
right_lights, // object to connect to the instance
right_door, // the DCS to add the instance to
dpl_isect_mode_obj, // type of intersections to do on this object
NULL, // intersection mask for the object
True); // initial visibility setting
Register_Object(right_door_lights_instance);
break;
}
//
// This is the script run on anything that isn't already listed above
//
default:
{
d3d_OBJECT *this_object;
dpl_ISECT_MODE intersect_mode;
uint32 intersect_mask;
LinearMatrix offset_matrix = LinearMatrix::Identity;
Component *component = NULL;
HierarchicalDrawComponent *rootCom = NULL;
HierarchicalDrawComponent *thisCom = NULL;
//
// First, establish that this level doesn't know what to do
// if the object has no video resource.
//
if (!model_resource)
{
VideoRenderer::MakeEntityRenderables(entity, model_resource, view_type);
Entity_Being_Created = NULL;
return;
}
//
// If we're inside the entity, set up the intersect mode and mask so we
// won't intersect ourselves with the pickpoint. Other items get full
// geometry intersection.
//
if (view_type == insideEntity)
{
// intersect_mode = dpl_isect_mode_obj;
intersect_mask = NULL;
}
else
{
// intersect_mode = dpl_isect_mode_geometry;
intersect_mask = INTERSECT_ALL;
}
//
// RP412RENDERDIAG=1: name what actually gets built, so a missing
// Winners Circle can be told from one that is simply out of shot.
//
{
static const char *diag = getenv("RP412RENDERDIAG");
if (diag != NULL && atoi(diag) != 0)
{
DEBUG_STREAM << "RenderDiag: building class"
<< entity->GetClassID() << " res "
<< entity->GetResourceID() << " at "
<< entity->localOrigin.linearPosition.x << ","
<< entity->localOrigin.linearPosition.y << ","
<< entity->localOrigin.linearPosition.z
<< "\n" << std::flush;
}
}
Logical first_object = True;
video_iterator.First();
while ((video_wrapper = video_iterator.ReadAndNext()) != NULL)
{
video_object = video_wrapper->GetVideoObject();
object_filename = video_object->GetObjectFilename();
resource_type = video_object->GetResourceType();
renderer_modes = video_object->GetRendererModes();
#if NOISY_RENDERER
Tell("L4VIDEO.cpp loading object " << object_filename);
Tell(" type " << resource_type);
Tell(" mode 0x" <<std::hex<<renderer_modes<<std::dec<< "." << std::endl);
#endif
if ((resource_type != L4VideoObject::Object) && (resource_type != L4VideoObject::Rubble))
{
DEBUG_STREAM << "L4VIDEO.cpp wrong video resource type for object "<<object_filename<<"\n" << std::flush;
continue; // next object
}
SET_VIDEO_LOAD_OBJECT();
this_object = d3d_OBJECT::LoadObject(mDevice, object_filename);
CLEAR_VIDEO_LOAD_OBJECT();
if (this_object == NULL)
{
DEBUG_STREAM << "L4VIDEO.cpp couldn't load object "<<object_filename<<"\n" << std::flush;
if (!first_object)
{
continue; // next object
}
}
if (first_object)
{
first_object = False;
//
// Determine if the entity is a mover or not, which tells us what type of
// renderable to use to construct it.
//
if (entity->IsDerivedFrom(*Mover::GetClassDerivations()))
{
//
// It's a mover, construct it with a dynamic root renderable so it can move
// also remember it's DCS so we can hook other shapes to it later.
//
SET_VIDEO_CONSTRUCT_ROOT();
rootCom = new RootRenderable(
entity, // Entity to attach the renderable to
RootRenderable::Dynamic, // How/when to execute the renderable
this_object, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
intersect_mode, // type of intersections to do on this object
intersect_mask); // intersection mask for the object
Register_Object(this_root);
CLEAR_VIDEO_CONSTRUCT_ROOT();
}
else
{
//
// It's a static, construct it with a static RootRenderable and
// remember it's DCS so we can hook other shapes to it later.
//
rootCom = new RootRenderable(
entity, // Entity to attach the renderable to
RootRenderable::Static, // How/when to execute the renderable
this_object, // object to hang on the DCS, may be a list later <NULL>
false, // DPL Zone this stuff will live in (for culling)
intersect_mode, // type of intersections to do on this object
intersect_mask); // intersection mask for the object
}
//
// Set my_root_dcs because we want this guy's hiearchy to be marked
// with his entity pointer
//
// my_root_dcs = root_DCS;
//
// If we are inside the entity, then we must build an eyepoint for it too.
// since there is no special construction, we build the eyepoint with a
// zero offset.
//
if (view_type == insideEntity)
{
EulerAngles *eyepoint_rotation = (EulerAngles *)entity->GetAttributePointer("EyepointRotation");
#if 0 //DEBUG_LEVEL > 0
DPLEyeRenderable *this_eye =
#endif
mCamera =
new DPLEyeRenderable(
entity,
LinearMatrix::Identity,
rootCom,
eyepoint_rotation);
Register_Object(this_eye);
}
//------------------------------------------------------
// if root object billboards (all others billboard too)
//------------------------------------------------------
// this_DCS = root_DCS;
}
else
{
if (renderer_modes & L4VideoObject::BillboardObject)
{
//------------------------------------------
// attach additional object to separate DCS
// because it is billboarded
//------------------------------------------
thisCom = new DPLStaticChildRenderable(
entity,
false,
this_object,
intersect_mode,
intersect_mask,
offset_matrix,
rootCom);
Register_Object(this_child);
// this_DCS = this_child->GetDCS();
}
else
{
//----------------------------------------
// attach additional objects to root_DCS
// (HACK) temporary implementation (HACK)
//----------------------------------------
thisCom = new DCSInstanceRenderable(
entity, // Entity to attach the renderable to
DCSInstanceRenderable::Static, // How/when to execute the renderable
this_object, // object to connect to the instance
rootCom, // the DCS to add the instance to
intersect_mode, // type of intersections to do on this object
intersect_mask, // intersection mask for the object
True); // initial visibility setting
Register_Object(another_instance);
// this_DCS = NULL;
}
}
//----------------------------------
// billboard object if so indicated
//----------------------------------
if (thisCom && (renderer_modes & L4VideoObject::BillboardObject))
{
// int axes = dpl_reorient_axes_none;
if (renderer_modes & L4VideoObject::BillboardXAxis)
{
// axes |= dpl_reorient_axes_x;
}
if (renderer_modes & L4VideoObject::BillboardYAxis)
{
// axes |= dpl_reorient_axes_y;
}
if (renderer_modes & L4VideoObject::BillboardZAxis)
{
// axes |= dpl_reorient_axes_z;
}
// dpl_SetDCSReorientAxes(this_DCS, (dpl_REORIENT_AXES)axes);
// dpl_FlushDCS(this_DCS);
}
//MOVED THIS TO ROOTRENDERABLE - Was this a hack?
//mRenderables.Add(component);
}
break;
}
}
//
// release the video chain memory
//
L4VideoObjectWrapper::DeleteVideoObjectChain(&video_chain);
//
// Clear the entity pointer passed to the callback system
//
Entity_Being_Created = NULL;
//
// If my_root_dcs is non-null, mark the entity's DCS hiearchy with it's
// entity pointer.
//
// if(my_root_dcs)
// {
// MarkDCSHiearchy(my_root_dcs,entity);
//#if 0
// if(entity->GetClassID() == DemolitionPackClassID)
// {
// Point3D temp_point(0.0,0.0,0.0);
// #if DEBUG_LEVEL > 0
// OnePSFXRenderable *this_effect=
// #endif
// new OnePSFXRenderable(
// entity, // Entity to attach the renderable to
// OnePSFXRenderable::Static, // How/when to execute the renderable
// myPSFXDescriptons[3], // name of file with the PFX description in it
// my_root_dcs, // DCS the effect is relative to (may be NULL)
// &temp_point); // Offset (or world coordinants if DCS is NULL)
// Register_Object(this_effect);
// }
//#endif
// }
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This should be called prior to the rendering of a frame to setup the culling
// data the renderer keeps (mostly the world to eye transform)
//
void
DPLRenderer::SetupCull()
{
Entity
*linked_entity;
LinearMatrix
site_to_world,
world_to_site,
eye_rotation,
eye_inverted;
EntitySegment
*eyepoint_segment;
EulerAngles
*eyepoint_rotation;
//
// To test the functionality, this is not as efficient as it could be.
// when it gets fully patched into the renderer it will be improved.
//
// Figure out what type of entity this is.
//
linked_entity = GetLinkedEntity();
eyepoint_rotation = (EulerAngles*)linked_entity->GetAttributePointer("EyepointRotation");
if(linked_entity->IsDerivedFrom(*JointedMover::GetClassDerivations()))
{
JointedMover
*linked_jointed_mover;
linked_jointed_mover = Cast_Object(JointedMover*, linked_entity);
eyepoint_segment = linked_jointed_mover->GetSegment("siteeyepoint");
if(!eyepoint_segment)
{
Fail("DPLRenderer::SetupCull jointed mover had no siteeyepoint\n");
}
if(!eyepoint_rotation)
{
Fail("DPLRenderer::SetupCull jointed mover had no EyepointRotation attribute\n");
}
linked_jointed_mover->GetSegmentToWorld(*eyepoint_segment, &site_to_world);
if(eyepoint_rotation)
{
world_to_site.Invert(site_to_world);
eye_rotation = *eyepoint_rotation;
eye_inverted.Invert(eye_rotation);
worldToEyeMatrix.Multiply(world_to_site, eye_inverted);
}
else
{
worldToEyeMatrix.Invert(site_to_world);
}
}
else
{
site_to_world = linked_entity->localOrigin;
if(eyepoint_rotation)
{
world_to_site.Invert(site_to_world);
eye_rotation = *eyepoint_rotation;
eye_inverted.Invert(eye_rotation);
worldToEyeMatrix.Multiply(world_to_site, eye_inverted);
}
else
{
worldToEyeMatrix.Invert(site_to_world);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
DPLRenderer::ResetStatistics()
{
total_cull = 0;
total_draw = 0;
total_pixelplanes = 0;
total_frame_time = 0;
frame_count = 0;
target_frame_time = 56000;
target_frame_count= 0;
report_time = currentFrameTime + 60.0f;
}
void
DPLRenderer::ReportStatistics()
{
if(frame_count != 0)
{
std::cout<<"Frames "<<frame_count<<"\n";
std::cout<<((float)target_frame_count/(float)frame_count)*100.0f<<"% of the frames were under the target frame time\n";
std::cout<<"Average Cull "<<(unsigned long)((float)total_cull/(float)frame_count)<<"\n";
std::cout<<"Average Draw "<<(unsigned long)((float)total_draw/(float)frame_count)<<"\n";
std::cout<<"Average Pixel Planes "<<(unsigned long)((float)total_pixelplanes/(float)frame_count)<<"\n";
std::cout<<"Average Frame Time "<<(unsigned long)((float)total_frame_time/(float)frame_count)<<"\n";
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Execute Method, performs the rendering of one frame
//
void DPLRenderer::ExecuteImplementation(RendererComplexity, RendererOrigin::InterestingEntityIterator* all_iterator)
{
Component *component;
HRESULT hr;
// timing variables
__int64 ticks = HiResNowTicks();
#ifdef LOGFRAMERATE
fputc(0, FRAMERATE_LOG);
fwrite(&ticks, sizeof(__int64), 1, FRAMERATE_LOG);
#endif
int currentAppState = application->GetApplicationState();
switch (currentAppState)
{
case Application::CreatingMission:
case Application::LoadingMission:
case Application::WaitingForLaunch:
//if (mLoadingScreenThread == NULL)
//{
// mLoadingScreenRunning = true;
// mLoadingScreenThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ExecuteLoadScreenThread, this, 0, NULL);
//}
//hr = mDevice->TestCooperativeLevel();
//if (hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET)
//{
// mPrimaryDeviceReseting = true;
// DEBUG_STREAM << this << " RESETTING DEVICE - WAITING FOR FRAME TO FINISH" << std::endl << std::flush;
// while (mRenderingLoadingFrame)
// {
// Sleep(100);
// }
// DEBUG_STREAM << this << " RESETTING DEVICE - DONE WAITING FOR FRAME TO FINISH" << std::endl << std::flush;
// int bbCount = mPresentParams.BackBufferCount;
// int bbWidth = mPresentParams.BackBufferWidth;
// int bbHeight = mPresentParams.BackBufferHeight;
// ParticleEngine::Destroy();
// V(mDevice->Reset(&mPresentParams));
// ParticleEngine::Initialize(mDevice);
// this->SetCoreRenderStates();
// mPresentParams.BackBufferCount = bbCount;
// mPresentParams.BackBufferWidth = bbWidth;
// mPresentParams.BackBufferHeight = bbHeight;
// mPrimaryDeviceReseting = false;
//}
ticks = HiResNowTicks();
#ifdef LOGFRAMERATE
fputc(1, FRAMERATE_LOG);
fwrite(&ticks, sizeof(__int64), 1, FRAMERATE_LOG);
#endif
return;
case Application::LaunchingMission:
case Application::RunningMission:
break;
}
if (lastAppState != currentAppState && currentAppState == Application::LaunchingMission)
{
this->mDevice->SetRenderState(D3DRS_LIGHTING, true);
this->mDevice->SetTransform(D3DTS_PROJECTION, &this->mProjectionMatrix);
this->mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, D3DCOLOR_ARGB(128, 255, 255, 255));
this->mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
}
lastAppState = currentAppState;
// before we execute everything we need to clear
// the render lists
memset(mRenderLists, 0, sizeof(mRenderLists));
HierarchicalDrawComponent *drawComp;
SChainIteratorOf<HierarchicalDrawComponent*> iterator(&mRenderables);
while ((drawComp = iterator.ReadAndNext()) != NULL)
drawComp->Execute();
if (mReticle)
mReticle->Execute();
if (mCamShipHUD)
mCamShipHUD->Execute();
//
// The eye renderable has just written D3DTS_VIEW from the viewpoint
// entity. For the Winners Circle the shot comes from off the stand
// instead, so stomp it here - before the read-back below that feeds
// every draw call.
//
if (mPresentationCamera)
{
mDevice->SetTransform(D3DTS_VIEW, &mPresentationView);
}
//
// RP412RENDERDIAG=1: report what the frame is actually made of once the
// mission is ending, which is the only way to tell an empty scene from a
// misaimed camera.
//
{
static const char *diag = getenv("RP412RENDERDIAG");
static int reported = 0;
if (diag != NULL && atoi(diag) != 0 &&
currentAppState == Application::EndingMission && reported < 4)
{
++reported;
int dynamic_count = 0;
SChainIteratorOf<HierarchicalDrawComponent*> diag_iter(&mRenderables);
while (diag_iter.ReadAndNext() != NULL)
{
++dynamic_count;
}
DEBUG_STREAM << "RenderDiag: ending frame " << reported
<< " dead=" << (l4_application->IsDead() ? 1 : 0)
<< " statics=" << (int) mConsolidatedStaticObjects.size()
<< " renderables=" << dynamic_count
<< " camera=" << (mPresentationCamera ? 1 : 0)
<< "\n" << std::flush;
}
}
gNumBatches = 0;
static Time lastFrameTime = mTargetRenderTime;
Scalar dT = mTargetRenderTime - lastFrameTime;
lastFrameTime = mTargetRenderTime;
currentFrameTime = Now();
//
// Fade the presentation up out of black, if one is running. Same lever
// the end-of-mission fade pulls: scale the fog colour and both fog
// distances, here from nothing up to what the podium asked for.
//
if (mPresentationFadeTime > 0.0f)
{
Scalar remaining = mPresentationFadeEnd - Now();
Scalar fade = 1.0f - (remaining / mPresentationFadeTime);
if (fade >= 1.0f)
{
fade = 1.0f;
mPresentationFadeTime = 0.0f; // done
}
if (fade < 0.0f)
{
fade = 0.0f;
}
fogRed = mPresentationFogRed * fade;
fogGreen = mPresentationFogGreen * fade;
fogBlue = mPresentationFogBlue * fade;
currentFogNear = mPresentationFogNear * fade;
currentFogFar = mPresentationFogFar * fade;
mDevice->SetRenderState(D3DRS_FOGCOLOR,
D3DCOLOR_XRGB((int)(255 * fogRed), (int)(255 * fogGreen),
(int)(255 * fogBlue)));
}
//
// Pillarbox: black the whole target first, then narrow the viewport so
// everything after this - clear, scene, reticle - lands inside the crop
// and the surround stays black. Restored after Present.
//
if (mPresentationAspect > 0.0f)
{
D3DVIEWPORT9 full;
full.X = 0;
full.Y = 0;
full.Width = mPresentParams.BackBufferWidth;
full.Height = mPresentParams.BackBufferHeight;
full.MinZ = 0.0f;
full.MaxZ = 1.0f;
mDevice->SetViewport(&full);
mDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
DWORD cropped = (DWORD)
(mPresentParams.BackBufferHeight * mPresentationAspect);
if (cropped > mPresentParams.BackBufferWidth)
{
cropped = mPresentParams.BackBufferWidth;
}
D3DVIEWPORT9 crop = full;
crop.Width = cropped;
crop.X = (mPresentParams.BackBufferWidth - cropped) / 2;
mDevice->SetViewport(&crop);
}
DWORD currentFog;
mDevice->GetRenderState(D3DRS_FOGCOLOR, &currentFog);
hr = mDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, currentFog, 1.0f, 0);
hr = mDevice->BeginScene();
mDevice->SetFVF(L4VERTEX_FVF);
D3DXMATRIX viewTransform;
mDevice->GetTransform(D3DTS_VIEW, &viewTransform);
//
// Start with the opaque pass
//
mDevice->SetRenderState(D3DRS_FOGSTART, *((DWORD*)(&currentFogNear)));
mDevice->SetRenderState(D3DRS_FOGEND, *((DWORD*)(&currentFogFar)));
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, true);
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
mDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
mDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE);
d3d_OBJECT::ResetState(mDevice);
if (!l4_application->IsDead())
{
std::list<d3d_OBJECT*>::const_iterator iter;
for (iter = this->mConsolidatedStaticObjects.begin(); iter != this->mConsolidatedStaticObjects.end(); ++iter)
{
(*iter)->Draw(PASS_OPAQUE, &viewTransform, mTargetRenderTime);
}
}
for (d3d_OBJECT *obj = mRenderLists[PASS_OPAQUE]; obj != NULL; obj = obj->GetNext(PASS_OPAQUE))
obj->Draw(PASS_OPAQUE, &viewTransform, mTargetRenderTime);
//
// Next up is the decal pass
//
mDevice->SetTransform(D3DTS_PROJECTION, &mDecalProjectionMatrix);
if (!l4_application->IsDead())
{
std::list<d3d_OBJECT*>::const_iterator iter;
for (iter = this->mConsolidatedStaticObjects.begin(); iter != this->mConsolidatedStaticObjects.end(); ++iter)
{
(*iter)->Draw(PASS_DECAL, &viewTransform, mTargetRenderTime);
}
}
for (d3d_OBJECT *obj = mRenderLists[PASS_DECAL]; obj != NULL; obj = obj->GetNext(PASS_DECAL))
obj->Draw(PASS_DECAL, &viewTransform, mTargetRenderTime);
//
// The sphere pass
//
//Set it up so the fog won't affect spheres' colors so much- extend the near fog plane out
float fogModNear = currentFogFar;
float fogModFar = fogModNear + (currentFogFar - currentFogNear);
mDevice->SetRenderState(D3DRS_FOGSTART, *((DWORD*)(&fogModNear)));
mDevice->SetRenderState(D3DRS_FOGEND, *((DWORD*)(&fogModFar)));
for (d3d_OBJECT *obj = mRenderLists[PASS_SPHERE]; obj != NULL; obj = obj->GetNext(PASS_SPHERE))
obj->Draw(PASS_SPHERE, &viewTransform, mTargetRenderTime);
//
// The sky pass
//
//Further extend the fog distance
fogModNear = currentFogNear * 3;
fogModFar = currentFogFar * 6;
mDevice->SetRenderState(D3DRS_FOGSTART, *((DWORD*)(&fogModNear)));
mDevice->SetRenderState(D3DRS_FOGEND, *((DWORD*)(&fogModFar)));
mDevice->SetTransform(D3DTS_PROJECTION, &mProjectionMatrix);
if (!l4_application->IsDead())
{
std::list<d3d_OBJECT*>::const_iterator iter;
for (iter = this->mConsolidatedStaticObjects.begin(); iter != this->mConsolidatedStaticObjects.end(); ++iter)
{
(*iter)->Draw(PASS_SKY, &viewTransform, mTargetRenderTime);
}
}
for (d3d_OBJECT *obj = mRenderLists[PASS_SKY]; obj != NULL; obj = obj->GetNext(PASS_SKY))
obj->Draw(PASS_SKY, &viewTransform, mTargetRenderTime);
//Reactivate fog
mDevice->SetRenderState(D3DRS_FOGSTART, *((DWORD*)(&currentFogNear)));
mDevice->SetRenderState(D3DRS_FOGEND, *((DWORD*)(&currentFogFar)));
//
// Finally we do the alpha blend pass
//
mDevice->SetRenderState(D3DRS_ZWRITEENABLE,false);
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
if (!l4_application->IsDead())
{
std::list<d3d_OBJECT*>::const_iterator iter;
for (iter = this->mConsolidatedStaticObjects.begin(); iter != this->mConsolidatedStaticObjects.end(); ++iter)
{
(*iter)->Draw(PASS_ALPHABLEND, &viewTransform, mTargetRenderTime);
}
}
for (d3d_OBJECT *obj = mRenderLists[PASS_ALPHABLEND]; obj != NULL; obj = obj->GetNext(PASS_ALPHABLEND))
obj->Draw(PASS_ALPHABLEND, &viewTransform, mTargetRenderTime);
//
// And don't forget particles too
//
D3DXMATRIX ident;
mDevice->SetTransform(D3DTS_WORLD, D3DXMatrixIdentity(&ident));
if (!l4_application->IsDead())
{
ParticleEngine::RenderParticles(&viewTransform, dT);
for (int i=0; i<MAX_INDIE_EMITTERS; ++i)
myPSFXEmitters[i].Execute();
}
//
// Wrap it up by doing the 2D pass
//
mDevice->SetFVF(L4VERTEX_2D_FVF);
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, true);
mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
mDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
mDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
mDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
//
// No gunsight on the podium - the race is over and nothing is being
// aimed at. It is drawn in the 2D pass, so it survives everything else
// the presentation turns off.
//
if (mReticle && !l4_application->IsDead() && !InPresentation())
mReticle->Render(0, &viewTransform);
if (mCamShipHUD && !InPresentation())
mCamShipHUD->Render(0, &viewTransform);
hr = mDevice->EndScene();
hr = mDevice->Present(NULL, NULL, gMainPresentWindow, NULL);
// hand the whole target back
if (mPresentationAspect > 0.0f)
{
D3DVIEWPORT9 full;
full.X = 0;
full.Y = 0;
full.Width = mPresentParams.BackBufferWidth;
full.Height = mPresentParams.BackBufferHeight;
full.MinZ = 0.0f;
full.MaxZ = 1.0f;
mDevice->SetViewport(&full);
}
//
// RP412RENDERDIAG=1: did the ending frame actually reach the window, and
// what colour did it clear to? A black clear with a blue-violet fog set
// means something is overwriting the fog behind us.
//
{
static const char *diag = getenv("RP412RENDERDIAG");
static int presented = 0;
if (diag != NULL && atoi(diag) != 0 &&
application->GetApplicationState() == Application::EndingMission &&
presented < 4)
{
++presented;
DWORD fog_now = 0;
mDevice->GetRenderState(D3DRS_FOGCOLOR, &fog_now);
HWND present_window = (HWND) gMainPresentWindow;
RECT present_rect;
present_rect.left = present_rect.top = 0;
present_rect.right = present_rect.bottom = 0;
if (present_window != NULL)
{
GetClientRect(present_window, &present_rect);
}
DEBUG_STREAM << "RenderDiag: present " << presented
<< " hr=0x" << std::hex << (unsigned int) hr << std::dec
<< " fogcolor=0x" << std::hex << (unsigned int) fog_now << std::dec
<< " window=" << (void*) present_window
<< " visible=" << (present_window != NULL &&
IsWindowVisible(present_window) ? 1 : 0)
<< " rect=" << present_rect.right << "x" << present_rect.bottom
<< " backbuf=" << mPresentParams.BackBufferWidth << "x"
<< mPresentParams.BackBufferHeight
<< "\n" << std::flush;
}
}
if (hr == D3DERR_DEVICELOST)
{
int bbCount = mPresentParams.BackBufferCount;
int bbWidth = mPresentParams.BackBufferWidth;
int bbHeight = mPresentParams.BackBufferHeight;
ParticleEngine::Destroy();
V(mDevice->Reset(&mPresentParams));
ParticleEngine::Initialize(mDevice);
this->SetCoreRenderStates();
mPresentParams.BackBufferCount = bbCount;
mPresentParams.BackBufferWidth = bbWidth;
mPresentParams.BackBufferHeight = bbHeight;
}
ticks = HiResNowTicks();
#ifdef LOGFRAMERATE
fputc(1, FRAMERATE_LOG);
fwrite(&ticks, sizeof(__int64), 1, FRAMERATE_LOG);
#endif
}
void DPLRenderer::ExecuteIdle()
{
HRESULT hr;
hr = mDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 1.0f, 0);
hr = mDevice->BeginScene();
hr = mDevice->EndScene();
if (mDevice->Present(NULL, NULL, gMainPresentWindow, NULL) == D3DERR_DEVICELOST)
{
int bbCount = mPresentParams.BackBufferCount;
int bbWidth = mPresentParams.BackBufferWidth;
int bbHeight = mPresentParams.BackBufferHeight;
ParticleEngine::Destroy();
V(mDevice->Reset(&mPresentParams));
ParticleEngine::Initialize(mDevice);
this->SetCoreRenderStates();
mPresentParams.BackBufferCount = bbCount;
mPresentParams.BackBufferWidth = bbWidth;
mPresentParams.BackBufferHeight = bbHeight;
}
}
//
//#############################################################################
// DPLDelayDCSFlush and DPLDoDCSBatchFlush queue up a list of DCS pointers
// for later std::flushing in one big batch.
//#############################################################################
//
void
DPLRenderer::DPLDelayDCSFlush(
dpl_DCS *my_dcs) // The DCS we want to remember for later
{
//
// Make sure the array hasn't become overfilled somehow and make
// sure the DCS is valid.
//
Verify(delayedDCSCount <= DELAY_DCS_FLUSH_ARRAY_SIZE);
Check_Pointer(my_dcs);
//
// If the array is full, std::flush it out to make space for this DCS
//
if(delayedDCSCount == DELAY_DCS_FLUSH_ARRAY_SIZE)
{
DPLDoDCSBatchFlush();
}
//
// Add the New DCS to the list
//
delayDCSFlushArray[delayedDCSCount++] = my_dcs;
}
void
DPLRenderer::DPLDoDCSBatchFlush() // Flush the dcs's remembered by DPLDelayDCSFlush
{
//STUBBED: DPL RB 1/14/07
//SET_VIDEO_BATCH_FLUSH();
////
//// Make sure the array hasn't become overfilled somehow
////
//Verify(delayedDCSCount <= DELAY_DCS_FLUSH_ARRAY_SIZE);
////
//// Flush the array and reset the counters that go with it
////
//if(delayedDCSCount != 0)
//{
// delayDCSFlushArray[delayedDCSCount] = NULL;
// dpl_FlushDCSArticulations(delayDCSFlushArray);
// delayedDCSCount = 0;
//}
//CLEAR_VIDEO_BATCH_FLUSH();
}
//
//#############################################################################
// DPLReportFreeMemory writes current free memory in graphics card to any
// output stream.
//#############################################################################
//
void
DPLRenderer::DPLReportFreeMemory(std::ostream &output)
{
//STUBBED: DPL RB 1/14/07
// output << "Free memory in card: " << dpl_FreeMemory() << " bytes." << std::endl;
return;
}
//
//#############################################################################
// DPLReportPerfStats writes performance statistics to std::cout (stdout).
//#############################################################################
//
void
DPLRenderer::DPLReportPerfStats(std::ostream &output)
{
//STUBBED: DPL RB 1/15/07
////-----------------------------------------------------
//// HACK - copied from camera.c must re-copy if changed
////
//// case '?':
//// printf ("sect time %d dcs 0x%x inst 0x%x\n",
//// __sect_time, sect_dcs, sect_inst );
////-----------------------------------------------------
//output << "sect time " << __sect_time <<
// " dcs and inst not available" << std::endl;
////------------------------------------------------------------
//// HACK - copied from dpl_vpx.c must re-copy if changed
////
//// void dpl_PerfStats(void)
//// printf ( "cull %d draw %d frame %d pxpl %d prims %d\n",
//// __last_cull_time,
//// __last_draw_time,
//// __last_frame_time,
//// __last_pxpl_time,
//// __last_frame_prims );
////------------------------------------------------------------
//output <<
// "cull " << __last_cull_time <<
// " draw " << __last_draw_time <<
// " frame " << __last_frame_time <<
// " pxpl " << __last_pxpl_time <<
// " prims " << __last_frame_prims <<
// std::endl;
//if(statistics_started)
//{
// ReportStatistics();
//}
//else
//{
// ResetStatistics();
// statistics_started = True;
//}
//return;
}
//
//#############################################################################
// DPLToggleWireframe toggles the state of dpl global wireframe.
//#############################################################################
//
void
DPLRenderer::DPLToggleWireframe()
{
//STUBBBED: DPL RB 1/14/07
//static Logical wireframe_on = 0;
//if ((wireframe_on ^= 1) != 0)
//{
// DEBUG_STREAM << "wireframe ON" << std::endl << std::flush;
// dpl_SetRenderProperty(dpl_render_prop_wireframe, dpl_render_value_on, NULL );
//}
//else
//{
// DEBUG_STREAM << "wireframe OFF" << std::endl << std::flush;
// dpl_SetRenderProperty(dpl_render_prop_wireframe, dpl_render_value_off, NULL );
//}
}
//
//#############################################################################
// DPLTogglePVision toggles the state of dpl "predator" vision.
//#############################################################################
//
void
DPLRenderer::DPLTogglePVision()
{
//STUBBED: DPL RB 1/14/07
//static Logical pvision_on = 0;
//dpl_EXPLOSION_EFFECT_INFO sfx_info;
//sfx_info.x = sfx_info.y = sfx_info.z = 0;
//if ((pvision_on ^= 1) != 0)
//{
// DEBUG_STREAM << "pvision ON" << std::endl << std::flush;
// sfx_info.type = -1;
//}
//else
//{
// DEBUG_STREAM << "pvision OFF" << std::endl << std::flush;
// sfx_info.type = -2;
//}
//dpl_Effect(dpl_effect_type_explosion, NULL, &sfx_info);
//return;
}
//
//#############################################################################
// DPLFrameDump writes screen image to targa file.
//#############################################################################
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// oneD_filter() antialiased framegrab support
void
oneD_filter(
uint32 *linebuffer,
unsigned short *rframe,
unsigned short *gframe,
unsigned short *bframe,
int32 y,
int32 x_size
)
{
int32
pos,
i,
r, g, b;
unsigned char
*clinebuf = (unsigned char *)linebuffer;
pos = y * x_size;
for (i=0; i<x_size; ++i)
{
r = rframe[pos];
g = gframe[pos];
b = bframe[pos];
++pos;
*clinebuf++ = (unsigned char)((r >> 8) & 0xff);
*clinebuf++ = (unsigned char)((g >> 8) & 0xff);
*clinebuf++ = (unsigned char)((b >> 8) & 0xff);
}
return;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// dump_frame_buffer()
void
dump_frame_buffer(
dpl_VIEW *eye,
int32 x_size,
int32 y_size,
Logical antialias
)
{
//STUBBED: DPL RB 1/14/07
////do not check eye here
////----------------------------------------
//// control variable and operating buffers
////----------------------------------------
//static uint32
// dumped_frames = 0,
// *line_buffer = NULL;
//static unsigned short
// *rframebuffer = NULL,
// *gframebuffer = NULL,
// *bframebuffer = NULL;
//if (eye == NULL)
//{
// //--------------------------
// // release allocated memory
// //--------------------------
// if (line_buffer)
// {
// Unregister_Pointer(line_buffer);
// delete line_buffer;
// }
// if (rframebuffer)
// {
// Unregister_Pointer(rframebuffer);
// delete rframebuffer;
// }
// if (gframebuffer)
// {
// Unregister_Pointer(gframebuffer);
// delete gframebuffer;
// }
// if (bframebuffer)
// {
// Unregister_Pointer(bframebuffer);
// delete bframebuffer;
// }
// return;
//}
//Check_Pointer(eye);
////-----------------------------------------------------------------
//// AA kernel definition:
////
//// normalized screen coordinates are -1.0 .. +1.0
//// these map (in NTSC) to 705 and 512.
//// So a pixel in x is
//// 2.0 / 704 = 2.841e-3
//// in y = 3.906e-3
//// for the re-use 5-sample kernel we displace by 0.5 pixels ...
////-----------------------------------------------------------------
//static const int32 kernel_size = 4;
//static const float xk = 2.0f / x_size;
//static const float yk = 2.0f / y_size;
//static const float ox = xk / 4.0f;
//static const float oy = yk / 4.0f;
//static const float jx = 0.0f; // ox / 4.0f
//static const float jy = 0.0f; // oy / 4.0f
//static const float x_kernel[4] = { -(ox+jx), ox-jx, jx-ox, jx+ox };
//static const float y_kernel[4] = { oy-jy, oy+jy, -(jy+oy), jy-oy };
//static const int kernel_weights[4] = { 64, 64, 64, 64 };
////---------------------
//// operating variables
////---------------------
//int32 passes = (antialias)?kernel_size:1;
//int32 size = x_size * y_size;
//int32 frameptr;
//int32 i, x, y;
//DEBUG_STREAM << "Dump frame buffer (antialias=" <<
// ((antialias)?"True":"False") << ") - press Esc to cancel." << std::endl;
////----------------------------
//// allocate operating buffers
////----------------------------
//if (line_buffer == NULL)
//{
// //-----------------------------------------------------------------------
// // NOTE - must call dump_frame_buffer(NULL, NULL, NULL, NULL) to release
// //-----------------------------------------------------------------------
// line_buffer = new uint32[1024];
// Register_Pointer(line_buffer);
// rframebuffer = new unsigned short[size];
// Register_Pointer(rframebuffer);
// gframebuffer = new unsigned short[size];
// Register_Pointer(gframebuffer);
// bframebuffer = new unsigned short[size];
// Register_Pointer(bframebuffer);
//}
////------------------------------
//// clear out r g b framebuffers
////------------------------------
//frameptr = 0;
//for (i=0; i<size; ++i)
//{
// rframebuffer[frameptr] = 0x0;
// gframebuffer[frameptr] = 0x0;
// bframebuffer[frameptr] = 0x0;
// ++frameptr;
//}
//dpl_RedrawScene();
//dpl_RedrawScene();
////--------------------------------
//// perform AA framecapture passes
////--------------------------------
//int this_weight;
//float32 x0, y0, x1, y1, zeye;
//for (i=0; i<passes; ++i)
//{
// DEBUG_STREAM << " pass " << (i+1) << " of " << passes << " " << std::flush;
// //------------
// // jitter eye
// //------------
// dpl_GetViewProjection(eye, &x0, &y0, &x1, &y1, &zeye);
// dpl_SetViewProjection(eye,
// x0 + x_kernel[i],
// y0 + y_kernel[i],
// x1 + x_kernel[i],
// y1 + y_kernel[i], zeye);
// dpl_FlushView(eye);
// //--------------
// // redraw frame
// //--------------
// dpl_RedrawScene();
// dpl_RedrawScene();
// //--------------------
// // capture accumulate
// //--------------------
// this_weight = kernel_weights[i];
// frameptr = 0;
// for (y=0; y<y_size; ++y )
// {
// unsigned char *linep = (unsigned char *)&line_buffer[0];
// //------------------------------
// // Esc key cancelles frame dump
// //------------------------------
// if (kbhit())
// {
// if (getch() == 27)
// {
// DEBUG_STREAM << std::endl << "cancelled." << std::endl << std::flush;
// return;
// }
// }
// if ((y & 15) == 0)
// { DEBUG_STREAM << "." << std::flush; }
// dpl_ReadFrameStore(eye, (uint32 *)linep, 0, y, x_size, 1);
// for (x=0; x<x_size; ++x)
// {
// rframebuffer[frameptr] += (unsigned short)(linep[2] * this_weight);
// gframebuffer[frameptr] += (unsigned short)(linep[1] * this_weight);
// bframebuffer[frameptr] += (unsigned short)(linep[0] * this_weight);
// ++frameptr;
// linep += 4;
// }
// }
// DEBUG_STREAM << std::endl << std::flush;
//}
////----------------------------------
//// write frame buffer to targa file
////----------------------------------
//FILE *fp;
//char fname[64];
//unsigned char tga_hdr[18];
//sprintf(fname, "dump%d.tga", dumped_frames);
//tga_hdr[0] = 0x00;
//tga_hdr[1] = 0x00;
//tga_hdr[2] = 0x02;
//tga_hdr[3] = 0x00;
//tga_hdr[4] = 0x00;
//tga_hdr[5] = 0x00;
//tga_hdr[6] = 0x00;
//tga_hdr[7] = 0x00;
//tga_hdr[8] = 0x00;
//tga_hdr[9] = 0x00;
//tga_hdr[10] = 0x00;
//tga_hdr[11] = 0x00;
//tga_hdr[12] = (unsigned char)(x_size & 0xff);
//tga_hdr[13] = (unsigned char)((x_size >> 8) & 0xff);
//tga_hdr[14] = (unsigned char)(y_size & 0xff);
//tga_hdr[15] = (unsigned char)((y_size >> 8) & 0xff);
//tga_hdr[16] = 0x18;
//tga_hdr[17] = 0x00;
//DEBUG_STREAM << "Writing image to file '" << fname << "' . . . " << std::flush;
//fp = fopen(fname, "wb");
//fwrite(tga_hdr, 18, 1, fp);
//for (y=0; y<y_size; ++y )
//{
// oneD_filter(line_buffer,
// rframebuffer,
// gframebuffer,
// bframebuffer,
// (y_size-1) - y,
// x_size);
// fwrite(line_buffer, x_size*3, 1, fp);
//}
//fclose(fp);
//DEBUG_STREAM << "done." << std::endl << std::flush;
//++dumped_frames; // increment for next frame dump
//return;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DPLRenderer::DPLFrameDump()
void
DPLRenderer::DPLFrameDump(Logical antialias)
{
//STUBBED: DPL RB 1/15/07
//dump_frame_buffer(dplMainView, x_size, y_size, antialias);
//return;
}
//
//#############################################################################
// DPLIndependantPFX lets you start up an effect in absolute space that is
// run to termination automatically by the renderer.
//#############################################################################
//
void
DPLRenderer::DPLIndependantPFX(
Point3D location, // Location in space to trigger the effect
dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // Description of the pfx
dpl_DCS *my_DCS, // Optional DCS to link to
int subid) // inserted into third byte of effect id.
{
//STUBBED: DPL RB 1/14/07
// we put our id into the lower 16 bits because (at least) the upper 8 bits are flags
// HACK...for testing pfx bug
//dpl_PARTICLESTART_EFFECT_INFO tempParticle;
//tempParticle = *psfx_definition;
//tempParticle.identifier = (psfx_definition->identifier & 0xffff0000) | GetUniqueID() | ((subid << 16) & 0x00ff0000);
//tempParticle.px = location.x;
//tempParticle.py = location.y;
//tempParticle.pz = location.z;
//dpl_Effect(dpl_effect_type_particlestart, my_DCS, &tempParticle);
// std::cout<<"psfx identifier used was "<<tempParticle.identifier<<"\n";
}
//
//#############################################################################
// DPLIndependantEffect lets you start up an effect in absolute space that is
// run to termination automatically by the renderer.
//#############################################################################
//
void
DPLRenderer::DPLIndependantEffect(
Point3D location,
int effect_number,
dpl_DCS *my_DCS, // Optional DCS to link to
int subid)
{
//STUBBED: DPL RB 1/14/07
if(effect_number >= 1000)
{
effect_number -= 1000;
if(effect_number < 0 || effect_number > MAX_PSFX_COUNT-1)
{
Fail("PSFX id number was not in the allowed range");
}
// DPLIndependantPFX(location,myPSFXDescriptons[effect_number],my_DCS,subid);
// find a free emitter
ParticleEmitter *emitter = NULL;
for (int i=0; i<MAX_INDIE_EMITTERS; ++i)
{
if (!myPSFXEmitters[i].IsActive())
{
emitter = &myPSFXEmitters[i];
break;
}
}
if (emitter != NULL)
{
emitter->SetEffect(&myPSFXDescriptons[effect_number]);
emitter->SetPosition(location.x, location.y, location.z);
emitter->Start();
}
return;
}
//dpl_EXPLOSION_EFFECT_INFO my_explosion;
//my_explosion.type = effect_number;
//my_explosion.x = location.x;
//my_explosion.y = location.y;
//my_explosion.z = location.z;
//dpl_Effect ( dpl_effect_type_explosion, my_DCS, &my_explosion );
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//
// Un-stubbed for the Winners Circle, which asks for 45 degrees to get all
// eight racers in frame. The DPL body below it built a dpl_View; the D3D9
// path builds the same two matrices DPLReadINIPage does and pushes them,
// because mProjectionMatrix only reaches the device on the LaunchingMission
// edge and on the sky-pass restore - rebuilding alone would not show until
// the next frame.
//
// Pass degrees, as the INI does. RPDPL.INI ships viewangle=40, which is what
// to hand back afterwards - not the 30 in the constructor, which the INI
// overwrites at load.
//
void DPLRenderer::SetViewAngle(Degree new_angle)
{
Check(this);
viewAngle = (float) new_angle.angle;
Radian view_angle;
view_angle = new_angle;
// tan(half angle): the culling helper GetViewRatio() reads this, and
// nothing has written it since the DPL body was stubbed out
viewRatio = (float) tan(view_angle / 2.0f);
aspectRatio = (float) y_size / (float) x_size;
// pillarboxed shots render into a narrower viewport, so the projection
// has to use that shape or the scene comes out squashed rather than
// cropped
float projection_aspect = (mPresentationAspect > 0.0f)
? mPresentationAspect
: ((float) x_size / (float) y_size);
D3DXMatrixIdentity(&mProjectionMatrix);
D3DXMatrixPerspectiveFovLH(
&mProjectionMatrix,
viewAngle * (PI / 180.0f),
projection_aspect,
clipNear,
clipFar);
mProjectionMatrix(0, 0) *= -1; // handedness flip - the view is RH
mDecalProjectionMatrix = mProjectionMatrix;
mDecalProjectionMatrix._33 -= mDecalEpsilon;
if (mDevice != NULL)
{
mDevice->SetTransform(D3DTS_PROJECTION, &mProjectionMatrix);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// The presentation camera. DPLEyeRenderable writes D3DTS_VIEW from the
// viewpoint entity every frame; ExecuteImplementation reads it straight back
// out of the device and hands it to every draw call. Overriding it between
// those two points is enough to move the shot without touching the eye
// renderable or building a CameraShip.
//
void
DPLRenderer::SetPresentationCamera(const Point3D &eye, const Point3D &look_at)
{
Check(this);
D3DXVECTOR3 from((float) eye.x, (float) eye.y, (float) eye.z);
D3DXVECTOR3 at((float) look_at.x, (float) look_at.y, (float) look_at.z);
//
// LookAt*LH*, to match the LH projection. The two differ by exactly the
// sign of the view direction, and RH here points the camera the opposite
// way: ask to look down at the stand and you get sky behind you.
//
// The engine's own eye renderable does use RH, and is right to - its
// forward and up come out of the entity matrix already in that
// convention. A camera aimed with plain world coordinates does not, so
// it wants the handedness the projection was built with.
//
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMatrixLookAtLH(&mPresentationView, &from, &at, &up);
mPresentationCamera = True;
}
void
DPLRenderer::ClearPresentationCamera()
{
Check(this);
mPresentationCamera = False;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Give the pilot a vehicle to look at. Their own is built insideEntity - a
// cockpit and no hull - so on the podium they would be the one empty spot.
// outsideEntity is what builds the exterior, and the renderables for it are
// added to what is already there.
//
void
DPLRenderer::ShowViewpointFromOutside()
{
Check(this);
Entity *viewpoint = GetLinkedEntity();
if (viewpoint == NULL)
{
DEBUG_STREAM << "WinnersCircle: no viewpoint entity to turn around\n"
<< std::flush;
return;
}
//
// Add the exterior alongside what is already there rather than tearing
// the entity down and rebuilding it. The teardown path is safe for
// scenery going out of range, but not for the viewpoint entity: it is
// never uninteresting, the eye renderable goes with it, and doing it
// mid-mission stops the scene rendering altogether.
//
// This is what NotifyOfNewInterestingEntity does, minus the teardown
// and with the view type forced.
//
Check(application);
ResourceFile *resource_file = application->GetResourceFile();
Check(resource_file);
ResourceDescription *video_resource = resource_file->SearchList(
viewpoint->GetResourceID(),
ResourceDescription::VideoModelResourceType);
if (video_resource == NULL)
{
DEBUG_STREAM << "WinnersCircle: own vehicle has no exterior model\n"
<< std::flush;
return;
}
video_resource->Lock();
MakeEntityRenderables(viewpoint, video_resource, outsideEntity);
video_resource->Unlock();
DEBUG_STREAM << "WinnersCircle: own vehicle given an exterior\n"
<< std::flush;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Come up out of the black. SetFogStyle(winnersCircleFogStyle) has already
// put the target fog in place, so remember it and ramp toward it - the same
// multiply the end-of-mission fade uses, run the other way.
//
void
DPLRenderer::StartPresentationFadeIn(Scalar seconds)
{
Check(this);
mPresentationFogRed = fogRed;
mPresentationFogGreen = fogGreen;
mPresentationFogBlue = fogBlue;
mPresentationFogNear = currentFogNear;
mPresentationFogFar = currentFogFar;
mPresentationFadeTime = (seconds > 0.0f) ? seconds : 0.01f;
mPresentationFadeEnd = Now();
mPresentationFadeEnd += mPresentationFadeTime;
}
//
//#############################################################################
// Startup the implementation of the Division video renderer
//#############################################################################
//
void
DPLRenderer::LoadMissionImplementation(Mission *mission)
{
Check(this);
Tell("DPLVideoRenderer::StartImplementation has been called\n");
DPLReadEnvironment(mission);
LoadNameBitmaps();
}
//##############################################################################
// Name Bitmap Support
//
void DPLRenderer::SortAndReloadNameBitmaps()
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get the Entity Group of Players
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EntityGroup *player_group = application->GetEntityManager()->FindGroup("Players");
ChainIteratorOf<Node*> player_iterator(player_group->groupMembers);
Player *current_player;
while ((current_player = (Player*)player_iterator.ReadAndNext()) != NULL)
{
BitMap *name_bitmap = application->GetCurrentMission()->GetLargeNameBitmap(current_player->playerBitmapIndex);
if (name_bitmap && current_player->IsScoringPlayer())
{
int index = current_player->playerRanking + 1;
if (mNameTextures[index])
mNameTextures[index]->Release();
mDevice->CreateTexture(128, 32, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &mNameTextures[index], NULL);
LoadBitSliceTexture(name_bitmap, mNameTextures[index]);
}
}
LoadOrdinalBitmaps();
BindNamePlates();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Put the callsigns on the Winners Circle plates.
//
// mNameTextures is indexed by finishing place (rank + 1), which is how the
// signs are numbered, so the plate beside each spot names whoever is standing
// on it. The plates are static geometry and have already been merged into the
// consolidated mesh by now, so it is the consolidated draw ops that have to be
// re-pointed - the objects they were built from are no longer drawn.
//
void DPLRenderer::BindNamePlates()
{
int name_count = (int) (sizeof(mNameTextures) / sizeof(mNameTextures[0]));
int bound = 0;
int found = 0;
std::list<d3d_OBJECT*>::const_iterator iter;
for (iter = mConsolidatedStaticObjects.begin();
iter != mConsolidatedStaticObjects.end(); ++iter)
{
d3d_OBJECT *object = *iter;
if (object == NULL)
{
continue;
}
for (int op = 0; op < object->GetDrawOpCount(); ++op)
{
L4DRAWOP *draw_op = object->GetDrawOp(op);
int plate = d3d_OBJECT::NamePlateFor(draw_op->texture.texture);
if (plate == 0)
{
continue;
}
++found;
if (plate < name_count && mNameTextures[plate] != NULL)
{
draw_op->texture.texture = mNameTextures[plate];
++bound;
}
}
}
DEBUG_STREAM << "NamePlates: " << bound << " of " << found
<< " plates given a callsign\n" << std::flush;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void DPLRenderer::LoadOrdinalBitmaps()
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Check if we have a Director on this machine,
// if so, create load the ordinal Bitmaps only
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//
if (application->GetMissionPlayer()->GetInstance() == CameraDirector::MasterInstance &&
application->GetMissionPlayer()->IsDerivedFrom(*CameraDirector::GetClassDerivations()))
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Make Sure index is in the right place
// in case < 8 players!!!!
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int index = 0;
for(int ii=1; ii<5; ++ii)
{
//
//~~~~~~~~~~~~~~~~~~
// Index Starts at 1
//~~~~~~~~~~~~~~~~~~
//
BitMap *ordinal_bitmap = application->GetCurrentMission()->GetOrdinalBitmap(ii);
if (mOrdinalTextures[index])
mOrdinalTextures[index]->Release();
mDevice->CreateTexture(128, 32, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &mOrdinalTextures[index], NULL);
LoadBitSliceTexture(ordinal_bitmap, mOrdinalTextures[index]);
++index;
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
unsigned int*
DPLRenderer::MakeBitSliceStorage()
{
Check(this);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Allocate some temporary memory
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
uint32 *worst_case_texels = new uint32[128*64];
if(!worst_case_texels)
{
Fail("Could not allocate RAM for worst case texels\n");
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Zero Out Memory so Empty Texture space is Black
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
for(int ii=0;ii<8192;++ii)
{
worst_case_texels[ii] = 0;
}
return worst_case_texels;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void DPLRenderer::LoadNameBitmaps()
{
int player_count = application->GetCurrentMission()->GetPlayerCount();
for (int ii=0; ii<player_count; ++ii)
{
BitMap *name_bitmap = application->GetCurrentMission()->GetLargeNameBitmap(ii + 1);
if (name_bitmap)
{
if (mNameTextures[ii])
mNameTextures[ii]->Release();
HRESULT hr;
V(mDevice->CreateTexture(128, 32, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &mNameTextures[ii], NULL));
LoadBitSliceTexture(name_bitmap, mNameTextures[ii]);
}
}
LoadOrdinalBitmaps();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DPLRenderer::ShutdownImplementation()
{
//STUBBED: DPL RB 1/14/07
// Tell("DPLVideoRenderer::StopImplementation has been called\n");
// dpl_EnableSyncOnCreate();
// SChainIteratorOf<InnerProjectileRenderable*> projectile_iterator(&projectile_list);
// TreeIteratorOf<DPLObjectCacheLine*, CString> cache_iterator(&dplObjectCacheSocket);
//#if defined(LAB_ONLY)
// std::cout<<"max projectiles "<<projectile_iterator.GetSize()<<"\n";
// std::cout<<"max cached objects "<<cache_iterator.GetSize()<<"\n";
//#endif
//// std::cout<<"DPL renderer has "<<dpl_FreeMemory()<<" free\n";
}
void
DPLRenderer::SuspendImplementation()
{
Tell("DPLVideoRenderer::SuspendImplementation has been called\n");
}
void
DPLRenderer::ResumeImplementation()
{
Tell("DPLVideoRenderer::ResumeImplementation has been called\n");
}
//-----------------------------------------------------------------------------
//--------------------------Id's for psfx effects---------------------------------
//-----------------------------------------------------------------------------
int
DPLRenderer::GetUniqueID()
{
myUniqueID = (myUniqueID + 1) & 0x0000ffff;
return(myUniqueID);
}
//-----------------------------------------------------------------------------
//--------------------------MUNGA caching of objects---------------------------
//-----------------------------------------------------------------------------
dpl_OBJECT*
DPLRenderer::GetCachedObject(
const CString &object_name) // Name of the object we want to get
{
dpl_OBJECT
*object_pointer;
//
// Get this object from the cache by name
//
DPLObjectCacheLine *my_cache_line;
if ((my_cache_line = dplObjectCacheSocket.Find(object_name)) == NULL)
return NULL;
//
// Remove the cache line from the cache
//
object_pointer = my_cache_line->objectPointer;
delete my_cache_line;
//
// Return the object pointer
//
return(object_pointer);
}
void
DPLRenderer::PutCachedObject(
const CString &object_name, // Name of the object we will cache
dpl_OBJECT *object_pointer) // pointer to the object being cached
{
//
// Create the cache line data structure
//
#if 0
typedef PlugOf<dpl_OBJECT*> DPLObjectCacheLine;
DPLObjectCacheLine *my_cache_line = new DPLObjectCacheLine(object_pointer);
#endif
DPLObjectCacheLine *my_cache_line =
new DPLObjectCacheLine(
object_name,
object_pointer);
Register_Object(my_cache_line);
//
// Store this cache line in the cache
//
dplObjectCacheSocket.AddValue(my_cache_line, object_name);
}
//-----------------------------------------------------------------------------
//--------------------------Projectile Speedup---------------------------------
//-----------------------------------------------------------------------------
InnerProjectileRenderable*
DPLRenderer::GetProjectile(
d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
bool isDeathZone) // DPL Zone this stuff will live in (for culling)
{
//STUBBED: DPL RB 1/14/07
//InnerProjectileRenderable
// *return_projectile;
//dpl_INSTANCE
// *temp_instance;
////
//// Are there projectiles in the list?
////
//SChainIteratorOf<InnerProjectileRenderable*> iterator(&projectile_list);
//if ((return_projectile = iterator.GetCurrent()) != NULL)
//{
// // Yes, remove it from the list set it's instance and return it
// iterator.Remove();
// temp_instance = return_projectile->GetInstance();
// if(graphical_object != dpl_GetInstanceObject(temp_instance))
// {
// dpl_SetInstanceObject (temp_instance, graphical_object);
// dpl_FlushInstance (temp_instance);
// }
// return(return_projectile);
//}
//else
//{
// // no, make a new one and return that
InnerProjectileRenderable *projectile =
new InnerProjectileRenderable(
graphical_object, // object to hang on the DCS, may be a list later <NULL>
isDeathZone); // DPL Zone this stuff will live in (for culling)
return(projectile);
//}
}
void
DPLRenderer::ReleaseProjectile(
InnerProjectileRenderable* inner_projectile)
{
// add the projectile back to the list
//projectile_list.Add(inner_projectile);
}
//-----------------------------------------------------------------------------
//--------------------------Joint to DCS translator----------------------------
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DPLJointToDCSTranslator is a class that contains a joint number to dcs
// pointer translation table. This lets a renderer find the dcs that goes
// with a particular segment.
//
DPLJointToDCSTranslator::DPLJointToDCSTranslator(
Entity *entity, // The entity to translate
dpl_DCS *dcs_array[]) // Array of DCS's to translate
{
JointedMover
*my_jointed_mover;
//
// Make sure this is a jointed mover, then cast the entity pointer over
//
if (entity->IsDerivedFrom(*JointedMover::GetClassDerivations()))
{
my_jointed_mover = (JointedMover*)entity;
}
else
{
Fail("DPLJointToDCSTranslator was called on an entity NOT a JointedMover\n");
}
//
// Find out how many joints the entity has, then allocate enough RAM for a
// DCS pointer to every joint.
//
JointSubsystem* joint_subsystem = my_jointed_mover->GetJointSubsystem();
Check(joint_subsystem);
translation_array = new (dpl_DCS(*[joint_subsystem->GetJointCount()]));
Register_Pointer(translation_array);
//
// Setup to iterate the entity segment table
//
EntitySegment::SegmentTableIterator segment_iterator(my_jointed_mover->segmentTable);
EntitySegment *current_segment;
while ((current_segment = segment_iterator.ReadAndNext()) != NULL)
{
//
// For each segment, see if it has a joint index, if it does, put the
// DCS for that joint into the translation array
//
Check(current_segment);
int joint_index = current_segment->GetJointIndex();
if(joint_index != -1)
{
translation_array[joint_index] = dcs_array[current_segment->GetIndex()];
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DPLJointToDCSTranslator::~DPLJointToDCSTranslator()
{
Unregister_Pointer(translation_array);
delete[] translation_array;
translation_array = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Logical
DPLJointToDCSTranslator::TestInstance() const
{
return True;
}
//-----------------------------------------------------------------------------
//--------------------------Resource creation support--------------------------
//-----------------------------------------------------------------------------
//#############################################################################
//############# DPLRenderer::CreateModelVideoStreamResource #############
//#############################################################################
ResourceDescription::ResourceID
DPLRenderer::CreateModelVideoStreamResource(
ResourceFile *resource_file,
const char *model_name,
NotationFile *model_file,
const ResourceDirectories * /*directories*/
)
{
ResourceDescription *res_description =
resource_file->FindResourceDescription(
model_name,
ResourceDescription::VideoModelResourceType
);
if (res_description == NULL)
{
NameList *video_entries = model_file->MakeEntryList("video");
if (video_entries != NULL)
{
Register_Object(video_entries);
//----------------------------------------------
// parse video model data and store in resource
//----------------------------------------------
Tell("Building video resource for model '" << model_name << "'.\n");
NameList::Entry
*entry,
*next_entry;
const char
*entry_name,
*entry_pointer,
*argument_start;
int
length;
char
argument[40],
*argument_pointer;
L4VideoObject::ResourceType
resource_type;
Enumeration //(see L4VideoObject::RendererModes)
renderer_modes;
enum
{
parsing_filename,
seeking_switch,
parsing_switch,
parsing_billboard
} state;
L4VideoObject
*video_object;
L4VideoObjectWrapper
*video_wrapper;
ChainOf<L4VideoObjectWrapper*>
video_chain(NULL);
char
*video_stream,
*video_pointer;
int
object_count;
long
object_size,
stream_length;
//------------------------------------------------
// parse each entry in [video] page of model file
//------------------------------------------------
next_entry = video_entries->GetFirstEntry();
while (next_entry)
{
entry = next_entry;
Check(entry);
next_entry = entry->GetNextEntry(); // so 'continue' works
entry_name = entry->GetName();
if (entry_name && *entry_name)
{
//--------------------------------------------
// could be "skeleton" or "object" or comment
//--------------------------------------------
if (strcmp(entry_name, "object") == 0)
{
resource_type = L4VideoObject::Object;
}
else if (strcmp(entry_name, "rubble") == 0)
{
resource_type = L4VideoObject::Rubble;
}
else if (strcmp(entry_name, "skeleton") == 0)
{
resource_type = L4VideoObject::Skeleton;
}
else if (Comment_Line(entry_name))
{
// do nothing - skip comments
continue;
}
else if (strncmp(entry_name, "skeleton", 8) == 0)
{
// do nothing - skip temporary skeleton entries
continue;
}
else if (strncmp(entry_name, "destroyed", 9) == 0)
{
// do nothing - skip destroyed skeleton entries
continue;
}
else if (strncmp(entry_name, "dzm", 3) == 0)
{
// do nothing - skip damage zone material entries
continue;
}
else
{
// resource_type = L4VideoObject::Unknown;
DEBUG_STREAM << "Unknown entry '" << entry_name <<
"' in model '" << model_name << "' ignored." << std::endl;
continue;
}
//---------------------------------
// parse and process each argument
//---------------------------------
entry_pointer = entry->GetChar();
while (entry_pointer && *entry_pointer)
{
//-------------------------
// skip leading whitespace
//-------------------------
while (*entry_pointer != '\0' && isspace(*entry_pointer))
{
++entry_pointer;
}
//---------------------------
// exit loop if nothing left
//---------------------------
if (*entry_pointer == '\0')
{
break;
}
//-------------------------------------------
// parse the next argument into local buffer
//-------------------------------------------
argument_start = entry_pointer;
while (*entry_pointer != '\0' && !isspace(*entry_pointer))
{
++entry_pointer;
}
length = entry_pointer - argument_start;
Verify( length < sizeof(argument) );
strncpy(argument, argument_start, length);
argument[length] = '\0';
//----------------------
// parse local argument
//----------------------
argument_pointer = argument;
renderer_modes = L4VideoObject::Normal;
state = parsing_filename;
while (*argument_pointer != '\0')
{
switch (state)
{
case parsing_filename:
switch (*argument_pointer)
{
#if 0
case '.':
if ((resource_type == L4VideoObject::Object) ||
(resource_type == L4VideoObject::Rubble))
{
*argument_pointer = '\0'; // terminate filename
state = seeking_switch;
}
break;
#endif
case '/':
*argument_pointer = '\0'; // terminate filename
state = parsing_switch;
break;
default:
// later check for valid filename character...
break;
}
break;
case seeking_switch:
if (*argument_pointer == '/')
{ state = parsing_switch; }
break;
case parsing_switch:
switch (*argument_pointer)
{
case 'b':
case 'B':
state = parsing_billboard;
break;
case 'i':
case 'I':
renderer_modes |= L4VideoObject::IntersectImmune;
state = seeking_switch;
break;
default:
state = seeking_switch;
break;
}
break;
case parsing_billboard:
switch (*argument_pointer)
{
case 'x':
case 'X':
renderer_modes |= L4VideoObject::BillboardXAxis;
break;
case 'y':
case 'Y':
renderer_modes |= L4VideoObject::BillboardYAxis;
break;
case 'z':
case 'Z':
renderer_modes |= L4VideoObject::BillboardZAxis;
break;
case '/':
state = parsing_switch;
break;
default:
state = seeking_switch;
break;
}
break;
// no default:
}
++argument_pointer;
}
//-----------------------------------------------
// create video resource object and add to chain
//-----------------------------------------------
video_object =
new L4VideoObject(
argument,
resource_type,
renderer_modes
);
Register_Pointer(video_object); // not _Object!
video_wrapper =
new L4VideoObjectWrapper(
video_object,
True // delete object when done
);
Register_Object(video_wrapper);
//Tell(" adding video object '"<<argument<<"' type ");
//Tell(resource_type<<" mode 0x"<<std::hex<<renderer_modes<<"\n");
video_chain.Add(video_wrapper);
} // arguments processed for this entry
}
} // all arguments processed
//----------------------------------------------
// convert chain of video resources into stream
//----------------------------------------------
ChainIteratorOf<L4VideoObjectWrapper*>
video_iterator(video_chain);
object_count = video_iterator.GetSize();
object_size = sizeof(L4VideoObject);
stream_length = sizeof(int) + object_count * object_size;
video_stream = new char[stream_length];
Register_Pointer(video_stream);
video_pointer = video_stream;
*((int *)video_pointer) = object_count;
video_pointer += sizeof(int);
Tell(" count " <<std::dec<< object_count << ", resource size " << stream_length << "\n");
while ((video_wrapper = video_iterator.ReadAndNext()) != NULL)
{
video_object = video_wrapper->GetVideoObject();
if (!stricmp(video_object->GetObjectFilename(), "bp1.bgf"))
video_pointer += 1 - 1;
*((L4VideoObject *)video_pointer) = *video_object;
video_pointer += object_size;
}
//--------------------------------------------------
// store stream of video resources in resource file
//--------------------------------------------------
res_description =
resource_file->AddResource(
model_name,
ResourceDescription::VideoModelResourceType,
1,
ResourceDescription::Preload,
video_stream,
stream_length
);
//--------------------------
// release allocated memory
//--------------------------
// video_chain
L4VideoObjectWrapper::DeleteVideoObjectChain(&video_chain);
// video_stream
Unregister_Pointer(video_stream);
delete video_stream;
// video_entries
Unregister_Object(video_entries);
delete video_entries;
}
else
{
//-------------------------------
// no [video] page in model file
//-------------------------------
return (ResourceDescription::NullResourceID);
}
}
return (res_description->resourceID);
}
//===========================================================================//