diff --git a/include/Inertia.h b/include/Inertia.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9c38c0be129f9874647ec456d8b40c89dab4ff6
--- /dev/null
+++ b/include/Inertia.h
@@ -0,0 +1,56 @@
+/* Copyright (c) 2006, NIF File Format Library and Tools
+All rights reserved.  Please see niflib.h for license. */
+
+#ifndef _NIF_INERTIA_H
+#define _NIF_INERTIA_H
+#pragma once
+
+//--Includes--//
+#include "nif_math.h"
+#include <vector>
+
+namespace Niflib {
+
+class Inertia {
+public:
+
+	/*! Return mass and inertia matrix for a sphere of given radius and
+	 *	density.
+	 */
+	static void GetMassInertiaSphere(float radius, float density, 
+		bool solid, float& mass, InertiaMatrix &inertia);
+
+	/*! Return mass and inertia matrix for a box of given size and
+	 *   density.
+	 */
+	static void GetMassInertiaBox(Vector3 size, float density, 
+		bool solid, float& mass, InertiaMatrix &inertia);
+	/*! Return mass and inertia matrix for a cylinder of given radius, 
+	 *   height and density.
+	 */
+	static void GetMassInertiaCylinder(float radius, float height, 
+		float density, bool solid,
+		float& mass, InertiaMatrix &inertia);
+
+	/*! Return mass and inertia matrix for a capsule of given radius, 
+	 *	height and density.
+	 */
+	static void GetMassInertiaCapsule(float radius, float height, 
+		float density, bool solid,
+		float& mass, InertiaMatrix &inertia);
+
+	/*! Return mass and inertia matrix for a capsule of given radius, 
+	 *	height and density.
+	 */
+	static void GetMassCenterInertiaPolyhedron(
+		const std::vector<Niflib::Vector3>& vertices, 
+		const std::vector<Niflib::Triangle>& triangles, 
+		float density, bool solid,
+		float& mass, Niflib::Vector3& center, InertiaMatrix &inertia);
+
+private:
+	explicit Inertia();
+};
+
+}
+#endif
\ No newline at end of file
diff --git a/include/NIF_IO.h b/include/NIF_IO.h
index cf557a2c2b80f152324abf2816c5de2b02669a0d..f6093cece9ab61b89f7f3c493c6ee2f883584be7 100644
--- a/include/NIF_IO.h
+++ b/include/NIF_IO.h
@@ -209,6 +209,9 @@ void NifStream( Char8String & val, istream& in, const NifInfo & info );
 void NifStream( Char8String const & val, ostream& out, const NifInfo & info );
 ostream & operator<<( ostream & out, Char8String const & val );
 
+//InertiaMatrix
+void NifStream( InertiaMatrix & val, istream& in, const NifInfo & info);
+void NifStream( InertiaMatrix const & val, ostream& out, const NifInfo & info);
 
 //--Templates--//
 
diff --git a/include/gen/InertiaMatrix.h b/include/gen/InertiaMatrix.h
deleted file mode 100644
index e6a2c138df1ef934f4a01ebd42016209869fc96f..0000000000000000000000000000000000000000
--- a/include/gen/InertiaMatrix.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright (c) 2006, NIF File Format Library and Tools
-All rights reserved.  Please see niflib.h for license. */
-
-//---THIS FILE WAS AUTOMATICALLY GENERATED.  DO NOT EDIT---//
-
-//To change this file, alter the niftools/docsys/gen_niflib.py Python script.
-
-#ifndef _INERTIAMATRIX_H_
-#define _INERTIAMATRIX_H_
-
-#include "../NIF_IO.h"
-
-namespace Niflib {
-
-
-/*! An inertia matrix. */
-struct InertiaMatrix {
-	/*! Default Constructor */
-	NIFLIB_API InertiaMatrix();
-	/*! Default Destructor */
-	NIFLIB_API ~InertiaMatrix();
-	/*! Copy Constructor */
-	NIFLIB_API InertiaMatrix( const InertiaMatrix & src );
-	/*! Copy Operator */
-	NIFLIB_API InertiaMatrix & operator=( const InertiaMatrix & src );
-	/*! Unknown. */
-	float m11;
-	/*! Unknown. */
-	float m12;
-	/*! Unknown. */
-	float m13;
-	/*! Zero */
-	float m14;
-	/*! Unknown. */
-	float m21;
-	/*! Unknown. */
-	float m22;
-	/*! Unknown. */
-	float m23;
-	/*! Zero */
-	float m24;
-	/*! Unknown. */
-	float m31;
-	/*! Unknown. */
-	float m32;
-	/*! Unknown. */
-	float m33;
-	/*! Zero */
-	float m34;
-};
-
-}
-#endif
diff --git a/include/nif_math.h b/include/nif_math.h
index 3dd3bf8365be08f4e733dad677a77859c1220a74..2c389be35c3a07bb4ea1e99e331d063afe5159f9 100644
--- a/include/nif_math.h
+++ b/include/nif_math.h
@@ -30,6 +30,7 @@ struct Float3;
 struct Matrix33;
 struct Float4;
 struct Matrix44;
