Unique results in a physics engine

Started by
9 comments, last by HappyCoder 7 years, 2 months ago
First of all i am not sure if coding horror fits this, but the results from my implementation of a rigid body physics system is very unique, check it out. There may be some deep critters hiding in the code...



...NOT, it was just three classics:

1.) vec2 * mat2 is not the same as mat2 * vec2
Rotate left against rotate right. -> contacts was wrong rotated.

2.) Cross(1.0f, normal) is not the same as Cross(normal, 1.0f).
Same as above, inverted rotation...

3.) There was always a friction impulse going on, even with friction set to zero.
A classic wrong arguments orders bug: Clamp(min, value, max) is not the same as Clamp(value, min, max) and i had:

contact->tangentImpulse = Clamp(oldTangentImpulse + tangentImpulse, -maxFriction, maxFriction);

Lessons learned:

- Porting from own old sources should never be underestimated, especially when there was no operator overload used or supported!
- Check your math library before doing any useful with that, especially matrices and rotations. Make Units tests or something...
Advertisement

Kinda looks like torque is being applied in the opposite direction.

Oh boy, after a few hours of debugging i found the culprits - updated the thread ;)

First of all i am not sure if coding horror fits this, but the results from my implementation of a rigid body physics system is very unique, check it out. There may be some deep critters hiding in the code...



...NOT, it was just three classics:

1.) vec2 * mat2 is not the same as mat2 * vec2 in "openGL mathematics".
Rotate left against rotate right. -> contacts was wrong rotated.

2.) Cross(1.0f, normal) is not the same as Cross(normal, 1.0f).
Same as above, inverted rotation...

3.) There was always a friction impulse going on, even with friction set to zero.
A classic wrong arguments orders bug: Clamp(min, value, max) is not the same as Clamp(value, min, max) and i had:

contact->tangentImpulse = Clamp(oldTangentImpulse + tangentImpulse, -maxFriction, maxFriction);

Lessons learned:

- Porting from own old sources should never be underestimated, especially when there was no operator overload used or supported!
- Check your math library before doing any useful with that, especially matrices and rotations. Make Units tests or something...

Uhm... M * v and v * M are never the same (for general matrices) not only in "OpenGL mathematics", but in linear algebra in general...

Uhm... M * v and v * M are never the same (for general matrices) not only in "OpenGL mathematics", but in linear algebra in general...


I dont know, i never learned linear algebra but i know that A times B is the same as B times A (True for scalars and vectors, commutative property of multiplication right?).

inline Vec2f operator *(const Vec2f &a, const Mat2f &mat)
{
	Vec2f result;
	result.x = mat.col1.x * a.x + mat.col2.x * a.y;
	result.y = mat.col1.y * a.x + mat.col2.y * a.y;
	return(result);
}
This multiplies a vector and a matrix and looking at the code, it does not matter in which order it is.

Edit: I double checked the glm implementation and its just transposed vs non-transposed Matrix multiplication (row vs col):

	template <typename T, precision P>
	GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::col_type operator*
	(
		tmat2x2<T, P> const & m,
		typename tmat2x2<T, P>::row_type const & v
	)
	{
		return tvec2<T, P>(
			m[0][0] * v.x + m[1][0] * v.y,
			m[0][1] * v.x + m[1][1] * v.y);
	}

	template <typename T, precision P>
	GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::row_type operator*
	(
		typename tmat2x2<T, P>::col_type const & v,
		tmat2x2<T, P> const & m
	)
	{
		return tvec2<T, P>(
			v.x * m[0][0] + v.y * m[0][1],
			v.x * m[1][0] + v.y * m[1][1]);
	}

PS: Sorry for the edits...

Does this imply that in math formulas when i see m * v it always mean column based multiplication and v * m means row based???

I really should learn linear algebra.

Uhm... M * v and v * M are never the same (for general matrices) not only in "OpenGL mathematics", but in linear algebra in general...


