reducing the data needed to describe a coordinates system

Started by
15 comments, last by dsecrieru 18 years, 8 months ago
Hi! I'm trying to make a space sim and therefore to give the player a 6DOF control over the ship. Like a good soldier, I've used local rotations in order to avoid all the problems usually asociated with Euler angles. So what I have is a 4x4 matrix. Now the problem comes, when I want to synchronize all the players over the network. Sending 16 floats over the network a couple of times per second is not an option. I can easily discard the 4th column, but that still leaves me with 12 floats, which is still unacceptable. So, how can I compress my matrix to a minimum number of floats, send it over the network and be able to recreate THE EXACT SAME matrix on the other side? I think Euler angles would come in handy now, but I haven't found any resources on how to extract the Euler angles from a matrix and create the same matrix from Euler angles. It seems to me that the two matrices will be slighly different due to many trigonometric conversions and floating point operations precision. Another option is of course to use quaternions. However, I tried to stay away from them so far. Another idea would be to describe two axes using two angles (pitch and yaw) for each. I could obtain the 3rd axis with a cross product between the other two. And of course, the translation. This would amount to 2 + 2 + 3 = 7 floats. Much better. I couldn't probably get less with quaternions (4 + 3 = also 7). Since a client's own's matrix is created from user input using OpenGL transformations, it would be nice to have a method of recreating the same matrix on the other clients using also OpenGL transformations. What are your thoughts?
Advertisement
Don't fear quaternions... They're your best friend here. As you said, only 7 floats, and quaternion compression can get that down even further. And the math will likely be simpler than that of specifying pitch and yaw for each of two axes.
I never heard of "quaternion compression". What exactly is that?
"Another idea would be to describe two axes using two angles (pitch and yaw) for each. I could obtain the 3rd axis with a cross product between the other two. And of course, the translation. This would amount to 2 + 2 + 3 = 7 floats. Much better. I couldn't probably get less with quaternions (4 + 3 = also 7)."

I don't think you need 2 angles for each axis, for the first axis yes, but the second one based on the first can only have a 2D range of values, one angle will suffice.

Totaling 6 then.

Also if you decide to transmit deltas of the current state instead of the absolute values, you could use DWORD integers to store the floats, use 16 bits for each value, and half the space required. You'de get almost 5 decimal spaces of precision(1/65536=0,0000152587890625), that would probably be enough to transmit those deltas.

Totaling 3 DWORDS then.

You might want to consider the extra processing time required to code and decode those though.
Quote:Original post by dsecrieru
I never heard of "quaternion compression". What exactly is that?

The form I've usually seen involves simply converting each scalar into a fixed-point number (since each element of a unit quaternion is between -1.0 and 1.0, floating-point numbers are overkill). There are more complicated methods which exploit the fact that you're only sending unit quaternions, but these often suffer from numerical instability and tend to require more processing.
I just cant understand why you need 7 float this system is 6 dof and needs only 6 float 3 position 3 orientation, the fourth dimension of the quaternion is redundant information, this redundancy manifests itself in the the magnatude becasue any magnitude of quaternion as long as it's in the same direction represents the same orientation. I'd transform the orientation to vector form(axis, angle), just a 3 vector whos direction specifies a rotation axis and magnitude specifies an angle. and the position I'd leave alone giving 6 float, or maybe I don't understand the question? why would you need 7 floats to represent a 6-dof? orientation is provably a 3 dimentional quanity and thus require 3 dof. there is nothing magical about a quaternion orientation, every orientation is reducable to a 3 dof and all orientations are equivilant to one another. the only redeaming trait about quaternion is in interpolation of orientations, not in the representation itself. it has the hypergeometric interpretation of being containted on the 4-sphere and thus spherical interpolatin on two quartinions represent in a sense "the shortest" path of orientations. hence the smoothness.

Tim

[Edited by - timw on July 27, 2005 5:17:36 PM]
Quote:why would you need 7 floats to represent a 6-dof?
I think what sneftel was referring to was that reducing a quaternion or axis-angle pair to 3 floats will require a sqrt() to decompress, which could introduce inaccuracy. For the OP though, you can compress quaternions and axis-angle pairs to 3 floats in similar ways. In either case, the value extracted via the square root is constrained to be positive, so if the value is originally negative you simply negate all four components, which makes it positive. This works because negating a quaternion or an axis-angle pair leaves the rotation unchanged.

As noted, Euler angles only require three values. Although they're not the best choice for overall representation in this case, they could certainly serve as an intermediate form. You just have to make sure that your matrix-to-Euler-angle code matches your Euler-angle-to-matrix code.

I know very little about networking, but I'll just mention that the matrix constructed from the intermediate form will most likely be slightly different than the original.
Yeah... if you try to leave the w off a quaternion and recompute it at the other end, you'll run into serious imprecision, particularly when the angle is small. Quaternions are an extremely stable representation of rotations (more stable than euler angles), and thus take to a fixed-point representation quite well.
Depending on how complicated you want to get, and the amount of precision you require, you could compress even further by doing something like compressing two lower-precision floats into one variable. Dean Calver had an interesting article about it called "Vertex Decompression in a Shader", in ShaderX: Vertex and Pixel Shader - Tips and Tricks. I'm not sure if you can find the article on the net, but you might be able to find the book in your local Barnes & Noble and flip through it.

It's a really interesting theory (although I haven't found the time to test it just yet). He describes several different compression ratios and how to decompress the values in a vertex shader, at little to no performance cost. Some of them can save you 50% of your memory and network footprint.

I wish I knew more about it though.

Outside of shaders, quaternions have been the most successful in my own experience in cutting down network traffic and the sheer number of calculations.
Damn, you are confusing me more :D. Joking, of course, many interesting suggestions here...

Someone mentined a "vector axis/angle". Anyone has any resources on how to convert a matrix to such a vector and back?

Most people seem to be suggesting quaternions. That might just be the way to go then.

This topic is closed to new replies.

Advertisement