+struct InertiaMatrix;
 
 /*! Stores 2D texture coordinates as two floating point variables, u and v. */
 struct TexCoord {
@@ -231,6 +232,13 @@ struct Vector3 {
 	 */
 	NIFLIB_API bool operator!=( const Vector3 & rh ) const;
 
+	/*! The bracket operator makes it possible to use this structure like a C++ array.
+	* \param[in] n The index into the data array.  Should be 0, 1, or 2.
+	* \return The value at the given array index by reference so it can be read or set via the bracket operator.
+	*/
+	NIFLIB_API float & operator[](int n);
+	NIFLIB_API float operator[](int n) const;
+
 	/* Computes the dot product of two vectors; the angle between two vectors.
 	 * \param[in] rh The vector to perform the dot product with
 	 * \return The angle in radians between this vector and the one given
@@ -823,6 +831,18 @@ struct Matrix44 {
 	 */
 	NIFLIB_API Matrix44 & operator+=( const Matrix44 & rh );
 
+	/* Adds this matrix to another.
+	* \param[in] rh The matrix to be added to this one.
+	* \return The result of the addition.
+	*/
+	NIFLIB_API Matrix44 operator-( const Matrix44 & rh ) const;
+
+	/* Adds this matrix to another and sets the result to itself.
+	* \param[in] rh The matrix to be added to this one.
+	* \return This matrix is returned.
+	*/
+	NIFLIB_API Matrix44 & operator-=( const Matrix44 & rh );
+
 	/* Sets the values of this matrix to those of the given matrix.
 	 * \param[in] rh The matrix to copy values from.
 	 * \return This matrix is returned.
@@ -1020,6 +1040,190 @@ struct Quaternion {
 	NIFLIB_API Float3 AsEulerYawPitchRoll();
 };
 
+
+/*! Stores a 4 by 3 matrix used for tensors. */
+struct InertiaMatrix {
+	/*! The 4x3 identity matrix constant */
+	NIFLIB_API static const InertiaMatrix IDENTITY;
+
+	Float4 rows[3]; /*!< The three rows of Float3 structures which hold three floating point numbers each. */ 
+
+	/*! The bracket operator makes it possible to use this structure like a 4x4 C++ array.
+	* \param[in] n The index into the row array.  Should be 0, 1, 2, or 3.
+	* \return The Float4 structure for the given row index by reference so it can be read or set via the bracket operator.
+	*/
+	NIFLIB_API Float4 & operator[](int n) {
+		return rows[n];
+	}
+	NIFLIB_API Float4 const & operator[](int n) const {
+		return rows[n];
+	}
+
+	/*! Default constructor. Initializes Matrix to Identity. */
+	NIFLIB_API InertiaMatrix();
+
+	/*! Copy constructor.  Initializes Matrix to another InertiaMatrix.
+	* \param[in] m The matrix to initialize this one to. 
+	*/
+	NIFLIB_API InertiaMatrix( const InertiaMatrix & m ) { memcpy(rows, m.rows, sizeof(Float4) * 4); }
+
+	/*! This constructor can be used to set all values in this matrix during initialization
+	* \param[in] m11 The value to set at row 1, column 1.
+	* \param[in] m12 The value to set at row 1, column 2.
+	* \param[in] m13 The value to set at row 1, column 3.
+	* \param[in] m14 The value to set at row 1, column 4.
+	* \param[in] m21 The value to set at row 2, column 1.
+	* \param[in] m22 The value to set at row 2, column 2.
+	* \param[in] m23 The value to set at row 2, column 3.
+	* \param[in] m24 The value to set at row 2, column 4.
+	* \param[in] m31 The value to set at row 3, column 1.
+	* \param[in] m32 The value to set at row 3, column 2.
+	* \param[in] m33 The value to set at row 3, column 3.
+	* \param[in] m34 The value to set at row 3, column 4.
+	* \param[in] m41 The value to set at row 4, column 1.
+	* \param[in] m42 The value to set at row 4, column 2.
+	* \param[in] m43 The value to set at row 4, column 3.
+	* \param[in] m44 The value to set at row 4, column 4.
+	*/
+	NIFLIB_API InertiaMatrix(
+		float m11, float m12, float m13, float m14,
+		float m21, float m22, float m23, float m24,
+		float m31, float m32, float m33, float m34
+		) {
+			rows[0][0] = m11; rows[0][1] = m12; rows[0][2] = m13; rows[0][3] = m14;
+			rows[1][0] = m21; rows[1][1] = m22; rows[1][2] = m23; rows[1][3] = m24;
+			rows[2][0] = m31; rows[2][1] = m32; rows[2][2] = m33; rows[2][3] = m34;
+	}
+
+	/*! This constructor allows a 4x4 transform matrix to be initalized from a
+	* a 3x3 rotation matrix.
+	* \param[in] rotation The 3x3 rotation matrix.
+	*/
+	NIFLIB_API InertiaMatrix( const Matrix33 & rotation );
+
+	/*! This function can be used to set all values in this matrix at the same time.
+	* \param[in] m11 The value to set at row 1, column 1.
+	* \param[in] m12 The value to set at row 1, column 2.
+	* \param[in] m13 The value to set at row 1, column 3.
+	* \param[in] m14 The value to set at row 1, column 4.
+	* \param[in] m21 The value to set at row 2, column 1.
+	* \param[in] m22 The value to set at row 2, column 2.
+	* \param[in] m23 The value to set at row 2, column 3.
+	* \param[in] m24 The value to set at row 2, column 4.
+	* \param[in] m31 The value to set at row 3, column 1.
+	* \param[in] m32 The value to set at row 3, column 2.
+	* \param[in] m33 The value to set at row 3, column 3.
+	* \param[in] m34 The value to set at row 3, column 4.
+	*/
+	NIFLIB_API void Set(
+		float m11, float m12, float m13, float m14,
+		float m21, float m22, float m23, float m24,
+		float m31, float m32, float m33, float m34
+		) {
+			rows[0][0] = m11; rows[0][1] = m12; rows[0][2] = m13; rows[0][3] = m14;
+			rows[1][0] = m21; rows[1][1] = m22; rows[1][2] = m23; rows[1][3] = m24;
+			rows[2][0] = m31; rows[2][1] = m32; rows[2][2] = m33; rows[2][3] = m34;
+	}
+
+	/* Multiplies this matrix by another.
+	* \param[in] rh The matrix to multiply this one with.
+	* \return The result of the multiplication.
+	*/
+	NIFLIB_API InertiaMatrix operator*( const InertiaMatrix & rh ) const;
+
+	/* Multiplies this matrix by another and sets the result to itself.
+	* \param[in] rh The matrix to multiply this one with.
+	* \return This matrix is returned.
+	*/
+	NIFLIB_API InertiaMatrix & operator*=( const InertiaMatrix & rh );
+
+	/* Multiplies this matrix by a scalar value.
+	* \param[in] rh The scalar value to multiply each component of this matrix by.
+	* \return The result of the multiplication.
+	*/
+	NIFLIB_API InertiaMatrix operator*( float rh ) const;
+
+	/* Multiplies this matrix by a scalar value and sets the resutl to itself.
+	* \param[in] rh The scalar value to multiply each component of this matrix by.
+	* \return This matrix is returned.
+	*/
+	NIFLIB_API InertiaMatrix & operator*=( float rh );
+
+	/* Multiplies this matrix by a vector with x, y, and z components.
+	* \param[in] rh The vector to multiply this matrix with.
+	* \return The result of the multiplication.
+	*/
+	NIFLIB_API Vector3 operator*( const Vector3 & rh ) const;
+
+	/* Adds this matrix to another.
+	* \param[in] rh The matrix to be added to this one.
+	* \return The result of the addition.
+	*/
+	NIFLIB_API InertiaMatrix operator+( const InertiaMatrix & rh ) const;
+
+	/* Adds this matrix to another and sets the result to itself.
+	* \param[in] rh The matrix to be added to this one.
+	* \return This matrix is returned.
+	*/
+	NIFLIB_API InertiaMatrix & operator+=( const InertiaMatrix & rh );
+
+	/* Sets the values of this matrix to those of the given matrix.
+	* \param[in] rh The matrix to copy values from.
+	* \return This matrix is returned.
+	*/
+	NIFLIB_API InertiaMatrix & operator=( const InertiaMatrix & rh );
+
+	/* Allows the contents of the matrix to be printed to an ostream.
+	* \param[in] lh The ostream to insert the text into.
+	* \param[in] rh The matrix to insert into the stream.
+	* \return The given ostream is returned.
+	*/
+	NIFLIB_API friend ostream & operator<<( ostream & lh, const InertiaMatrix & rh );
+
+	/* Compares two 4x4 matricies.  They are considered equal if all components are equal.
+	* \param[in] rh The matrix to compare this one with.
+	* \return true if the matricies are equal, false otherwise.
+	*/
+	NIFLIB_API bool operator==( const InertiaMatrix & rh ) const;
+
+	/* Compares two 4x4 matricies.  They are considered inequal if any corresponding
+	* components are inequal.
+	* \param[in] rh The matrix to compare this one with.
+	* \return true if the matricies are inequal, false otherwise.
+	*/
+	NIFLIB_API bool operator!=( const InertiaMatrix & rh ) const;
+
+	/*! Calculates the transpose of this matrix.
+	* \return The transpose of this matrix.
+	*/
+	NIFLIB_API InertiaMatrix Transpose() const;
+
+	/*! Calculates the determinant of this matrix.
+	* \return The determinant of this matrix.
+	*/
+	NIFLIB_API float Determinant() const;
+
+	/*! Calculates the inverse of this matrix.
+	* \return The inverse of this matrix.
+	*/
+	NIFLIB_API InertiaMatrix Inverse() const;
+
+	/*! Returns a 3x3 submatrix of this matrix created by skipping the indicated row and column.
+	* \param[in] skip_r The row to skip.  Must be a value between 0 and 3.
+	* \param[in] skip_c The colum to skip.  Must be a value between 0 and 3.
+	* \return The 3x3 submatrix obtained by skipping the indicated row and column.
+	*/
+	NIFLIB_API Matrix33 Submatrix( int skip_r, int skip_c ) const;
+
+	/*! Calculates the adjunct of this matrix created by skipping the indicated row and column.
+	* \param[in] skip_r The row to skip.  Must be a value between 0 and 3.
+	* \param[in] skip_c The colum to skip.  Must be a value between 0 and 3.
+	* \return The adjunct obtained by skipping the indicated row and column.
+	*/
+	NIFLIB_API float Adjoint( int skip_r, int skip_c ) const;
+};
+
+
 //--ostream functions for printing with cout--//
 
 NIFLIB_API ostream & operator<<( ostream & out, TexCoord const & val );
@@ -1033,6 +1237,8 @@ NIFLIB_API ostream & operator<<( ostream & out, Float4 const & val );
 NIFLIB_API ostream & operator<<( ostream & out, Color3 const & val );
 NIFLIB_API ostream & operator<<( ostream & out, Color4 const & val );
 NIFLIB_API ostream & operator<<( ostream & out, Quaternion const & val );
+NIFLIB_API ostream & operator<<( ostream & out, Matrix44 const & val );
+NIFLIB_API ostream & operator<<( ostream & out, InertiaMatrix const & val );
 
 }
 #endif
diff --git a/include/obj/NiMorphData.h b/include/obj/NiMorphData.h
index 426ab11ef764390d1d9a4558113b984173fbe91a..4ead91ae12d8fdf4469df6531380ead019bd495a 100644
--- a/include/obj/NiMorphData.h
+++ b/include/obj/NiMorphData.h
@@ -164,7 +164,7 @@ protected:
 	/*! Number of vertices. */
 	unsigned int numVertices;
 	/*! This byte is always 1 in all official files. */
-	bool relativeTargets;
+	byte relativeTargets;
 	/*! The geometry morphing objects. */
 	vector<Morph > morphs;
 public:
diff --git a/include/obj/bhkBoxShape.h b/include/obj/bhkBoxShape.h
index dc14ea944157323b34df8b9ccfe61233610d0ff4..c17851aa8d67f0e9689b653c9687bd2bed311907 100644
--- a/include/obj/bhkBoxShape.h
+++ b/include/obj/bhkBoxShape.h
@@ -66,6 +66,16 @@ public:
 	 */
 	NIFLIB_API void SetDimensions( const Vector3 & value );
 
+	/*! Helper routine for calculating mass properties.
+	*  \param[in]  density Uniform density of object
+	*  \param[in]  solid Determines whether the object is assumed to be solid or not
+	*  \param[out] mass Calculated mass of the object
+	*  \param[out] center Center of mass
+	*  \param[out] inertia Mass Inertia Tensor
+	*  \return Return mass, center, and inertia tensor.
+	*/
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Unknown. */
diff --git a/include/obj/bhkBvTreeShape.h b/include/obj/bhkBvTreeShape.h
index 16e32e98e462b55e9df087b22b0f66cf7827f3c9..03d8c929d3d4238ae80c18f0e24cfa6c3eac1b7e 100644
--- a/include/obj/bhkBvTreeShape.h
+++ b/include/obj/bhkBvTreeShape.h
@@ -52,6 +52,17 @@ public:
 	 */
 	NIFLIB_API virtual const Type & GetType() const;
 
+
+	/*! Helper routine for calculating mass properties.
+	*  \param[in]  density Uniform density of object
+	*  \param[in]  solid Determines whether the object is assumed to be solid or not
+	*  \param[out] mass Calculated mass of the object
+	*  \param[out] center Center of mass
+	*  \param[out] inertia Mass Inertia Tensor
+	*  \return Return mass, center, and inertia tensor.
+	*/
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--BEGIN MISC CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 public:
diff --git a/include/obj/bhkCapsuleShape.h b/include/obj/bhkCapsuleShape.h
index 2eaf164f46b39783145b46a4592d10116451661f..6428b717d86316a17cc074c53dd98f8efde22bd2 100644
--- a/include/obj/bhkCapsuleShape.h
+++ b/include/obj/bhkCapsuleShape.h
@@ -114,6 +114,16 @@ public:
 	 */
 	NIFLIB_API void SetRadius2( float value );
 
+	/*! Helper routine for calculating mass properties.
+	*  \param[in]  density Uniform density of object
+	*  \param[in]  solid Determines whether the object is assumed to be solid or not
+	*  \param[out] mass Calculated mass of the object
+	*  \param[out] center Center of mass
+	*  \param[out] inertia Mass Inertia Tensor
+	*  \return Return mass, center, and inertia tensor.
+	*/
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Unknown. */
diff --git a/include/obj/bhkConvexShape.h b/include/obj/bhkConvexShape.h
index 2b7dd380587f53284ca1bfcad8f2e04cd5d301c1..aec3cdb557ba8d93f9b86c1cb96ba54fe48acc21 100644
--- a/include/obj/bhkConvexShape.h
+++ b/include/obj/bhkConvexShape.h
@@ -53,6 +53,17 @@ public:
 	NIFLIB_API virtual const Type & GetType() const;
 
 	//--BEGIN MISC CUSTOM CODE--//
+
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
diff --git a/include/obj/bhkConvexTransformShape.h b/include/obj/bhkConvexTransformShape.h
index 2e835654b8ceb60426815cd60d94457365e84ad9..9b8864bcfe9f57550f3b24064e1dd43a54f422f1 100644
--- a/include/obj/bhkConvexTransformShape.h
+++ b/include/obj/bhkConvexTransformShape.h
@@ -53,6 +53,16 @@ public:
 	NIFLIB_API virtual const Type & GetType() const;
 
 	//--BEGIN MISC CUSTOM CODE--//
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
diff --git a/include/obj/bhkConvexVerticesShape.h b/include/obj/bhkConvexVerticesShape.h
index 24b7a1fc7af623a74ab44fbf371a765d2d09a38b..3155f085891eeadf991b9c5b13b318fb0538dd2a 100644
--- a/include/obj/bhkConvexVerticesShape.h
+++ b/include/obj/bhkConvexVerticesShape.h
@@ -111,6 +111,16 @@ public:
 	*/
 	NIFLIB_API void SetNormalsAndDist(const vector<Vector4>& value);
 
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 protected:
 	/*!
diff --git a/include/obj/bhkListShape.h b/include/obj/bhkListShape.h
index 605c85ad5b1eaf66be4a2bab40c5e6751590a07f..7d362570e837d263c26c34da478fba87762112cc 100644
--- a/include/obj/bhkListShape.h
+++ b/include/obj/bhkListShape.h
@@ -91,6 +91,16 @@ public:
 	 */
 	NIFLIB_API void SetMaterial( HavokMaterial value );
 
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! The number of sub shapes referenced. */
diff --git a/include/obj/bhkMoppBvTreeShape.h b/include/obj/bhkMoppBvTreeShape.h
index 7e563487f05122617c310715f93d2641065085cf..8ef6c4f755e3ea3600e8054816276d1fbb777c89 100644
--- a/include/obj/bhkMoppBvTreeShape.h
+++ b/include/obj/bhkMoppBvTreeShape.h
@@ -130,6 +130,16 @@ public:
 	*/
 	NIFLIB_API void SetMoppScale( float value );
 
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! The shape. */
diff --git a/include/obj/bhkMultiSphereShape.h b/include/obj/bhkMultiSphereShape.h
index 61a06437bb3b154a8c069f445174d8cc76638daf..abdf67585fc9b98f8a1ac7bff8a88c845d4dbb97 100644
--- a/include/obj/bhkMultiSphereShape.h
+++ b/include/obj/bhkMultiSphereShape.h
@@ -70,6 +70,16 @@ public:
 
 	NIFLIB_API void SetSpheres( const vector<SphereBV> & value );
 
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Unknown. */
diff --git a/include/obj/bhkNiTriStripsShape.h b/include/obj/bhkNiTriStripsShape.h
index ba5454aa233124634013a4d21b4d41365e0e7ef4..f1a5f0b7c1158f96aea6ce9104e2124c6ddfb0ff 100644
--- a/include/obj/bhkNiTriStripsShape.h
+++ b/include/obj/bhkNiTriStripsShape.h
@@ -131,6 +131,16 @@ public:
 	NIFLIB_API unsigned char GetOblivionFilter( unsigned int index ) const;
 	NIFLIB_API void SetOblivionFilter( unsigned int index, unsigned char filter ); 
 
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! The shape's material. */
diff --git a/include/obj/bhkPackedNiTriStripsShape.h b/include/obj/bhkPackedNiTriStripsShape.h
index d534d8dd248162a0131b5ad72f2b567c44169f21..b9326232e18f3a9a381926700c6a7a2cc6307b67 100644
--- a/include/obj/bhkPackedNiTriStripsShape.h
+++ b/include/obj/bhkPackedNiTriStripsShape.h
@@ -83,6 +83,16 @@ public:
 	*/
 	NIFLIB_API void SetSubShapes( vector<OblivionSubShape>& value );	
 
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Number of subparts. */
diff --git a/include/obj/bhkRigidBody.h b/include/obj/bhkRigidBody.h
index 76104f3f10f2e4611c8f32fd02b0160a5d83f278..b71f1f0ff83add376e884c8adfd1477db11221a4 100644
--- a/include/obj/bhkRigidBody.h
+++ b/include/obj/bhkRigidBody.h
@@ -17,7 +17,6 @@ All rights reserved.  Please see niflib.h for license. */
 
 // Include structures
 #include "../gen/QuaternionXYZW.h"
-#include "../gen/InertiaMatrix.h"
 #include "../Ref.h"
 namespace Niflib {
 
@@ -133,13 +132,13 @@ public:
 	 * Gets the current inertia of this rigid body.
 	 * \return The inertia of this rigid body.
 	 */
-	NIFLIB_API array<12,float> GetInertia() const;
+	NIFLIB_API InertiaMatrix GetInertia() const;
 
 	/*!
 	 * Sets a new inertia for this rigid body.
 	 * \param[in] value The new inertia for this rigid body.
 	 */
-	NIFLIB_API void SetInertia( const array<12,float> & value );
+	NIFLIB_API void SetInertia( const InertiaMatrix & value );
 
 	/*!
 	 * Gets the current center point of this rigid body.
@@ -284,13 +283,21 @@ public:
 	// Usually set to 1 for fixed objects, or set to 2 for moving ones.  Seems to
 	// always be same as Unknown Byte 1.
 	// \return The current value.
-	SolverDeactivation GetSolverDeactivation() const;
+	NIFLIB_API SolverDeactivation GetSolverDeactivation() const;
 
 	// Usually set to 1 for fixed objects, or set to 2 for moving ones.  Seems to
 	// always be same as Unknown Byte 1.
 	// \param[in] value The new value.
-	void SetSolverDeactivation( const SolverDeactivation & value );
+	NIFLIB_API void SetSolverDeactivation( const SolverDeactivation & value );
 
+	// Apply scale factor <scale> on data.
+	// \param[in] scale Factor to scale by
+	NIFLIB_API void ApplyScale(float scale);
+
+	// Look at all the objects under this rigid body and update the mass
+	//  center of gravity, and inertia tensor accordingly. If the mass parameter
+	//  is given then the density argument is ignored.
+	NIFLIB_API void UpdateMassCenterInertia(float density = 1.0f, bool solid = true, float mass = 0.0f);
 
 	//--END CUSTOM CODE--//
 protected:
diff --git a/include/obj/bhkShape.h b/include/obj/bhkShape.h
index d1704f6bf24477263356bc828b0180a2c4f59e18..6b858a03977cd502c54425a15388256cbb8343c5 100644
--- a/include/obj/bhkShape.h
+++ b/include/obj/bhkShape.h
@@ -11,6 +11,7 @@ All rights reserved.  Please see niflib.h for license. */
 #define _BHKSHAPE_H_
 
 //--BEGIN FILE HEAD CUSTOM CODE--//
+#include "../NIF_IO.h"
 //--END CUSTOM CODE--//
 
 #include "bhkSerializable.h"
@@ -53,6 +54,17 @@ public:
 	NIFLIB_API virtual const Type & GetType() const;
 
 	//--BEGIN MISC CUSTOM CODE--//
+
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
diff --git a/include/obj/bhkSphereRepShape.h b/include/obj/bhkSphereRepShape.h
index 27cb1b44073c83c2966519c04419be5039c80018..fd08bad8992eeb9788d0f57465149ce5a7f26b1d 100644
--- a/include/obj/bhkSphereRepShape.h
+++ b/include/obj/bhkSphereRepShape.h
@@ -81,6 +81,16 @@ public:
 	*/
 	NIFLIB_API void SetRadius( float value );
 
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! The shape's material. */
diff --git a/include/obj/bhkSphereShape.h b/include/obj/bhkSphereShape.h
index 0b32da66980f4e8acf55f7b8048dfad097da5c03..1145b7eea82f1c561178a02e7d98d2e99772ddff 100644
--- a/include/obj/bhkSphereShape.h
+++ b/include/obj/bhkSphereShape.h
@@ -66,6 +66,16 @@ public:
 	 */
 	NIFLIB_API void SetRadius( float value );
 
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 	//--END CUSTOM CODE--//
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
diff --git a/include/obj/bhkTransformShape.h b/include/obj/bhkTransformShape.h
index 6cf083005f7551a9d17f7839451821b1025c337a..34d7470d6a6ae736a35e31d1e3ee76640c845410 100644
--- a/include/obj/bhkTransformShape.h
+++ b/include/obj/bhkTransformShape.h
@@ -94,6 +94,16 @@ public:
 	 */
 	NIFLIB_API virtual void SetTransform( const Matrix44 & value );
 
+	/*! Helper routine for calculating mass properties.
+	 *  \param[in]  density Uniform density of object
+	 *  \param[in]  solid Determines whether the object is assumed to be solid or not
+	 *  \param[out] mass Calculated mass of the object
+	 *  \param[out] center Center of mass
+	 *  \param[out] inertia Mass Inertia Tensor
+	 *  \return Return mass, center, and inertia tensor.
+	 */
+	NIFLIB_API virtual void CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia);
+
 
 	//--END CUSTOM CODE--//
 protected:
diff --git a/niflib.vcproj b/niflib.vcproj
index ba817327407efc9df66cf58f0f934a4ab1cc4d31..33bf04b4475e1471ae4c5ee3567b0f34eff5f55a 100644
--- a/niflib.vcproj
+++ b/niflib.vcproj
@@ -597,7 +597,7 @@
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
 			<File
-				RelativePath=".\src\ComplexShape.cpp"
+				RelativePath=".\src\Inertia.cpp"
 				>
 			</File>
 			<File
@@ -652,6 +652,10 @@
 					/>
 				</FileConfiguration>
 			</File>
+			<File
+				RelativePath=".\src\nifqhull.cpp"
+				>
+			</File>
 			<File
 				RelativePath=".\src\ObjectRegistry.cpp"
 				>
@@ -1851,6 +1855,10 @@
 					RelativePath=".\src\gen\ChannelData.cpp"
 					>
 				</File>
+				<File
+					RelativePath=".\src\ComplexShape.cpp"
+					>
+				</File>
 				<File
 					RelativePath=".\src\gen\ControllerLink.cpp"
 					>
@@ -1883,10 +1891,6 @@
 					RelativePath=".\src\gen\hkTriangle.cpp"
 					>
 				</File>
-				<File
-					RelativePath=".\src\gen\InertiaMatrix.cpp"
-					>
-				</File>
 				<File
 					RelativePath=".\src\gen\LimitedHingeDescriptor.cpp"
 					>
@@ -2054,6 +2058,10 @@
 				RelativePath=".\include\FixLink.h"
 				>
 			</File>
+			<File
+				RelativePath=".\include\Inertia.h"
+				>
+			</File>
 			<File
 				RelativePath=".\include\Key.h"
 				>
@@ -2086,6 +2094,10 @@
 				RelativePath=".\include\niflib.h"
 				>
 			</File>
+			<File
+				RelativePath=".\include\nifqhull.h"
+				>
+			</File>
 			<File
 				RelativePath=".\include\ObjectRegistry.h"
 				>
@@ -2105,6 +2117,10 @@
 			<Filter
 				Name="obj"
 				>
+				<File
+					RelativePath=".\include\obj\ATextureRenderData.h"
+					>
+				</File>
 				<File
 					RelativePath=".\include\obj\AvoidNode.h"
 					>
diff --git a/niflib_VC2008.vcproj b/niflib_VC2008.vcproj
index d31472d6d3d5d63bbdfc6f32793bc6b21d5a9652..3146ad080f7afdbe68b567d75dec197394b5a1cf 100644
--- a/niflib_VC2008.vcproj
+++ b/niflib_VC2008.vcproj
@@ -593,6 +593,10 @@
 			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
+			<File
+				RelativePath=".\src\Inertia.cpp"
+				>
+			</File>
 			<File
 				RelativePath=".\src\kfm.cpp"
 				>
@@ -645,6 +649,10 @@
 					/>
 				</FileConfiguration>
 			</File>
+			<File
+				RelativePath=".\src\nifqhull.cpp"
+				>
+			</File>
 			<File
 				RelativePath=".\src\ObjectRegistry.cpp"
 				>
@@ -1880,10 +1888,6 @@
 					RelativePath=".\src\gen\hkTriangle.cpp"
 					>
 				</File>
-				<File
-					RelativePath=".\src\gen\InertiaMatrix.cpp"
-					>
-				</File>
 				<File
 					RelativePath=".\src\gen\LimitedHingeDescriptor.cpp"
 					>
@@ -2051,6 +2055,10 @@
 				RelativePath=".\include\FixLink.h"
 				>
 			</File>
+			<File
+				RelativePath=".\include\Inertia.h"
+				>
+			</File>
 			<File
 				RelativePath=".\include\Key.h"
 				>
@@ -2083,6 +2091,10 @@
 				RelativePath=".\include\niflib.h"
 				>
 			</File>
+			<File
+				RelativePath=".\include\nifqhull.h"
+				>
+			</File>
 			<File
 				RelativePath=".\include\ObjectRegistry.h"
 				>
@@ -2798,6 +2810,10 @@
 					RelativePath=".\include\obj\NiPathInterpolator.h"
 					>
 				</File>
+				<File
+					RelativePath=".\include\obj\NiPersistentSrcTextureRendererData.h"
+					>
+				</File>
 				<File
 					RelativePath=".\include\obj\NiPhysXActorDesc.h"
 					>
@@ -3034,6 +3050,14 @@
 					RelativePath=".\include\obj\NiRotatingParticlesData.h"
 					>
 				</File>
+				<File
+					RelativePath=".\include\obj\NiScreenElements.h"
+					>
+				</File>
+				<File
+					RelativePath=".\include\obj\NiScreenElementsData.h"
+					>
+				</File>
 				<File
 					RelativePath=".\include\obj\NiScreenLODData.h"
 					>
@@ -3370,6 +3394,10 @@
 					RelativePath=".\include\gen\physXMaterialRef.h"
 					>
 				</File>
+				<File
+					RelativePath=".\include\gen\Polygon.h"
+					>
+				</File>
 				<File
 					RelativePath=".\include\gen\QuaternionXYZW.h"
 					>
diff --git a/src/Inertia.cpp b/src/Inertia.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1b103488effec7447f402cc394d6594da6a21fba
--- /dev/null
+++ b/src/Inertia.cpp
@@ -0,0 +1,238 @@
+/* Copyright (c) 2006, NIF File Format Library and Tools
+All rights reserved.  Please see niflib.h for license. */
+
+#include "../include/Inertia.h"
+#include <vector>
+#include <algorithm>
+#include <functional>
+#include <numeric>
+#define _USE_MATH_DEFINES
+#include <math.h>
+using namespace Niflib;
+
+void Inertia::GetMassInertiaSphere(float radius, float density, bool solid, 
+								   float& mass, InertiaMatrix &inertia)
+{
+	float inertiaScalar;
+    if (solid) {
+        mass = density * (4.0f * float(M_PI) * pow(radius, 3.0f)) / 3.0f;
+        inertiaScalar = (2.0f * mass * pow(radius, 2.0f)) / 5.0f;
+	} else {
+        mass = density * 4.0f * float(M_PI) * pow(radius, 2.0f);
+        inertiaScalar = (2.0f * mass * pow(radius, 2.0f)) / 3.0f;
+	}
+	inertia = InertiaMatrix::IDENTITY;
+	inertia[0][0] = inertia[1][1] = inertia[2][2] = inertiaScalar;
+}
+
+
+
+void Inertia::GetMassInertiaBox(Vector3 size, float density, bool solid,
+								float& mass, InertiaMatrix &inertia)
+{
+	Vector3 tmp;
+    if (solid)
+	{
+        mass = density * (size[0] * size[1] * size[2]);
+        tmp[0] = mass * pow(size[0], 2.0f) / 12.0f;
+		tmp[1] = mass * pow(size[1], 2.0f) / 12.0f;
+		tmp[2] = mass * pow(size[2], 2.0f) / 12.0f;
+	}
+    else
+	{
+        mass = density * ((size[0]*size[1]*2.0f) + (size[0]*size[2]*2.0f) + (size[1]*size[2]*2.0f));
+		tmp[0] = mass * pow(size[0], 2.0f) / 6.0f;
+		tmp[1] = mass * pow(size[1], 2.0f) / 6.0f;
+		tmp[2] = mass * pow(size[2], 2.0f) / 6.0f;
+		//TODO: just guessing here, calculate it
+	}
+	inertia = InertiaMatrix::IDENTITY;
+	inertia[0][0] = tmp[1] + tmp[2];
+	inertia[1][1] = tmp[2] + tmp[0];
+	inertia[2][2] = tmp[0] + tmp[1];
+}
+
+void Inertia::GetMassInertiaCylinder(float radius, float height, 
+								float density, bool solid,
+								float& mass, InertiaMatrix &inertia)
+{
+	inertia = InertiaMatrix::IDENTITY;
+	if (solid)
+	{
+		mass = density * height * float(M_PI) * pow(radius, 2.0f);
+		inertia[0][0] = 
+		inertia[1][1] = mass * (3.0f * pow(radius, 3.0f) + pow(height, 2.0f)) / 12.0f;
+		inertia[2][2] = mass * (pow(radius, 2.0f)) / 2.0f;
+	}
+	else
+	{
+		mass = density * height * float(M_PI) * pow(radius, 2.0f);
+		inertia[0][0] = 
+		inertia[1][1] = mass * (6.0f * pow(radius, 3.0f) + pow(height, 2.0f)) / 12.0f;
+		inertia[2][2] = mass * (pow(radius, 2.0f));
+	}
+}
+
+void Inertia::GetMassInertiaCapsule(float radius, float height, 
+									float density, bool solid,
+									float& mass, InertiaMatrix &inertia)
+{
+    // cylinder + caps, and caps have volume of a sphere
+	inertia = InertiaMatrix::IDENTITY;
+	if (solid)
+	{
+		mass = density * (height * float(M_PI) * pow(radius, 2.0f) + (4.0f * float(M_PI) * pow(radius, 3.0f)) / 3.0f);
+		inertia[0][0] = mass * (3.0f * pow(radius, 3.0f) + pow(height, 2.0f)) / 12.0f;
+		inertia[1][1] = inertia[0][0];
+		inertia[2][2] = mass * (pow(radius, 2.0f)) / 2.0f;
+	}
+	else
+	{
+		mass = density * (height * 2.0f * float(M_PI) * radius + 2.0f * float(M_PI) * pow(radius, 2.0f));
+		inertia[0][0] = mass * (6.0f * pow(radius, 2.0f) + pow(height, 2.0f)) / 12.0f;
+		inertia[1][1] = inertia[0][0];
+		inertia[2][2] = mass * pow(radius, 2.0f);
+	}
+}
+
+//
+// References
+// ----------
+//
+// Jonathan Blow, Atman J Binstock
+// "How to find the inertia tensor (or other mass properties) of a 3D solid body represented by a triangle mesh"
+// http://number-none.com/blow/inertia/bb_inertia.doc
+//
+// David Eberly
+// "Polyhedral Mass Properties (Revisited)"
+// http://www.geometrictools.com//LibPhysics/RigidBody/Wm4PolyhedralMassProperties.pdf
+//
+// The function is an implementation of the Blow and Binstock algorithm,
+// extended for the case where the polygon is a surface (set parameter
+// solid = False).
+void Inertia::GetMassCenterInertiaPolyhedron(const vector<Vector3>& vertices, 
+											 const vector<Triangle>& triangles, 
+											 float density, bool solid,
+											 float& mass, Vector3& center, InertiaMatrix &inertia)
+{
+    // 120 times the covariance matrix of the canonical tetrahedron
+    // (0,0,0),(1,0,0),(0,1,0),(0,0,1)
+    // integrate(integrate(integrate(z*z, x=0..1-y-z), y=0..1-z), z=0..1) = 1/120
+    // integrate(integrate(integrate(y*z, x=0..1-y-z), y=0..1-z), z=0..1) = 1/60
+    Matrix33 covariance_canonical(	2.0f, 1.0f, 1.0f, 
+									1.0f, 2.0f, 1.0f, 
+									1.0f, 1.0f, 2.0f );
+    float covariance_correction = 1.0f/120.0f;
+
+    vector<Matrix44> covariances;
+    vector<float> masses;
+    vector<Vector3> centers;
+
+    // for each triangle
+    // construct a tetrahedron from triangle + (0,0,0)
+    // find its matrix, mass, and center (for density = 1, will be corrected at
+    // the end of the algorithm)
+	for (vector<Triangle>::const_iterator itr=triangles.begin(), end=triangles.end(); itr != end; ++itr)
+	{
+        // get vertices
+        const Vector3& vert0 = vertices[ (*itr)[0] ];
+		const Vector3& vert1 = vertices[ (*itr)[1] ];
+		const Vector3& vert2 = vertices[ (*itr)[2] ];
+
+        // construct a transform matrix that converts the canonical tetrahedron
+        // into (0,0,0),vert0,vert1,vert2
+		Matrix44 transform_transposed(Matrix33(
+			vert0[0], vert0[1], vert0[2],
+			vert1[0], vert1[1], vert1[2],
+			vert2[0], vert2[1], vert2[2]));
+		Matrix44 transform = transform_transposed.Transpose();
+
+        // find the covariance matrix of the transformed tetrahedron/triangle
+        if (solid)
+		{
+            // we shall be needing the determinant more than once, so
+            // precalculate it
+			float determinant = transform.Determinant();
+
+            // C' = det(A) * A * C * A^T
+			covariances.push_back( transform * covariance_canonical * transform_transposed * determinant );
+            // m = det(A) / 6.0
+            masses.push_back(determinant / 6.0f);
+            // find center of gravity of the tetrahedron
+			centers.push_back(
+				Vector3(0.25f * (vert0[0] + vert1[0] + vert2[0]),
+						0.25f * (vert0[1] + vert1[1] + vert2[1]),
+						0.25f * (vert0[2] + vert1[2] + vert2[2]))
+				);
+		} else {
+            // find center of gravity of the triangle
+			Vector3 com( (vert0[0] + vert1[0] + vert2[0]) / 3.0f,
+						 (vert0[1] + vert1[1] + vert2[1]) / 3.0f,
+						 (vert0[2] + vert1[2] + vert2[2]) / 3.0f);
+			centers.push_back( com );
+
+            // find mass of triangle
+            // mass is surface, which is half the norm of cross product
+            // of two edges
+			float calc_mass = ((vert1 - vert0) ^ (vert2 - vert0)).Magnitude() / 2.0f;
+			masses.push_back( calc_mass );
+
+            // find covariance at center of this triangle
+            // (this is approximate only as it replaces triangle with point mass
+            // TODO: find better way)
+			Matrix33 calc_c( com[0]*com[0], com[0]*com[1], com[0]*com[2],
+							 com[1]*com[0], com[1]*com[1], com[1]*com[2],
+							 com[2]*com[0], com[2]*com[1], com[2]*com[2]);
+            covariances.push_back( Matrix44(calc_c) );
+		}
+	}
+    // accumulate the results
+	mass = std::accumulate(masses.begin(), masses.end(), 0.0f);
+    if (mass < 0.0001f)
+	{
+        // dimension is probably badly chosen
+        //raise ZeroDivisionError("mass is zero (consider calculating inertia with a lower dimension)")
+        //printf("WARNING: mass is zero");
+		mass = 0.0f;
+		center = Vector3();
+		inertia = InertiaMatrix::IDENTITY;
+		return;
+	}
+
+    // weighed average of centers with masses
+	center = Vector3();
+	for (size_t i = 0; i<masses.size(); ++i)
+		center += (centers[i] * (masses[i] / mass) );
+
+    // add covariances, and correct the values
+	Matrix44 total_covariance;
+	if (solid)
+	{
+		for (size_t i = 0; i<covariances.size(); ++i)
+			total_covariance *= covariances[i];
+	}
+
+
+    // translate covariance to center of gravity:
+    // C' = C - m * ( x dx^T + dx x^T + dx dx^T )
+    // with x the translation vector and dx the center of gravity
+
+	Matrix44 translate_correction(
+		Matrix33( center[0]*center[0], center[0]*center[1], center[0]*center[2],
+				 center[1]*center[0], center[1]*center[1], center[1]*center[2],
+				 center[2]*center[0], center[2]*center[1], center[2]*center[2]
+				) 
+		);
+	translate_correction *= mass;
+
+    total_covariance = total_covariance - translate_correction;
+
+    // convert covariance matrix into inertia tensor
+	float trace = total_covariance[0][0] + total_covariance[1][1] + total_covariance[2][2];
+	Matrix44 trace_matrix;
+	trace_matrix[0][0] = trace_matrix[1][1] = trace_matrix[2][2] = trace;
+		
+	// correct for given density
+    inertia = InertiaMatrix((trace_matrix - total_covariance).GetRotation()) * density;
+    mass *= density;
+}
\ No newline at end of file
diff --git a/src/NIF_IO.cpp b/src/NIF_IO.cpp
index 96ec1b20907b70aeb5c672ecdc6f63033e3d0293..91d24d38335f010c976ef5755edf95dfbb863016 100644
--- a/src/NIF_IO.cpp
+++ b/src/NIF_IO.cpp
@@ -837,5 +837,22 @@ ostream & operator<<( ostream & out, Char8String const & val ) {
 	return out;
 }
 
+//InertiaMatrix
+void NifStream( InertiaMatrix & val, istream& in, const NifInfo & info ) {
+	for (int c = 0; c < 3; ++c) {
+		for (int r = 0; r < 4; ++r) {
+			val[r][c] = ReadFloat( in );
+		}
+	}
+}
+
+void NifStream( InertiaMatrix const & val, ostream& out, const NifInfo & info ) {
+	for (int c = 0; c < 3; ++c) {
+		for (int r = 0; r < 4; ++r) {
+			WriteFloat( val[r][c], out );
+		}
+	}
+}
+
 
 }
