//===========================================================================// // File: l4video.cpp // // Project: MUNGA Brick: Video Renderer Manager // // Contents: Interface specification Video Renderer Manager // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 01/11/95 GAC Initial coding. // // 07/11/95 KEO Modify video resource format. // // 02/08/96 KEO Add rubble entry to video resource. // //---------------------------------------------------------------------------// // Copyright (C) 1995-1996, Virtual World Entertainment, Inc. // // All Rights reserved worldwide. // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL. // //===========================================================================// #include #pragma hdrstop #if !defined(DOOR_HPP) # include #endif #if !defined(DOORFRAM_HPP) # include #endif #if !defined(EYECANDY_HPP) # include #endif #if !defined(L4VIDRND_HPP) # include #endif #if !defined(L4VIDEO_HPP) # include #endif #if !defined(MATRIX_HPP) # include #endif #if !defined(MOVER_HPP) # include #endif #if !defined(JMOVER_HPP) # include #endif #if !defined(PLAYER_HPP) # include #endif #if !defined(CAMSHIP_HPP) # include #endif #if !defined(DIRECTOR_HPP) # include #endif #if !defined(MISSION_HPP) # include #endif #if !defined(CULTURAL_HPP) # include #endif #if !defined(NTTMGR_HPP) # include #endif #if !defined(APP_HPP) # include #endif #include // // Includes for the DPL libraries // #include #include #include #include #include // // 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, 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 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" { 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() 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() 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) { 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); } strncpy(TempBuff, special,special_len); TempBuff[special_len] = 0; if(TempBuff[special_len-1] != 0) { DEBUG_STREAM<<"Caution, the following SPECIAL was not null terminated\n"; 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= 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 << endl << "Damage zone '" << *argptr << "' not in table." << 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"; Verify(damagize_material); } } else { DEBUG_STREAM<<"SPECIAL GEOGROUP DAMAGE no material name \n"; 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"; 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"; } } 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"; Verify(*argptr); } } else { DEBUG_STREAM<<"SPECIAL MATERIAL "<<*argptr<<" is not a material modifier\n"; } } 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"; Verify(*argptr); } if(*(++argptr)) v0 = atof(*argptr); else { DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing v0\n"; Verify(*argptr); } if(*(++argptr)) du = atof(*argptr); else { DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing du\n"; Verify(*argptr); } if(*(++argptr)) dv = atof(*argptr); else { DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing dv\n"; 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"; Verify(*argptr); } if(*(++argptr)) offset = atoi(*argptr); else { DEBUG_STREAM<<"SPECIAL TEXTURE FAKESIZE missing offset\n"; 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"; } } 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"; 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; /* dPL material name callback function type. */ //typedef char8 *(dpl_MATERIAL_NAME_CALLBACK)(char8 *mat_name); char8* substituteMaterial( char8 *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. //---------------------------------------------- entry = materialSubstitutionList->GetFirstEntry(); while (entry) { search = entry->GetName(); if (search && *search && (pc = strstr(source, search)) != NULL) { replace = entry->GetChar(); *buffer = '\0'; len = pc - source; while (*replace == '<') { ++replace; --len; } if (len > 0) { strncat(buffer, 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); Str_Copy(source, buffer, MATERIAL_NAME_BUFFER_LENGTH); break; } entry = entry->GetNextEntry(); } return source; } //----------------------------------------------------------------------------- //--------------------------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 *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: ("<GetObjectFilename()<<"' 0x"<GetRendererModes()); video_wrapper = new L4VideoObjectWrapper(video_object, False); Register_Object(video_wrapper); video_chain->Add(video_wrapper); } //Tell(dec<<"\n"); return object_count; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // static void L4VideoObjectWrapper::DeleteVideoObjectChain( ChainOf *video_chain ) { //do not Check(this) - static Check(video_chain); ChainIteratorOf 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; } //----------------------------------------------------------------------------- //-------------------Actual DPL video renderer starts below-------------------- //----------------------------------------------------------------------------- UserHeap* DPLRenderer::DPLHeap = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Constructor for DPLRenderer // DPLRenderer::DPLRenderer( RendererRate calibration_rate, RendererComplexity calibration_complexity, RendererPriority calibration_priority, InterestType interest_type, InterestDepth depth_calibration ): VideoRenderer( calibration_rate, calibration_complexity, calibration_priority, interest_type, depth_calibration ), projectile_list(NULL), dplObjectCacheSocket(NULL, False), dplJointToDCSTranslatorSocket(NULL,False), dplRenderableSocket(NULL) { 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; 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; dplMainView = NULL; dplDeathZone = NULL; dplMainZone = NULL; vehicleReticle = NULL; dplHitInstance = NULL; dplHitDCS = NULL; dplHitGeoGroup = NULL; dplHitGeometry = NULL; delayedDCSCount = 0; myUniqueID = 0; ambientLight = NULL; 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. // for( psfx_number = 0; psfx_number < MAX_PSFX_COUNT; psfx_number++) { myPSFXDescriptons[psfx_number] = NULL; } // // 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"; 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"; 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"; 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", "", "" ); // cout<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) { cout<<"pfx file "<px, &psfx_info->py, &psfx_info->pz, &psfx_info->pv ); if(status < 4) { cout<<"pfx file "<velx, &psfx_info->vely, &psfx_info->velz, &psfx_info->velxv, &psfx_info->velyv, &psfx_info->velzv ); if(status < 6) { cout<<"pfx file "<rad, &psfx_info->radv, &psfx_info->exp, &psfx_info->expv, &psfx_info->dexp, &psfx_info->dexpv ); if(status < 6) { cout<<"pfx file "<accelx, &psfx_info->accely, &psfx_info->accelz, &psfx_info->accelxv, &psfx_info->accelyv, &psfx_info->accelzv ); if(status < 6) { cout<<"pfx file "<atten, &psfx_info->attenv ); if(status < 2) { cout<<"pfx file "<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) { cout<<"pfx file "<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) { cout<<"pfx file "<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) { cout<<"pfx file "<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) { cout<<"pfx file "<colour_warp, &psfx_info->alpha_warp ); if(status < 2) { cout<<"pfx file "<dur, &psfx_info->durv ); if(status < 2) { cout<<"pfx file "<\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) { 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) cout<<"DPLReadINIPage processing "<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() << "'" << endl; } } 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() << "'" << endl; } } 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() << "'" << endl; } } 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 << "'" << endl; } } if (master_notation_file->GetEntry(starting_page_name, "prioritytexmappath", &TempStringPtr)) { dpl_AddToTexmapFilePath((char *)TempStringPtr, dpl_path_system); if (debug_printing) { DEBUG_STREAM << "prioritytexmappath '" << TempStringPtr << "'" << endl; } } if (master_notation_file->GetEntry(starting_page_name, "prioritymaterialpath", &TempStringPtr)) { dpl_AddToMaterialFilePath((char *)TempStringPtr, dpl_path_system); if (debug_printing) { DEBUG_STREAM << "prioritymaterialpath '" << TempStringPtr << "'" << endl; } } // // 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) { dpl_OBJECT *dpl_a_object; Register_Object(cache_namelist); for( entry = cache_namelist->GetFirstEntry(); entry; entry = entry->GetNextEntry()) { dpl_a_object = dpl_LoadObject((char *)entry->dataReference, dpl_load_normal); if(!dpl_a_object) DEBUG_STREAM<<"Unable to cache "<<(char *)entry->dataReference<<"\n"; else { if(debug_printing) cout<<"Caching "<<(char *)entry->dataReference<<"\n"; } } Unregister_Object(cache_namelist); delete cache_namelist; } // // Setup the clip range // if(master_notation_file->GetEntry(starting_page_name, "clip" ,&TempStringPtr)) { sscanf( TempStringPtr, "%f %f", &clipNear, &clipFar); dpl_SetViewClipPlanes ( dplMainView, clipNear, clipFar ); if(debug_printing) cout<<"Clip Range "<GetEntry(starting_page_name, "backgnd" ,&TempStringPtr)) { sscanf( TempStringPtr, "%f %f %f", &backgroundRed, &backgroundGreen, &backgroundBlue); dpl_SetViewBackGround ( dplMainView, backgroundRed, backgroundGreen, backgroundBlue); if(debug_printing) cout<<"Background Color "<GetEntry(starting_page_name, "viewangle" ,&TempStringPtr)) { sscanf( TempStringPtr, "%f", &viewAngle); dpl_SetPipeWindow (0, 0, 0, x_size, y_size); SetViewAngle(viewAngle); dpl_SetViewPipe ( dplMainView, 0); if(debug_printing) cout<<"View Angle "<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; // 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 ); if(debug_printing) cout<<"Fog "<GetEntry(starting_page_name, "nosearchlightfog" ,&TempStringPtr)) { sscanf( TempStringPtr, "%f %f %f %f %f", &noSearchLightFogNear, &noSearchLightFogFar, &noSearchLightFogRed, &noSearchLightFogGreen, &noSearchLightFogBlue); if(debug_printing) cout<<"nosearchlightfog "<GetEntry(starting_page_name, "ambient" ,&TempStringPtr)) { sscanf( TempStringPtr, "%f %f %f ", &red, &green, &blue); ambientLight = dpl_NewLight(); Register_Pointer(ambientLight); dpl_SetLightType ( ambientLight, dpl_light_type_ambient ); dpl_SetLightColor ( ambientLight, red, green, blue ); dpl_FlushLight ( ambientLight ); if(debug_printing) cout<<"Ambient Light "<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) { sceneLightDCS = new (dpl_DCS (*[sceneLightCount])); Register_Pointer(sceneLightDCS); sceneLight = new (dpl_LIGHT (*[sceneLightCount])); Register_Pointer(sceneLight); } 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) cout<<"Light "<<(char *)entry->dataReference<<"\n"; // // Create and rotate a dcs to hold the light, and the light itself // Verify(current_entry <= sceneLightCount); sceneLight[current_entry] = dpl_NewLight(); Register_Pointer(sceneLight[current_entry]); sceneLightDCS[current_entry] = dpl_NewDCS(); Register_Pointer(sceneLightDCS[current_entry]); 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; Register_Object(psfx_namelist); // // 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) cout<<"psfx"< 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]) { cout<<"psfx#"<MakeEntryList(starting_page_name, "specialfx")) != NULL) { char *texture_name; const char *effect_page_name; int status, spfx_number, spfx_type, spfx_count, spfx_repeats; float spfx_size, spfx_velocity, spfx_bias, spfx_y_off, spfx_cook_r, spfx_cook_g, spfx_cook_b, spfx_varience, spfx_gravity, spfx_cool, spfx_ocool; dpl_TEXTURE *effect_texture; Register_Object(specialfx_namelist); // // create all the effects on the current page // for( entry = specialfx_namelist->GetFirstEntry(); entry; entry = entry->GetNextEntry()) { spfx_number = atoi(entry->GetName()+9); // // Get the page with this effect on it // effect_page_name = entry->GetChar(); if(debug_printing) cout<<"specialfx"<GetEntry(effect_page_name, "type", &spfx_type); master_notation_file->GetEntry(effect_page_name, "size", &spfx_size); master_notation_file->GetEntry(effect_page_name, "velocity", &spfx_velocity); master_notation_file->GetEntry(effect_page_name, "v_bias", &spfx_bias); master_notation_file->GetEntry(effect_page_name, "y_off", &spfx_y_off); master_notation_file->GetEntry(effect_page_name, "variance", &spfx_varience); master_notation_file->GetEntry(effect_page_name, "gravity", &spfx_gravity); master_notation_file->GetEntry(effect_page_name, "count", &spfx_count); master_notation_file->GetEntry(effect_page_name, "repeats", &spfx_repeats); master_notation_file->GetEntry(effect_page_name, "cook", &TempStringPtr); sscanf( TempStringPtr, "%f %f %f", &spfx_cook_r, &spfx_cook_g, &spfx_cook_b); master_notation_file->GetEntry(effect_page_name, "cool", &TempStringPtr); sscanf( TempStringPtr, "%f %f", &spfx_cool, &spfx_ocool); // // install the effect // master_notation_file->GetEntry(effect_page_name, "texture" ,&TempStringPtr); texture_name = SKIPPY_CAST(char*, TempStringPtr); effect_texture = dpl_LookupTexture ( texture_name, dpl_lookup_normal, &status ); if (effect_texture == NULL) DEBUG_STREAM<<"couldn't find texture "<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) cout<<"DPLReadINIPage returned to "<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) cout<<"compare = "<FindResourceDescription(mission->GetMapID()))->resourceName; // cout<GetMissionTime(); // cout<GetMissionWeather(); // cout<GetScenarioName(); // cout<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) cout<<"branch = "<GetFileName() << "' NO MATCH FOUND!!" << endl; } } } // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Read environment // routine to read in an environment from a notation file and setup lights, // spfx and such... // void DPLRenderer::DPLReadEnvironment(Mission *mission) { 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"; 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 "<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; } 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() << "'" << endl; DEBUG_STREAM << "TexmapFilePath '" << dpl_GetTexmapFilePath() << "'" << endl; DEBUG_STREAM << "MaterialFilePath '" << dpl_GetMaterialFilePath() << "'" << endl; } // // 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() { 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= 1); Verify(load_position <=12); Check(bitmap_to_load); Check_Pointer(local_storage); // // Figure out the position to start copying the data at // word_pointer = bitmap_to_load->Data.MapPointer; if(load_position & 0x1) { pixel_pointer = local_storage + 4096; } else { pixel_pointer = local_storage; } // // Find the bit position to merge the data into // switch(load_position) { case 1: case 2: turn_on = 0x0000f000; turn_off = 0xffff0fff; break; case 3: case 4: turn_on = 0x00000f00; turn_off = 0xfffff0ff; break; case 5: case 6: turn_on = 0x00f00000; turn_off = 0xff0fffff; break; case 7: case 8: turn_on = 0x000f0000; turn_off = 0xfff0ffff; break; case 9: case 10: turn_on = 0xf0000000; turn_off = 0x0fffffff; break; case 11: case 12: turn_on = 0x0f000000; turn_off = 0xf0ffffff; break; } // // Actually process the texels // bit_number = 15; for(y = 0; y < 32; y++) { for(x = 0; x < 128; x++) { if((*word_pointer & (1< dplMainZone, // 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 dplMainZone, // 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"; // // 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 dplMainZone, // 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 dplMainZone, // 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"; // // 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 dplMainZone, // 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 dplMainZone, // 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"; // // 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 dplMainZone, // 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"; // // 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, dplMainZone, 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, dplMainZone, 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, dplMainZone, 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, dplMainZone, 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, dplMainZone, 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, dplMainZone, 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, dplMainZone, 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, dplMainZone, 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 dplMainZone, // 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"; // 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 dplMainZone, // 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 dplMainZone, // 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, dplMainZone, 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, dplMainZone, 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, dplMainZone, 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, dplMainZone, 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 dplMainZone, // 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 dplMainZone, // 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) { 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"; // 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"; #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.) { char *object_filename; #if DEBUG_LEVEL > 0 int object_count; #endif L4VideoObject // should be const *video_object; L4VideoObjectWrapper *video_wrapper; ChainOf video_chain(NULL); L4VideoObject::ResourceType resource_type; dpl_DCS *my_root_dcs; Enumeration // L4VideoObject::RendererModes 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 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; dpl_OBJECT *this_object; dpl_ISECT_MODE intersect_mode; 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" < dplMainZone, // 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_static_root); 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 //------------------------------------------ DPLStaticChildRenderable *this_child = new DPLStaticChildRenderable( entity, dplMainZone, this_object, intersect_mode, intersect_mask, offset_matrix, root_DCS); Register_Object(this_child); this_DCS = this_child->GetDCS(); this_instance = this_child->GetInstance(); } else { //---------------------------------------- // attach additional objects to root_DCS // (HACK) temporary implementation (HACK) //---------------------------------------- DCSInstanceRenderable *another_instance = 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 root_DCS, // 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; this_instance = another_instance->GetInstance(); } } // // 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: { #if DEBUG_LEVEL > 0 StateInstanceSwitchRenderable *undamaged_state = #endif 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 Register_Object(undamaged_state); break; } case L4VideoObject::Rubble: { #if DEBUG_LEVEL > 0 StateInstanceSwitchRenderable *undamaged_state = #endif 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 Register_Object(undamaged_state); break; } } //---------------------------------- // 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: { dpl_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 = dpl_LoadObject(object_filename, dpl_load_normal); #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 dplMainZone); // DPL Zone this stuff will live in (for culling) Register_Object(projectile); break; } // // Script for generating renderables for eyecandy // case EyeCandyClassID: { int effect_number; 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 dplMainZone, // 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 dplMainZone, // DPL zone everything will be in Point3D::Identity, // Point offset from the parent DCS this_root->GetDCS(), // 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: { int effect_number; video_iterator.First(); while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) { video_object = video_wrapper->GetVideoObject(); effect_number = atoi(video_object->GetObjectFilename()); if(effect_number < 100 || effect_number >= 1000) { DPLIndependantEffect( entity->localOrigin.linearPosition, effect_number); } else { 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); #if DEBUG_LEVEL > 0 CameraShipHUDRenderable *my_camera_hud = #endif new CameraShipHUDRenderable( entity, CameraShipHUDRenderable::Dynamic, player_index, display_rank_window ); Register_Object(my_camera_hud); } 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 // 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 dplMainZone, // 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 DEBUG_LEVEL > 0 DPLEyeRenderable* this_eye = #endif new DPLEyeRenderable( entity, dplMainZone, LinearMatrix::Identity, this_root->GetDCS(), dplMainView, 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. //------------------------------------------------ dpl_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 "<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; 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 dplMainZone, // 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, dplMainZone, left, dpl_isect_mode_obj, NULL, my_ident, door_sill->GetDCS(), left_door_position); Register_Object(left_door); DPLChildPointRenderable* right_door = new DPLChildPointRenderable( entity, dplMainZone, right, dpl_isect_mode_obj, NULL, my_ident, door_sill->GetDCS(), 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->GetDCS(), // 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->GetDCS(), // 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->GetDCS(), // 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: { dpl_OBJECT *this_object; dpl_ISECT_MODE intersect_mode; uint32 intersect_mask; LinearMatrix offset_matrix = LinearMatrix::Identity; dpl_DCS *root_DCS, *this_DCS; // // 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; } 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" <IsDerivedFrom(Mover::ClassDerivations)) { // // 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(); RootRenderable *this_root = 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 dplMainZone, // 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(); root_DCS = this_root->GetDCS(); } 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. // RootRenderable *this_static_root = 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 dplMainZone, // 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_static_root); root_DCS = this_static_root->GetDCS(); } // // 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 DEBUG_LEVEL > 0 DPLEyeRenderable *this_eye = #endif new DPLEyeRenderable( entity, dplMainZone, LinearMatrix::Identity, root_DCS, dplMainView, 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 //------------------------------------------ DPLStaticChildRenderable *this_child = new DPLStaticChildRenderable( entity, dplMainZone, this_object, intersect_mode, intersect_mask, offset_matrix, root_DCS); Register_Object(this_child); this_DCS = this_child->GetDCS(); } else { //---------------------------------------- // attach additional objects to root_DCS // (HACK) temporary implementation (HACK) //---------------------------------------- #if DEBUG_LEVEL > 0 DCSInstanceRenderable *another_instance = #endif 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 root_DCS, // 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 (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; } } // // 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::ClassDerivations)) { 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) { cout<<"Frames "<GetApplicationState(); if(application->GetApplicationState() != lastAppState) { switch(current_app_state) { case Application::RunningMission: dpl_SetViewFog( dplMainView, dpl_fog_type_pixel_lin, fogRed, fogGreen, fogBlue, fogNear, fogFar ); dpl_FlushView(dplMainView); dpl_DisableSyncOnCreate(); break; case Application::StoppingMission: #if 0 dpl_SetViewFog( dplMainView, dpl_fog_type_pixel_lin, 0.0, 0.0, 0.0, 0.1, 0.2 ); dpl_FlushView(dplMainView); #endif break; } lastAppState = current_app_state; } // // !!!! This may be the WRONG place to do this, but we'll try it // // extern dpl_INSTANCE *dpl_SectPixel(dpl_VIEW *, float32, float32, uint32, // float32 *, float32 *, float32 *, // dpl_DCS **, dpl_GEOGROUP **, dpl_GEOMETRY **); // extern dpl_INSTANCE *dpl_RapidSectPixel(float32, float32, float32, uint32, // float32 *, float32 *, float32 *, // dpl_DCS **, dpl_GEOGROUP **, dpl_GEOMETRY **); // // If there is a reticle pointer defined, do the pickpoint processing // SET_VIDEO_PICKPOINT(); if(vehicleReticle) { // // Check the reticle structure to make sure it's ok, then see if pick // point processing is turned on. // Check(vehicleReticle); if(vehicleReticle->pickPointingOn) { // // Remember the last thing we were targeted on, then go ahead and do the // intersection call. // #if PRINT_PICKPOINT_TEST old_instance = dplHitInstance; old_damage_zone = vehicleReticle->targetDamageZone; #endif #if RAPID_SECT_PIXEL dplHitInstance = dpl_RapidSectPixel ( (((vehicleReticle->reticlePosition.x*aspectRatio)/2.0) + 0.5), // go from reticle coordinant system (((vehicleReticle->reticlePosition.y*aspectRatio)/2.0) + 0.5), // to the screen coordinant system. 1.0e5, INTERSECT_ALL, &vehicleReticle->rayIntersection.x, &vehicleReticle->rayIntersection.y, &vehicleReticle->rayIntersection.z, &dplHitDCS, &dplHitGeoGroup, &dplHitGeometry); #else dplHitInstance = dpl_SectPixel ( dplMainView, (vehicleReticle->reticlePosition.x/2.0) + 0.5, // go from reticle coordinant system (vehicleReticle->reticlePosition.y/2.0) + 0.5, // to the screen coordinant system. INTERSECT_ALL, &vehicleReticle->rayIntersection.x, &vehicleReticle->rayIntersection.y, &vehicleReticle->rayIntersection.z, &dplHitDCS, &dplHitGeoGroup, &dplHitGeometry); #endif } else { // // When pickpoint is off, we should return something sensable // dplHitInstance = 0; } // // Set the reticle variables based on whether we hit anything or not // if(dplHitInstance) { #if PARTICLE_TEST DPLIndependantEffect( vehicleReticle->rayIntersection, 1); #endif vehicleReticle->targetEntity = (Entity *)dpl_GetAppSpecific(dplHitDCS); #if USE_TRACKER_STRUCTURE this_tracker = (dpl_tracker *)dpl_GetAppSpecific(dplHitGeoGroup); #endif if(dpl_GetAppSpecific(dplHitGeoGroup)) { #if USE_TRACKER_STRUCTURE vehicleReticle->targetDamageZone = this_tracker->Damage_Zone_Number; #else vehicleReticle->targetDamageZone = ((int)dpl_GetAppSpecific(dplHitGeoGroup))-1; #endif // vehicleReticle->targetEntity = this_tracker->This_Entity; } else { vehicleReticle->targetDamageZone = -1; // vehicleReticle->targetEntity = NULL; } } else { vehicleReticle->targetDamageZone = -1; vehicleReticle->targetEntity = NULL; } #if PRINT_PICKPOINT_TEST //------------------------------------------ // code for testing and debugging pickpoint //------------------------------------------ // If the object we are targeted on changes, we will print out the data if(dplHitInstance) { if( old_instance != dplHitInstance || old_damage_zone != vehicleReticle->targetDamageZone) { cout<<"instance app specific="<targetEntity) cout<<"Target Class="<targetEntity->GetClassID()<<"\n"; #if USE_TRACKER_STRUCTURE cout<<"Damage zone #="<targetDamageZone<<" "<dz_name<<"\n"; #else cout<<"Damage zone #="<targetDamageZone<<"\n"; #endif } } #endif } CLEAR_VIDEO_PICKPOINT(); // // Setup the video culling system, this generates the world to eye matrix for // the currently linked entity and sets the current frame time to Now() // #if VIDEO_CULLING SET_VIDEO_CULL_SETUP(); SetupCull(); CLEAR_VIDEO_CULL_SETUP(); #endif // // If we've asked the system to count renderables, setup the total count // SET_VIDEO_RENDERABLES(); #if COUNT_RENDERABLES int renderable_socket_count; renderable_socket_count = 0; #endif // // Execute all the dynamic renderables attached to this renderer. // SChainIteratorOf renderable_iterator(&dplRenderableSocket); while ((component = renderable_iterator.ReadAndNext()) != NULL) { #if COUNT_RENDERABLES renderable_socket_count++; #endif SET_VIDEO_ALL_RENDERABLES(); component->Execute(); CLEAR_VIDEO_ALL_RENDERABLES(); } // // Flip trace for all renderables and report renderable count if enabled // CLEAR_VIDEO_RENDERABLES(); #if COUNT_RENDERABLES cout<<"dplRenderableSocket "<ReadAndNext()) != NULL) { // // If enabled, flip this trace on vehicle or player renderables // #if defined(TRACE_VIDEO_VEHICLE_RENDERABLES) if( entity->GetClassID() == MechClassID || entity->GetClassID() == VTVClassID || entity->GetClassID() == BTPlayerClassID) { SET_VIDEO_VEHICLE_RENDERABLES(); } #endif // // Create an iterator to iterate over all the dynamic video components // in this entity. If renderable counting is turned on, initialize // a counter for this entities renderables // Entity::DynamicVideoSocketIterator component_iterator(entity); component_count=0; // // Iterate through all the dynamic video components for this entity // while ((component = component_iterator.ReadAndNext()) != NULL) { // // Execute each of the entities components // SET_VIDEO_ALL_RENDERABLES(); component->Execute(); CLEAR_VIDEO_ALL_RENDERABLES(); component_count++; } // // If renderable counting is on, report how many renderables this entity // had and update the totals // if(component_count != 0) { cout<<"Class "<GetClassID()<<" had "<GetClassID() == MechClassID || entity->GetClassID() == VTVClassID || entity->GetClassID() == BTPlayerClassID) { CLEAR_VIDEO_VEHICLE_RENDERABLES(); } #endif } if(total_components != 0) cout<<"Renderables in entity sockets "<GetSize()<<" in the all iterator\n"; #endif // // Do a batch DCS flush if we need to // DPLDoDCSBatchFlush(); // // We use the complete cycle handler to take care of calling DrawScene as soon as // the renderer completes the the frame it's working on. // completeCycleNeeded = True; CLEAR_VIDEO_RENDERER(); CompleteCycle(); } // //############################################################################# // DPLDelayDCSFlush and DPLDoDCSBatchFlush queue up a list of DCS pointers // for later 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, 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 { 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(ostream &output) { output << "Free memory in card: " << dpl_FreeMemory() << " bytes." << endl; return; } // //############################################################################# // DPLReportPerfStats writes performance statistics to cout (stdout). //############################################################################# // void DPLRenderer::DPLReportPerfStats(ostream &output) { //----------------------------------------------------- // 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" << 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 << endl; if(statistics_started) { ReportStatistics(); } else { ResetStatistics(); statistics_started = True; } return; } // //############################################################################# // DPLToggleWireframe toggles the state of dpl global wireframe. //############################################################################# // void DPLRenderer::DPLToggleWireframe() { static Logical wireframe_on = 0; if ((wireframe_on ^= 1) != 0) { DEBUG_STREAM << "wireframe ON" << endl; dpl_SetRenderProperty(dpl_render_prop_wireframe, dpl_render_value_on, NULL ); } else { DEBUG_STREAM << "wireframe OFF" << endl; dpl_SetRenderProperty(dpl_render_prop_wireframe, dpl_render_value_off, NULL ); } } // //############################################################################# // DPLTogglePVision toggles the state of dpl "predator" vision. //############################################################################# // void DPLRenderer::DPLTogglePVision() { 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" << endl; sfx_info.type = -1; } else { DEBUG_STREAM << "pvision OFF" << endl; 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> 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 ) { //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." << 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> 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 << "' . . . "; fp = fopen(fname, "wb"); fwrite(tga_hdr, 18, 1, fp); for (y=0; y report_time) { ReportStatistics(); report_time = currentFrameTime + 60.0f; } } #if DEBUG_LEVEL > 0 // // Code to try and measure average frame rate // Only active for builds above d0 // current = Now(); FrameCount ++; if((current - StartSample) > 10.0f) { float frame_rate; frame_rate = FrameCount / (current-StartSample); if(frame_rate < 28.0f) printf("%4.2f fps\n", frame_rate); StartSample = Now(); FrameCount = 0; } #endif // // We've started the next frame, so indicate we don't need to do this again. // completeCycleNeeded = False; CLEAR_VIDEO_RENDERER_FRAME_DONE(); return True; } CLEAR_VIDEO_RENDERER_FRAME_DONE(); } return False; } // //############################################################################# // 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. { // 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 ); // cout<<"psfx identifier used was "<= 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); 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 ); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void DPLRenderer::SetViewAngle(Degree new_angle) { Check(this); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Convert From Degree To Radian //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Radian view_angle; view_angle = new_angle; viewAngle = view_angle; viewRatio = tan(viewAngle/2.0f); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Calc Aspect Ratio and Set View Projection //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // aspectRatio = (float) y_size / (float) x_size; dpl_SetViewProjection ( dplMainView, -1.0f, -aspectRatio, 1.0f, aspectRatio, 1.0f/viewRatio); dpl_FlushView(dplMainView); } // //############################################################################# // 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() { Check(this); uint32 *worst_case_texels = MakeBitSliceStorage(); Register_Pointer(worst_case_texels); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Get the Entity Group of Players //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // EntityGroup *player_group = application->GetEntityManager()->FindGroup("Players"); Check(player_group); ChainIteratorOf player_iterator(player_group->groupMembers); Player *current_player; BitMap *name_bitmap; while((current_player = (Player*) player_iterator.ReadAndNext() ) != NULL) { Check(current_player); name_bitmap = application->GetCurrentMission()-> GetLargeNameBitmap(current_player->playerBitmapIndex); if (name_bitmap && current_player->IsScoringPlayer()) { Check(name_bitmap); LoadBitSliceTexture( name_bitmap, // MUNGA 1 bit bitmap to load (current_player->playerRanking + 1), // Position to load bitmap into worst_case_texels // 8192 longword array for storage of the texmap ); } } LoadOrdinalBitmaps(worst_case_texels); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Flush all bitmaps down to the card //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // FlushBitSliceTexture(worst_case_texels); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Free the temporary memory the texmaps used //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Unregister_Pointer(worst_case_texels); free(worst_case_texels); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void DPLRenderer::LoadOrdinalBitmaps(unsigned int *worst_case_texels) { Check(this); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // 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::ClassDerivations)) ) { // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Make Sure index is in the right place // in case < 8 players!!!! //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int index = 9; for(int ii=1;ii<5;++ii) { // //~~~~~~~~~~~~~~~~~~ // Index Starts at 1 //~~~~~~~~~~~~~~~~~~ // BitMap *ordinal_bitmap = application->GetCurrentMission()->GetOrdinalBitmap(ii); Check(ordinal_bitmap); LoadBitSliceTexture( ordinal_bitmap, // MUNGA 1 bit bitmap to load index, // Position to load bitmap into worst_case_texels // 8192 longword array for storage of the texmap ); ++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() { Check(this); uint32 *worst_case_texels = MakeBitSliceStorage(); Register_Pointer(worst_case_texels); int player_count; player_count = application->GetCurrentMission()->GetPlayerCount(); Check(application); Check(application->GetCurrentMission()); BitMap *name_bitmap; for (int ii=0;iiGetCurrentMission()->GetLargeNameBitmap(ii+1); if (name_bitmap) { Check(name_bitmap); LoadBitSliceTexture( name_bitmap, // MUNGA 1 bit bitmap to load ii+1, // Position to load bitmap into worst_case_texels // 8192 longword array for storage of the texmap ); } } LoadOrdinalBitmaps(worst_case_texels); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Flush all bitmaps down to the card //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // FlushBitSliceTexture(worst_case_texels); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Free the temporary memory the texmaps used //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Unregister_Pointer(worst_case_texels); delete[] worst_case_texels; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void DPLRenderer::ShutdownImplementation() { Tell("DPLVideoRenderer::StopImplementation has been called\n"); dpl_EnableSyncOnCreate(); SChainIteratorOf projectile_iterator(&projectile_list); TreeIteratorOf cache_iterator(&dplObjectCacheSocket); #if defined(LAB_ONLY) cout<<"max projectiles "<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 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( dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later dpl_ZONE *this_zone) // DPL Zone this stuff will live in (for culling) { InnerProjectileRenderable *return_projectile; dpl_INSTANCE *temp_instance; // // Are there projectiles in the list? // SChainIteratorOf 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 this_zone); // 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::ClassDerivations)) { 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 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." << 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 '"< 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 " <GetVideoObject(); *((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); } //===========================================================================//