From 48c5581db9cf82ac8e8ceeb3ed14a175ff0f998e Mon Sep 17 00:00:00 2001
From: Tazpn <tazpn@users.sourceforge.net>
Date: Tue, 11 Sep 2007 02:17:56 +0000
Subject: [PATCH] Add misc. collision fixes. And a capsule skeleton code with
 wildmagic disabled by default.

---
 NifExport/Coll.cpp               |  5 ++-
 NifExport/Exporter.cpp           |  2 +-
 NifProps/NifProps.rc             | 15 +++----
 NifProps/bhkHelperFuncs.cpp      | 70 ++++++++++++++++++++++++++++++++
 NifProps/bhkHelperFuncs.h        |  2 +
 NifProps/bhkProxyObj.cpp         | 47 ++++++++++++++++++---
 NifProps/bhkRigidBodyModifer.cpp | 21 +++++-----
 7 files changed, 137 insertions(+), 25 deletions(-)

diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp
index 548a50b..709d8ba 100755
--- a/NifExport/Coll.cpp
+++ b/NifExport/Coll.cpp
@@ -421,7 +421,8 @@ bhkConvexVerticesShapeRef Exporter::makeConvexShape(Mesh& mesh, Matrix3& tm)
 	bhkConvexVerticesShapeRef shape = StaticCast<bhkConvexVerticesShape>(bhkConvexVerticesShape::Create());
 	Point3 center(0.0f, 0.0f, 0.0f);
 	float radius = 0.10f;
-	//CalcAxisAlignedSphere(mesh, center, radius);
+	CalcCenteredSphere(mesh, center, radius);
+	radius /= Exporter::bhkScaleFactor;
 	shape->SetRadius(radius);
 	vector<Vector3> verts;
 	vector<Float4> norms;
@@ -444,7 +445,7 @@ bhkConvexVerticesShapeRef Exporter::makeConvexShape(Mesh& mesh, Matrix3& tm)
 		value[0] = pt.x;
 		value[1] = pt.y;
 		value[2] = pt.z;
-		value[3] = -mesh.FaceCenter(i).Length();
+		value[3] = -(mesh.FaceCenter(i) * tm).Length() / Exporter::bhkScaleFactor;
 	}
 	sortVector3(verts);
 	sortFloat4(norms);
diff --git a/NifExport/Exporter.cpp b/NifExport/Exporter.cpp
index 525cc25..669ba2c 100755
--- a/NifExport/Exporter.cpp
+++ b/NifExport/Exporter.cpp
@@ -296,7 +296,7 @@ Exporter::Result Exporter::exportNodes(NiNodeRef &parent, INode *node)
    {
       return exportLight(nodeParent, node, (GenLight*)os.obj);
    }
-   else if (isMeshGroup(node) && local) // only create node if local
+   else if (isMeshGroup(node) && local && !mSkeletonOnly) // only create node if local
    {
       newParent = makeNode(parent, node, local);
    } 
diff --git a/NifProps/NifProps.rc b/NifProps/NifProps.rc
index 92f8ce7..748a2b7 100755
--- a/NifProps/NifProps.rc
+++ b/NifProps/NifProps.rc
@@ -295,22 +295,23 @@ BEGIN
     LTEXT           "Collision Meshes:",IDC_STATIC,9,28,77,8
 END
 
-IDD_PROXYPARAM1 DIALOGEX 0, 0, 107, 210
+IDD_PROXYPARAM1 DIALOGEX 0, 0, 107, 223
 STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE
 FONT 8, "MS Sans Serif", 0, 0, 0x0
 BEGIN
     CONTROL         "Material",IDC_LBL_MATERIAL,"Static",SS_LEFTNOWORDWRAP | SS_CENTERIMAGE | WS_GROUP,12,4,83,8
     COMBOBOX        IDC_CB_MATERIAL,12,13,83,157,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
