www.pudn.com > Falcon.zip > AcmiTape.h


#ifndef _ACMITAPE_H_ 
#define _ACMITAPE_H_ 
 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
 
#include "FalcMesg.h" 
 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
 
#define		MAX_ENTITY_CAMS	50 
 
#define ACMI_VERSION 2 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
 
class ACMITape; 
class SimBaseClass; 
class DrawableTrail; 
class DrawableBSP; 
class Drawable2D; 
class RViewPoint; 
class RenderOTW; 
class DrawableTracer; 
class SfxClass; 
 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
 
 
#define ACMI_LABEL_LEN 15 
 
// this structure will hold the in-memory, Sim representation for the 
// entity.  IOW base class, drawable objs, etc... 
typedef struct  
{ 
	SimBaseClass *objBase; 
	DrawableTrail *objTrail; 
 
	int			flags; 
 
	// object orientation 
	float		x; 
	float		y; 
	float		z; 
	float		yaw; 
	float		pitch; 
	float		roll; 
 
	// average speed between 2 positions 
	float		aveSpeed; 
	float		aveTurnRate; 
	float		aveTurnRadius; 
 
	// for trails, the start and end times 
	float		trailStartTime; 
	float		trailEndTime; 
 
	// missiles need engine glow drawables 
	DrawableBSP  *objBsp1; 
	DrawableBSP  *objBsp2; 
 
	// for flare need a glowing sphere 
	Drawable2D  *obj2d; 
 
	// for wing tip trails 
	int			  wtLength; 
	DrawableTrail *wlTrail; 
	DrawableTrail *wrTrail; 
 
	// for features we may need an index to the lead component and 
	// the slot # that was in the camp component list (for bridges, bases...) 
	long		  leadIndex; 
	int			  slot; 
 
} SimTapeEntity; 
 
/* 
** This struct holds info necessary for handling active tracer events 
*/ 
typedef struct 
{ 
	float		x; 
	float		y; 
	float		z; 
	float		dx; 
	float		dy; 
	float		dz; 
	DrawableTracer *objTracer; 
} TracerEventData; 
 
 
/* 
** Each active event will have one of these in a chain 
*/ 
typedef struct _ActiveEvent 
{ 
	long		eventType; 
	long		index; 
	float		time; 
	float		timeEnd; 
	void		*eventData; 
	struct _ActiveEvent *next; 
	struct _ActiveEvent *prev; 
} ActiveEvent; 
 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
// 
// These are the headers and data that are used internally for the .vhs format. 
// These use offsets instead of pointers so that we can memory map them. 
// All offsets are from the start of the file!!!. 
 
//////////////////////////////////////////////////////////////////////////////// 
// 
// Header for the tape file. 
 
#pragma pack (push, pack1, 1) 
typedef struct  
{ 
	long		fileID; 
	long		fileSize; 
	long		numEntities; 
	long		numFeat; 
	long 		entityBlockOffset; 
	long 		featBlockOffset; 
	long		numEntityPositions; 
	long		timelineBlockOffset; 
	long		firstEntEventOffset; 
	long		firstGeneralEventOffset; 
	long		firstEventTrailerOffset; 
	long		firstTextEventOffset; 
	long		firstFeatEventOffset; 
	long		numEvents; 
	long		numEntEvents; 
	long		numTextEvents; 
	long		numFeatEvents; 
	float		startTime; 
	float		totPlayTime; 
	float 		todOffset; 
} ACMITapeHeader; 
#pragma pack (pop, pack1) 
 
//////////////////////////////////////////////////////////////////////////////// 
// 
// Entity data. 
 
