From 2ca8c0a9c236927f56d4601158917d2190f11227 Mon Sep 17 00:00:00 2001
From: Gundalf <gundalf01@users.sourceforge.net>
Date: Thu, 22 Jun 2006 23:07:16 +0000
Subject: [PATCH] Remap indices for better vertex cache locality.

---
 NifExport/Coll.cpp      |   4 +-
 NifExport/Config.cpp    |   2 +
 NifExport/Exporter.cpp  |   1 +
 NifExport/Exporter.h    |   5 +-
 NifExport/Mesh.cpp      |   4 +-
 NifExport/NifExport.cpp |   2 +
 NifExport/NifExport.rc  |  14 +++--
 NifExport/Strips.cpp    | 135 ++++++++++++++++++++++++++++++++++------
 NifExport/resource.h    |   2 +
 9 files changed, 141 insertions(+), 28 deletions(-)

diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp
index be93b14..25ddf2c 100755
--- a/NifExport/Coll.cpp
+++ b/NifExport/Coll.cpp
@@ -77,7 +77,9 @@ bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue
 	for (int i=0; i<mesh->getNumFaces(); i++)
 		addFace(tris, verts, vnorms, i, vi, mesh);
 
-	NiTriStripsDataRef data = makeTriStripsData(tris);
+	TriStrips strips;
+	strippify(strips, verts, vnorms, tris);
+	NiTriStripsDataRef data = makeTriStripsData(strips);
 	data->SetVertices(verts);
 	data->SetNormals(vnorms);
 
diff --git a/NifExport/Config.cpp b/NifExport/Config.cpp
index 3c4493a..0790e33 100755
--- a/NifExport/Config.cpp
+++ b/NifExport/Config.cpp
@@ -32,6 +32,7 @@ void Exporter::writeConfig()
 //	regSet(hKey, "npx_wthresh", mWeldThresh);
 	regSet(hKey, "npx_tprefix", mTexPrefix);
 	regSet(hKey, "npx_coll", mExportCollision);
+	regSet(hKey, "npx_remap", mRemapIndices);
 }
 
 void Exporter::readConfig(INode *node)
@@ -55,6 +56,7 @@ void Exporter::readConfig()
 //	regGet(hKey, "npx_wthresh", mWeldThresh);
 	regGet(hKey, "npx_tprefix", mTexPrefix);
 	regGet(hKey, "npx_coll", mExportCollision);
+	regGet(hKey, "npx_remap", mRemapIndices);
 }
 
 
diff --git a/NifExport/Exporter.cpp b/NifExport/Exporter.cpp
index 7caaa46..36ddf81 100755
--- a/NifExport/Exporter.cpp
+++ b/NifExport/Exporter.cpp
@@ -10,6 +10,7 @@ bool Exporter::mVertexColors=true;
 float Exporter::mWeldThresh=0.1f;
 string Exporter::mTexPrefix="textures";
 bool Exporter::mExportCollision=true;
+bool Exporter::mRemapIndices=true;
 
 Exporter::Exporter(Interface *i)
 	: mI(i)
diff --git a/NifExport/Exporter.h b/NifExport/Exporter.h
index 46b1120..abc98cf 100755
--- a/NifExport/Exporter.h
+++ b/NifExport/Exporter.h
@@ -30,6 +30,7 @@ public:
 	static bool			mVertexColors;
 	static float		mWeldThresh;
 	static bool			mExportCollision;
+	static bool			mRemapIndices;
 
 	Exporter(Interface *i);
 
@@ -83,9 +84,9 @@ private:
 	bool				equal(const Vector3 &a, const Point3 &b, float thresh);
 
 	/* tristrips */
-	void				strippify(TriStrips &strips, const Triangles &tris);
+	void				strippify(TriStrips &strips, vector<Vector3> &verts, vector<Vector3> &norms, const Triangles &tris);
+	void				strippify(TriStrips &strips, FaceGroup &grp);
 	NiTriStripsDataRef	makeTriStripsData(const TriStrips &strips);
