From 01709a5b263a450d63cde2dd6d3fa16485ee3441 Mon Sep 17 00:00:00 2001
From: D-AIRY <admin@ds-servers.com>
Date: Mon, 3 Mar 2025 08:59:13 +0300
Subject: [PATCH] Optimized level saving

---
 source/common                |  2 +-
 source/xcsg/BrushMesh.cpp    | 24 ++++++++++++++++++++++--
 source/xcsg/BrushMesh.h      |  7 ++++++-
 source/xcsg/Combiner.cpp     | 12 +++++++++++-
 source/xcsg/EditorModel.cpp  |  9 ++++++++-
 source/xcsg/EditorObject.cpp |  4 ++--
 source/xcsg/EditorObject.h   |  2 +-
 7 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/source/common b/source/common
index 8c9eadcdf..6ac114eeb 160000
--- a/source/common
+++ b/source/common
@@ -1 +1 @@
-Subproject commit 8c9eadcdfdb5e5c8cd8dad0fd0eabb6e3fe0f00a
+Subproject commit 6ac114eeb7c088e7560e26475ad41f5aded8a047
diff --git a/source/xcsg/BrushMesh.cpp b/source/xcsg/BrushMesh.cpp
index b92d8af81..6dee95569 100644
--- a/source/xcsg/BrushMesh.cpp
+++ b/source/xcsg/BrushMesh.cpp
@@ -64,7 +64,7 @@ void CBrushMesh::enable(bool yesNo)
 	}
 }
 
-void CBrushMesh::buildMesh(CMeshBuilder *pBuilder)
+void CBrushMesh::buildMesh(CMeshBuilder *pBuilder, bool bOnlyComputeCounts)
 {
 	Array<UINT> aSubsets(m_aMaterials.size());
 	fora(i, m_aMaterials)
@@ -82,6 +82,14 @@ void CBrushMesh::buildMesh(CMeshBuilder *pBuilder)
 		TextureInfo &texInfo = face.texInfo;
 		Subset &subset = pBuilder->getSubset(aSubsets[texInfo.uMatId]);
 
+		if(bOnlyComputeCounts)
+		{
+			UINT uEdges = face.aEdges.size();
+			subset.uVertexCount += uEdges;
+			subset.uIndexCount += (uEdges - 2) * 3;
+			continue;
+		}
+
 		bool isFirst = true;
 		UINT uFirstIdx;
 		UINT uNextIdx;
@@ -161,7 +169,9 @@ void CBrushMesh::buildModel(bool bBuildPhysbox)
 	}
 
 	CMeshBuilder meshBuilder;
-	buildMesh(&meshBuilder);
+	buildMesh(&meshBuilder, true);
+	meshBuilder.allocArrays();
+	buildMesh(&meshBuilder, false);
 
 	// create model
 	IXResourceManager *pRM = m_pCore->getResourceManager();
@@ -2399,6 +2409,16 @@ UINT CMeshBuilder::getSubsetIndexForMaterial(const char *szMat)
 	return(idx);
 }
 
