Eight byte-identical field stacks from night 6, all one player, all in an
Owens: ParticleEngine::Destroy +0x11, access=0 target=0x0, from the plain
per-frame render path. Nothing in the stack touches weapons or the Owens.
Conn Man's Surface Pro 9 (Iris Xe, 128 MB shared) is simply the only GPU in
the fleet that ever actually LOSES the D3D9 device -- his two-trigger
missile+laser bursts are what provoke the timeout, not what crashes.
What crashed is our device-loss handling, which was wrong three ways at once,
in two inline copies (the scene Present and the wait-screen Present):
1. On D3DERR_DEVICELOST it called Reset() IMMEDIATELY. Reset on a
still-lost device ALWAYS fails, and V() only logs. There was no
TestCooperativeLevel gate at all.
2. It then ran ParticleEngine::Initialize against the lost device. The
creates fail there and NULL their out-params -- proven, not assumed:
the bench repro faults at target=0x0, not at a dangling address.
3. The next lost frame called ParticleEngine::Destroy again, which
Release()d those NULLs blind. Read of vtable at 0x0. Dead.
So: lost frame 1 tears down and leaves NULLs, lost frame 2 crashes. Two
frames, every time, deterministic -- which is exactly why all 8 field stacks
are byte-identical.
Reproduced before fixing. BT_DEVICELOST_TEST=<frame>,crashrepro runs the
field sequence on the bench; on the unfixed build it died at Destroy +0x11,
access=0 target=0x0, and symbolized to the same four frames as the field
logs. Same shape, same offsets-modulo-hook. That run also proved the
out-param-nulling assumption the whole diagnosis rested on.
The fix -- one shared DPLRenderer::BTResetLostDevice() replacing both inline
copies:
- Destroy() is idempotent and null-safe, and nulls after release.
- Reset() is gated on TestCooperativeLevel() != D3DERR_DEVICELOST; while
the driver still says lost, skip the frame and retry.
- The Reset HRESULT is checked; on failure, log and retry next frame
instead of driving on.
- On success, re-create via the new CreateDeviceObjects(), NOT
Initialize(): Initialize memsets the installed-effects table, so every
reset that DID succeed silently killed all particle effects for the rest
of the mission. The quieter sibling bug, fixed by the same split.
- Initialize checks its HRESULTs and defends MAXPARTICLES<=0; the draw
paths guard the NULL buffer, and ExecuteParticles keeps draining
particles while the engine is dormant so they cannot pile up.
Verified: the crashrepro shape now logs SURVIVED and play continues; three
forced full loss/reset cycles each log "[render] device reset OK"; a plain
run is assert-free.
Found while verifying, worth its own line: VIDEO\particles.png has NEVER
existed -- not in the tree, not in BTL4.RES, not anywhere in git history.
The texture load has failed on every machine since the engine was written,
and every billboard particle ever rendered was untextured quads via
SetTexture(0, NULL). RenderParticles deliberately does NOT gate on the
texture -- that would disable all particles everywhere; untextured IS the
shipped look. Filed separately; a real particle sheet is a content task.
The field verification that counts is Conn Man flying his exact crash
loadout on this build: instead of a dead process he should see at worst a
brief hitch and "[render] device reset OK" in his log. #35 stays open until
that happens.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
625 lines
20 KiB
C++
625 lines
20 KiB
C++
#pragma once
|
|
|
|
#include "..\munga\vidrend.h"
|
|
#include "..\munga\rotation.h"
|
|
#include "..\munga\reticle.h"
|
|
#include "..\munga\graph2d.h"
|
|
#include "..\munga\simulate.h"
|
|
#include "l4vidrnd.h"
|
|
#include "..\munga\tree.h"
|
|
#include "..\munga\table.h"
|
|
#include "l4d3d.h"
|
|
#include <string>
|
|
#include <hash_map>
|
|
#include <vector>
|
|
|
|
using namespace std;
|
|
using namespace stdext;
|
|
|
|
//STUBBED: DPL RB 1/14/07
|
|
//once the stubs are removed, the following can be removed
|
|
#define char8 unsigned char
|
|
|
|
// RB 1/14/07
|
|
//#include <dpl\dpl.h>
|
|
//#include <dpl\dpl_2d.h>
|
|
#include <D3DX9.h>
|
|
#include <D3DX9math.h>
|
|
|
|
class NotationFile;
|
|
|
|
#define INTERSECT_ALL (0xFFFFFFFF)
|
|
|
|
//##########################################################################
|
|
// Declaration of dpl callback function that performs in-place text
|
|
// substitution on all material names before they are looked up.
|
|
// There must be at least MATERIAL_NAME_LENGTH bytes available at source!
|
|
//
|
|
#define MATERIAL_NAME_BUFFER_LENGTH 256
|
|
|
|
char*
|
|
substituteMaterial(char *source);
|
|
|
|
// dpl material-name callback registry (FUN_0049664c): install/clear the
|
|
// per-load substitution hook; dpl_ApplyMaterialNameCallback runs the installed
|
|
// hook over a name (identity when none installed). Consumed by the BGF
|
|
// loader's material resolver.
|
|
void dpl_SetMaterialNameCallback(char *(*callback)(char *source));
|
|
std::string dpl_ApplyMaterialNameCallback(const std::string &name);
|
|
|
|
void loadTables();
|
|
const char* opMaterialName(const char *fileName, int opId);
|
|
|
|
struct ReplacementMaterialData
|
|
{
|
|
float r, g, b;
|
|
string texName;
|
|
};
|
|
|
|
hash_map<string, hash_map<int, string>> *gOpNames;
|
|
hash_map<string, ReplacementMaterialData> *gReplacementData;
|
|
|
|
//##########################################################################
|
|
// This structure is attached to DPL nodes so we can put information in them
|
|
// on what entity the node is part of and what damage zone it belongs to.
|
|
//
|
|
#define MAX_DZ_NAME_LENGTH 25
|
|
|
|
struct dpl_tracker
|
|
{
|
|
Entity
|
|
*This_Entity; // The entity this is part of
|
|
char
|
|
dz_name[MAX_DZ_NAME_LENGTH]; // this is temporary, to make testing easier
|
|
int
|
|
Damage_Zone_Number; // number of this damage zone
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//--------------------------DPL video resource object--------------------------
|
|
//-----------------------------------------------------------------------------
|
|
//##########################################################################
|
|
//########################## L4VideoObject ###########################
|
|
//##########################################################################
|
|
|
|
#define MAX_OBJECT_FILENAME_LENGTH 15
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// This class gets stored in a resource so it is derived from nothing.
|
|
//
|
|
class L4VideoObject
|
|
{
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Construction, Destruction and testing
|
|
//
|
|
public:
|
|
enum ResourceType
|
|
{
|
|
Unknown,
|
|
Skeleton,
|
|
Object,
|
|
Rubble,
|
|
VidFile
|
|
};
|
|
enum RendererModes // bit flags
|
|
{
|
|
Normal = 0x000,
|
|
BillboardXAxis = 0x001,
|
|
BillboardYAxis = 0x002,
|
|
BillboardZAxis = 0x004,
|
|
BillboardObject = (BillboardXAxis | BillboardYAxis | BillboardZAxis),
|
|
BlinkObject = 0x008,
|
|
IntersectImmune = 0x010
|
|
};
|
|
|
|
// L4VideoObject();
|
|
L4VideoObject(
|
|
const char *filename,
|
|
ResourceType resource_type,
|
|
Enumeration renderer_modes, // RendererModes
|
|
float blink_period = 0.0f,
|
|
float percent_time_on = 0.0f
|
|
);
|
|
~L4VideoObject();
|
|
|
|
const char*
|
|
GetObjectFilename() const
|
|
{ return objectFilename; }
|
|
char*
|
|
GetObjectFilename()
|
|
{ return objectFilename; }
|
|
ResourceType
|
|
GetResourceType() const
|
|
{ return resourceType; }
|
|
Enumeration // RendererModes
|
|
GetRendererModes() const
|
|
{ return rendererModes; }
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Implementations
|
|
//
|
|
// private:
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Private data
|
|
//
|
|
private:
|
|
char
|
|
objectFilename[MAX_OBJECT_FILENAME_LENGTH];
|
|
ResourceType
|
|
resourceType;
|
|
Enumeration // RendererModes
|
|
rendererModes; // bit flags (see RendererModes)
|
|
float
|
|
blinkPeriod, // cycle length in seconds
|
|
percentTimeOn; // percent of cycle on
|
|
};
|
|
|
|
//##########################################################################
|
|
//####################### L4VideoObjectWrapper #######################
|
|
//##########################################################################
|
|
|
|
class L4VideoObjectWrapper:
|
|
public Plug
|
|
{
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Construction, Destruction and testing
|
|
//
|
|
public:
|
|
// L4VideoObjectWrapper();
|
|
L4VideoObjectWrapper(
|
|
L4VideoObject *video_object,
|
|
Logical delete_object = False
|
|
);
|
|
~L4VideoObjectWrapper();
|
|
|
|
L4VideoObject*
|
|
GetVideoObject() const
|
|
{ Check(this); return videoObject; }
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
static int
|
|
BuildVideoObjectChainFromResource(
|
|
ChainOf<L4VideoObjectWrapper*> *video_chain,
|
|
ResourceDescription *video_resource
|
|
);
|
|
static void
|
|
DeleteVideoObjectChain(
|
|
ChainOf<L4VideoObjectWrapper*> *video_chain
|
|
);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Implementations
|
|
//
|
|
// public:
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Private data
|
|
//
|
|
private:
|
|
L4VideoObject
|
|
*videoObject;
|
|
Logical
|
|
deleteObject;
|
|
};
|
|
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
//--------------Actual DPL video renderer class starts below-------------------
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
class DPLObjectCacheLine:
|
|
public Plug
|
|
{
|
|
public:
|
|
DPLObjectCacheLine(
|
|
const CString &object_name,
|
|
dpl_OBJECT *object_ptr)
|
|
{
|
|
objectName = object_name;
|
|
objectPointer = object_ptr;
|
|
};
|
|
|
|
~DPLObjectCacheLine(){};
|
|
|
|
Logical
|
|
TestInstance() const
|
|
{
|
|
Check(&objectName);
|
|
Check_Pointer(objectPointer);
|
|
|
|
return True;
|
|
};
|
|
|
|
CString
|
|
objectName;
|
|
dpl_OBJECT
|
|
*objectPointer;
|
|
};
|
|
|
|
class DPLJointToDCSTranslator:
|
|
public Plug
|
|
{
|
|
public:
|
|
DPLJointToDCSTranslator(
|
|
Entity *entity, // The entity to translate
|
|
dpl_DCS *dcs_array[]); // Array of DCS's to translate
|
|
|
|
~DPLJointToDCSTranslator();
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
int
|
|
DCSCount;
|
|
dpl_DCS
|
|
**translation_array; // array to translate from joint # to DCS*
|
|
};
|
|
|
|
//##########################################################################
|
|
//########################### DPLRenderer ############################
|
|
//##########################################################################
|
|
#define DELAY_DCS_FLUSH_ARRAY_SIZE 100
|
|
#define MAX_PSFX_COUNT 40
|
|
#define MAX_INDIE_EMITTERS 32
|
|
class DPLRenderer :
|
|
public VideoRenderer
|
|
{
|
|
public:
|
|
//
|
|
// Construction, Destruction and test instance declarations
|
|
//
|
|
DPLRenderer(HWND hWnd, unsigned int screenWidth, unsigned int screenHeight, bool fullscreen, InterestType interest_type, InterestDepth depth_calibration);
|
|
~DPLRenderer();
|
|
|
|
virtual vector<MONITORINFO> MonitorsCreateAll(int &monitorCount);
|
|
|
|
Logical TestInstance() const;
|
|
//
|
|
// These routines are the renderer side of the culling system, they are
|
|
// used to setup the stored data on the eyepoint's transformation matrices
|
|
//
|
|
inline Scalar GetCurrentFrameTime() { return(currentFrameTime); } // Returns the time at the start of the frame
|
|
|
|
inline LinearMatrix* GetWorldToEyeMatrix() { return(&worldToEyeMatrix); } // Returns the world to eye matrix (for culling)
|
|
inline Scalar GetViewRatio() { return(viewRatio); } // Returns tan(viewAngle/2.0)
|
|
void SetupCull(); // Sets up the WorldToEyeMatrix each frame
|
|
//
|
|
// These routines manage the renderer's list of renderables that need to be
|
|
// executed each frame. For the moment these routines just blindly add and
|
|
// remove the items from the dplRenderableSocket
|
|
//
|
|
void AddDynamicRenderable(Component *my_renderable);
|
|
void RemoveDynamicRenderable(Component *my_renderable);
|
|
//
|
|
// These routines are used for tracking target frame time
|
|
//
|
|
void ResetStatistics();
|
|
void ReportStatistics();
|
|
//
|
|
// Other renderer stuff
|
|
//
|
|
dpl_ZONE* MakeNewZone();
|
|
|
|
// #35: the one true device-loss recovery -- both Present sites route here.
|
|
// Correct D3D9 protocol: release POOL_DEFAULT resources, then Reset ONLY
|
|
// once TestCooperativeLevel says the device is ready; a Reset while still
|
|
// lost always fails, and the old inline copies drove on past that failure.
|
|
void BTResetLostDevice();
|
|
|
|
void MarkDCSHiearchy(dpl_DCS *root_DCS, Entity *entity);
|
|
void FlushBitSliceTexture(unsigned int *local_storage);
|
|
void LoadBitSliceTexture(BitMap *bitmap_to_load, LPDIRECT3DTEXTURE9 local_storage);
|
|
|
|
void SetViewAngle(Degree new_angle);
|
|
|
|
unsigned int* MakeBitSliceStorage();
|
|
|
|
void SortAndReloadNameBitmaps();
|
|
|
|
void LoadNameBitmaps();
|
|
|
|
void LoadOrdinalBitmaps();
|
|
|
|
void DPLIndependantEffect(Point3D location, // Location of the effect in world space
|
|
int effect_number, // DPL effect number to trigger at this location
|
|
dpl_DCS *my_dcs = NULL,
|
|
int subid = 0); // inserted into third byte of effect id.
|
|
|
|
void DPLIndependantPFX(Point3D location, // Location in space to trigger the effect
|
|
dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // Description of the pfx
|
|
dpl_DCS *my_dcs = NULL, // optional DCS to issue from
|
|
int subid = 0); // inserted into third byte of effect id.
|
|
|
|
void DPLDelayDCSFlush(dpl_DCS *my_dcs); // The DCS we want to remember for later
|
|
|
|
void DPLDoDCSBatchFlush(); // Flush the dcs's remembered by DPLDelayDCSFlush
|
|
|
|
void DPLReportFreeMemory(std::ostream &output); // Report current free memory in card
|
|
|
|
void DPLReportPerfStats(std::ostream &output); // Report performance statistics
|
|
|
|
void DPLToggleWireframe(); // Toggle state of dpl wireframe
|
|
|
|
void DPLTogglePVision(); // Toggle state of dpl pvision
|
|
|
|
void DPLFrameDump(Logical antialias); // Write framedump to targa file
|
|
|
|
InnerProjectileRenderable* 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)
|
|
|
|
void ReleaseProjectile(InnerProjectileRenderable *inner_projectile);
|
|
|
|
int GetUniqueID();
|
|
|
|
dpl_PARTICLESTART_EFFECT_INFO* ReadPSFX(const char *file_name); // Name of the file containing the PSFX description
|
|
|
|
dpl_OBJECT* GetCachedObject(const CString &object_name); // Name of the object we want to get
|
|
|
|
void PutCachedObject(
|
|
const CString &object_name, // Name of the object we will cache
|
|
dpl_OBJECT *object_pointer); // pointer to the object being cached
|
|
|
|
static ResourceDescription::ResourceID CreateModelVideoStreamResource(ResourceFile *resource_file, const char *model_name, NotationFile *model_file, const ResourceDirectories *directories);
|
|
|
|
void CacheExplosionScripts(int script_select); // The script to be cached
|
|
|
|
enum FogStyle
|
|
{
|
|
updateFogSetting,
|
|
noUpdateFogSetting,
|
|
searchLightOnFogStyle,
|
|
searchLightOffFogStyle,
|
|
winnersCircleFogStyle
|
|
};
|
|
|
|
void SetFogStyle(FogStyle my_fog);
|
|
|
|
void GetCurrentFogSettings(float *fogRed, float *fogGreen, float *fogBlue, float *fogNear, float *fogFar);
|
|
void SetCurrentFogLimits(float fogNear, float fogFar);
|
|
|
|
LPDIRECT3DTEXTURE9 GetNameTexture(int playerIndex) { return mNameTextures[playerIndex]; }
|
|
LPDIRECT3DTEXTURE9 GetOrdinalTexture(int rank) { return mOrdinalTextures[rank]; }
|
|
|
|
inline LPDIRECT3DDEVICE9 GetDevice() { return mDevice; }
|
|
inline LPD3DXMATRIXSTACK GetMatrixStack() { return m_MatrixStack; }
|
|
inline void AddRenderable(HierarchicalDrawComponent *component) { mRenderables.Add(component); }
|
|
void AddToPassList(d3d_OBJECT *object, int pass);
|
|
void AddStaticObject(d3d_OBJECT *object);
|
|
void RecurseStaticObject(HierarchicalDrawComponent *obj);
|
|
virtual void ConsolidateStaticObjects();
|
|
|
|
inline unsigned int GetWidth() { return x_size; }
|
|
inline unsigned int GetHeight() { return y_size; }
|
|
|
|
inline int *GetSecondaryIndex() { return mSecondaryIndex; }
|
|
inline int *GetAux1Index() { return mAux1Index; }
|
|
inline int *GetAux2Index() { return mAux2Index; }
|
|
|
|
private:
|
|
d3d_OBJECT *ConsolidateSingleObject(LPD3DXMESH *meshes, D3DXMATRIX *transforms, UINT startMesh, UINT meshCount, hash_map<DWORD, hyper> subsetHash, hash_map<hyper, DWORD> hashToOp, vector<L4DRAWOP*> finalOps);
|
|
void 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);
|
|
void DPLRenderer::DPLReadINIPage(NotationFile *master_notation_file, const char *starting_page_name, Mission *mission, Logical debug_print);
|
|
|
|
void DPLRenderer::DPLReadEnvironment(Mission *mission);
|
|
void ShutdownImplementation();
|
|
void SuspendImplementation();
|
|
void ResumeImplementation();
|
|
void ExecuteImplementation(RendererComplexity complexity_update, RendererOrigin::InterestingEntityIterator *iterator);
|
|
void ExecuteIdle();
|
|
|
|
hyper HashAdd(hyper input, char data);
|
|
hyper HashDrawOp(L4DRAWOP *op);
|
|
|
|
//Damn eye renderable is our camera and I hate it
|
|
public:
|
|
DPLEyeRenderable *mCamera;
|
|
float GetCloudRed() { return mCloudRed;}
|
|
float GetCloudGreen() { return mCloudGreen;}
|
|
float GetCloudBlue() { return mCloudBlue;}
|
|
float GetCloudEmitRed() { return mCloudEmitRed; }
|
|
float GetCloudEmitGreen() { return mCloudEmitGreen; }
|
|
float GetCloudEmitBlue() { return mCloudEmitBlue; }
|
|
|
|
void SetCoreRenderStates();
|
|
|
|
//
|
|
// DEBUG(bring-up): BT never ran DPLReadEnvironment, so mProjectionMatrix was
|
|
// uninitialised garbage -> all geometry clipped (black frame). This installs
|
|
// a valid RH perspective projection + bright ambient + fog off so the loaded
|
|
// mech body is visible. Called from BTL4VideoRenderer::LoadMissionImplementation.
|
|
//
|
|
void EnsureValidProjection();
|
|
|
|
//
|
|
// BT (task #20): window-resize aspect fix. The projection aspect was baked
|
|
// from the configured backbuffer size (x_size/y_size); D3D9 then stretches
|
|
// the backbuffer into a resized client area -> fat/skinny distortion.
|
|
// Rebuilds the projection for the live client aspect (called on WM_SIZE via
|
|
// L4NotifyWindowResized).
|
|
//
|
|
void UpdateWindowAspect(int client_w, int client_h);
|
|
|
|
private:
|
|
//
|
|
// Direct3D Required Variables
|
|
//
|
|
LPDIRECT3DDEVICE9 mDevice;
|
|
D3DPRESENT_PARAMETERS mPresentParams;
|
|
// wait-screen overlay cache (ExecuteIdle GDI paint -> StretchRect; the
|
|
// backbuffer refuses GetDC on some drivers). D3DPOOL_DEFAULT -- released
|
|
// at every device Reset site.
|
|
IDirect3DSurface9 *mWaitOverlaySurface = NULL;
|
|
unsigned int x_size;
|
|
unsigned int y_size;
|
|
SChainOf<HierarchicalDrawComponent *> mRenderables;
|
|
d3d_OBJECT *mRenderLists[PASS_TOTAL_COUNT];
|
|
LPD3DXMATRIXSTACK m_MatrixStack;
|
|
D3DXMATRIX mProjectionMatrix;
|
|
D3DXMATRIX mDecalProjectionMatrix;
|
|
float mDecalEpsilon;
|
|
|
|
void FindBestAdapterIndices(bool isWindowed);
|
|
|
|
float mCloudRed, mCloudGreen, mCloudBlue;
|
|
float mCloudEmitRed, mCloudEmitGreen, mCloudEmitBlue;
|
|
|
|
// BT (task #20): the AUTHENTIC scene ambient the DPL environment set from
|
|
// the map's INI page (ambient=, e.g. des_day 0.45 0.4 0.45). Captured so
|
|
// the per-frame render loop re-asserts the real value instead of the
|
|
// bring-up gray floor (0x404040 was ~0.25 -> whole world too dark).
|
|
DWORD mEnvAmbient;
|
|
|
|
// BT (task #20): the INI's objectpath/materialpath/texmappath search dirs,
|
|
// accumulated MOST-SPECIFIC-FIRST across the pages DPLReadEnvironment visits,
|
|
// then pushed to the loader (SetVideoPathPriority) so the day/night variant
|
|
// of a colliding stem is picked correctly.
|
|
std::vector<std::string> mObjectPaths, mMaterialPaths, mTexmapPaths;
|
|
|
|
int *mPrimaryIndex, *mSecondaryIndex, *mAux1Index, *mAux2Index;
|
|
|
|
// these are used for the map rendering
|
|
d3d_OBJECT *mStaticObjectsHead;
|
|
int mStaticObjectsCount;
|
|
std::list<d3d_OBJECT *> mConsolidatedStaticObjects;
|
|
|
|
// name and ordinal texture maps
|
|
LPDIRECT3DTEXTURE9 mNameTextures[MAX_PLAYER_NAMES];
|
|
LPDIRECT3DTEXTURE9 mOrdinalTextures[MAX_PLAYER_NAMES];
|
|
|
|
protected:
|
|
ReticleRenderable *mReticle;
|
|
CameraShipHUDRenderable *mCamShipHUD;
|
|
|
|
void LoadMissionImplementation(Mission *mission);
|
|
|
|
//
|
|
// These variables hold some culling related information
|
|
//
|
|
|
|
LinearMatrix worldToEyeMatrix; // the current world to eye transform for our linked entity
|
|
Scalar currentFrameTime; // the time at the start of renderable execution
|
|
|
|
//
|
|
// These variables are used for tracking target frame time
|
|
//
|
|
unsigned long total_cull,
|
|
total_draw,
|
|
total_pixelplanes,
|
|
total_frame_time,
|
|
target_frame_time,
|
|
frame_count,
|
|
target_frame_count;
|
|
Logical statistics_started;
|
|
Scalar report_time;
|
|
//
|
|
// The rest of the renderer's variables.
|
|
//
|
|
|
|
Time StartSample; // For generating a framerate printout
|
|
|
|
Logical fogUpdating,
|
|
eyeRelative, // True if the eye will be relative to the linked entity origin
|
|
completeCycleNeeded; // True when we are waiting for DPL to be ready for the next frame
|
|
|
|
int myUniqueID, // Generates a unique 16 bit id value for PSFX use
|
|
lastAppState; // For keeping track of what the application is doing
|
|
|
|
float aspectRatio, // aspect ratio of the screen
|
|
FrameCount, // For keeping track of framerate
|
|
// Fog is setup as standard fog used for vehicles without simulated lights
|
|
// and used when a vehicle with lights has them switched on. This setting
|
|
// is replicated into the "noSearchLight" setting so vehicles with lights
|
|
// will always get this setting if the environment doesn't specifically say
|
|
// that headlight simulation will work.
|
|
fogRed, // Fog setting to use when vehicle lights are on
|
|
fogBlue, // This is the default for vehicles with no lights
|
|
fogGreen,
|
|
fogNear,
|
|
fogFar,
|
|
currentFogNear,
|
|
currentFogFar,
|
|
searchLightFogRed, // Fog setting to use when vehicle lights are on
|
|
searchLightFogBlue,
|
|
searchLightFogGreen,
|
|
searchLightFogNear,
|
|
searchLightFogFar,
|
|
noSearchLightFogRed, // Fog setting to use when vehicle lights are off
|
|
noSearchLightFogBlue,
|
|
noSearchLightFogGreen,
|
|
noSearchLightFogNear,
|
|
noSearchLightFogFar,
|
|
clipNear, // Near clipping plane (from INI file)
|
|
clipFar, // Far clipping plane (from INI file)
|
|
backgroundRed, // Background color (from INI file)
|
|
backgroundGreen,
|
|
backgroundBlue,
|
|
viewAngle, // Viewing angle (from INI file)
|
|
viewRatio; // This is tan(viewAngle/2.0f) (handy for culling)
|
|
|
|
dpl_DCS *dplTestEyeDCS; // A DCS we temporarily hook our eye on (for testing)
|
|
|
|
void MakeEntityRenderables(Entity *this_entity, // The entity we are dealing with
|
|
ResourceDescription *model_resource, // Pointer to the video resource
|
|
ViewFrom type); // Type of reference (inside/outside...etc.)
|
|
|
|
dpl_VIEW *dplMainView; // The DPL view we create at the beginning and use for our eye
|
|
|
|
dpl_ZONE *dplDeathZone, // The DPL zone that holds our vehicle (for death effect)
|
|
*dplMainZone; // The DPL zone that holds the rest of the world
|
|
|
|
Reticle *vehicleReticle; // Pointer to our vehicle's reticle if one exists.
|
|
|
|
dpl_DCS *delayDCSFlushArray[DELAY_DCS_FLUSH_ARRAY_SIZE+1];
|
|
int delayedDCSCount;
|
|
INDIE_EFFECT myPSFXDescriptons[MAX_PSFX_COUNT];
|
|
ParticleEmitter myPSFXEmitters[MAX_INDIE_EMITTERS];
|
|
//
|
|
// This information is captured from the pickpoint when it is enabled
|
|
//
|
|
dpl_INSTANCE *dplHitInstance;
|
|
dpl_DCS *dplHitDCS;
|
|
dpl_GEOGROUP *dplHitGeoGroup;
|
|
dpl_GEOMETRY *dplHitGeometry;
|
|
//
|
|
// This information holds the list of projectile renderables
|
|
//
|
|
SChainOf<InnerProjectileRenderable*> projectile_list;
|
|
//
|
|
// This holds the list of cached objects
|
|
//
|
|
TreeOf<DPLObjectCacheLine*, CString> dplObjectCacheSocket;
|
|
//
|
|
// This holds the list of jointed mover DCS tables
|
|
//
|
|
TableOf<DPLJointToDCSTranslator*, RegisteredClassMemoryAddress> dplJointToDCSTranslatorSocket;
|
|
//
|
|
// This chain contains the list of active renderables
|
|
//
|
|
SChainOf<Component*> dplRenderableSocket;
|
|
|
|
public:
|
|
//
|
|
// Store Lights for Later Revision
|
|
//
|
|
// dpl_LIGHT *ambientLight;
|
|
D3DLIGHT9 *sceneLight; // Array of all the lights
|
|
|
|
dpl_DCS **sceneLightDCS; // Array of DCS's for Lights
|
|
|
|
int sceneLightCount;
|
|
|
|
//static UserHeap *DPLHeap;
|
|
};
|
|
|
|
extern LPDIRECT3D9 gD3D;
|