-	NiTriStripsDataRef	makeTriStripsData(const Triangles &tris);
 
 	/* mesh export */
 	// adds a vertex to a face group if it doesn't exist yet. returns new or previous index into the
diff --git a/NifExport/Mesh.cpp b/NifExport/Mesh.cpp
index 5d07d3e..faf6c32 100755
--- a/NifExport/Mesh.cpp
+++ b/NifExport/Mesh.cpp
@@ -79,7 +79,9 @@ bool Exporter::makeMesh(NiNodeRef &parent, Mtl *mtl, FaceGroup &grp)
 		NiTriStripsRef stripsShape = DynamicCast<NiTriStrips>(CreateBlock("NiTriStrips"));
 		shape = DynamicCast<NiTriBasedGeom>(stripsShape);
 
-		NiTriStripsDataRef stripData = makeTriStripsData(grp.faces);
+		TriStrips strips;
+		strippify(strips, grp);
+		NiTriStripsDataRef stripData = makeTriStripsData(strips);
 		data = DynamicCast<NiTriBasedGeomData>(stripData);
 
 	} else
diff --git a/NifExport/NifExport.cpp b/NifExport/NifExport.cpp
index cf53f9a..b356d58 100755
--- a/NifExport/NifExport.cpp
+++ b/NifExport/NifExport.cpp
@@ -70,6 +70,7 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
 				CheckDlgButton(hWnd, IDC_CHK_VCOLORS, Exporter::mVertexColors);
 				SetDlgItemText(hWnd, IDC_ED_TEXPREFIX, Exporter::mTexPrefix.c_str());
 				CheckDlgButton(hWnd, IDC_CHK_COLL, Exporter::mExportCollision);
+				CheckDlgButton(hWnd, IDC_CHK_REMAP, Exporter::mRemapIndices);
 
 				TSTR tmp;
 				tmp.printf("%.4f", Exporter::mWeldThresh);
@@ -97,6 +98,7 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
 						Exporter::mExportLights = IsDlgButtonChecked(hWnd, IDC_CHK_LIGHTS);
 						Exporter::mVertexColors = IsDlgButtonChecked(hWnd, IDC_CHK_VCOLORS);
 						Exporter::mExportCollision = IsDlgButtonChecked(hWnd, IDC_CHK_COLL);
+						Exporter::mRemapIndices = IsDlgButtonChecked(hWnd, IDC_CHK_REMAP);
 							
 						GetDlgItemText(hWnd, IDC_ED_TEXPREFIX, tmp, MAX_PATH);
 						Exporter::mTexPrefix = tmp;
diff --git a/NifExport/NifExport.rc b/NifExport/NifExport.rc
index c878de8..251a824 100755
--- a/NifExport/NifExport.rc
+++ b/NifExport/NifExport.rc
@@ -80,9 +80,9 @@ EXSTYLE WS_EX_TOOLWINDOW
 CAPTION "Export Nif"
 FONT 8, "MS Sans Serif", 0, 0, 0x1
 BEGIN
-    CONTROL         "",IDC_EDIT,"CustEdit",NOT WS_VISIBLE | WS_TABSTOP,122,
-                    48,35,10
-    CONTROL         "",IDC_SPIN,"SpinnerControl",NOT WS_VISIBLE,160,47,7,10
+    CONTROL         "",IDC_EDIT,"CustEdit",NOT WS_VISIBLE | WS_TABSTOP,148,8,
+                    35,10
+    CONTROL         "",IDC_SPIN,"SpinnerControl",NOT WS_VISIBLE,186,7,7,10
     PUSHBUTTON      "&Export",IDOK,7,87,34,14
     PUSHBUTTON      "&Cancel",IDCANCEL,44,87,33,14
     CONTROL         "Include &Hidden",IDC_CHK_HIDDEN,"Button",
