Jump to content
  • Advertisement

Mailbox

Member
  • Content Count

    10
  • Joined

  • Last visited

Community Reputation

0 Neutral

About Mailbox

  • Rank
    Member

Personal Information

  • Role
    Programmer
  • Interests
    Programming

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Mailbox

    Incorrect angular collision response

    Glad someone at least got a chuckle out of it. I've had my fair share of silly programming errors over the years, but this was one of the tougher ones for me to spot, that I remember, and definitely one of the most frustrating. Anyway, it's working great now:
  2. Mailbox

    Incorrect angular collision response

    After weeks of having not the slightest desire to continue fiddling around with this, I gave it another go today and finally managed to make it work. I settled for column vectors as convention and adapted my matrix calculations accordingly. The error was somewhere else though. I integrated the angular velocity using Orientation += 0.5 * Orientation * AngularVelocity instead of Orientation += AngularVelocity * Orientation * 0.5 I definitely learned my lesson to pay more attention to the order of operations. Thanks for all your help!
  3. Mailbox

    Incorrect angular collision response

    My math knowledge is quite lacking. I tried it with that formula, but it results in even weirder behaviour, including the X and Z axes being swapped. result.M11 = q.X * q.X + q.Y * q.Y - q.Z * q.Z - q.W * q.W; result.M12 = 2.f * q.Y * q.Z - 2.f * q.X * q.W; result.M13 = 2.f * q.Y * q.W + 2.f * q.X * q.Z; result.M21 = 2.f * q.Y * q.Z + 2.f * q.X * q.W; result.M22 = q.X * q.X - q.Y * q.Y + q.Z * q.Z - q.W * q.W; result.M23 = 2.f * q.Z * q.W - 2.f * q.X * q.Y; result.M31 = 2.f * q.Y * q.W - 2.f * q.X * q.Z; result.M32 = 2.f * q.Z * q.W + 2.f * q.X * q.Y; result.M33 = q.X * q.X - q.Y * q.Y - q.Z * q.Z + q.W * q.W; Wouldn't I simply have use the transpose with the code I posted earlier? qu3e calculates the matrix the same way I do, but uses columns instead of rows in the dot product when multiplying with vectors. Bullet calculates the transpose, but multiplies with vectors the same way I do. Seems I mixed something up. Is the decision to use one or the other based on the handedness of the coordinate system, and/or something else? Originally, I actually did multiply matrices with vectors the same way qu3e does it, but I tried out all kinds of things so my code is a huge mess now.
  4. Mailbox

    Incorrect angular collision response

    I don't understand why calculating the world space inverse inertia tensor with R*I*R^T doesn't work. It has the same effect as using only I. The only way I can get it to work is to transpose all my quaternion derived matrices, including the ones used for rendering, but then all rotations are negated. Otherwise I have to use R*I. I've checked all functions involved in the calculation countless times. Maybe my coordinate system handedness is inconsistent, but I don't know where. My intention is to use a right-handed coordinate system, with x pointing to the right, y down and z away from the user. Matrices are row-major. Some relevant functions: Matrix3x3 Matrix3x3::Rotate(const Quaternion& quaternion) { Matrix3x3 result; float xx = quaternion.X * quaternion.X; float yy = quaternion.Y * quaternion.Y; float zz = quaternion.Z * quaternion.Z; float xy = quaternion.X * quaternion.Y; float wz = quaternion.Z * quaternion.W; float xz = quaternion.Z * quaternion.X; float wy = quaternion.Y * quaternion.W; float yz = quaternion.Y * quaternion.Z; float wx = quaternion.X * quaternion.W; result.M11 = 1.f - 2.f * (yy + zz); result.M12 = 2.f * (xy + wz); result.M13 = 2.f * (xz - wy); result.M21 = 2.f * (xy - wz); result.M22 = 1.f - 2.f * (zz + xx); result.M23 = 2.f * (yz + wx); result.M31 = 2.f * (xz + wy); result.M32 = 2.f * (yz - wx); result.M33 = 1.f - 2.f * (yy + xx); return result; } Matrix3x3 Matrix3x3::Scale(const Vector3& v) { return Matrix3x3( v.X, 0.f, 0.f, 0.f, v.Y, 0.f, 0.f, 0.f, v.Z); } Vector3 operator *(const Matrix3x3& m, const Vector3& v) { return Vector3( Vector3::Dot(m.Row(0), v), Vector3::Dot(m.Row(1), v), Vector3::Dot(m.Row(2), v)); } I also checked qu3e a bit more thoroughly than the first time, but couldn't find any relevant differences in the calculations. The ones I found didn't make a difference.
  5. Mailbox

    Incorrect angular collision response

    Thanks, tomorrow I'll definitely give it another try to understand what you're doing differently, hopefully getting closer to solve this mystery.
  6. Mailbox

    Incorrect angular collision response

    Well, I'm not certain whether the world space tensors are correct. However, I'm pretty sure the local ones are. Currently I have two boxes, both with the dimensions (X=0.5, Y=1.0, Z=1.5), mass 7.5 and inertia (X=2.03, Y=1.56, Z=0.78). The inertia is calculated using the equation for solid cuboids I found on Wikipedia. The inverse inertia tensor/matrix then has the values (M11=0.49, M22=0.63, M33=1.27), with the other components set to zero.
  7. Mailbox

    Incorrect angular collision response

    Yes, I'm trying to get the basic collision response, without friction or restitution, working for now (although I have code for it already).
  8. Mailbox

    Incorrect angular collision response

    Thanks a lot for all the responses! All the contact data should be correct (the contact normal is normalized, the position is where it should be etc.). I'm using the equation found on Wikipedia: Apart from the fact that I'm applying the dot product for both bodies seperately (which doesn't seem to make a difference and is also done in other physics libraries), I can't see what I'm doing wrong. I already tried numerous different ways to calculate the tensor, including orienting the non-inverse and also what Randy Gaul suggests (also flipped, see code below), without success. Matrix3x3 rotationA = Matrix3x3::Rotate(bodyA.Orientation); Matrix3x3 rotationB = Matrix3x3::Rotate(bodyB.Orientation); Matrix3x3 inverseInertiaTensorA = Matrix3x3::Scale(bodyA.InverseInertia); Matrix3x3 inverseInertiaTensorB = Matrix3x3::Scale(bodyB.InverseInertia); Matrix3x3 inverseWorldInertiaTensorA = rotationA * inverseInertiaTensorA * Matrix3x3::Transpose(rotationA); Matrix3x3 inverseWorldInertiaTensorB = rotationB * inverseInertiaTensorB * Matrix3x3::Transpose(rotationB); // Flipped Matrix3x3 inverseWorldInertiaTensorA = Matrix3x3::Transpose(rotationA) * inverseInertiaTensorA * rotationA; Matrix3x3 inverseWorldInertiaTensorB = Matrix3x3::Transpose(rotationB) * inverseInertiaTensorB * rotationB; As for checking it against Box2D, I actually made a functional 2d engine including physics some years ago. The obvious problem is that, in the two dimensional space, inertia, angular velocity and orientation can be represented by simple scalar values, whereas I'm dealing with a matrix, a vector and a quaternion respectively, so it requires different equations. That's what I think is where I'm doing something wrong, as it only fails for the angular part. I also tried calculating the rotation matrix differently, but again to no avail. Like I said, I checked it against Bullet already. I also tried to figure out how qu3e does it a few days ago, but it seems to do things a bit differently as far as I could see. One thing that might be worth noting is that it at least seems to work more or less when both bodies have zero rotation, but fails as their rotation changes. Applying impulses to individual bodies works too (using fixed values or using the cursor and ray casting), regardless of rotation.
  9. Mailbox

    Incorrect angular collision response

    Ah, thanks for pointing it out! Sadly, it's not responsible for the problem. I just cleaned up the code a bit before posting it, and that's when I made that mistake.
  10. Hello, I'm in the midst of developing a simple 3d physics engine, but have been stuck on a problem for quite a while now. I would really appreciate it if someone could have a look at it, because I'm at a loss. The issue I'm having concerns the collision response code, which seems to fail spectacularly in some cases, generating wrong impulse magnitudes. Specifically, something with the angular part of it is wrong, since it works as expected when only dealing with the linear part. I'm still not sure if I calculate the inertia tensor in world coordinates the right way, so that could be one possible culprit (though I've tried a few different ways). Impulses seem to be applied correctly to the bodies, so I think the error lies in the calculation of the impulse magnitude denominator. I've checked it many times with the way the Bullet physics engine does it, with the formulas available at Wikipedia, and some other sources, to no avail. The bodies simply keep bouncing off eachother (even though there is supposed to be no restitution) or spinning wildly on collisions. Here is the code that deals with the collision response: Vector3 originA = contactOrigin - bodyA.Position; Vector3 originB = contactOrigin - bodyB.Position; Vector3 velocityA = bodyA.Velocity + Vector3::Cross(bodyA.AngularVelocity, originA); Vector3 velocityB = bodyB.Velocity + Vector3::Cross(bodyB.AngularVelocity, originB); Vector3 velocity = velocityA - velocityB; Matrix3x3 inverseWorldInertiaTensorA = Matrix3x3::Scale(bodyA.InverseInertia) * Matrix3x3::Rotate(bodyA.Orientation); Matrix3x3 inverseWorldInertiaTensorB = Matrix3x3::Scale(bodyB.InverseInertia) * Matrix3x3::Rotate(bodyB.Orientation); float normalVelocity = Vector3::Dot(velocity, contactNormal); if (normalVelocity > 0.f) { float impulseDenominator = bodyA.InverseMass + bodyB.InverseMass + Vector3::Dot(Vector3::Cross(inverseWorldInertiaTensorA * Vector3::Cross(originA, contactNormal), originA), contactNormal) + Vector3::Dot(Vector3::Cross(inverseWorldInertiaTensorB * Vector3::Cross(originB, contactNormal), originB), contactNormal); float j = -normalVelocity / impulseDenominator; bodyA.Velocity += j * bodyA.InverseMass * contactNormal; bodyB.Velocity -= j * bodyB.InverseMass * contactNormal; bodyA.AngularVelocity += j * (inverseWorldInertiaTensorA * Vector3::Cross(originA, contactNormal)); bodyB.AngularVelocity -= j * (inverseWorldInertiaTensorB * Vector3::Cross(originB, contactNormal)); } Thanks in advance!
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!