-    GROUPBOX        "Bounding Volume",IDC_STATIC,4,31,97,74
+    GROUPBOX        "Bounding Volume",IDC_STATIC,4,31,97,81
     CONTROL         "No Collision",IDC_RDO_NO_COLL,"Button",BS_AUTORADIOBUTTON | WS_GROUP,8,41,82,10
     CONTROL         "Axis Aligned Box",IDC_RDO_AXIS_ALIGNED_BOX,"Button",BS_AUTORADIOBUTTON,8,52,82,10
     CONTROL         "Strips Shape",IDC_RDO_STRIPS_SHAPE,"Button",BS_AUTORADIOBUTTON,8,64,82,10
     CONTROL         "Packed Strips Shape",IDC_RDO_PACKED_STRIPS,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,8,76,80,10
     CONTROL         "Convex Shape",IDC_RDO_CONVEX,"Button",BS_AUTORADIOBUTTON,8,88,80,10
-    LTEXT           "Proxied Collision Meshes:",IDC_STATIC,8,107,92,8
-    LISTBOX         IDC_LIST1,6,118,94,71,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
-    CONTROL         "Add",IDC_ADD,"CustButton",WS_TABSTOP,4,192,47,12
-    CONTROL         "Remove",IDC_REMOVE,"CustButton",WS_TABSTOP,56,192,46,12
+    LTEXT           "Proxied Collision Meshes:",IDC_STATIC,8,116,92,8
+    LISTBOX         IDC_LIST1,6,127,94,71,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+    CONTROL         "Add",IDC_ADD,"CustButton",WS_TABSTOP,4,201,47,12
+    CONTROL         "Remove",IDC_REMOVE,"CustButton",WS_TABSTOP,56,201,46,12
+    CONTROL         "Capsule",IDC_RDO_CAPSULE,"Button",BS_AUTORADIOBUTTON,8,99,80,10
 END
 
 
@@ -372,7 +373,7 @@ BEGIN
     IDD_PROXYPARAM1, DIALOG
     BEGIN
         RIGHTMARGIN, 106
-        BOTTOMMARGIN, 208
+        BOTTOMMARGIN, 221
     END
 END
 #endif    // APSTUDIO_INVOKED
diff --git a/NifProps/bhkHelperFuncs.cpp b/NifProps/bhkHelperFuncs.cpp
index 883fd0d..dbaeff2 100644
--- a/NifProps/bhkHelperFuncs.cpp
+++ b/NifProps/bhkHelperFuncs.cpp
@@ -5,6 +5,23 @@
 #include "NifStrings.h"
 #include "NifPlugins.h"
 #include "NifGui.h"
+#include "meshadj.h"
+
+// Includes for WildMagic so we can do the Capsule fitting
+#ifdef USES_WILDMAGIC
+#  ifdef _DEBUG
+#    pragma comment (lib, "Wm4Foundation80d")
+#  else
+#    pragma comment (lib, "Wm4Foundation80")
+#  endif
+#undef PI
+#undef DEG_TO_RAD
+#undef RAD_TO_DEG
+#define WM4PLATFORMS_H
+#define WM4_FOUNDATION_ITEM
+#include <Wm4ContCapsule3.h>
+#define PI (Wm4::Math<double>::PI)
+#endif
 
 using namespace std;
 
@@ -754,3 +771,56 @@ void BuildScubaMesh(Mesh &mesh, int segs, int smooth, int llsegs,
 	//	assert(nv==mesh.numVerts);
 	mesh.InvalidateTopologyCache();
 }