\ No newline at end of file
diff --git a/src/gen/InertiaMatrix.cpp b/src/gen/InertiaMatrix.cpp
deleted file mode 100644
index 5fc8a753469bfc7b0fe7ffcccf010ec1ce30a92f..0000000000000000000000000000000000000000
--- a/src/gen/InertiaMatrix.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright (c) 2006, NIF File Format Library and Tools
-All rights reserved.  Please see niflib.h for license. */
-
-//---THIS FILE WAS AUTOMATICALLY GENERATED.  DO NOT EDIT---//
-
-//To change this file, alter the niftools/docsys/gen_niflib.py Python script.
-
-#include "../../include/gen/InertiaMatrix.h"
-using namespace Niflib;
-
-//Constructor
-InertiaMatrix::InertiaMatrix() : m11(0.0f), m12(0.0f), m13(0.0f), m14(0.0f), m21(0.0f), m22(0.0f), m23(0.0f), m24(0.0f), m31(0.0f), m32(0.0f), m33(0.0f), m34(0.0f) {};
-
-//Copy Constructor
-InertiaMatrix::InertiaMatrix( const InertiaMatrix & src ) {
-	*this = src;
-};
-
-//Copy Operator
-InertiaMatrix & InertiaMatrix::operator=( const InertiaMatrix & src ) {
-	this->m11 = src.m11;
-	this->m12 = src.m12;
-	this->m13 = src.m13;
-	this->m14 = src.m14;
-	this->m21 = src.m21;
-	this->m22 = src.m22;
-	this->m23 = src.m23;
-	this->m24 = src.m24;
-	this->m31 = src.m31;
-	this->m32 = src.m32;
-	this->m33 = src.m33;
-	this->m34 = src.m34;
-	return *this;
-};
-
-//Destructor
-InertiaMatrix::~InertiaMatrix() {};
diff --git a/src/nif_math.cpp b/src/nif_math.cpp
index 9ee0ca018e6f6eb451b92af234379fbc7a69e856..d368a2f24e54711c1ef94b35a1e921e99bdac0d1 100644
--- a/src/nif_math.cpp
+++ b/src/nif_math.cpp
@@ -19,6 +19,11 @@ const Matrix33 Matrix33::IDENTITY( 1.0f, 0.0f, 0.0f,
 const Matrix22 Matrix22::IDENTITY( 1.0f, 0.0f,
 								   0.0f, 1.0f );
 
+const InertiaMatrix InertiaMatrix::IDENTITY( 
+								  1.0f, 0.0f, 0.0f, 0.0f,
+								  0.0f, 1.0f, 0.0f, 0.0f,
+								  0.0f, 0.0f, 1.0f, 0.0f );
+
 /* TexCoord Methods
  *
  */
@@ -124,6 +129,24 @@ bool Vector3::operator!=( const Vector3 & rh) const {
 		return true;
 }
 
+float & Vector3::operator[](int n) {
+	switch (n) {
+			case 0: return x; break;
+			case 1: return y; break;
+			case 2: return z; break;
+			default: throw std::out_of_range("Index out of range for Vector3");
+	};
+}
+
+float Vector3::operator[](int n) const {
+	switch (n) {
+			case 0: return x; break;
+			case 1: return y; break;
+			case 2: return z; break;
+			default: throw std::out_of_range("Index out of range for Vector3");
+	};
+}
+
 float Vector3::DotProduct( const Vector3 & rh) const {
 	return x * rh.x + y * rh.y + z * rh.z;
 }
@@ -475,6 +498,19 @@ Matrix44 & Matrix44::operator+=( const Matrix44 & rh ) {
 	return *this;
 }
 
+Matrix44 Matrix44::operator-( const Matrix44 & rh ) const {
+	return Matrix44(*this) -= rh;
+} 
+
+Matrix44 & Matrix44::operator-=( const Matrix44 & rh ) {
+	for (int i = 0; i < 4; i++) {
+		for (int j = 0; j < 4; j++) {
+			(*this)[i][j] -= rh[i][j];
+		}
+	}
+	return *this;
+}
+
 Matrix44 & Matrix44::operator=( const Matrix44 & rh ) {
 	memcpy(rows, rh.rows, sizeof(Float4) * 4);
 	return *this;
@@ -623,6 +659,157 @@ Matrix33 Quaternion::AsMatrix() {
 	return m;
 }
 
+
+/*
+* InertiaMatrix Methods
+*/
+
+InertiaMatrix::InertiaMatrix() {
+	*this = InertiaMatrix::IDENTITY;
+}
+
+InertiaMatrix::InertiaMatrix( const Matrix33 & r ) {
+	//Set this matrix with rotate and translate information
+	InertiaMatrix & m = *this;
+	m[0][0] = r[0][0];  m[0][1] = r[0][1];  m[0][2] = r[0][2];  m[0][3] = 0.0f;
+	m[1][0] = r[1][0];  m[1][1] = r[1][1];  m[1][2] = r[1][2];  m[1][3] = 0.0f;
+	m[2][0] = r[2][0];  m[2][1] = r[2][1];  m[2][2] = r[2][2];  m[2][3] = 0.0f;
+}
+
+InertiaMatrix InertiaMatrix::operator*( const InertiaMatrix & rh ) const {
+	return InertiaMatrix(*this) *= rh;
+}
+
+InertiaMatrix & InertiaMatrix::operator*=( const InertiaMatrix & rh ) {
+	InertiaMatrix r;
+	InertiaMatrix & lh = *this;
+	float t;
+	for (int i = 0; i < 3; i++) {
+		for (int j = 0; j < 4; j++) {
+			t = 0.0f;
+			for (int k = 0; k < 4; k++) {
+				t += lh[i][k] * rh[k][j];
+			}
+			r[i][j] = t;
+		}
+	}
+
+	*this = r;
+	return *this;
+}
+
+InertiaMatrix InertiaMatrix::operator*( float rh ) const {
+	return InertiaMatrix(*this) *= rh;
+}
+
+InertiaMatrix & InertiaMatrix::operator*=( float rh ) {
+	for (int i = 0; i < 3; i++) {
+		for (int j = 0; j < 4; j++) {
+			(*this)[i][j] *= rh;
+		}
+	}
+	return *this;
+}
+
+Vector3 InertiaMatrix::operator*( const Vector3 & rh ) const {
+	const InertiaMatrix & t = *this;
+	Vector3 v;
+	//Multiply, ignoring w
+	v.x = rh.x * t[0][0] + rh.y * t[1][0] + rh.z * t[2][0];
+	v.y = rh.x * t[0][1] + rh.y * t[1][1] + rh.z * t[2][1];
+	v.z = rh.x * t[0][2] + rh.y * t[1][2] + rh.z * t[2][2];
+	return v;
+}
+
+InertiaMatrix InertiaMatrix::operator+( const InertiaMatrix & rh ) const {
+	return InertiaMatrix(*this) += rh;
+} 
+
+InertiaMatrix & InertiaMatrix::operator+=( const InertiaMatrix & rh ) {
+	for (int i = 0; i < 3; i++) {
+		for (int j = 0; j < 4; j++) {
+			(*this)[i][j] += rh[i][j];
+		}
+	}
+	return *this;
+}
+
+InertiaMatrix & InertiaMatrix::operator=( const InertiaMatrix & rh ) {
+	memcpy(rows, rh.rows, sizeof(Float4) * 4);
+	return *this;
+}
+
+bool InertiaMatrix::operator==( const InertiaMatrix & rh ) const {
+	for (int i = 0; i < 3; i++) {
+		for (int j = 0; j < 4; j++) {
+			if ( (*this)[i][j] != rh[i][j] )
+				return false;
+		}
+	}
+	return true;
+}
+
+bool InertiaMatrix::operator!=( const InertiaMatrix & rh ) const {
+	for (int i = 0; i < 3; i++) {
+		for (int j = 0; j < 4; j++) {
+			if ( (*this)[i][j] != rh[i][j] )
+				return true;
+		}
+	}
+	return false;
+}
+
+InertiaMatrix InertiaMatrix::Transpose() const {
+	const InertiaMatrix & t = *this;
+	return InertiaMatrix( t[0][0], t[1][0], t[2][0], t[3][0],
+		t[0][1], t[1][1], t[2][1], t[3][1],
+		t[0][2], t[1][2], t[2][2], t[3][2]);
+}
+
+Matrix33 InertiaMatrix::Submatrix( int skip_r, int skip_c ) const {
+	Matrix33 sub;
+	int i = 0, j = 0;
+	for (int r = 0; r < 3; r++) {
+		if (r == skip_r)
+			continue;
+		for (int c = 0; c < 4; c++) {
+			if (c == skip_c)
+				continue;
+			sub[i][j] = (*this)[r][c];
+			j++;
+		}
+		i++;
+		j = 0;
+	}
+	return sub;
+}
+
+float InertiaMatrix::Adjoint( int skip_r, int skip_c ) const {
+	Matrix33 sub = Submatrix( skip_r, skip_c );
+	return pow(-1.0f, float(skip_r + skip_c)) * sub.Determinant();
+}
+
+InertiaMatrix InertiaMatrix::Inverse() const {
+	InertiaMatrix result;
+
+	float det = Determinant();
+	for (int r = 0; r < 3; r++) {
+		for (int c = 0; c < 4; c++) {
+			result[c][r] = Adjoint(r, c) / det;
+		}
+	}
+
+	return result;
+}
+
+float InertiaMatrix::Determinant() const {
+	const InertiaMatrix & t = *this;
+	return  t[0][0] * Submatrix(0, 0).Determinant()
+		- t[0][1] * Submatrix(0, 1).Determinant()
+		+ t[0][2] * Submatrix(0, 2).Determinant()
+		- t[0][3] * Submatrix(0, 3).Determinant();
+}
+
 /*
  * ostream functions for printing with cout
  */
@@ -686,4 +873,13 @@ ostream & operator<<( ostream & out, Color4 const & val ) {
 ostream & operator<<( ostream & out, Quaternion const & val ) {
 	return out << "[" << setw(6) << val.w << ",(" << setw(6) << val.x << "," << setw(6) << val.y << "," << setw(6) << val.z << ")]";
 }
+
+ostream & operator<<( ostream & out, InertiaMatrix const & val ) {
+	out << endl
+		<< "   |" << setw(6) << val[0][0] << "," << setw(6) << val[0][1] << "," << setw(6) << val[0][2] << "," << setw(6) << val[0][3] << " |" << endl
+		<< "   |" << setw(6) << val[1][0] << "," << setw(6) << val[1][1] << "," << setw(6) << val[1][2] << "," << setw(6) << val[1][3] << " |" << endl
+		<< "   |" << setw(6) << val[2][0] << "," << setw(6) << val[2][1] << "," << setw(6) << val[2][2] << "," << setw(6) << val[2][3] << " |";
+	return out;
+}
+
 }
diff --git a/src/obj/NiMorphData.cpp b/src/obj/NiMorphData.cpp
index ef544290744b65291800ac09b635c4ca42075044..093222941b403e6ffdea1c1abb0308b7d227dc11 100644
--- a/src/obj/NiMorphData.cpp
+++ b/src/obj/NiMorphData.cpp
@@ -20,7 +20,7 @@ using namespace Niflib;
 //Definition of TYPE constant
 const Type NiMorphData::TYPE("NiMorphData", &NiObject::TYPE );
 
-NiMorphData::NiMorphData() : numMorphs((unsigned int)0), numVertices((unsigned int)0), relativeTargets(1) {
+NiMorphData::NiMorphData() : numMorphs((unsigned int)0), numVertices((unsigned int)0), relativeTargets((byte)1) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
diff --git a/src/obj/bhkBoxShape.cpp b/src/obj/bhkBoxShape.cpp
index ee08584857a6d1ec93b5ee1b24920ea78e603078..86eb94a23838c9decefb21669e69e4ab759785a5 100644
--- a/src/obj/bhkBoxShape.cpp
+++ b/src/obj/bhkBoxShape.cpp
@@ -8,6 +8,7 @@ All rights reserved.  Please see niflib.h for license. */
 //-----------------------------------NOTICE----------------------------------//
 
 //--BEGIN FILE HEAD CUSTOM CODE--//
+#include "../../include/Inertia.h"
 //--END CUSTOM CODE--//
 
 #include "../../include/FixLink.h"
@@ -121,4 +122,9 @@ void bhkBoxShape::SetDimensions(const Vector3 &value) {
 	minimumSize = min( min(value.x, value.y), value.z );
 }
 
+void bhkBoxShape::CalcMassCenterInertia( float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia )
+{
+	center = Vector3(0,0,0);
+	Inertia::GetMassInertiaBox( dimensions * 2.0f, density, solid, mass, inertia ); 
+}
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkBvTreeShape.cpp b/src/obj/bhkBvTreeShape.cpp
index b0741761c0724625a4cfdf2d6a7aacf93d5f96d7..d115e16024d2607419c4a0c478906a1184d2a704 100644
--- a/src/obj/bhkBvTreeShape.cpp
+++ b/src/obj/bhkBvTreeShape.cpp
@@ -86,5 +86,12 @@ std::list<NiObjectRef> bhkBvTreeShape::GetRefs() const {
 	return refs;
 }
 
+void bhkBvTreeShape::CalcMassCenterInertia( float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia )
+{
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+}
+
 //--BEGIN MISC CUSTOM CODE--//
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkCapsuleShape.cpp b/src/obj/bhkCapsuleShape.cpp
index eb27e2863d209534dc72ae5aa0e66c5d4b52e0d6..66d6face748a677825591b39fb33e794a6a273f2 100644
--- a/src/obj/bhkCapsuleShape.cpp
+++ b/src/obj/bhkCapsuleShape.cpp
@@ -8,6 +8,7 @@ All rights reserved.  Please see niflib.h for license. */
 //-----------------------------------NOTICE----------------------------------//
 
 //--BEGIN FILE HEAD CUSTOM CODE--//
+#include "../../include/Inertia.h"
 //--END CUSTOM CODE--//
 
 #include "../../include/FixLink.h"
@@ -158,4 +159,19 @@ void bhkCapsuleShape::SetRadius2( float value ) {
 	radius2 = value;
 }
 
+/*! Helper routine for calculating mass properties.
+*  \param[in]  density Uniform density of object
+*  \param[in]  solid Determines whether the object is assumed to be solid or not
+*  \param[out] mass Calculated mass of the object
+*  \param[out] center Center of mass
+*  \param[out] inertia Mass Inertia Tensor
+*  \return Return mass, center, and inertia tensor.
+*/
+void bhkCapsuleShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	center = Vector3();
+	float height = (secondPoint - firstPoint).Magnitude();
+	Inertia::GetMassInertiaCapsule(radius, height, density, solid, mass, inertia);
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkConvexShape.cpp b/src/obj/bhkConvexShape.cpp
index c2e93ef4c8c7127c5468258b4418053de24c1575..b762579b2f77fa355edf9d354975d12accfc9f84 100644
--- a/src/obj/bhkConvexShape.cpp
+++ b/src/obj/bhkConvexShape.cpp
@@ -87,4 +87,12 @@ std::list<NiObjectRef> bhkConvexShape::GetRefs() const {
 }
 
 //--BEGIN MISC CUSTOM CODE--//
+
+void bhkConvexShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkConvexTransformShape.cpp b/src/obj/bhkConvexTransformShape.cpp
index 2bd655b8fe0d92ad788aa5d07909f215df914527..2cfb3476f51f776f09384877ecad23d535d4032d 100644
--- a/src/obj/bhkConvexTransformShape.cpp
+++ b/src/obj/bhkConvexTransformShape.cpp
@@ -87,4 +87,12 @@ std::list<NiObjectRef> bhkConvexTransformShape::GetRefs() const {
 }
 
 //--BEGIN MISC CUSTOM CODE--//
+void bhkConvexTransformShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+}
+
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkConvexVerticesShape.cpp b/src/obj/bhkConvexVerticesShape.cpp
index 4b242b177548f490891cd64b0f179f472c46322d..d1dbcd586d29bb91de4b9654a4ae489f6652acd1 100644
--- a/src/obj/bhkConvexVerticesShape.cpp
+++ b/src/obj/bhkConvexVerticesShape.cpp
@@ -8,6 +8,8 @@ All rights reserved.  Please see niflib.h for license. */
 //-----------------------------------NOTICE----------------------------------//
 
 //--BEGIN FILE HEAD CUSTOM CODE--//
+#include "../../include/nifqhull.h"
+#include "../../include/Inertia.h"
 //--END CUSTOM CODE--//
 
 #include "../../include/FixLink.h"
@@ -243,5 +245,13 @@ void bhkConvexVerticesShape::SetNormalsAndDist(const vector<Vector4>& value)
 	normals = value;
 }
 
-
+void bhkConvexVerticesShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+	vector<Vector3> verts = GetVertices();
+	vector<Triangle> tris = NifQHull::compute_convex_hull(verts);
+	Inertia::GetMassCenterInertiaPolyhedron(verts, tris, density, solid, mass, center, inertia);
+}
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkListShape.cpp b/src/obj/bhkListShape.cpp
index ce10aeacb2088be159cbb8570638379cdd5a26a9..b01268fc098c747f4f0b1a39b98e0a37ba7e8a0f 100644
--- a/src/obj/bhkListShape.cpp
+++ b/src/obj/bhkListShape.cpp
@@ -198,4 +198,29 @@ void bhkListShape::SetSubShapes(const vector<Ref<bhkShape > >& shapes) {
 	unknownInts.resize(subShapes.size(), 0);
 }
 
