Shrinking numbers

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
mr_happy
Citizen
Posts: 84
Joined: Fri Mar 18, 2016 8:57 pm

Shrinking numbers

Post by mr_happy »

Why do the values gradually 'shrink' with this piece of code which rotates points in 3d around the y axis:

Code: Select all

   cos1 = math.cos(math.rad(1))
   sin1 = math.sin(math.rad(1))
   
   for i = 1, numPoints do
      points[i].x = points[i].x * cos1 + points[i].z * sin1
      points[i].z = points[i].z * cos1 - points[i].x * sin1  
  end
   
For example, watching a starting x value of -12 gives the following after each 360 degree circuit:
-11.429731395506
-10.886154091496
-10.368043324118
-9.8742290380113

I can't see where there's a rounding error, which is what it looks like, and the values are only being read elsewhere in the code (I even tried using math.floor(x + 0.5) to get rounded integer values but the problem persists).
User avatar
pgimeno
Party member
Posts: 3548
Joined: Sun Oct 18, 2015 2:58 pm

Re: Shrinking numbers

Post by pgimeno »

You're asking too much from floating-point precision. What you seem to be trying to achieve is typically done with a model matrix (or quaternion) that gets renormalized every while, to avoid this kind of drift. In your case the drift is always towards shrinking, but it can be either way.

The idea is: you have a model that is always in the same position. For example, a cube centred on origin and with side 24 would have vertices at coordinates {-12,-12,-12}, ...(all combos of signs)..., {12, 12, 12}. These numbers would be fixed, as they define the geometry of the model with respect to the origin, not its actual position or orientation.

Then you have either an orthogonal matrix or a quaternion (your choice) that represents the orientation of your model. That's the model matrix. After rotating the matrix or the quaternion, a small drift may happen, so every while you renormalise it again. For example, you check the squared norm of the quaternion, or the squared norm of each column of the 3x3 matrix (the first three rows and columns, if you use a 4x4 matrix that includes displacement), and if they differ from 1 in more than a certain threshold, you renormalise.

To represent the object, you apply the model matrix to every vertex. The vertex shader can do that for you, if you use a matrix (not sure if you use a quaternion) or you can do it in Lua.

Your application may be simpler and not need that much complication. If your object only rotates in that axis, and nothing can make it rotate in any other axis, you can just track the total angle, transforming the original model by that angle rather than the previous positions, using a formula similar to yours, except only the angle is treated incrementally:

Code: Select all

   angle = (angle + math.rad(1)) % (math.pi * 2)

   cos1 = math.cos(angle)
   sin1 = math.sin(angle)

   for i = 1, numPoints do
      points[i].x = model[i].x * cos1 + model[i].z * sin1
      points[i].z = model[i].z * cos1 - model[i].x * sin1
   end
User avatar
mr_happy
Citizen
Posts: 84
Joined: Fri Mar 18, 2016 8:57 pm

Re: Shrinking numbers

Post by mr_happy »

Thank you for the detailed reply, it makes perfect sense, I shall try to incorporate it in my code :D
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot], Imnotaplayer and 84 guests