+
+// Calculate capsule from mesh.  While radii on the endcaps is possible we do 
+//   currently calculate then differently.
+extern void CalcCapsule(Mesh &mesh, Point3& pt1, Point3& pt2, float& r1, float& r2)
+{
+#ifdef USES_WILDMAGIC
+	int nv = mesh.getNumVerts();
+	Wm4::Vector3<float>* akPoint = new Wm4::Vector3<float>[nv];
+	for (int i=0; i<nv; i++)
+	{
+		Point3& mp = mesh.verts[i];
+		Wm4::Vector3<float>& wp = akPoint[i];
+		wp.X() = mp.x;
+		wp.Y() = mp.y;
+		wp.Z() = mp.z;
+	}
+	Wm4::Capsule3<float> capsule = ContCapsule (nv, akPoint);
+	delete [] akPoint;
+
+	Wm4::Vector3<float> end1 = capsule.Segment.GetPosEnd();
+	Wm4::Vector3<float> end2 = capsule.Segment.GetNegEnd();
+	pt1.Set(end1.X(), end1.Y(), end1.Z());
+	pt2.Set(end2.X(), end2.Y(), end2.Z());
+
+	r1 = r2 = capsule.Radius;
+#endif
+	return;
+}
+
+extern void BuildCapsule(Mesh &mesh, Point3 pt1, Point3 pt2, float r1, float r2)
+{
+	int segs = 12;
+	int hsegs = 1;
+	int smooth = 1;
+
+	float h = (pt1 - pt2).Length();
+
+	Point3 center = ((pt2 + pt1) / 2.0f);
+	Point3 norm = Normalize(pt2 - pt1);
+	Matrix3 mat;
+	MatrixFromNormal(norm,mat);
+	Matrix3 newTM = mat * TransMatrix(center);
+
+	// Build capsule to suggested size
+	BuildScubaMesh(mesh, segs, smooth, hsegs, r1, r2, h);
+
+	// Reorient the capsule.
+	MNMesh mn(mesh);
+	Matrix3 tm(true);
+	tm.Translate(center);
+	mn.Transform(newTM);
+	mn.OutToTri(mesh);
+}
diff --git a/NifProps/bhkHelperFuncs.h b/NifProps/bhkHelperFuncs.h
index 5d59f65..9697f08 100644
--- a/NifProps/bhkHelperFuncs.h
+++ b/NifProps/bhkHelperFuncs.h
@@ -5,9 +5,11 @@ extern void CalcAxisAlignedBox(Mesh& mesh, Box3& box);
 extern void CalcAxisAlignedBox(Mesh& mesh, Box3& box, Matrix3* tm);
 extern void CalcAxisAlignedSphere(Mesh& mesh, Point3& center, float& radius);
 extern void CalcCenteredSphere(Mesh& mesh, Point3& center, float& radius);
+extern void CalcCapsule(Mesh &mesh, Point3& pt1, Point3& pt2, float& r1, float& r2);
 
 extern void BuildBox(Mesh&mesh, float l, float w, float h);
 extern void BuildSphere(Mesh&mesh, float radius, int segs=32, int smooth=1, float startAng = 0.0f);
+extern void BuildCapsule(Mesh &mesh, Point3 pt1, Point3 pt2, float r1, float r2);
 extern void BuildScubaMesh(Mesh &mesh, int segs, int smooth, int llsegs, 
 						   float radius1, float radius2, float cylh);
 
diff --git a/NifProps/bhkProxyObj.cpp b/NifProps/bhkProxyObj.cpp
index df6ea32..8e3ed05 100644
--- a/NifProps/bhkProxyObj.cpp
+++ b/NifProps/bhkProxyObj.cpp
@@ -105,6 +105,7 @@ public:
    void BuildColStrips();
    void BuildColPackedStrips();
    void BuildColConvex();
+   void BuildColCapsule();
    void BuildOptimize(Mesh&mesh);
 
    void UpdateUI();
@@ -151,7 +152,7 @@ enum
    PB_OPT_ENABLE, PB_MAXEDGE, PB_FACETHRESH, PB_EDGETHRESH, PB_BIAS, 
 };
 
-enum { bv_type_none, bv_type_box, bv_type_shapes, bv_type_packed, bv_type_convex, };  // pblock ID
+enum { bv_type_none, bv_type_box, bv_type_shapes, bv_type_packed, bv_type_convex, bv_type_capsule };  // pblock ID
 
 static ParamBlockDesc2 param_blk ( 
     list_params, _T("parameters"),  0, NULL, P_AUTO_CONSTRUCT + P_AUTO_UI + P_MULTIMAP, 0,
@@ -168,8 +169,8 @@ static ParamBlockDesc2 param_blk (
 
     PB_BOUND_TYPE, 	_T("boundType"),	TYPE_INT, 0, IDS_BV_BOUNDING_TYPE,
 	  p_default, 		0, 
-	  p_range, 			0, 4, 
-	  p_ui, 			list_params,	TYPE_RADIO, 5, IDC_RDO_NO_COLL, IDC_RDO_AXIS_ALIGNED_BOX, IDC_RDO_STRIPS_SHAPE, IDC_RDO_PACKED_STRIPS, IDC_RDO_CONVEX,
+	  p_range, 			0, 5, 
+	  p_ui, 			list_params,	TYPE_RADIO, 6, IDC_RDO_NO_COLL, IDC_RDO_AXIS_ALIGNED_BOX, IDC_RDO_STRIPS_SHAPE, IDC_RDO_PACKED_STRIPS, IDC_RDO_CONVEX, IDC_RDO_CAPSULE,
 	  end,
 
 	PB_MESHLIST,   _T("meshProxy"),  TYPE_INODE_TAB,		0,	P_AUTO_UI|P_VARIABLE_SIZE,	IDS_MESHLIST,
@@ -513,11 +514,14 @@ void bhkProxyObject::BuildMesh(TimeValue t)
 		//BuildSphere();
 		break;
 
-	case bv_type_convex: // Capsule
+	case bv_type_convex:
 		BuildColConvex();
-		
 		//BuildScubaMesh();
 		break;
+
+	case bv_type_capsule:
+		BuildColCapsule();
+		break;
 	}
 }
 