+void bhkListShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+
+	vector<float> masses;
+	vector<Vector3> centers;
+	vector<InertiaMatrix> inertias;
+	for (vector<bhkShapeRef>::iterator itr = subShapes.begin(); itr != subShapes.end(); ++itr)
+	{
+		float m; Vector3 c; InertiaMatrix i;
+		(*itr)->CalcMassCenterInertia(density, solid, m, c, i);
+		masses.push_back(m);
+		centers.push_back(c);
+		inertias.push_back(i);
+		mass += m;
+	}
+
+	// TODO: doubt this inertia calculation is even remotely close
+	for (size_t i=0; i < masses.size(); ++i) {
+		center += centers[i] * (masses[i] / mass);
+		inertia *= inertias[i];
+	}
+}
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkMoppBvTreeShape.cpp b/src/obj/bhkMoppBvTreeShape.cpp
index 2df51bd504bc5d43d9f58641e77eb20e12a569db..189b17c7507b2898ecb205f7dd5f3932033f24ea 100644
--- a/src/obj/bhkMoppBvTreeShape.cpp
+++ b/src/obj/bhkMoppBvTreeShape.cpp
@@ -200,4 +200,14 @@ void bhkMoppBvTreeShape::SetMoppScale( float value ) {
 	scale = value;
 }
 