#pragma pack (push, pack1, 1) 
typedef struct  
{ 
	long		uniqueID; 
	long		type; 
	long		count; 
	long		flags; 
	 
		#define		ENTITY_FLAG_MISSILE			0x00000001 
		#define		ENTITY_FLAG_FEATURE			0x00000002 
		#define		ENTITY_FLAG_AIRCRAFT		0x00000004 
		#define		ENTITY_FLAG_CHAFF			0x00000008 
		#define		ENTITY_FLAG_FLARE			0x00000010 
 
	// for features we may need an index to the lead component and 
	// the slot # that was in the camp component list (for bridges, bases...) 
	long		leadIndex; 
	int			slot; 
	int			specialFlags; 
 
 
	// Offset from the start of the file to the start of my positional data. 
	long 		firstPositionDataOffset; 
	long 		firstEventDataOffset; 
 
} ACMIEntityData; 
#pragma pack (pop, pack1) 
 
//////////////////////////////////////////////////////////////////////////////// 
// 
// Entity position data. 
 
// enum types for position 
enum 
{ 
	PosTypePos = 0, 
	PosTypeSwitch, 
	PosTypeDOF, 
}; 
 
#pragma pack (push, pack1, 1) 
typedef struct 
{ 
	// Time stamp for the positional data 
	float		time; 
	BYTE		type; 
 
	// dereference based on type 
	union 
	{ 
		// Positional data. 
		struct posTag 
		{ 
			float		x; 
			float		y; 
			float		z; 
			float		pitch; 
			float		roll; 
			float		yaw; 
			long	    radarTarget; 
		} posData; 
		// switch change 
		struct switchTag 
		{ 
			int			switchNum; 
			int			switchVal; 
			int			prevSwitchVal; 
		} switchData; 
		// DOF change 
		struct dofTag 
		{ 
			int			DOFNum; 
			float		DOFVal; 
			float		prevDOFVal; 
		} dofData; 
	}; 
 
	// Although position data is a fixed size, we still want 
	// this so that we can organize the data to be friendly for 
	// paging. 
	long		nextPositionUpdateOffset; 
	long		prevPositionUpdateOffset; 
} ACMIEntityPositionData; 
#pragma pack (pop, pack1) 
 
// 
// This raw format is used by the position/event/sfx bundler to 
// create a .vhs file (dig that extension), which is the ACMITape playback format. 
// This is the format stored in the flight file. 
 
typedef struct  
{ 
	int			type;			// type of object 
	long		uniqueID;		// A unique ID for the object. Many to One correlation to Falcon Entities 
	int			flags;			// side 
 
	// for features we may need an index to the lead component and 
	// the slot # that was in the camp component list (for bridges, bases...) 
	long		leadIndex; 
	int			slot; 
	int			specialFlags; 
	ACMIEntityPositionData entityPosData; 
} ACMIRawPositionData; 
 
//////////////////////////////////////////////////////////////////////////////// 
// 
// Header for event data. 
 
#pragma pack (push, pack1, 1) 
typedef struct 
{ 
	// type of event this is 
	BYTE		eventType; 
	long 		index; 
 
	// Time stamp for this event. 
	float		time; 
	float		timeEnd; 
 
	// data specific to type of event 
	long		type; 
	long		user; 
	long		flags; 
	float		scale; 
	float		x, y, z; 
	float		dx, dy, dz; 
	float		roll, pitch, yaw; 
 
} ACMIEventHeader; 
#pragma pack (pop, pack1) 
 
// 
// Trailer for event data. 
// 
 
#pragma pack (push, pack1, 1) 
typedef struct 
{ 
	float		timeEnd; 
	long 		index;		// into EventHeader 
} ACMIEventTrailer; 
#pragma pack (pop, pack1) 
 
//////////////////////////////////////////////////////////////////////////////// 
// 
// Feature Status Event 
 
#pragma pack (push, pack1, 1) 
typedef struct 
{ 
	// Time stamp for this event. 
	float		time; 
 
	// index of feature on tape 
	long 		index; 
 
	// data specific to type of event 
	long		newStatus; 
	long		prevStatus; 
 
} ACMIFeatEvent; 
#pragma pack (pop, pack1) 
 
typedef struct 
{ 
	long		uniqueID; 
	ACMIFeatEvent data; 
} ACMIFeatEventImportData; 
 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