I dont know, i never learned linear algebra but i know that A times B is the same as B times A (True for scalars and vectors, commutative property of multiplication right?).


inline Vec2f operator *(const Vec2f &a, const Mat2f &mat)
{
	Vec2f result;
	result.x = mat.col1.x * a.x + mat.col2.x * a.y;
	result.y = mat.col1.y * a.x + mat.col2.y * a.y;
	return(result);
}
This multiplies a vector and a matrix and looking at the code, it does not matter in which order it is.

Edit: I double checked the glm implementation and its just transposed vs non-transposed Matrix multiplication (row vs col):


	template <typename T, precision P>
	GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::col_type operator*
	(
		tmat2x2<T, P> const & m,
		typename tmat2x2<T, P>::row_type const & v
	)
	{
		return tvec2<T, P>(
			m[0][0] * v.x + m[1][0] * v.y,
			m[0][1] * v.x + m[1][1] * v.y);
	}

	template <typename T, precision P>
	GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::row_type operator*
	(
		typename tmat2x2<T, P>::col_type const & v,
		tmat2x2<T, P> const & m
	)
	{
		return tvec2<T, P>(
			v.x * m[0][0] + v.y * m[0][1],
			v.x * m[1][0] + v.y * m[1][1]);
	}

PS: Sorry for the edits...

Does this imply that in math formulas when i see m * v it always mean column based multiplication and v * m means row based???

I really should learn linear algebra.

Nope, matrix multiplication (including matrix-vector multiplication) is non-commutative. Dot products are commutative though, but cross products on the other hand are anti-commutative.

Mv implies that v is a column vector, vM implies that v is a row vector (the latter notation is extremely rare in mathematics textbooks and is pretty much exclusive to computer graphics nowadays)

And yes, understanding linear algebra is extremely important in computer graphics (and physics)

Maybe your engine is right and reality is wrong.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Since all matrix operations comprise of row dot column, there is actually not such thing as a vector * matrix, because there is no such meaningful operation that consists of a column vector dotted with a row vector. The result of this operation would be the following:


| a |  *  | x y z |  =  | ax ay az |  
| b |                   | bx by bz |
| c |                   | cx cy cz |

And this operation (from my basic understanding) has no benefit/purpose in the field of linear algebraic studies.

Since all matrix operations comprise of row dot column, there is actually not such thing as a vector * matrix, because there is no such meaningful operation that consists of a column vector dotted with a row vector. The result of this operation would be the following:

| a |  *  | x y z |  =  | ax ay az |  
| b |                   | bx by bz |
| c |                   | cx cy cz |
And this operation (from my basic understanding) has no benefit/purpose in the field of linear algebraic studies.


Maybe you need to do more linear algebra studying. https://en.wikipedia.org/wiki/Outer_product

Edit: So far I've used the out product to project vectors onto planes, during vector calculus involving springs, and in inertia tensor calculations for triangle meshes.

Since all matrix operations comprise of row dot column, there is actually not such thing as a vector * matrix, because there is no such meaningful operation that consists of a column vector dotted with a row vector. The result of this operation would be the following:

| a |  *  | x y z |  =  | ax ay az |  | b |                   | bx by bz || c |                   | cx cy cz |
And this operation (from my basic understanding) has no benefit/purpose in the field of linear algebraic studies.
Maybe you need to do more linear algebra studying. https://en.wikipedia.org/wiki/Outer_productEdit: So far I've used the out product to project vectors onto planes, during vector calculus involving springs, and in inertia tensor calculations for triangle meshes.
Thank you for that. As I said my knowledge regarding Lin Al and the operation is very rudimentary. Surprisingly, it was my physics professor back in 2005 who described it as a rather pointless operation. I suspected otherwise, happy I was wrong l, and I'm actually excited to read up on it now.

To add to this, a vector * matrix still is an invalid operation due to dimensional mismatch.

This topic is closed to new replies.

Advertisement