+void bhkMoppBvTreeShape::CalcMassCenterInertia( float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia )
+{
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+
+	if (shape != NULL)
+		shape->CalcMassCenterInertia(density, solid, mass, center, inertia);
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkMultiSphereShape.cpp b/src/obj/bhkMultiSphereShape.cpp
index eb8bea24348a0372b83e7514f5bd4d3399500693..da68b33f7af973185cbb83b518f2664f375a279e 100644
--- a/src/obj/bhkMultiSphereShape.cpp
+++ b/src/obj/bhkMultiSphereShape.cpp
@@ -126,4 +126,11 @@ void bhkMultiSphereShape::SetSpheres( const vector<SphereBV >& value ) {
 	spheres = value;
 }
 
+void bhkMultiSphereShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	// TODO: Calculate this properly
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+}
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkNiTriStripsShape.cpp b/src/obj/bhkNiTriStripsShape.cpp
index b12d2f217a29b970643a3dce0761e5a4842f2eda..6e0aa018ca9f6dde00c501db5b0e391f460ded16 100644
--- a/src/obj/bhkNiTriStripsShape.cpp
+++ b/src/obj/bhkNiTriStripsShape.cpp
@@ -8,6 +8,7 @@ All rights reserved.  Please see niflib.h for license. */
 //-----------------------------------NOTICE----------------------------------//
 
 //--BEGIN FILE HEAD CUSTOM CODE--//