// 
// .vhs file format: 
// 
// |                        |                 |                 | 
// |        header          | entity block    | timeline block  | 
// | sizeof(ACMITapeHeader) | (variable size) | (variable size) | 
// 
//////////////////////////////////////////////////////////////////////////////// 
// 
// entity block: 
// 
// |                    |                                       | 
// | number of entities |              entities                 |     
// |  sizeof(long)      | num entities * sizeof(ACMIEntityData) | 
// 
// entity: 
// 
// |                        | 
// |      ACMIEntityData    | 
// | sizeof(ACMIEntityData) | 
// 
//////////////////////////////////////////////////////////////////////////////// 
// 
// timeline block: 
// 
// |                              |                    |                     | 
// | entity position update block | entity event block | general event block |    
// |     (variable size)          |  (variable size)   |    (variable size)  | 
// 
// The entity position update block contains all entity position updates. 
// The position updates are threaded on a per-entity basis, with a separate doubly linked list 
// for each entity. 
// The position updates should be chronologically sorted. 
// There should be a position update read-head for each entity for traversing its linked list 
// of position updates. 
// 
// The entity event block contains all events which are relevant to entities. 
// The events are threaded on a per-entity basis, with a separate doubly linked list 
// for each entity. 
// The events should be chronologically sorted.   
// There should be an event read-head for each entity for traversing its linked list of events. 
// 
// The general event block contains all events which are not relevant to a specific entity. 
// The events are threaded in doubly linked list. 
// The events should be chronologically sorted. 
// There should be an event read-head for traversing the linked list of events. 
// 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
 
extern "C" 
{ 
	void DestroyACMIRawPositionDataList(LIST* _frameList); 
	void DeleteACMIRawPositionData(ACMIRawPositionData* rawPositionData); 
	void DeleteACMIEntityPositionData(ACMIEntityPositionData *data); 
	void DeleteACMIEntityData(ACMIEntityData *data); 
	void DeleteACMIEventHeader(ACMIEventHeader *data); 
	void DeleteACMIFeatEventImportData(ACMIFeatEventImportData *data); 
	int CompareEventTrailer( const void *t1, const void *t2 ); 
}; 
 
 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
// 
// Callback for events that are not entity-specific. 
// The EventIdData parameter is the event id. 
// The first void * parameter points to the event data, which 
// can be decoded with the event id. 
// The second void * parameter is for user data. 
 
typedef void (*ACMI_GENERAL_EVENT_CALLBACK) (ACMITape *, EventIdData, void *, void *); 
 
typedef struct 
{ 
	ACMI_GENERAL_EVENT_CALLBACK		forwardCallback; 
	ACMI_GENERAL_EVENT_CALLBACK		reverseCallback; 
	void									*userData; 
} ACMIGeneralEventCallback; 
 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
 
typedef struct 
{ 
 
	long			positionDataOffset; 
	long			eventDataOffset; 
} ACMIEntityReadHead; 
 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
 
class ACMITape 
{ 
public: 
	 
	// Constructors. 
	// Do not put the extension with name. 
	// This should be the name of the desired .vcr file. 
	ACMITape(char *name, RenderOTW *renderer, RViewPoint *viewPoint); 
 
	// Destructor. 
	~ACMITape(); 
 
	// Import the current positional, event, and sfx data. 
	// The filenames of these files will always be the same  
	// so we don't have to pass them in. 
	static BOOL Import(char *inFltFile, char *outTapeFileName); 
	static void WriteTapeFile ( char *fname, ACMITapeHeader *tapeHdr ); 
	 
	// Time-independent entity access. 
	int NumEntities() ; 
	int EntityId(int index); 
	int EntityType(int index); 
 
	// Time-dependent entity access. 
	BOOL GetEntityPosition 
	( 
		int index, 
		float &x, 
		float &y, 
		float &z, 
		float &yaw, 
		float &pitch, 
		float &roll, 
		float &speed, 
		float &turnrate, 
		float &turnradius 
	); 
 
 
	// Prototype of an ACMI_GENERAL_EVENT_CALLBACK: 
	// void PoopooCB(ACMITape *tape, EventIdData id, void *eventData, void *userData); 
	void SetGeneralEventCallbacks 
	( 
		ACMI_GENERAL_EVENT_CALLBACK forwardEventCallback, 
		ACMI_GENERAL_EVENT_CALLBACK reverseEventCallback, 
		void *userData 
	); 
 