@@ -801,6 +805,39 @@ void bhkProxyObject::BuildColConvex()
 	forceRedraw = true;
 }
 
+void bhkProxyObject::BuildColCapsule()
+{
+	proxyMesh.FreeAll();
+	MeshDelta md(proxyMesh);
+	for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) {
+		INode *tnode = NULL;
+		pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i);	
+		if (tnode)
+		{
+			ObjectState os = tnode->EvalWorldState(0);
+			Matrix3 wm = tnode->GetNodeTM(0);
+			TriObject *tri = (TriObject *)os.obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0));
+			if (tri)
+			{
+				Mesh& mesh = tri->GetMesh();
+				MeshDelta tmd (mesh);
+				md.AttachMesh(proxyMesh, mesh, wm, 0);
+				md.Apply(proxyMesh);
+			}
+		}
+	}
+	Point3 pt1 = Point3::Origin;
+	Point3 pt2 = Point3::Origin;
+	float r1 = 0.0;
+	float r2 = 0.0;
+
+	CalcCapsule(proxyMesh, pt1, pt2, r1, r2);
+	BuildCapsule(proxyMesh, pt1, pt2, r1, r2);
+
+	proxyPos = Point3::Origin;
+	forceRedraw = true;
+}
+
 
 void bhkProxyObject::BuildOptimize(Mesh& mesh)
 {
diff --git a/NifProps/bhkRigidBodyModifer.cpp b/NifProps/bhkRigidBodyModifer.cpp
index 111a47f..1578c41 100644
--- a/NifProps/bhkRigidBodyModifer.cpp
+++ b/NifProps/bhkRigidBodyModifer.cpp
@@ -431,12 +431,16 @@ void bhkRigidBodyModifier::ModifyObject (TimeValue t, ModContext &mc, ObjectStat
 		BuildOptimize(proxyMesh);
 		break;
 
+	case bv_type_capsule:
+		BuildColCapsule(proxyMesh);
+		break;
+
 	//case bv_type_packed: // Packed
 	//	BuildColPackedStrips();
 	//	//BuildSphere();
 	//	break;
 
-	case bv_type_convex: // Capsule
+	case bv_type_convex:
 		BuildColConvex(proxyMesh);
 		BuildOptimize(proxyMesh);
 		//BuildScubaMesh();
@@ -649,16 +653,13 @@ void bhkRigidBodyModifier::BuildColSphere(Mesh& mesh)
 
 void bhkRigidBodyModifier::BuildColCapsule(Mesh& mesh)
 {
-	Point3 center = Point3::Origin;
-	float radius = 0.0f;
-	CalcCenteredSphere(mesh, center, radius);
-	BuildSphere(mesh, radius);
+	Point3 pt1 = Point3::Origin;
+	Point3 pt2 = Point3::Origin;
+	float r1 = 0.0;
+	float r2 = 0.0;
 
-	MNMesh mn(mesh);
-	Matrix3 tm(true);
-	tm.Translate(center);
-	mn.Transform(tm);
-	mn.OutToTri(mesh);
+	CalcCapsule(mesh, pt1, pt2, r1, r2);
+	BuildCapsule(mesh, pt1, pt2, r1, r2);
 }
 
 void bhkRigidBodyModifier::BuildColStrips(Mesh& mesh)
-- 
GitLab