@@ -95,16 +95,18 @@ BEGIN
     LTEXT           "Texture &Prefix",IDC_STATIC,7,60,44,8
     CONTROL         "&Lights",IDC_CHK_LIGHTS,"Button",BS_AUTOCHECKBOX | 
                     WS_DISABLED | WS_TABSTOP,7,31,35,10
-    EDITTEXT        IDC_ED_WELDTHRESH,44,44,35,12,ES_AUTOHSCROLL | NOT 
-                    WS_VISIBLE | WS_DISABLED
-    LTEXT           "Auto-&Weld",IDC_LBL_WELDTHRESH,44,34,34,8,NOT 
+    EDITTEXT        IDC_ED_WELDTHRESH,16,44,35,12,ES_AUTOHSCROLL | NOT 
                     WS_VISIBLE | WS_DISABLED
+    LTEXT           "Auto-&Weld",IDC_LBL_WELDTHRESH,7,45,34,8,NOT WS_VISIBLE | 
+                    WS_DISABLED
     CONTROL         "Export Co&llision",IDC_CHK_COLL,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,85,18,68,10
     CONTROL         "&Vertex Colors",IDC_CHK_VCOLORS,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,85,31,68,10
     LTEXT           "http://niftools.sourceforge.net",IDC_LBL_LINK,98,87,95,
                     14,SS_NOTIFY | SS_CENTERIMAGE
+    CONTROL         "&Remap Indices",IDC_CHK_REMAP,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,85,46,68,10
 END
 
 
diff --git a/NifExport/Strips.cpp b/NifExport/Strips.cpp
index 8787bb2..331bba2 100755
--- a/NifExport/Strips.cpp
+++ b/NifExport/Strips.cpp
@@ -1,10 +1,11 @@
 #include "pch.h"
 