+#include "../../include/Inertia.h"
 //--END CUSTOM CODE--//
 
 #include "../../include/FixLink.h"
@@ -257,4 +258,24 @@ void bhkNiTriStripsShape::SetOblivionFilter( unsigned int index, unsigned char f
 	dataLayers[index].colFilter = filter;
 }
 
+void bhkNiTriStripsShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+
+	vector<Vector3> verts;
+	vector<Triangle> tris;
+	for ( vector<NiTriStripsDataRef>::iterator itr = stripsData.begin(); itr != stripsData.end(); ++itr )
+	{
+		size_t nv = verts.size(), nt = tris.size();
+		vector<Vector3> v = (*itr)->GetVertices();
+		vector<Triangle> t = (*itr)->GetTriangles();
+		for (size_t i=0; i<nv; ++i)
+			verts.push_back( v[i] );
+		for (size_t i=0; i<nt; ++i)
+			tris.push_back( Triangle(t[i][0] + nt, t[i][1] + nt, t[i][2] + nt) );
+	}
+	Inertia::GetMassCenterInertiaPolyhedron(verts, tris, density, solid, mass, center, inertia);
+}
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkPackedNiTriStripsShape.cpp b/src/obj/bhkPackedNiTriStripsShape.cpp
index 4e488b13f77a910d59c594fe9c3e1840df2d2cf6..a6791005baa5268f09ec730e49568684fa33884c 100644
--- a/src/obj/bhkPackedNiTriStripsShape.cpp
+++ b/src/obj/bhkPackedNiTriStripsShape.cpp
@@ -8,6 +8,7 @@ All rights reserved.  Please see niflib.h for license. */
 //-----------------------------------NOTICE----------------------------------//
 
 //--BEGIN FILE HEAD CUSTOM CODE--//
