| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678 |
- /*
- ** 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 <http://www.gnu.org/licenses/>.
- */
- //
- // 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 "enbassetmgr.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 "vector2i.h"
- #include "bmp2d.h"
- #include "decalsys.h"
- #include "shattersystem.h"
- #include "light.h"
- #include "keyboard.h"
- #include "wwmouse.h"
- #include "predlod.h"
- #include "sphere.h"
- #include <stdio.h>
- #include "dx8renderer.h"
- #include "ini.h"
- #define MAX_LOADSTRING 100
- static void Log_Statistics();
- static void Init_3D_Scene();
- // 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;
- SimpleSceneClass * my_scene = NULL;
- CameraClass * my_camera = NULL;
- Render2DTextClass * mytext = NULL;
- RenderObjClass * orig_object = NULL;
- RenderObjClass * shift_object = NULL;
- HAnimClass * my_anim = NULL;
- Font3DInstanceClass *my_font_a=NULL;
- Font3DInstanceClass *my_font_b=NULL;
- DecalSystemClass TheDecalSystem;
- bool running=true;
- bool rotate=false;
- bool staticsort=true;
- bool sort=true;
- float sep;
- // 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 Render();
- void WWDebug_Message_Callback(DebugType type, const char * message);
- void WWAssert_Callback(const char * message);
- void Debug_Refs(void);
- void LoadAssets();
- // ----------------------------------------------------------------------------
- //
- // 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;i<frame_time_count;++i) {
- if (frame_times[i]<limit) {
- frame_times[i]=frame_times[frame_time_count-1];
- frame_time_count--;
- }
- }
- if (frame_time_count<MAX_FPS) {
- frame_times[frame_time_count++]=frame_time;
- }
- }
- // ----------------------------------------------------------------------------
- unsigned FPSCounterClass::Get_FPS()
- {
- return frame_time_count;
- }
- // ----------------------------------------------------------------------------
- //
- //
- //
- // ----------------------------------------------------------------------------
- int APIENTRY WinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
- {
- HACCEL hAccelTable;
- hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_SKELETON);
-
- // install debug callbacks
- WWDebug_Install_Message_Handler(WWDebug_Message_Callback);
- WWDebug_Install_Assert_Handler(WWAssert_Callback);
- // Initialize global strings
- LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
- LoadString(hInstance, IDC_SKELETON, szWindowClass, MAX_LOADSTRING);
- MyRegisterClass(hInstance);
- // Perform application initialization:
- hInst = hInstance; // Store instance handle in our global variable
- HWND hWnd = CreateWindow(
- szWindowClass,
- szTitle,
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- 0,
- CW_USEDEFAULT,
- 0,
- NULL,
- NULL,
- hInstance,
- NULL);
- ShowWindow(hWnd, nCmdShow);
- UpdateWindow(hWnd);
- // WW Inits
- WWMath::Init ();
- AssetManager=new ENBAssetManager;
- AssetManager->Register_Prototype_Loader(&_ParticleEmitterLoader);
- WW3D::Init(hWnd);
- WW3D::Set_Texture_Thumbnail_Mode(WW3D::TEXTURE_THUMBNAIL_MODE_ON);
- // 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(0,800,600,32,1,true)!=WW3D_ERROR_OK) {
- WW3D::Shutdown();
- WWMath::Shutdown ();
- Debug_Refs();
- return 0;
- }
-
- Init_3D_Scene();
- WW3D::Enable_Static_Sort_Lists(staticsort);
- WW3D::Enable_Sorting(sort);
- // main loop
- int time=timeGetTime();
- float theta = 0.0f;
- while (running)
- {
- if (rotate) {
- theta += DEG_TO_RADF(0.5f);
- Matrix3D tm(1);
- tm.Rotate_Z(theta);
- if (orig_object) orig_object->Set_Transform(tm);
- if (shift_object) shift_object->Set_Transform(tm);
- const SphereClass &sp1=shift_object->Get_Bounding_Sphere();
- const SphereClass &sp2=orig_object->Get_Bounding_Sphere();
- shift_object->Set_Position(Vector3(0,sep,0));
- orig_object->Set_Position(Vector3(0,-sep,0));
- }
-
- Render();
- Windows_Message_Handler();
- WW3D::Sync(timeGetTime()-time);
- Log_Statistics();
- }
- REF_PTR_RELEASE(my_scene);
- REF_PTR_RELEASE(my_camera);
- delete mytext;
- REF_PTR_RELEASE(my_font_a);
- REF_PTR_RELEASE(my_font_b);
- REF_PTR_RELEASE(orig_object);
- REF_PTR_RELEASE(shift_object);
- REF_PTR_RELEASE(my_anim);
- 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
-
- my_scene->Visibility_Check(my_camera);
- PredictiveLODOptimizerClass::Optimize_LODs(150000);
- WW3D::Begin_Render(true,true,Vector3(0.5f,0.5f,0.5f));
- // Render 3D scene
- WW3D::Render(my_scene,my_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;
- case IDM_RELOAD:
- LoadAssets();
- 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 '-':
- WW3D::Make_Screen_Shot("screen");
- break;
- case '+':
- WW3D::Toggle_Movie_Capture();
- break;
- case ' ':
- rotate=!rotate;
- break;
- case 's':
- staticsort=!staticsort;
- WW3D::Enable_Static_Sort_Lists(staticsort);
- break;
- case 'S':
- sort=!sort;
- WW3D::Enable_Sorting(sort);
- 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;
- }
- // ----------------------------------------------------------------------------
- //
- // 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
- }
- // ----------------------------------------------------------------------------
- void Debug_Refs(void)
- {
- #ifdef _DEBUG
- WWDEBUG_SAY(("Dumping Un-Released Ref-Counted objects...\r\n"));
- RefBaseNodeClass * first = RefBaseClass::ActiveRefList.First();
- RefBaseNodeClass * node = first;
- while (node->Is_Valid())
- {
- RefBaseClass * obj = node->Get();
- ActiveRefStruct * ref = &(obj->ActiveRefInfo);
- bool display = true;
- int count = 0;
- RefBaseNodeClass * search = first;
- while (search->Is_Valid()) {
- if (search == node) { // if this is not the first one
- if (count != 0) {
- display = false;
- break;
- }
- }
- RefBaseClass * 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;
- if (sort)
- format.Format("Sorting On\n");
- else
- format.Format("Sorting Off\n");
- status_text+=format;
- if (staticsort)
- format.Format("Static Sorting On\n");
- else
- format.Format("Static Sorting Off\n");
- status_text+=format;
- break;
- }
- mytext->Reset();
- mytext->Set_Location(Vector2(0.0,0.0));
- mytext->Draw_Text(status_text,0xffff0000);
- }
- void LoadAssets()
- {
- if (shift_object)
- {
- my_scene->Remove_Render_Object(shift_object);
- REF_PTR_RELEASE(shift_object);
- }
- if (orig_object)
- {
- my_scene->Remove_Render_Object(orig_object);
- REF_PTR_RELEASE(orig_object);
- }
- INIClass ini;
- ini.Load("hueshift.ini");
- StringClass asset=ini.Get_String("GENERAL","ASSET");
- float scale=ini.Get_Float("GENERAL","SCALE",1.0f);
- Vector3 hsv;
- hsv.X=ini.Get_Float("GENERAL","HUE",0.0f);
- hsv.Y=ini.Get_Float("GENERAL","SAT",1.0f);
- hsv.Z=ini.Get_Float("GENERAL","VAL",1.0f);
- AssetManager->Load_3D_Assets(asset+".w3d");
- shift_object = ((ENBAssetManager*)AssetManager)->Create_Render_Obj(asset,scale,hsv);
- orig_object = AssetManager->Create_Render_Obj(asset);
-
- if (shift_object && orig_object)
- {
- const SphereClass &sp1=shift_object->Get_Bounding_Sphere();
- const SphereClass &sp2=orig_object->Get_Bounding_Sphere();
- my_scene->Add_Render_Object(shift_object);
- my_scene->Add_Render_Object(orig_object);
- sep=WWMath::Max(sp1.Radius,sp2.Radius);
- shift_object->Set_Position(Vector3(0,sep,0));
- orig_object->Set_Position(Vector3(0,-sep,0));
- }
- Matrix3D camtransform(1);
- camtransform.Look_At(Vector3(3*sep,0,3*sep),Vector3(0,0,0),0);
- my_camera->Set_Transform(camtransform);
- my_camera->Set_Clip_Planes(1.0f,8*sep);
- }
- void Init_3D_Scene()
- {
- my_font_a = AssetManager->Get_Font3DInstance("font12x16.tga");
- my_font_b = AssetManager->Get_Font3DInstance("fontnew4.tga");
-
- mytext=new Render2DTextClass(my_font_a);
- mytext->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
- // build scene
- my_scene=NEW_REF(SimpleSceneClass,());
- my_scene->Set_Ambient_Light(Vector3(1.0f,1.0f,1.0f));
- my_camera=NEW_REF(CameraClass,());
- LoadAssets();
- }
|