	// Was the tape file found and opened successfully? 
	BOOL IsLoaded(); 
 
	// Is the tape paused? 
	BOOL IsPaused() ; 
 
	// Playback controls. 
	void Play(); 
	void Pause(); 
	 
	// Step in sim time. 
	void StepTime(float numSeconds); 
 
	// return a sim time based on pct into tape parm is 
	float GetNewSimTime( float pct ); 
	 
	// Play speed controls. 
	// This is a ratio of sim time / real time. 
	void SetPlayVelocity(float n); 
	float PlayVelocity() ; 
 
	// Increase in play velocity per second of real time. 
	void SetPlayAcceleration(float n); 
	float PlayAcceleration() ; 
 
	// This will be used to clamp play velocity. 
	// It will be clamped to (-fabs(speed) <= velocity <= fabs(speed)); 
	void SetMaxPlaySpeed(float n); 
	float MaxPlaySpeed() ; 
 
	// Set the read head position.  This should be a number  
	// from 0 to 1 (0 = beginning of tape, 1 = end of tape). 
	// The input value will be clamped to fit this range. 
	void SetHeadPosition(float t); 
	float HeadPosition() ; 
 
	// This gives the current simulation time. 
	float SimTime() ; 
	float GetTapePercent() ; 
 
	void Update( float newSimTime ); 
 
	// YPR interpolation 
	float AngleInterp( float begAng, float endAng, float dT ); 
 
	// access function for sim tape entity 
	SimTapeEntity *GetSimTapeEntity( int index ); 
 
	// does entity exist at current read head 
	BOOL IsEntityInFrame( int index ); 
	void InsertEntityInFrame( int index ); 
	void RemoveEntityFromFrame( int index ); 
 
	// get the entity's current radar target (entity index returned) 
	int GetEntityCurrentTarget( int index ); 
 
	// update sim tape Entities for this frame 
	void UpdateSimTapeEntities( void ); 
 
	// sets the draw position and matrix for bsp update 
	void ObjectSetData(SimBaseClass*, Tpoint*, Trotation*); 
 
	void SetScreenCapturing( BOOL val ) 
	{ 
		_screenCapturing = val; 
	}; 
 
	void SetObjScale( float val ) 
	{ 
		_tapeObjScale = val; 
	}; 
 
	float GetObjScale( void ) 
	{ 
		return _tapeObjScale; 
	}; 
 
	float GetDeltaSimTime( void ) 
	{ 
		return _deltaSimTime; 
	}; 
 
	void SetWingTrails( BOOL val ); 
 
	void SetWingTrailLength( int val ) 
	{ 
		_wtMaxLength = val; 
	}; 
 
	void * GetTextEvents( int *count ); 
	void * GetCallsignList(long *count); 
 
 
	// list of sim entities from the tape that are manipulated and drawn 
	SimTapeEntity						*_simTapeEntities; 
	ACMIEntityData *EntityData(int index); 
 
	float GetTodOffset( void ) 
	{ 
		return _tapeHdr.todOffset; 
	}; 
	 
private: 
 
	void Init(); 
 
	// These are used for importation. 
	static void ParseEntities ( void ); 
	static void ThreadEntityPositions( ACMITapeHeader *tapeHdr ); 
	static void ThreadEntityEvents( ACMITapeHeader *tapeHdr ); 
	static void ImportTextEventList( FILE *fd, ACMITapeHeader *tapeHdr ); 
 
	// Get at the entity data. 
	ACMIEntityData *FeatureData(int index); 
	ACMIEntityPositionData *CurrentFeaturePositionHead(int i); 
 
	// Traverse an entity's position update thread. 
	ACMIEntityPositionData *CurrentEntityPositionHead(int i); 
	ACMIEntityPositionData *CurrentEntityEventHead(int i); 
	ACMIEntityPositionData *HeadNext(ACMIEntityPositionData *current); 
	ACMIEntityPositionData *HeadPrev(ACMIEntityPositionData *current); 
 