+void CMeshBuilder::allocArrays()
+{
+	fora(i, m_aSubsets)
+	{
+		Subset &ss = m_aSubsets[i];
+		ss.aIndices.reserve(ss.uIndexCount);
+		ss.aVertices.reserve(ss.uVertexCount);
+	}
+}
+
 UINT CMeshBuilder::getSubsetCount()
 {
 	return(m_aMaterials.size());
diff --git a/source/xcsg/BrushMesh.h b/source/xcsg/BrushMesh.h
index 352c664c1..39f72d434 100644
--- a/source/xcsg/BrushMesh.h
+++ b/source/xcsg/BrushMesh.h
@@ -34,6 +34,9 @@ struct Subset
 {
 	Array<XResourceModelStaticVertex> aVertices;
 	Array<UINT> aIndices;
+
+	UINT uVertexCount = 0;
+	UINT uIndexCount = 0;
 };
 
 class CMeshBuilder
@@ -48,6 +51,8 @@ public:
 
 	void buildResource(IXResourceModelStatic *pResource, UINT idx = UINT_MAX);
 
+	void allocArrays();
+
 private:
 	Array<Subset> m_aSubsets;
 	Array<String> m_aMaterials;
@@ -101,7 +106,7 @@ public:
 	bool findInternalFace(Array<float3_t> &aDest);
 	bool fillInternalFace(const Array<float3_t> &aSrc);
 
-	void buildMesh(CMeshBuilder *pBuilder);
+	void buildMesh(CMeshBuilder *pBuilder, bool bOnlyComputeCounts);
 	void buildPhysbox(IXResourceModel *pResource);
 
 	void setFinalized(bool set);
diff --git a/source/xcsg/Combiner.cpp b/source/xcsg/Combiner.cpp
index 5ce45e312..63f0cdad3 100644
--- a/source/xcsg/Combiner.cpp
+++ b/source/xcsg/Combiner.cpp
@@ -33,7 +33,17 @@ void CCombiner::build()
 		if(!aObjects[i]->getModel())
 		{
 			hasObjects = true;
-			aObjects[i]->buildMesh(&meshBuilder);
+			aObjects[i]->buildMesh(&meshBuilder, true);
+		}
+	}
+
+	meshBuilder.allocArrays();
+
+	fora(i, aObjects)
+	{
+		if(!aObjects[i]->getModel())
+		{
+			aObjects[i]->buildMesh(&meshBuilder, false);
 			aObjects[i]->buildPhysbox(pResource);
 		}
 	}
diff --git a/source/xcsg/EditorModel.cpp b/source/xcsg/EditorModel.cpp
index 273ae59f4..28fca2c72 100644
--- a/source/xcsg/EditorModel.cpp
+++ b/source/xcsg/EditorModel.cpp
@@ -60,7 +60,14 @@ void XMETHODCALLTYPE CEditorModel::getResource(IXResourceModel **ppOut)
 	CMeshBuilder meshBuilder;
 	fora(i, m_aObjects)
 	{
-		m_aObjects[i]->buildMesh(&meshBuilder);
+		m_aObjects[i]->buildMesh(&meshBuilder, true);
+	}
+
+	meshBuilder.allocArrays();
+
+	fora(i, m_aObjects)
+	{
+		m_aObjects[i]->buildMesh(&meshBuilder, false);
 		m_aObjects[i]->buildPhysbox(pResource);
 	}
 
diff --git a/source/xcsg/EditorObject.cpp b/source/xcsg/EditorObject.cpp
index 1ff892343..47fcd5fd4 100644
--- a/source/xcsg/EditorObject.cpp
+++ b/source/xcsg/EditorObject.cpp
@@ -691,11 +691,11 @@ void CEditorObject::removeBrush(UINT idx)
 	m_aBrushes.erase(idx);
 }
 
-void CEditorObject::buildMesh(CMeshBuilder *pBuilder)
+void CEditorObject::buildMesh(CMeshBuilder *pBuilder, bool bOnlyComputeCounts)
 {
 	fora(i, m_aBrushes)
 	{
-		m_aBrushes[i]->buildMesh(pBuilder);
+		m_aBrushes[i]->buildMesh(pBuilder, bOnlyComputeCounts);
 	}
 }
 
diff --git a/source/xcsg/EditorObject.h b/source/xcsg/EditorObject.h
index 938a3fb44..365cf5c27 100644
--- a/source/xcsg/EditorObject.h
+++ b/source/xcsg/EditorObject.h
@@ -103,7 +103,7 @@ public:
 		return(m_pModel);
 	}
 
-	void buildMesh(CMeshBuilder *pBuilder);
+	void buildMesh(CMeshBuilder *pBuilder, bool bOnlyComputeCounts);
 	void buildPhysbox(IXResourceModel *pResource);
 
 	bool isRemoved()
-- 
GitLab