| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- /*
- ** 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/>.
- */
- // GeneratingVisDialog.cpp : implementation file
- //
- #include "stdafx.h"
- #include "leveledit.h"
- #include "generatingvisdialog.h"
- #include "utils.h"
- #include "sceneeditor.h"
- #include "nodemgr.h"
- #include "vispointgenerator.h"
- #include "leveleditview.h"
- #include "groupmgr.h"
- #include "node.h"
- #include "VisPointNode.h"
- #include "camera.h"
- #include "cameramgr.h"
- #include "vismgr.h"
- #include "vissectorsampler.h"
- #include "visgenprogress.h"
- #include "collisiongroups.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- //
- // GeneratingVisDialogClass dialog
- //
- /////////////////////////////////////////////////////////////////////////////
- GeneratingVisDialogClass::GeneratingVisDialogClass (float granularity, CWnd *parent)
- : m_bStop (false),
- m_Granularity (granularity),
- m_SampleHeight (10.0f),
- m_CurrentPoint (0),
- m_TotalPoints (0),
- m_StartTime (0),
- m_FarmMode (false),
- m_IgnoreBias (false),
- m_SelectionOnly (false),
- CDialog(GeneratingVisDialogClass::IDD, parent)
- {
- //{{AFX_DATA_INIT(GeneratingVisDialogClass)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
- //
- // Determine the section of the status file
- //
- DWORD process_id = ::GetCurrentProcessId ();
- m_StatusSection.Format ("%d", process_id);
- //
- // Get the installation directory of this application
- //
- TCHAR exe_path[MAX_PATH] = { 0 };
- ::GetModuleFileName (::AfxGetInstanceHandle (), exe_path, sizeof (exe_path));
- CString path = ::Strip_Filename_From_Path (exe_path);
- if (path[::lstrlen(path)-1] != '\\') {
- path += "\\";
- }
- m_StatusFilename = path + "status.vis";
- ::WritePrivateProfileString ("Status", m_StatusSection, "Point Gen", m_StatusFilename);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // GeneratingVisDialogClass
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- GeneratingVisDialogClass::DoDataExchange (CDataExchange *pDX)
- {
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(GeneratingVisDialogClass)
- DDX_Control(pDX, IDC_PROGRESS_CTRL, m_ProgressCtrl);
- //}}AFX_DATA_MAP
- return ;
- }
- BEGIN_MESSAGE_MAP(GeneratingVisDialogClass, CDialog)
- //{{AFX_MSG_MAP(GeneratingVisDialogClass)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- //////////////////////////////////////////////////////////////////////////////
- //
- // OnInitDialog
- //
- //////////////////////////////////////////////////////////////////////////////
- BOOL
- GeneratingVisDialogClass::OnInitDialog (void)
- {
- CDialog::OnInitDialog ();
- m_ProgressCtrl.SetRange (0, 100);
- m_ProgressCtrl.SetPos (0);
- ShowWindow (SW_SHOW);
- PostMessage (WM_USER+101);
- return TRUE;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // OnCancel
- //
- //////////////////////////////////////////////////////////////////////////////
- void
- GeneratingVisDialogClass::OnCancel (void)
- {
- m_bStop = true;
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reset_Vis_Data_For_Nodes
- //
- //////////////////////////////////////////////////////////////////////////////
- void
- GeneratingVisDialogClass::Reset_Vis_Data_For_Nodes (NODE_LIST &node_list)
- {
- SceneEditorClass *scene = ::Get_Scene_Editor ();
- if (scene == NULL) {
- return ;
- }
- //
- // Reset vis for the current node list
- //
- for (int index = 0; index < node_list.Count (); index ++) {
- NodeClass *node = node_list[index];
- if (node != NULL) {
- scene->Reset_Vis_For_Node (node);
- }
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Build_Node_List
- //
- //////////////////////////////////////////////////////////////////////////////
- void
- GeneratingVisDialogClass::Build_Node_List (NODE_LIST &node_list)
- {
- //
- // Build a list of nodes that should be used to calculate
- // vis renders
- //
- VisMgrClass::Build_Node_List (node_list, m_SelectionOnly);
- //
- // Determine which nodes to process if we
- // are in farm mode.
- //
- if (m_FarmMode) {
- int nodes = node_list.Count ();
- float nodes_per_processor = ((float)nodes) / ((float)m_TotalProcessors);
- int starting_node = (int)::floor (nodes_per_processor * (float)m_ProcessorIndex);
- int ending_node = (int)::ceil (nodes_per_processor * (float)(m_ProcessorIndex+1));
- ending_node = min (ending_node, nodes);
- //
- // Copy the nodes from the total list into a temporary list
- //
- NODE_LIST temp_list;
- for (int index = starting_node; index < ending_node; index ++) {
- temp_list.Add (node_list[index]);
- }
- node_list.Delete_All ();
- node_list = temp_list;
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // WindowProc
- //
- //////////////////////////////////////////////////////////////////////////////
- LRESULT
- GeneratingVisDialogClass::WindowProc
- (
- UINT message,
- WPARAM wParam,
- LPARAM lParam
- )
- {
- if (message == WM_USER+101) {
- ::Get_Main_View ()->Allow_Repaint (false);
- m_StartTime = ::GetTickCount();
- //
- // Build a list of nodes we should use during the vis-generation
- //
- NODE_LIST node_list;
- Build_Node_List (node_list);
- //
- // Reset vis if we are doing a selection set only
- //
- if (m_SelectionOnly) {
- Reset_Vis_Data_For_Nodes (node_list);
- }
- //
- // Generate a list of points we need to render
- //
- VisPointGeneratorClass generator (m_Granularity);
- generator.Set_Ignore_Bias (m_IgnoreBias);
- generator.Set_Vis_Sample_Height (m_SampleHeight);
- Generate_Points (node_list, generator);
- //
- // Update the dialog so the user know we are about to start rendering
- // vis points
- //
- ::ShowWindow (::GetDlgItem (m_hWnd, IDC_BUILD_LIST_CHECK_ICON), SW_SHOW);
- m_ProgressCtrl.SetPos (0);
- General_Pump_Messages ();
- //
- // Setup the vis render
- //
- SceneEditorClass *scene_editor = ::Get_Scene_Editor ();
- bool restore_vis_point_display = scene_editor->Are_Vis_Points_Displayed ();
- scene_editor->Display_Vis_Points (false);
- m_TotalPoints = generator.Get_Total_Points ();
- m_CurrentPoint = 0;
- scene_editor->Set_Total_Vis_Points (m_TotalPoints);
- //
- // Render the generated vis points
- //
- VIS_POINT_LIST &point_list = generator.Peek_Point_List ();
- Render_Vis_Points (point_list);
-
- //
- // Update the dialog so the user knows we are done
- //
- ::ShowWindow (::GetDlgItem (m_hWnd, IDC_BUILD_LIST_CHECK_ICON), SW_SHOW);
- General_Pump_Messages ();
- if (restore_vis_point_display) {
- scene_editor->Display_Vis_Points (true);
- }
- // Close the dialog
- ::Get_Main_View ()->Allow_Repaint (true);
- EndDialog (TRUE);
- }
- // Allow the base class to process this message
- return CDialog::WindowProc (message, wParam, lParam);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Update_Time
- //
- //////////////////////////////////////////////////////////////////////////////
- void
- GeneratingVisDialogClass::Update_Time (void)
- {
- //
- // Compute the elapsed and estimated remaining time
- //
- DWORD cur_ticks = ::GetTickCount();
- DWORD elapsed_ticks;
- if (cur_ticks > m_StartTime) {
- elapsed_ticks = cur_ticks - m_StartTime;
- } else {
- elapsed_ticks = 0xFFFFFFFF - m_StartTime + cur_ticks;
- }
- DWORD avg_ticks = elapsed_ticks / m_CurrentPoint;
- DWORD remaining_ticks = (m_TotalPoints - m_CurrentPoint) * avg_ticks;
- float elapsed_minutes = (float)elapsed_ticks / 60000.0f;
- float remaining_minutes = (float)remaining_ticks / 60000.0f;
- //
- // Update the UI
- //
- CString status_text;
- status_text.Format ("Rendering %d of %d points.", m_CurrentPoint + 1, m_TotalPoints);
- SetDlgItemText (IDC_STATUS_TEXT, status_text);
- CString elapsed_time_text;
- elapsed_time_text.Format ("Elapsed: %.1f min. Remaining: %.1f min.",elapsed_minutes,remaining_minutes);
- SetDlgItemText (IDC_ELAPSED_TIME_TEXT, elapsed_time_text);
-
- m_ProgressCtrl.SetPos (((m_CurrentPoint + 1) * 100) / m_TotalPoints);
- General_Pump_Messages ();
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Render_Vis_Points
- //
- //////////////////////////////////////////////////////////////////////////////
- void
- GeneratingVisDialogClass::Render_Vis_Points (VIS_POINT_LIST &point_list)
- {
- SceneEditorClass *scene_editor = ::Get_Scene_Editor ();
- VisLogClass &vis_log = scene_editor->Get_Vis_Log ();
- //
- // Loop through all the points and vis-render them
- //
- int count = point_list.Count ();
- for (int index = 0; (index < count) && !m_bStop; index ++) {
- VisPointListClass *sub_point_list = point_list[index];
- //
- // Render vis for this point
- //
- Vector3 sample_point = sub_point_list->sample_point;
- VisSampleClass vis_sample = scene_editor->Update_Vis (sample_point, sub_point_list->transform);
- vis_log.Log_Sample (vis_sample);
- scene_editor->Create_Vis_Point (sub_point_list->transform);
- m_CurrentPoint ++;
- //
- // Update the estimated time remaining
- //
- Update_Time ();
- //
- // Render vis for any sub-points
- //
- for (int sub_point = 0; sub_point < sub_point_list->Count (); sub_point ++) {
- Matrix3D &transform = (*sub_point_list)[sub_point];
- //
- // Render vis in each of the directions available to us
- //
- vis_sample = scene_editor->Update_Vis (sample_point, transform, VisDirBitsType(VIS_FORWARD_BIT | VIS_LEFT_BIT | VIS_RIGHT_BIT | VIS_UP_BIT | VIS_DOWN_BIT));
- vis_log.Log_Sample (vis_sample);
- scene_editor->Create_Vis_Point (transform);
- // Increment our total count of points
- m_CurrentPoint ++;
- //
- // Update the estimated time remaining
- //
- Update_Time ();
- }
- //
- // Output our current status to the status file
- //
- if (m_FarmMode) {
- CString status;
- status.Format ("Sectors: %d%%", int(((m_CurrentPoint + 1) * 100) / m_TotalPoints));
- ::WritePrivateProfileString ("Status", m_StatusSection, status, m_StatusFilename);
- }
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Generate_Points
- //
- //////////////////////////////////////////////////////////////////////////////
- void
- GeneratingVisDialogClass::Generate_Points
- (
- NODE_LIST & node_list,
- VisPointGeneratorClass &generator
- )
- {
- //
- // Count up the total number of polygongs
- //
- int total_polys = 0;
- int count = node_list.Count ();
- for (int index = 0; (index < count) && !m_bStop; index ++) {
- NodeClass *node = node_list[index];
- RenderObjClass *rendobj = node->Peek_Render_Obj ();
- if (rendobj != NULL) {
- total_polys += rendobj->Get_Num_Polys ();
- }
- }
- //
- // Now, ask all the nodes to generate vis points
- //
- for (index = 0; (index < count) && !m_bStop; index ++) {
-
- //
- // Update the UI
- //
- int poly_count = generator.Get_Polys_Processed ();
- CString status_text;
- status_text.Format ("Processing %d / %d nodes, %d / %d polys.", index + 1, count, poly_count, total_polys);
- SetDlgItemText (IDC_STATUS_TEXT, status_text);
- CString elapsed_text;
- elapsed_text.Format ("Elapsed Time: %.1f minutes.",(::GetTickCount() - m_StartTime) / 60000.0f);
- SetDlgItemText (IDC_ELAPSED_TIME_TEXT, elapsed_text);
-
- m_ProgressCtrl.SetPos ((index * 100) / count);
- General_Pump_Messages ();
-
- //
- // Generate the points
- //
- NodeClass *node = node_list[index];
- node->Add_Vis_Points (generator);
- }
- return ;
- }
|