+#include "../../include/Inertia.h"
 //--END CUSTOM CODE--//
 
 #include "../../include/FixLink.h"
@@ -181,5 +182,17 @@ void bhkPackedNiTriStripsShape::SetSubShapes( vector<OblivionSubShape>& value )
 	subShapes = value;
 }
 
-
+void bhkPackedNiTriStripsShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+
+	if (data != NULL)
+	{
+		vector<Vector3> verts = data->GetVertices();
+		vector<Triangle> tris = data->GetTriangles();
+		Inertia::GetMassCenterInertiaPolyhedron(verts, tris, density, solid, mass, center, inertia);
+	}
+}
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkRigidBody.cpp b/src/obj/bhkRigidBody.cpp
index de3b84a7e5b885975abbf0bd773e183c4c0480d3..f89c8abbe3cbb98e954eaee0fb7216ce03ad3f3d 100644
--- a/src/obj/bhkRigidBody.cpp
+++ b/src/obj/bhkRigidBody.cpp
@@ -8,6 +8,7 @@ All rights reserved.  Please see niflib.h for license. */
 //-----------------------------------NOTICE----------------------------------//
 
 //--BEGIN FILE HEAD CUSTOM CODE--//
+#include "../../include/obj/bhkShape.h"
 //--END CUSTOM CODE--//
 
 #include "../../include/FixLink.h"
