19

Rotation and Translation about arbitrary point

In order to rotate/translate object (rotation only about z-axis and translation only in xy plane) not just w.r.t to global center (device center) but also w.r.t other arbitrary points, I created an algorithm, which is correct (because all senior coders I have discussed with consider it correct), but it is taking a lot of time to remove an undesired translation in the implementation (algorithm was created on August 4 and was implemented on the same day, since then the code has been revised 15 times).

Here is the implementation http://www.pixdip.com/opengles/transform.php#ALGO1

The lines of code that are producing undesired translation are inside:

private static void updateModel(int upDown, float xAngle, float yAngle, float zAngle) {

and are listed below:

  1. Matrix.multiplyMV(GLES20Renderer._uBodyCentreMatrix, 0, GLES20Renderer._ModelMatrixBody, 0, GLES20Renderer._uBodyCentre, 0);

  2. objX = GLES20Renderer._uBodyCentreMatrix[0];

  3. objY = GLES20Renderer._uBodyCentreMatrix[1];

The undesired translation along +Y persists even if the following changes are made:

  1. objY = _uBodyCentreMatrix[1] - _uBodyCentre[1];

  2. zAngle = 0;

  3. ds = 0;

The value -0.545867f is added to the Y coordinate on every call to onDrawFrame(), because of these fields of the Renderer class:

private static final float[] _uBodyCentre = new float[]{-0.019683f, -0.545867f, -0.000409f, 1.0f};

protected static float[] _uBodyCentreMatrix = new float[4];

in http://www.pixdip.com/opengles/transform.php#FIELDS

I need help to understand why does that undesired translation happen, what is exactly wrong with the transformations, or is it the algorithm that is wrong.

Can Gimbal lock be an issue here ?

Please do not ask me to perform/practice simpler examples, because I have prepared the Renderer class for rotation/translation about global z-axis, and this new task that I am into, uses the same class with slight modification in updateModel()

(Please note that the desired rotation is only about z-axis and translation only in xy plane)

[API 10->15]

The actual Renderer class has two objects: tank turret(nozzle) and tank body, while turret(nozzle) has undesired forward translation, the body has undesired backward translation

Apk for translation/rotation about device center (which is easy to make in opengles 2.0): http://www.pixdip.com/opengles/global.php

Apk for translation/rotation about arbitrary points (which has undesired translation along +Y): http://www.pixdip.com/opengles/local.php

Apk for translation/rotation about arbitrary points in which updateModel() is called 4 times only: http://www.pixdip.com/opengles/limited.php and required code (which should be sufficient) is here: http://www.pixdip.com/opengles/code.php

Parts of object (nozzle/turret,body) are currently rotating about their own centres not the centre of object (which is _playerCentre), I will modify that later.

I have tried to demonstrate logic http://www.pixdip.com/opengles/images.php

Patt Mehta
  • 4,110
  • 1
  • 23
  • 47
  • I don't get it, why do you have undesired translation? Is your algorithm producing them?? Where are they coming from? I'd suggest you eliminate the undesired translation before they arise. – RaphMclee Aug 15 '12 at 07:42
  • Lines of code that are producing undesired translation cannot be removed because they are part of the algo, I do not have any other option. The algo is correct or not I am still not sure, and the implementation is producing an automatic translation, I do not know how to remove it, because I have only one algo and I cannot use an alternate one, try the apk plz to understand it more clearly. – Patt Mehta Aug 15 '12 at 07:44
  • I can see you've put a lot of effort into this question, but I have to say I can't really understand what you're talking about. I can't figure out what you're trying to say on in your `images.php` page, and I downloaded your application `local.php` but it doesn't seem to do anything. I just see two buttons and a purple square, and nothing happens when I touch the buttons. You keep mentioning an undesired translation, but it's not clear anywhere exactly what's it is or what's undesired about it. Can you try to link a single image, and clearly circle and annotate what the problem is? – Tim Aug 17 '12 at 16:16
  • Download this : http://www.pixdip.com/opengles/limited.php – Patt Mehta Aug 17 '12 at 17:52
  • Is it a question of the order of operations? Translation before rotation and vice versa? I found the code too much to go through; would you be able to simplify and post the code here rather than on the webpage, and where exactly you see the undesired translation coming into play? – Learn OpenGL ES Aug 17 '12 at 20:27
  • No, it isn't the order. While obtaining the current position (which will be used later to translate back) last modelMatrix is used and it is multiplied with the object center. This is where the mistake is (I know this because only the ycentre is added repeatedly) – Patt Mehta Aug 17 '12 at 20:32
  • Could you explain this line of code? `private static final float[] _uBodyCentre = new float[]{ -0.019683f, -0.545867f, -0.000409f, 1.0f};` How did you get that? – Kamil Aug 21 '12 at 19:00
  • So, the problem happens when you multiply the bodyCenter vector with the ModelMatrix, am I right? – dragostis Aug 22 '12 at 16:48
  • It's hard for me to understand you method: how do you use the int upDown? What's it for? Isn't this method used to rotate an object around another center point, different from its own? If this is the case, don't you need to provide a new, 3 coordinate vector for the new center point? – dragostis Aug 22 '12 at 16:53
  • I don't understand something: if you simply want to rotate something to an arbitrary point, why don't you try rotating first, then translating. This will change your rotation point. – dragostis Aug 22 '12 at 17:10

4 Answers4

5

It looks like the problem is:

Matrix.multiplyMV(GLES20Renderer._uBodyCentreMatrix, 0, GLES20Renderer._ModelMatrixBody, 0, GLES20Renderer._uBodyCentre, 0);

Matrix.multiplyMV is a method to multiply a 4 element vector by a 4x4 matrix and store the result in a 4 element column vector. In matrix notation: result = lhs x rhs. The resultVector element values are undefined if the resultVector elements overlap either the lhsMatrix or rhsVector elements.

I don't think you posted all the code so I can't check for sure, but judging by your naming of '_uBodyCentreMatrix' you are probably encountering an error because it is not a 4 element column vector.

I'm assuming that '_ModelMatrixBody' is a 4x4 matrix and '_uBodyCentre' is a 4 element vector, otherwise these could be problematic as well.

Joseph Lormand
  • 694
  • 5
  • 13
4

[SOLVED] java floating point errors were the only cause

M = T * I * T[inv]

did not result into an identity matrix, so instead of using Matrix.MultiplyMM

I type all the multiplications between the matrices

Patt Mehta
  • 4,110
  • 1
  • 23
  • 47
3

You could use a method like this:

public void rotateToAbritrary(float[] arbitraryPoint, float xAngle, float yAngle, float zAngle) {
    Matrix.translateM(modelMatrix, 0, arbitraryPoint[0], arbitraryPoint[1], arbitraryPoint[2]);
    float max = Math.max(xAngle, Math.max(yAngle, zAngle));
    if(max != 0.0f) Matrix.rotateM(modelMatrix, 0, max, xAngle / max, yAngle / max, zAngle / max);
    Matrix.translateM(modelMatrix, 0, -arbitraryPoint[0], -arbitraryPoint[1], -arbitraryPoint[2]);
}

That's how I see it, at least, I leave you to the implementation. I gather your code doesn't suffer the Gimbal lock.

dragostis
  • 2,574
  • 2
  • 20
  • 39
3

http://tutorialrandom.blogspot.com/2012/08/how-to-rotate-in-3d-using-opengl-proper.html

I find this the simplest way to do rotations without getting any sort of gimbal lock or odd translation. its an iOS example but im sure can be applied easily to android. Also its for 3d rotations but can easily be applied to 2d by just not rotating about one of the axis.

Fonix
  • 11,447
  • 3
  • 45
  • 74