	// Traverse an event thread. 
	ACMIEventHeader *GeneralEventData(void); 
	ACMIEventHeader *GetGeneralEventData(int i); 
	ACMIEventHeader *Next(ACMIEventHeader *current); 
	ACMIEventHeader *Prev(ACMIEventHeader *current); 
 
	ACMIEventTrailer *GeneralEventTrailer(void); 
	ACMIEventTrailer *Next(ACMIEventTrailer *current); 
	ACMIEventTrailer *Prev(ACMIEventTrailer *current); 
 
	ACMIFeatEvent *CurrFeatEvent(void); 
	ACMIFeatEvent *Next(ACMIFeatEvent *current); 
	ACMIFeatEvent *Prev(ACMIFeatEvent *current); 
 
	// Advance heads to current sim time. 
	void AdvanceEntityPositionHead(int index); 
	void AdvanceEntityEventHead(int index); 
	void AdvanceGeneralEventHead( void ); 
	void AdvanceGeneralEventHeadHeader( void ); 
	void AdvanceGeneralEventHeadTrailer( void ); 
	void AdvanceFeatEventHead( void ); 
	void AdvanceAllHeads( void ); 
 
	// Entity setup and cleanup 
	void SetupSimTapeEntities( void ); 
	void CleanupSimTapeEntities( void ); 
 
	// open the tape file and setup memory mapping 
	long OpenTapeFile( char *fname ); // returns tape length 
	void CloseTapeFile( void ); 
 
	// event list related functions 
	void CleanupEventList( void ); 
	ActiveEvent *InsertActiveEvent( ACMIEventHeader *, float dT ); 
	void RemoveActiveEvent( ActiveEvent ** ); 
	void UpdateActiveEvents( void ); 
 
	// create/update feature drawables 
	void CreateFeatureDrawable( SimTapeEntity *feat ); 
	SimBaseClass *FindComponentFeature( long leadIndex, int slot ); 
 
	// update tracer data 
	void UpdateTracerEvent( TracerEventData *td, float dT ); 
 
	// tape header 
	ACMITapeHeader						_tapeHdr; 
 
	BOOL								_screenCapturing; 
 
	// system info for tape file access 
	HANDLE								_tapeFileHandle; 
	HANDLE								_tapeMapHandle; 
 
	// sim time / real time 
	float								_playVelocity; 
	float								_playAcceleration; 
	float								_maxPlaySpeed; 
 
	// Current sim time 
	float								_simTime; 
	float								_stepTrail; 
	float								_deltaSimTime; 
 
	// list of sim entities from the tape that are manipulated and drawn 
	SimTapeEntity						*_simTapeFeatures; 
 
	// viewpoint and renderer objs from acmiview 
	RViewPoint							*_viewPoint; 
	RenderOTW							*_renderer; 
 
	// Current real time 
	float								_lastRealTime; 
 
	BOOL									_simulateOnly; 
	BOOL									_paused; 
	BOOL									_unpause; 
 
	BOOL									_wingTrails; 
	int										_wtMaxLength; 
 
	// Base memory address of the file mapping 
	// for the tape data. 
	void									*_tape; 
	ACMIEntityReadHead				*_entityReadHeads; 
	long							_generalEventReadHeadHeader; 
	ACMIEventTrailer				*_generalEventReadHeadTrailer; 
	ACMIGeneralEventCallback		_generalEventCallbacks; 
	ACMIFeatEvent					*_featEventReadHead; 
 
	// events 
	ActiveEvent						**_eventList; 
	ActiveEvent						*_activeEventHead; 
	ACMIEventTrailer				*_firstEventTrailer; 
	ACMIEventTrailer				*_lastEventTrailer; 
	ACMIFeatEvent					*_firstFeatEvent; 
	ACMIFeatEvent					*_lastFeatEvent; 
 
	// for scaling objects 
	float							_tapeObjScale; 
}; 
 
 
#include "acmtpinl.cpp" 
 
#endif  // _ACMITAPE_H_