@@ -15,7 +16,6 @@ All rights reserved.  Please see niflib.h for license. */
 #include "../../include/NIF_IO.h"
 #include "../../include/obj/bhkRigidBody.h"
 #include "../../include/gen/QuaternionXYZW.h"
-#include "../../include/gen/InertiaMatrix.h"
 #include "../../include/obj/bhkConstraint.h"
 using namespace Niflib;
 
@@ -69,18 +69,7 @@ void bhkRigidBody::Read( istream& in, list<unsigned int> & link_stack, const Nif
 	NifStream( rotation.w, in, info );
 	NifStream( linearVelocity, in, info );
 	NifStream( angularVelocity, in, info );
-	NifStream( inertia.m11, in, info );
-	NifStream( inertia.m12, in, info );
-	NifStream( inertia.m13, in, info );
-	NifStream( inertia.m14, in, info );
-	NifStream( inertia.m21, in, info );
-	NifStream( inertia.m22, in, info );
-	NifStream( inertia.m23, in, info );
-	NifStream( inertia.m24, in, info );
-	NifStream( inertia.m31, in, info );
-	NifStream( inertia.m32, in, info );
-	NifStream( inertia.m33, in, info );
-	NifStream( inertia.m34, in, info );
+	NifStream( inertia, in, info );
 	NifStream( center, in, info );
 	NifStream( mass, in, info );
 	NifStream( linearDamping, in, info );
@@ -138,18 +127,7 @@ void bhkRigidBody::Write( ostream& out, const map<NiObjectRef,unsigned int> & li
 	NifStream( rotation.w, out, info );
 	NifStream( linearVelocity, out, info );
 	NifStream( angularVelocity, out, info );
-	NifStream( inertia.m11, out, info );
-	NifStream( inertia.m12, out, info );
-	NifStream( inertia.m13, out, info );
-	NifStream( inertia.m14, out, info );
-	NifStream( inertia.m21, out, info );
-	NifStream( inertia.m22, out, info );
-	NifStream( inertia.m23, out, info );
-	NifStream( inertia.m24, out, info );
-	NifStream( inertia.m31, out, info );
-	NifStream( inertia.m32, out, info );
-	NifStream( inertia.m33, out, info );
-	NifStream( inertia.m34, out, info );
+	NifStream( inertia, out, info );
 	NifStream( center, out, info );
 	NifStream( mass, out, info );
 	NifStream( linearDamping, out, info );
@@ -242,18 +220,7 @@ std::string bhkRigidBody::asString( bool verbose ) const {
 	out << "  w:  " << rotation.w << endl;
 	out << "  Linear Velocity:  " << linearVelocity << endl;
 	out << "  Angular Velocity:  " << angularVelocity << endl;
-	out << "  m11:  " << inertia.m11 << endl;
-	out << "  m12:  " << inertia.m12 << endl;
-	out << "  m13:  " << inertia.m13 << endl;
-	out << "  m14:  " << inertia.m14 << endl;
-	out << "  m21:  " << inertia.m21 << endl;
-	out << "  m22:  " << inertia.m22 << endl;
-	out << "  m23:  " << inertia.m23 << endl;
-	out << "  m24:  " << inertia.m24 << endl;
-	out << "  m31:  " << inertia.m31 << endl;
-	out << "  m32:  " << inertia.m32 << endl;
-	out << "  m33:  " << inertia.m33 << endl;
-	out << "  m34:  " << inertia.m34 << endl;
+	out << "  Inertia:  " << inertia << endl;
 	out << "  Center:  " << center << endl;
 	out << "  Mass:  " << mass << endl;
 	out << "  Linear Damping:  " << linearDamping << endl;
@@ -355,36 +322,12 @@ void bhkRigidBody::SetAngularVelocity( const Vector4 & value ) {
 	angularVelocity = value;
 }
 
-array<12,float>  bhkRigidBody::GetInertia() const {
-	array<12, float> result;
-	result[0] = inertia.m11;
-	result[1] = inertia.m12;
-	result[2] = inertia.m13;
-	result[3] = inertia.m14;
-	result[4] = inertia.m21;
-	result[5] = inertia.m22;
-	result[6] = inertia.m23;
-	result[7] = inertia.m24;
-	result[8] = inertia.m31;
-	result[9] = inertia.m32;
-	result[10] = inertia.m33;
-	result[11] = inertia.m34;
-	return result;
-}
-
-void bhkRigidBody::SetInertia( const array<12,float>&  value ) {
-	inertia.m11 = value[0];
-	inertia.m12 = value[1];
-	inertia.m13 = value[2];
-	inertia.m14 = value[3];
-	inertia.m21 = value[4];
-	inertia.m22 = value[5];
-	inertia.m23 = value[6];
-	inertia.m24 = value[7];
-	inertia.m31 = value[8];
-	inertia.m32 = value[9];
-	inertia.m33 = value[10];
-	inertia.m34 = value[11];
+InertiaMatrix  bhkRigidBody::GetInertia() const {
+	return inertia;
+}
+
+void bhkRigidBody::SetInertia( const InertiaMatrix&  value ) {
+	inertia = value;
 }
 
 Vector4 bhkRigidBody::GetCenter() const {
@@ -491,4 +434,45 @@ void bhkRigidBody::SetSolverDeactivation( const SolverDeactivation & value ) {
 	solverDeactivation = value;
 }
 
+
+
+// Apply scale factor <scale> on data.
+void bhkRigidBody::ApplyScale(float scale)
+{
+    // apply scale on transform
+    translation *= scale;
+
+    // apply scale on center of gravity
+    center *= scale;
+
+    // apply scale on inertia tensor
+    inertia *= pow(scale, 2.0f);
+
+    //# apply scale on all blocks down the hierarchy
+    //ApplyScale(scale)
+}
+
+void bhkRigidBody::UpdateMassCenterInertia(float density, bool solid, float mass)
+{
+    // Look at all the objects under this rigid body and update the mass
+    //  center of gravity, and inertia tensor accordingly. If the C{mass} parameter
+    //  is given then the C{density} argument is ignored.
+
+	if (mass != 0.0f)
+        density = 1.0f;
+
+	if (shape != NULL)
+	{
+		Vector3 com;
+		shape->CalcMassCenterInertia(density, solid, this->mass, com, inertia);
+		center = com;
+		if (mass != 0.0f)
+		{
+			float mass_correction = (this->mass != 0.0f) ? mass / this->mass : 1.0f;
+			this->mass = mass;
+			inertia *= mass_correction;
+		}
+	}
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkShape.cpp b/src/obj/bhkShape.cpp
index 468065a7c8a97cfd1a71e42e918766c09567b426..fdfac180bb23ee7aa1f3d4f8848fb9700065e736 100644
--- a/src/obj/bhkShape.cpp
+++ b/src/obj/bhkShape.cpp
@@ -87,4 +87,11 @@ std::list<NiObjectRef> bhkShape::GetRefs() const {
 }
 
 //--BEGIN MISC CUSTOM CODE--//
+
+void bhkShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+}
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkSphereRepShape.cpp b/src/obj/bhkSphereRepShape.cpp
index 0e7bc31eb0e1f62587286403d001465136c98a17..3bc83d8d0ce50be1be485b6088b7e241958f1190 100644
--- a/src/obj/bhkSphereRepShape.cpp
+++ b/src/obj/bhkSphereRepShape.cpp
@@ -8,6 +8,7 @@ All rights reserved.  Please see niflib.h for license. */
 //-----------------------------------NOTICE----------------------------------//
 
 //--BEGIN FILE HEAD CUSTOM CODE--//
+#include "../../include/Inertia.h"
 //--END CUSTOM CODE--//
 
 #include "../../include/FixLink.h"
@@ -110,5 +111,12 @@ void bhkSphereRepShape::SetRadius( float value ) {
 	radius = value;
 }
 
+void bhkSphereRepShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+	Inertia::GetMassInertiaSphere(radius, density, solid, mass, inertia);
 
+}
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkSphereShape.cpp b/src/obj/bhkSphereShape.cpp
index 61a06172243aeae0b77babd995b97a5f3fc3616f..c0c378e19df48bdd4b26d290f8f31969a3fef144 100644
--- a/src/obj/bhkSphereShape.cpp
+++ b/src/obj/bhkSphereShape.cpp
@@ -8,6 +8,7 @@ All rights reserved.  Please see niflib.h for license. */
 //-----------------------------------NOTICE----------------------------------//
 
 //--BEGIN FILE HEAD CUSTOM CODE--//
+#include "../../include/Inertia.h"
 //--END CUSTOM CODE--//
 
 #include "../../include/FixLink.h"
@@ -96,4 +97,11 @@ void bhkSphereShape::SetRadius( float value ) {
 	radius = value;
 }
 
+void bhkSphereShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	center = Vector3(0,0,0);
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+	Inertia::GetMassInertiaSphere(radius, density, solid, mass, inertia);
+}
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkTransformShape.cpp b/src/obj/bhkTransformShape.cpp
index f98afa078afded2a4f0238422f446eaf900a305b..33fba51a4fb1043f654af7565a930ba6a1097961 100644
--- a/src/obj/bhkTransformShape.cpp
+++ b/src/obj/bhkTransformShape.cpp
@@ -156,4 +156,20 @@ void bhkTransformShape::SetTransform(const Matrix44 & value ) {
 	transform = value;
 }
 
+void bhkTransformShape::CalcMassCenterInertia(float density, bool solid, float &mass, Vector3 &center, InertiaMatrix& inertia)
+{
+	center = transform.GetTranslation();
+	mass = 0.0f;
+	inertia = InertiaMatrix::IDENTITY;
+	if (shape != NULL)
+	{
+		Matrix44 transform_transposed = transform.Transpose();
+		shape->CalcMassCenterInertia(density, solid, mass, center, inertia);
+		center = transform * center;
+
+		Matrix44 tm(inertia.Submatrix(0, 0));
+		Matrix44 im = transform_transposed * tm * transform;
+		inertia = InertiaMatrix(im.GetRotation());
+	}
+}
 //--END CUSTOM CODE--//