/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ // // skeleton.cpp : Defines the entry point for the application. // // Skeleton WW3D code, Hector Yee, 8/31/00 #include "resource.h" #include "wwmath.h" #include "ww3d.h" #include "scene.h" #include "rendobj.h" #include "camera.h" #include "AssetMgr.H" #include "msgloop.h" #include "part_ldr.h" #include "rendobj.h" #include "hanim.h" #include "dx8wrapper.h" #include "dx8indexbuffer.h" #include "dx8vertexbuffer.h" #include "dx8fvf.h" #include "vertmaterial.h" #include "font3d.h" #include "render2d.h" #include "textdraw.h" #include "rect.h" #include "mesh.h" #include "meshmdl.h" #include "line3d.h" #include "dynamesh.h" #include "sphereobj.h" #include "ringobj.h" #include "surfaceclass.h" #include "vector2i.h" #include "bmp2d.h" #include "decalsys.h" #include "shattersystem.h" #include "light.h" #include "texproject.h" #include "keyboard.h" #include "wwmouse.h" #include "predlod.h" #include "segline.h" #include #include "dx8renderer.h" #include "textureloader.h" #define MAX_LOADSTRING 100 const int RESOLUTION_X = 640; const int RESOLUTION_Y = 480; const int BIT_DEPTH = 16; const Vector3 CAMERA_POSITION(3.0f,0.0f,1.0f); const Vector3 CAMERA_TARGET(0.0f,0.0f,0.90f); const Vector3 OBJECT_POSITION(0.0f,0.0f,0.0f); const char * OBJECT_NAME = "area1-LM"; const char * ANIM_NAME = NULL; static void Log_Statistics(); static void Init_Assets(); static void Init_3D_Scene(); static void Init_2D_Scene(); class SkeletonSceneClass; // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text WW3DAssetManager * AssetManager=NULL; SkeletonSceneClass * my_scene = NULL; SimpleSceneClass * my_2d_scene = NULL; CameraClass * my_camera = NULL; CameraClass * my_2d_camera = NULL; Render2DTextClass * mytext = NULL; RenderObjClass * my_object = NULL; HAnimClass * my_anim = NULL; TexProjectClass * my_texture_projector = NULL; MaterialPassClass * my_material_pass = NULL; LightClass * my_lights[3]; Font3DInstanceClass *my_font_a=NULL; Font3DInstanceClass *my_font_b=NULL; DecalSystemClass TheDecalSystem; bool running=true; bool rotate=true; bool randmat=false; bool randtex=false; bool staticsort=true; bool using_mat_pass=false; int shatter=0; // Foward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); void Enable_Alternate_Materials(RenderObjClass * model,bool onoff); void Render(); void Render2(); RenderObjClass * Create_Dynamesh(void); RenderObjClass * Create_Sphere(void); RenderObjClass * Create_Ring(void); RenderObjClass * Create_bitmap2d(void); RenderObjClass * Create_segline(void); void WWDebug_Message_Callback(DebugType type, const char * message); void WWAssert_Callback(const char * message); void Debug_Refs(void); void Create_Decal(RenderObjClass * obj,Matrix3D & tm,float radius,char * texture); MaterialPassClass * Create_Material_Pass(void); TexProjectClass * Create_Texture_Projector(void); // ---------------------------------------------------------------------------- // // FPS counter class counts how many times Update() has been called during the // last second. The fps counter caps at MAX_FPS which is the maximum fps count // that can be measured. // // ---------------------------------------------------------------------------- const unsigned MAX_FPS=2000; class FPSCounterClass { unsigned frame_times[MAX_FPS]; unsigned frame_time_count; public: FPSCounterClass(); void Update(); unsigned Get_FPS(); }; static FPSCounterClass fps_counter; // ---------------------------------------------------------------------------- FPSCounterClass::FPSCounterClass() : frame_time_count(0) { } // ---------------------------------------------------------------------------- void FPSCounterClass::Update() { unsigned frame_time=timeGetTime(); unsigned limit=frame_time-1000; for (unsigned i=0;iRegister_Prototype_Loader(&_ParticleEmitterLoader); AssetManager->Load_3D_Assets("ShatterPlanes0.w3d"); // Shatter planes WW3D::Init(hWnd); // WW3D::Set_Prelit_Mode(WW3D::PRELIT_MODE_VERTEX); WW3D::Set_Prelit_Mode(WW3D::PRELIT_MODE_LIGHTMAP_MULTI_PASS); // WW3D::Set_Prelit_Mode(WW3D::PRELIT_MODE_LIGHTMAP_MULTI_TEXTURE); // WW3D::Set_Collision_Box_Display_Mask(0xFF); if (WW3D::Set_Render_Device(-1,RESOLUTION_X,RESOLUTION_Y,BIT_DEPTH,1,true)!=WW3D_ERROR_OK) { if (WW3D::Set_Any_Render_Device()!=WW3D_ERROR_OK) { WW3D::Shutdown(); WWMath::Shutdown (); Debug_Refs(); return 0; } } Init_Assets(); Init_2D_Scene(); Init_3D_Scene(); // main loop int time=timeGetTime(); float theta = 0.0f; while (running) { if (my_object && rotate) { theta += DEG_TO_RADF(0.1f); Matrix3D tm(1); tm.Rotate_Z(theta); //tm.Rotate_X(theta*1.37f); //tm.Rotate_Y(theta*1.09f); tm.Set_Translation(OBJECT_POSITION); my_object->Set_Transform(tm); } if (my_object && my_texture_projector) { my_texture_projector->Set_Transform(my_object->Get_Bone_Transform("ProjectorBone")); } if (shatter==1) { if (my_object->Class_ID()==RenderObjClass::CLASSID_MESH) { my_scene->Remove_Render_Object(my_object); ShatterSystem::Shatter_Mesh((MeshClass*)my_object,Vector3(0,0,0),Vector3(1,0,0)); REF_PTR_RELEASE(my_object); int count=ShatterSystem::Get_Fragment_Count(); int i; for (i=0; iSet_Position(my_object->Get_Position()+Vector3(rand()%15,rand()%15,rand()%15)); my_scene->Add_Render_Object(my_object); REF_PTR_RELEASE(my_object); } } shatter++; } if (randmat) { if (my_object->Class_ID()==RenderObjClass::CLASSID_MESH) { MeshClass *mesh=(MeshClass*) my_object; MaterialInfoClass *mi=mesh->Get_Material_Info(); VertexMaterialClass *vm=mi->Get_Vertex_Material(0); VertexMaterialClass *newvm=NEW_REF(VertexMaterialClass,(*vm)); newvm->Set_Emissive(rand()%256/256.0,rand()%256/256.0,rand()%256/256.0); mesh->Replace_VertexMaterial(vm,newvm); mi->Replace_Material(0,newvm); REF_PTR_RELEASE(vm); REF_PTR_RELEASE(newvm); } randmat=!randmat; } if (randtex) { if (my_object->Class_ID()==RenderObjClass::CLASSID_MESH) { MeshClass *mesh=(MeshClass*) my_object; MaterialInfoClass *mi=mesh->Get_Material_Info(); TextureClass *tex=mi->Peek_Texture(0); int ran=rand() % 3; char name[100]; switch (ran) { case 0: sprintf(name,"catwalk.tga"); break; case 1: sprintf(name,"chickonmap.tga"); break; case 2: sprintf(name,"fullmoon.tga"); break; } TextureClass *newtex=AssetManager->Get_Texture(name); mesh->Replace_Texture(tex,newtex); mi->Replace_Texture(0,newtex); REF_PTR_RELEASE(newtex); } randtex=!randtex; } if (my_texture_projector != NULL) { my_texture_projector->Pre_Render_Update(my_camera->Get_Transform()); } WW3D::Enable_Static_Sort_Lists(staticsort); Render(); Windows_Message_Handler(); WW3D::Sync(timeGetTime()-time); Log_Statistics(); } REF_PTR_RELEASE(my_scene); REF_PTR_RELEASE(my_camera); REF_PTR_RELEASE(my_2d_scene); REF_PTR_RELEASE(my_2d_camera); REF_PTR_RELEASE(my_lights[0]); REF_PTR_RELEASE(my_lights[1]); REF_PTR_RELEASE(my_lights[2]); delete mytext; REF_PTR_RELEASE(my_font_a); REF_PTR_RELEASE(my_font_b); REF_PTR_RELEASE(my_object); REF_PTR_RELEASE(my_anim); REF_PTR_RELEASE(my_material_pass); REF_PTR_RELEASE(my_texture_projector); PredictiveLODOptimizerClass::Free(); // shutdown AssetManager->Free_Assets (); delete AssetManager; WW3D::Shutdown (); WWMath::Shutdown (); Debug_Refs(); return 0; } // ---------------------------------------------------------------------------- // // Render everything. Rendering stars with Begin_Scene() and ends to End_Scene(). // // ---------------------------------------------------------------------------- void Render() { // Predictive LOD optimizer optimizes the mesh LOD levels to match the given polygon budget PredictiveLODOptimizerClass::Optimize_LODs(5000); WW3D::Begin_Render(true,true,Vector3(0.0f,0.0f,0.0f)); // Render 3D scene WW3D::Render(my_scene,my_camera); // Render 2D scene WW3D::Render(my_2d_scene,my_2d_camera); if (mytext) mytext->Render(); WW3D::End_Render(); fps_counter.Update(); } // ---------------------------------------------------------------------------- // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage is only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // // ---------------------------------------------------------------------------- ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SKELETON); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCSTR)IDC_SKELETON; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } // ---------------------------------------------------------------------------- // // FUNCTION: WndProc(HWND, unsigned, WORD, LONG) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // // ---------------------------------------------------------------------------- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_ACTIVATEAPP: if (wParam) WW3D::On_Activate_App(); else WW3D::On_Deactivate_App(); return DefWindowProc(hWnd, message, wParam, lParam); case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... EndPaint(hWnd, &ps); break; case WM_DESTROY: running=false; PostQuitMessage(0); break; case WM_KEYUP: if ((wParam&0xff)==VK_ESCAPE) { DestroyWindow(hWnd); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); case WM_CHAR: { char key=LOWORD(wParam); switch (key) { case ' ': shatter++; break; case '-': WW3D::Make_Screen_Shot("screen"); break; case '+': WW3D::Toggle_Movie_Capture(); break; case 'r': rotate=!rotate; break; case '1': WW3D::Set_NPatches_Level(1); break; case '2': WW3D::Set_NPatches_Level(2); break; case '3': WW3D::Set_NPatches_Level(3); break; case '4': WW3D::Set_NPatches_Level(4); break; case '5': WW3D::Set_NPatches_Level(5); break; case '6': WW3D::Set_NPatches_Level(6); break; case '7': WW3D::Set_NPatches_Level(7); break; case '8': WW3D::Set_NPatches_Level(8); break; case 'q': randmat=!randmat; break; case 'w': randtex=!randtex; break; case 's': staticsort=!staticsort; break; case 'b': { using_mat_pass=!using_mat_pass; if (!using_mat_pass) { my_scene->Set_Material_Pass(0); } else { my_scene->Set_Material_Pass(my_material_pass); } } break; case 'g': { if (WW3D::Get_NPatches_Gap_Filling_Mode()==WW3D::NPATCHES_GAP_FILLING_DISABLED) { WW3D::Set_NPatches_Gap_Filling_Mode(WW3D::NPATCHES_GAP_FILLING_ENABLED); } else { WW3D::Set_NPatches_Gap_Filling_Mode(WW3D::NPATCHES_GAP_FILLING_DISABLED); } } break; case 'm': { SceneClass::PolyRenderType type = my_scene->Get_Polygon_Mode(); type = (type == SceneClass::POINT) ? SceneClass::LINE : ((type == SceneClass::LINE) ? SceneClass::FILL : SceneClass::POINT); my_scene->Set_Polygon_Mode(type); } break; } } default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Mesage handler for about box. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; } void Enable_Alternate_Materials(RenderObjClass * model,bool onoff) { if (model == NULL) return; for (int i=0; iGet_Num_Sub_Objects(); i++) { RenderObjClass * subobj = model->Get_Sub_Object(i); Enable_Alternate_Materials(subobj,onoff); REF_PTR_RELEASE(subobj); } if (model->Class_ID() == RenderObjClass::CLASSID_MESH) { MeshModelClass * mesh_model = ((MeshClass *)model)->Get_Model(); mesh_model->Enable_Alternate_Material_Description(onoff); REF_PTR_RELEASE(mesh_model); } } // ---------------------------------------------------------------------------- // // WWDebug message callback defines the behavior of WWDEBUG_SAY(). // // ---------------------------------------------------------------------------- void WWDebug_Message_Callback(DebugType type, const char * message) { OutputDebugString(message); } // ---------------------------------------------------------------------------- // // WWAssert callback defines the behavior of WWASSERT(). // // ---------------------------------------------------------------------------- void WWAssert_Callback(const char * message) { OutputDebugString(message); _asm int 0x03 } // ---------------------------------------------------------------------------- RenderObjClass * Create_Dynamesh(void) { // Create a tetrahedron DynamicMeshClass *dynamesh = NEW_REF(DynamicMeshClass, (4, 6)); dynamesh->Set_Shader(ShaderClass::_PresetOpaqueShader); VertexMaterialClass *vm = VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_NODIFFUSE); dynamesh->Set_Vertex_Material(vm); vm->Release_Ref(); TextureClass *texture = AssetManager->Get_Texture("chickonmap.tga"); dynamesh->Set_Texture(texture); texture->Release_Ref(); dynamesh->Vertex(0.0f, 100.0f, 0.0f, 1.0f, 0.0f); dynamesh->Vertex(100.0f, -100.0f, 0.0f ,1.0f, -1.0f); dynamesh->Vertex(-100.0f, -100.0f, 0.0f, -1.0f, -1.0f); dynamesh->Vertex(0.0f, -100.0f, -100.0f, 0.0f, 0.0f); dynamesh->Vertex(0.0f, 100.0f, 0.0f, 1.0f, 0.0f); dynamesh->Vertex(100.0f, -100.0f, 0.0f ,1.0f, -1.0f); return dynamesh; } RenderObjClass *Create_segline(void) { SegmentedLineClass *segline = NEW_REF(SegmentedLineClass,()); Vector3 locations[4]; locations[0].Set(0,0,0); locations[1].Set(50,50,50); locations[2].Set(50,-50,10); locations[3].Set(-50,50,10); segline->Set_Points(4, locations); //segline->Set_Shader(ShaderClass::_PresetOpaqueShader); segline->Set_Shader(ShaderClass::_PresetAlphaShader); segline->Set_Color(Vector3(1,0,1)); segline->Set_Opacity(0.5); segline->Set_Freeze_Random(1); segline->Set_Visible(1); segline->Set_Width(10); TextureClass *tex=NEW_REF(TextureClass,("cloudlayer.tga")); segline->Set_Texture(tex); REF_PTR_RELEASE(tex); // segline->Set_Texture_Mapping_Mode(SegmentedLineClass::TILED_TEXTURE_MAP); segline->Set_Texture_Tile_Factor(5); segline->Set_Noise_Amplitude(5); segline->Set_Merge_Intersections(1); return segline; } // ---------------------------------------------------------------------------- RenderObjClass * Create_Sphere(void) { SphereRenderObjClass *sph=NEW_REF(SphereRenderObjClass,()); sph->Set_Color(Vector3(1,0,1)); sph->Set_Scale(Vector3(100,100,100)); return sph; } // ---------------------------------------------------------------------------- RenderObjClass * Create_bitmap2d(void) { Bitmap2DObjClass *bmp=NEW_REF(Bitmap2DObjClass,("chickonmap.tga",0.0,0.0,false,false,false)); return bmp; } // ---------------------------------------------------------------------------- RenderObjClass * Create_Ring(void) { RingRenderObjClass *rng=NEW_REF(RingRenderObjClass,()); rng->Set_Color(Vector3(1,0,1)); rng->Set_Inner_Scale(Vector2(10,10)); rng->Set_Outer_Scale(Vector2(50,50)); return rng; } // ---------------------------------------------------------------------------- void Create_Decal(RenderObjClass * robj,Matrix3D & tm,float radius,char * texture_name) { /* ** Allocate the decal generator */ DecalGeneratorClass * gen = TheDecalSystem.Lock_Decal_Generator(); WWASSERT(gen != NULL); /* ** Set up the transform, projection, and bounding volume parameters */ const float DECAL_HALF_SLAB_THICKNESS = 50.0f; const float DECAL_BACKFACE_THRESHHOLD = 0.0f; float backup_dist = DECAL_HALF_SLAB_THICKNESS + 0.01f; Matrix3D transform = tm; transform.Translate_Z(backup_dist); gen->Set_Transform(transform); gen->Set_Ortho_Projection(-radius,radius,-radius,radius,0.01f,backup_dist + 2.0f * DECAL_HALF_SLAB_THICKNESS); gen->Set_Backface_Threshhold(DECAL_BACKFACE_THRESHHOLD); /* ** Set up the material settings. Just plug in the standard alpha shader and the ** vertex material which all decals use. Then grab the texture which the user ** specified... */ MaterialPassClass * material = gen->Get_Material(); VertexMaterialClass * decal_mtl = NEW_REF(VertexMaterialClass,()); decal_mtl->Set_Ambient(0,0,0); decal_mtl->Set_Diffuse(0,0,0); decal_mtl->Set_Specular(0,0,0); decal_mtl->Set_Emissive(1,1,1); decal_mtl->Set_Opacity(1.0f); decal_mtl->Set_Shininess(0.0f); TextureClass * tex = WW3DAssetManager::Get_Instance()->Get_Texture(texture_name); tex->Set_U_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP); tex->Set_V_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP); material->Set_Shader(ShaderClass::_PresetAlphaShader); material->Set_Material(decal_mtl); material->Set_Texture(tex); REF_PTR_RELEASE(decal_mtl); REF_PTR_RELEASE(tex); REF_PTR_RELEASE(material); /* ** Apply! */ robj->Create_Decal(gen); TheDecalSystem.Unlock_Decal_Generator(gen); } // ---------------------------------------------------------------------------- MaterialPassClass * Create_Material_Pass(void) { TextureClass * texture = WW3DAssetManager::Get_Instance()->Get_Texture("decal.tga"); VertexMaterialClass * mtl = NEW_REF(VertexMaterialClass,()); mtl->Set_Diffuse(0.5f,0.5f,0.5f); mtl->Set_Specular(0,0,0); mtl->Set_Ambient(0,0,0); mtl->Set_Emissive(0.5f,0.5f,0.5f); mtl->Set_Lighting(false); EnvironmentMapperClass * mapper = NEW_REF(EnvironmentMapperClass,(0)); mtl->Set_Mapper(mapper,0); MaterialPassClass * test_pass = NEW_REF(MaterialPassClass,()); test_pass->Set_Shader(ShaderClass::_PresetAdditiveShader); test_pass->Set_Material(mtl); test_pass->Set_Texture(texture); REF_PTR_RELEASE(mtl); REF_PTR_RELEASE(texture); REF_PTR_RELEASE(mapper); return test_pass; } // ---------------------------------------------------------------------------- TexProjectClass * Create_Texture_Projector(void) { const float SIZE = 10.0f; const float ZNEAR = 0.1f; const float ZFAR = 300.0f; TexProjectClass * new_projector = NEW_REF(TexProjectClass,()); new_projector->Init_Additive(); new_projector->Set_Intensity(1.0,true); new_projector->Set_Ortho_Projection(-SIZE,SIZE,-SIZE,SIZE,ZNEAR,ZFAR); Matrix3D tm; tm.Look_At(Vector3(200,200,200),Vector3(0,0,0),0.0f); new_projector->Set_Transform(tm); TextureClass * texture = WW3DAssetManager::Get_Instance()->Get_Texture("GreenSpot.tga"); new_projector->Set_Texture(texture); REF_PTR_RELEASE(texture); return new_projector; } // ---------------------------------------------------------------------------- void Debug_Refs(void) { #ifdef _DEBUG WWDEBUG_SAY(("Dumping Un-Released Ref-Counted objects...\r\n")); RefCountNodeClass * first = RefCountClass::ActiveRefList.First(); RefCountNodeClass * node = first; while (node->Is_Valid()) { RefCountClass * obj = node->Get(); ActiveRefStruct * ref = &(obj->ActiveRefInfo); bool display = true; int count = 0; RefCountNodeClass * search = first; while (search->Is_Valid()) { if (search == node) { // if this is not the first one if (count != 0) { display = false; break; } } RefCountClass * search_obj = search->Get(); ActiveRefStruct * search_ref = &(search_obj->ActiveRefInfo); if ( ref->File && search_ref->File && !strcmp(search_ref->File, ref->File) && (search_ref->Line == ref->Line) ) { count++; } else if ( (ref->File == NULL) && (search_ref->File == NULL) ) { count++; } search = search->Next(); } if ( display ) { WWDEBUG_SAY(( "%d Active Ref: %s %d %p\n", count, ref->File,ref->Line,obj)); static int num_printed = 0; if (++num_printed > 20) { WWDEBUG_SAY(( "And Many More......\n")); break; } } node = node->Next(); } WWDEBUG_SAY(("Done.\r\n")); #endif } // ---------------------------------------------------------------------- // // Ugly statistics block!!! // // ---------------------------------------------------------------------- void Log_Statistics() { StringClass format(255,true); StringClass status_text(500,true); // static unsigned last_frame_time=0; // unsigned frame_time=timeGetTime(); // unsigned time=frame_time-last_frame_time; // last_frame_time=frame_time; // if (time>1000) time=1000; // float fps=1000.0f/float(time); // static float time_fps; // static float current_fps; // static unsigned fps_count; // time_fps+=fps; // fps_count++; // if (fps_count==20) { // fps_count=0; // current_fps=time_fps/20.0f; // time_fps=0.0f; // } unsigned current_fps=fps_counter.Get_FPS(); static unsigned stats_mode; static bool tab_pressed; if (GetAsyncKeyState(VK_TAB)) { if (!tab_pressed) { stats_mode++; stats_mode%=3; } tab_pressed=true; } else { tab_pressed=false; } switch (stats_mode) { case 0: Debug_Statistics::Record_Texture_Mode(Debug_Statistics::RECORD_TEXTURE_NONE); break; case 1: Debug_Statistics::Record_Texture_Mode(Debug_Statistics::RECORD_TEXTURE_NONE); format.Format("%d FPS\n",current_fps); status_text+=format; format.Format("%d Polys/frame (%dk pps)\n",Debug_Statistics::Get_DX8_Polygons(),unsigned(Debug_Statistics::Get_DX8_Polygons()*float(current_fps))/1000); status_text+=format; break; case 2: Debug_Statistics::Record_Texture_Mode(Debug_Statistics::RECORD_TEXTURE_NONE); format.Format("%d FPS\n",current_fps); status_text+=format; format.Format("%d Polys/frame (%dk pps)\n",Debug_Statistics::Get_DX8_Polygons(),unsigned(Debug_Statistics::Get_DX8_Polygons()*float(current_fps))/1000); status_text+=format; format.Format("%d Verts/frame (%dk vps)\n",Debug_Statistics::Get_DX8_Vertices(),unsigned(Debug_Statistics::Get_DX8_Vertices()*float(current_fps))/1000); status_text+=format; format.Format("%d DX8 calls\n",DX8Wrapper::Get_Last_Frame_DX8_Calls()); status_text+=format; format.Format("%d VB changes\n",DX8Wrapper::Get_Last_Frame_Vertex_Buffer_Changes()); status_text+=format; format.Format("%d IB changes\n",DX8Wrapper::Get_Last_Frame_Index_Buffer_Changes()); status_text+=format; format.Format("%d texture changes\n",DX8Wrapper::Get_Last_Frame_Texture_Changes()); status_text+=format; format.Format("%d material changes\n",DX8Wrapper::Get_Last_Frame_Material_Changes()); status_text+=format; format.Format("%d light changes\n",DX8Wrapper::Get_Last_Frame_Light_Changes()); status_text+=format; format.Format("%d RS changes\n",DX8Wrapper::Get_Last_Frame_Render_State_Changes()); status_text+=format; format.Format("%d TSS changes\n",DX8Wrapper::Get_Last_Frame_Texture_Stage_State_Changes()); status_text+=format; format.Format("%d Mtx changes\n",DX8Wrapper::Get_Last_Frame_Matrix_Changes()); status_text+=format; break; } mytext->Reset(); mytext->Set_Location(Vector2(0.0,0.0)); mytext->Draw_Text(status_text,0xffff0000); } // ---------------------------------------------------------------------------- void Init_Assets() { TextureClass *tex=AssetManager->Get_Texture("PPVF0102.TGA"); REF_PTR_RELEASE(tex); // Preload test assets. Note that not all of these will actually be used. /* AssetManager->Load_3D_Assets("GreenSphere.w3d"); // Tests regular meshes AssetManager->Load_3D_Assets("TexSphere.w3d"); // Tests texture mapping AssetManager->Load_3D_Assets("TexScrlSphere.w3d"); // Tests Linear Offset mapper AssetManager->Load_3D_Assets("SphereAnim.w3d"); // Tests hierarchical animation (if you install its anim) AssetManager->Load_3D_Assets("SkinTest.w3d"); // Tests skinning and environment mapping AssetManager->Load_3D_Assets("sorting_test.w3d"); // Tests skinning and environment mapping AssetManager->Load_3D_Assets("boxtest.w3d"); // Tests BoxRenderObjClass (turn on the box display mask) AssetManager->Load_3D_Assets("Test1.w3d"); // Test yellow particles AssetManager->Load_3D_Assets("Test2.w3d"); // Tests alpha particles AssetManager->Load_3D_Assets("MPassSphere.w3d"); // Tests more than 2 passes on a mesh AssetManager->Load_3D_Assets("MPassTeapot.w3d"); // Tests more that 2 passes AssetManager->Load_3D_Assets("DupSphere.w3d"); // Tests 3 passes which all share the same uv coords AssetManager->Load_3D_Assets("vcolortest.w3d"); // Tests vertex color AssetManager->Load_3D_Assets("valphatest.w3d"); // Tests vertex alpha AssetManager->Load_3D_Assets("LightmapTest0.w3d"); // Tests pre-lighting, 3 solves: vertex, multi-pass, multi-stage AssetManager->Load_3D_Assets("LightmapTest1.w3d"); // Tests pre-lighting with alternate solves! (not currently runtime switchable) AssetManager->Load_3D_Assets("CubeSkin.w3d"); // Tests a simple skin, also can be used to test decals on skin meshes AssetManager->Load_3D_Assets("ProjectorTest.w3d"); // This model contains a mesh and an animated "ProjectorBone" for testing texture projections AssetManager->Load_3D_Assets("PolyRateTest.w3d"); // This model has lots of polys! AssetManager->Load_3D_Assets("PPVF01A.w3d"); // Game asset AssetManager->Load_3D_Assets("SPHERE_TEST.w3d"); // Tests multitexturing AssetManager->Load_3D_Assets("SCREEN_ALIGN.w3d"); // Tests camera aligned meshes AssetManager->Load_3D_Assets("halfsphere.w3d"); // Tests two-sided flag, camera aligned, and camera oriented meshes AssetManager->Load_3D_Assets("tsi01a.w3d"); // Tests static sort level AssetManager->Load_3D_Assets("tsi08a.w3d"); // Tests static sort level */ AssetManager->Load_3D_Assets("area1-LM.w3d"); /* AssetManager->Load_3D_Assets("S_A_Human.W3D"); AssetManager->Load_3D_Assets("c_nod_rsold_L0.W3D"); AssetManager->Load_3D_Assets("h_a_a0a1.W3D"); */ } // ---------------------------------------------------------------------------- // // Create a scene for 2D-display, such as text and rectangles. // // ---------------------------------------------------------------------------- void Init_2D_Scene() { // Create a scene for the 2D stuff ----------------------------------------- my_2d_scene=NEW_REF(SimpleSceneClass,()); my_2d_scene->Set_Ambient_Light(Vector3(1,1,1)); // Create fonts to be used for text rendering ------------------------------ my_font_a = AssetManager->Get_Font3DInstance("font12x16.tga"); my_font_b = AssetManager->Get_Font3DInstance("fontnew4.tga"); mytext=new Render2DTextClass(my_font_b); mytext->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); // Scene needs camera to be rendered with ---------------------------------- my_2d_camera = NEW_REF(CameraClass,()); #ifdef DRAWBITMAP my_2d_camera->Set_Position(Vector3(0,0,1)); my_2d_camera->Set_Clip_Planes(0.995,2); #else my_2d_camera->Set_Position(Vector3(0,0,320)); my_2d_camera->Set_Clip_Planes(300,1000); #endif Vector2 min = Vector2(-1, -0.75f); Vector2 max = Vector2(+1, +0.75f); my_2d_camera->Set_View_Plane(min, max); } void Init_3D_Scene() { WW3D::Enable_Sorting(false); WW3D::Set_NPatches_Level(1); // build scene my_scene=NEW_REF(SkeletonSceneClass,()); my_scene->Set_Ambient_Light(Vector3(0.5f,0.5f,0.5f)); // set up a light my_lights[0]=my_lights[1]=my_lights[2]=NULL; my_lights[0]=NEW_REF(LightClass,(LightClass::DIRECTIONAL)); my_lights[0]->Set_Ambient(Vector3(0.1f,0.1f,0.1f)); my_lights[0]->Set_Diffuse(Vector3(1.0f,1.0f,1.0f)); my_lights[0]->Set_Spot_Direction(Vector3(0,1,0)); my_scene->Add_Render_Object(my_lights[0]); // Scene needs camera to be rendered with ---------------------------------- my_camera=NEW_REF(CameraClass,()); Matrix3D camtransform(1); camtransform.Look_At(CAMERA_POSITION,CAMERA_TARGET,0); my_camera->Set_Transform(camtransform); my_object = AssetManager->Create_Render_Obj(OBJECT_NAME); if (ANIM_NAME != NULL) { my_anim = AssetManager->Get_HAnim(ANIM_NAME); } if (my_object != NULL) { my_object->Set_Position(OBJECT_POSITION); #if 0 Enable_Alternate_Materials(my_object,true); #endif // Decal System #if 0 Matrix3D decal_tm; decal_tm.Look_At(Vector3(30,5,10),Vector3(0,0,10),DEG_TO_RADF(65.5f)); Create_Decal(my_object,decal_tm,13.7f,"decal.tga"); #endif // PredictiveLODOptimizerClass::Add_Object(my_object); my_object->Set_Position(Vector3(0,0,0)); if (my_anim != NULL) { my_object->Set_Animation(my_anim,0,RenderObjClass::ANIM_MODE_LOOP); } my_scene->Add_Render_Object(my_object); if (my_object->Class_ID()==RenderObjClass::CLASSID_PARTICLEEMITTER) { ((ParticleEmitterClass*) my_object)->Start(); } } // 3D line object ---------------------------------------------------------- #if 0 Line3DClass *line = NULL; line = NEW_REF(Line3DClass,(Vector3(0,0,0),Vector3(100,100,0), 10,1,1,1,1)); my_scene->Add_Render_Object(line); REF_PTR_RELEASE(line); // Obejct can be freed after adding scene so that it gets killed when scene dies #endif // Create texture projector material pass ---------------------------------- #if 0 my_texture_projector = Create_Texture_Projector(); my_scene->Set_Material_Pass(my_texture_projector->Peek_Material_Pass()); // REF_PTR_RELEASE(my_texture_projector); #endif // Create material pass ---------------------------------------------------- #if 0 my_material_pass = Create_Material_Pass(); my_scene->Set_Material_Pass(my_material_pass); REF_PTR_RELEASE(my_material_pass); #endif }