-void Exporter::strippify(TriStrips &strips, const Triangles &tris)
+void Exporter::strippify(TriStrips &strips, vector<Vector3> &verts, vector<Vector3> &norms, const Triangles &tris)
 {
 	unsigned short *data = (unsigned short *)malloc(tris.size() * 3 * 2);
 
-	for (int i=0; i<tris.size(); i++)
+	int i;
+	for (i=0; i<tris.size(); i++)
 	{
 		data[i * 3 + 0] = tris[i][0];
 		data[i * 3 + 1] = tris[i][1];
@@ -14,7 +15,7 @@ void Exporter::strippify(TriStrips &strips, const Triangles &tris)
 	PrimitiveGroup * groups = 0;
 	unsigned short numGroups = 0;
 	
-	// GF 3, what about others?
+	// GF 3+
 	SetCacheSize(CACHESIZE_GEFORCE3);
 	// don't generate hundreds of strips
 	SetStitchStrips(true);
@@ -24,19 +25,125 @@ void Exporter::strippify(TriStrips &strips, const Triangles &tris)
 	
 	if (!groups)
 		return;
-	
-	for (int g=0; g<numGroups; g++)
+
+	if (!mRemapIndices)
 	{
-		if (groups[g].type == PT_STRIP)
+		for (int g=0; g<numGroups; g++)
 		{
-			strips.push_back(TriStrip(groups[g].numIndices));
-			TriStrip &strip = strips.back();
+			if (groups[g].type == PT_STRIP)
+			{
+				strips.push_back(TriStrip(groups[g].numIndices));
+				TriStrip &strip = strips.back();
 
-			for (int s=0; s<groups[g].numIndices; s++)
-				strip[s] = groups[g].indices[s];
+				for (int s=0; s<groups[g].numIndices; s++)
+					strip[s] = groups[g].indices[s];
+			}
 		}
+
+	} else 
+	{
+		// remap indices
+		PrimitiveGroup *rmGroups;
+		RemapIndices(groups, numGroups, verts.size(), &rmGroups);
+
+		vector<Vector3> tverts = verts;
+		vector<Vector3> tnorms = norms;
+
+		for (int g=0; g<numGroups; g++)
+		{
+			if (rmGroups[g].type == PT_STRIP)
+			{
+				strips.push_back(TriStrip(rmGroups[g].numIndices));
+				TriStrip &strip = strips.back();
+
+				for (int s=0; s<rmGroups[g].numIndices; s++)
+				{
+					strip[s] = rmGroups[g].indices[s];
+
+					unsigned short a = strip[s], b = groups[g].indices[s];
+					verts[a] = tverts[b];
+					norms[a] = tnorms[b];
+				}
+			}
+		}
+
+		delete [] rmGroups;
+	}
+
+	delete [] groups;
+}
+
+void Exporter::strippify(TriStrips &strips, FaceGroup &grp)
+{
+	unsigned short *data = (unsigned short *)malloc(grp.faces.size() * 3 * 2);
+
+	int i;
+	for (i=0; i<grp.faces.size(); i++)
+	{
+		data[i * 3 + 0] = grp.faces[i][0];
+		data[i * 3 + 1] = grp.faces[i][1];
+		data[i * 3 + 2] = grp.faces[i][2];
 	}
 	
+	PrimitiveGroup * groups = 0;
+	unsigned short numGroups = 0;
+	
+	// GF 3+
+	SetCacheSize(CACHESIZE_GEFORCE3);
+	// don't generate hundreds of strips
+	SetStitchStrips(true);
+	GenerateStrips(data, grp.faces.size()*3, &groups, &numGroups);
+
+	free( data );
+	
+	if (!groups)
+		return;
+
+	if (!mRemapIndices)
+	{
+		for (int g=0; g<numGroups; g++)
+		{
+			if (groups[g].type == PT_STRIP)
+			{
+				strips.push_back(TriStrip(groups[g].numIndices));
+				TriStrip &strip = strips.back();
+
+				for (int s=0; s<groups[g].numIndices; s++)
+					strip[s] = groups[g].indices[s];
+			}
+		}
+	} else
+	{
+		// remap indices
+		PrimitiveGroup *rmGroups;
+		RemapIndices(groups, numGroups, grp.verts.size(), &rmGroups);
+
+		FaceGroup tmp = grp;
+
+		for (int g=0; g<numGroups; g++)
+		{
+			if (rmGroups[g].type == PT_STRIP)
+			{
+				strips.push_back(TriStrip(rmGroups[g].numIndices));
+				TriStrip &strip = strips.back();
+
+				for (int s=0; s<rmGroups[g].numIndices; s++)
+				{
+					strip[s] = rmGroups[g].indices[s];
+
+					unsigned short a = strip[s], b = groups[g].indices[s];
+
+					grp.verts[a] = tmp.verts[b];
+					grp.vnorms[a] = tmp.vnorms[b];
+					grp.uvs[a] = tmp.uvs[b];
+					if (grp.vcolors.size() > 0)
+						grp.vcolors[a] = tmp.vcolors[b];
+				}
+			}
+		}
+		delete [] rmGroups;
+	}
+
 	delete [] groups;
 }
 
@@ -56,11 +163,3 @@ NiTriStripsDataRef Exporter::makeTriStripsData(const TriStrips &strips)
 
 	return stripData;
 }
-
-NiTriStripsDataRef Exporter::makeTriStripsData(const Triangles &tris)
-{
-	TriStrips strips;
-	strippify(strips, tris);
-
-	return makeTriStripsData(strips);
-}
diff --git a/NifExport/resource.h b/NifExport/resource.h
index 9064d8e..9802b63 100755
--- a/NifExport/resource.h
+++ b/NifExport/resource.h
@@ -20,6 +20,8 @@
 #define IDC_CHK_COLL                    1010
 #define IDC_LBL_LINK                    1011
 #define IDC_CHK_VCOLORS                 1012
+#define IDC_CHK_VCOLORS2                1013
+#define IDC_CHK_REMAP                   1013
 #define IDC_COLOR                       1456
 #define IDC_EDIT                        1490
 #define IDC_SPIN                        1496
-- 
GitLab