This is Interesting: Free Magazines for Graphics designers and webmasters  


Home > Archive > VRML > January 2005 > how to add two rotations?





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author how to add two rotations?
Lucia

2005-01-10, 12:19 pm

Hi,

can someone provide me the formula to add two rotaions like

1 0 0 1.57 + 0 1 0 1.57=?

Thanks a lot

Lucia
bensmyth

2005-01-11, 7:14 am

Use matrix addition? - can't remember of the top of my head..... try Google.

"Lucia" <cheng_lucia@yahoo.com> wrote in message
news:7390d0bf.0501100738.5c1a2db1@posting.google.com...
> Hi,
>
> can someone provide me the formula to add two rotaions like
>
> 1 0 0 1.57 + 0 1 0 1.57=?
>
> Thanks a lot
>
> Lucia



Joerg Scheurich aka MUFTI

2005-01-11, 7:19 pm

Lucia <cheng_lucia@yahoo.com> wrote:
> Hi,


> can someone provide me the formula to add two rotaions like


> 1 0 0 1.57 + 0 1 0 1.57=?


What means "add" ?

When you add two values, it makes no difference if you make (a + b) or (b + a)

For rotationations, it makes a difference, if you do rotation1 first and
rotation2 second or rotation2 first and rotation1 second.

To account two combined rotations, you can convert the axis/angle pair
to a normalized quaternion and then use quaternion multiplication.

There is a FAQ about matrix and quaternion math in the internet, which
tells about quaternions and rotations.

You can also use the multiply in the VRML javascript API, but unfortunalty
the standard do not clear say, what is first and what is second rotation, so
different browsers can give different results 8-(


#VRML V2.0 utf8

DEF Script1 Script
{
field SFRotation rot1 0 1 0 1.570000
field SFRotation rot2 0 0 1 1.570000
url
[
"java script:

// field SFRotation rot1 //
// field SFRotation rot2 //

function initialize()
{
print('rot1 * rot2: ' + rot1.multiply(rot2));
print('rot2 * rot1: ' + rot2.multiply(rot1));
}


"
]
}

Transform
{
children
[
Transform
{
children
[
DEF Shape1 Shape
{
appearance Appearance
{
material Material
{
}
}
geometry Extrusion
{
crossSection
[
1.041146 -1.152379
-2.848128e-2 -2.414731
-1 -1
-1 1
0.755227 0.743695
]
solid FALSE
}
}
]
rotation 0 0 1 1.570000
}
]
rotation 0 1 0 1.570000
translation -3.460000 0 0
}

Transform
{
children
[
USE Shape1
]
rotation 0.577043 0.577503 0.577503 2.093480
translation 0.839999 0 0
}

Transform
{
children
[
Transform
{
children
[
USE Shape1
]
rotation 0 1 0 1.570000
translation 0.909412 0 7.242899e-4
}
]
rotation 0 0 1 1.570000
translation 2.100883e-3 2.637850 -0.209701
}

Transform
{
children
[
USE Shape1
]
rotation -0.577043 0.577503 0.577503 2.093480
translation -2.029705 2.639470 -0.209701
}

Viewpoint
{
orientation 4.273203e-2 0.997040 -6.390678e-2 0.455952
position 2.951291 1.185134 9.724634
}

Robert Lipman

2005-01-11, 7:19 pm

Lucia wrote:
> Hi,
>
> can someone provide me the formula to add two rotaions like
>
> 1 0 0 1.57 + 0 1 0 1.57=?


To add VRML rotations you have to use quaternions. At the end of this
email is some C code that converts VRML rotation to quaternions,
multiplies quaternions to add the rotations, and converts the resulting
quaternion back to a VRML rotation.

There is also a tool called Dizzy available here
http://www.vapourtech.com/dev/vrmltools.php that adds VRML rotations.

--
Bob Lipman
http://cic.nist.gov/lipman/
--

/*
* A little program to figure out the single axis+angle that
* corresponds to a series of rotations.
*
* Written by Gavin Bell.
*/

#include <stdio.h>
#include <math.h>

/*
* Convert axis/angle to quaternion form:
* Assumes axis is unit-length, angle is in radians.
*/
void
to_quaternion(float axis[3], float angle, float result[4])
{
int i;
for (i = 0; i < 3; i++) {
result[i] = axis[i]*sin(angle / 2.0);
}
result[3] = cos(angle / 2.0);
}
/*
* Convert unit-length quaternion to axis/angle.
*/
void
from_quaternion(float q[4], float axis[3], float *angle)
{
int i;
*angle = acos(q[3]) * 2.0;
for (i = 0; i < 3; i++) {
axis[i] = q[i] / sin(*angle / 2.0);
}
}

/*
* Multiply two quaternions together. Result may be the same as
* either input:
*/
void
multiply_quaternion(float q1[4], float q2[4], float result[4])
{
float tmp[4];
tmp[0] = q2[3] * q1[0] + q2[0] * q1[3] +
q2[1] * q1[2] - q2[2] * q1[1];
tmp[1] = q2[3] * q1[1] + q2[1] * q1[3] +
q2[2] * q1[0] - q2[0] * q1[2];
tmp[2] = q2[3] * q1[2] + q2[2] * q1[3] +
q2[0] * q1[1] - q2[1] * q1[0];
tmp[3] = q2[3] * q1[3] - q2[0] * q1[0] -
q2[1] * q1[1] - q2[2] * q1[2];
result[0] = tmp[0]; result[1] = tmp[1];
result[2] = tmp[2]; result[3] = tmp[3];
}

#define MAX_ROTATIONS 10

main(int argc, char **argv)
{
float axis[MAX_ROTATIONS][3], angle[MAX_ROTATIONS];
float q[4], result_axis[3], result_angle;
int num_entered = 0;
int i;

printf("\nThis program allows you to enter a series of rotations\n"
"about the X, Y, or Z axes. It will combine them into\n"
"one rotation about an arbitrary axis, suitable for\n"
"use in a VRML camera's orientation field or any other\n"
"VRML SFRotation field.\n"
"Enter rotations as if you are rotating the object or\n"
"camera (the opposite order from nested transformations in\n"
"a VRML file):\n\n");

for (i = 0; i < MAX_ROTATIONS; i++) {
char axisString[10];
int done = 0;
float angle_degrees;

axis[i][0] = 0.0;
axis[i][1] = 0.0;
axis[i][2] = 0.0;
angle[i] = 0.0;

if (i == 0) {
printf("Axis (X, Y or Z): ");
} else {
printf("Axis [XYZ or Q]: ");
}
fflush(stdout);
scanf("%s", axisString);
switch(axisString[0]) {
case 'X':
case 'x':
axis[i][0] = 1.0;
break;
case 'Y':
case 'y':
axis[i][1] = 1.0;
break;
case 'Z':
case 'z':
axis[i][2] = 1.0;
break;
default:
done = 1;
break;
}
if (done) {
num_entered = i;
break;
}

printf("Angle in degrees: ");
fflush(stdout);
scanf("%f", &angle_degrees);
angle[i] = angle_degrees * 3.141592653 / 180.0;
printf(" You entered: (%g %g %g), %g\n", axis[i][0],
axis[i][1], axis[i][2], angle[i]);
}

to_quaternion(axis[0], angle[0], q);
for (i = 1; i < num_entered; i++) {
float q1[4];

to_quaternion(axis[i], angle[i], q1);
multiply_quaternion(q, q1, q);
}
from_quaternion(q, result_axis, &result_angle);

printf("\nCombined rotation is:\n");
printf("Transform { rotation %g %g %g %g }\n\n",
result_axis[0], result_axis[1], result_axis[2],
result_angle);

return 0;
}
Richard Kennaway

2005-01-11, 7:19 pm

Joerg Scheurich aka MUFTI <rusmufti@helpdesk.rus.uni-stuttgart.de>
wrote:
> You can also use the multiply in the VRML javascript API, but unfortunalty
> the standard do not clear say, what is first and what is second rotation, so
> different browsers can give different results 8-(


Cortona and Contact are consistent with each other, and with the usual
mathematical notation (which is as good a definition of "right" as any):
if rot3 = rot1.multiply(rot2), then the following two pieces of VRML
will apply the same transformation to the children.

Transform {
rotation rot3
children [ ... ]
}

Transform {
rotation rot1
children Transform {
rotation rot2
children [ ... ]
}
}

CosmoPlayer does it the other way round (i.e. "wrong"), but it's
obsolete and can be ignored.

In some browsers (I've found this with the Mac version of Cortona), you
must make sure that the axes of the SFRotations are normalised (i.e.
unit vectors) before calling .multiply(), otherwise you get incorrect
results.

-- Richard Kennaway
Braden McDaniel

2005-01-11, 7:19 pm

On Tue, 2005-01-11 at 14:33 +0000, Richard Kennaway wrote:

[snip]

> In some browsers (I've found this with the Mac version of Cortona), you
> must make sure that the axes of the SFRotations are normalised (i.e.
> unit vectors) before calling .multiply(), otherwise you get incorrect
> results.


Technically a browser is in error for allowing you even to have an
SFRotation whose axis isn't normalized. By definition, the axis of an
SFRotation is normalized.

--
Braden McDaniel e-mail: <braden@endoframe.com>
<http://endoframe.com> Jabber: <braden@jabber.org>

Joerg Scheurich aka MUFTI

2005-01-11, 7:19 pm

> Technically a browser is in error for allowing you even to have an
> SFRotation whose axis isn't normalized. By definition, the axis of an
> SFRotation is normalized.


The requirement of a normalized axis

http://www.web3d.org/x3d/specificat...html#SFRotation

| The first three values specify a normalized rotation axis vector about
| which the rotation takes place.

is one of the silliest point in the VRML97 standard. The rotation axis vector
represent only a direction. Length make no sense for a direction.

If the length of the rotation axis vector would be allowed to be anything,
nothing is lost, cause only the normalization of a quaternion (which is
accounted differently) is required to account rotations.

The same problem is repeated in the X3D standard draft:

http://www.web3d.org/x3d/specificat...html#SFRotation

| The first three values specify a normalized rotation axis vector about
| which the rotation takes place.

Most VRML browsers (except possibly OpenVRML based) understand not
normalized axis vectors, cause proofing the normalization costs about the
same computer time as normalizing the axis vector (which lead to nothing...).

so long
MUFTI
--
Englisch: Deutsch:
collator die Zusammentragmaschine
to collateralize [finan.] lombardieren
(von dict.leo.org)
James Anderson

2005-01-11, 7:19 pm

Robert Lipman wrote:

> There is also a tool called Dizzy available here
> http://www.vapourtech.com/dev/vrmltools.php that adds VRML rotations.


Here's a simple Java applet I wrote which multiplies rotations:

http://www.ccir.ed.ac.uk/~jad/multiply/index.html

Beats doing it in your head. :)

James
Joerg Scheurich aka MUFTI

2005-01-13, 7:16 am

Lucia <cheng_lucia@yahoo.com> wrote:
> Hi,


> can someone provide me the formula to add two rotaions like


> 1 0 0 1.57 + 0 1 0 1.57=?


What means "add" ?

When you add two values, it makes no difference if you make (a + b) or (b + a)

For rotationations, it makes a difference, if you do rotation1 first and
rotation2 second or rotation2 first and rotation1 second.

To account two combined rotations, you can convert the axis/angle pair
to a normalized quaternion and then use quaternion multiplication.

There is a FAQ about matrix and quaternion math in the internet, which
tells about quaternions and rotations.

You can also use the multiply in the VRML javascript API, but unfortunalty
the standard do not clear say, what is first and what is second rotation, so
different browsers can give different results 8-(


#VRML V2.0 utf8

DEF Script1 Script
{
field SFRotation rot1 0 1 0 1.570000
field SFRotation rot2 0 0 1 1.570000
url
[
"java script:

// field SFRotation rot1 //
// field SFRotation rot2 //

function initialize()
{
print('rot1 * rot2: ' + rot1.multiply(rot2));
print('rot2 * rot1: ' + rot2.multiply(rot1));
}


"
]
}

Transform
{
children
[
Transform
{
children
[
DEF Shape1 Shape
{
appearance Appearance
{
material Material
{
}
}
geometry Extrusion
{
crossSection
[
1.041146 -1.152379
-2.848128e-2 -2.414731
-1 -1
-1 1
0.755227 0.743695
]
solid FALSE
}
}
]
rotation 0 0 1 1.570000
}
]
rotation 0 1 0 1.570000
translation -3.460000 0 0
}

Transform
{
children
[
USE Shape1
]
rotation 0.577043 0.577503 0.577503 2.093480
translation 0.839999 0 0
}

Transform
{
children
[
Transform
{
children
[
USE Shape1
]
rotation 0 1 0 1.570000
translation 0.909412 0 7.242899e-4
}
]
rotation 0 0 1 1.570000
translation 2.100883e-3 2.637850 -0.209701
}

Transform
{
children
[
USE Shape1
]
rotation -0.577043 0.577503 0.577503 2.093480
translation -2.029705 2.639470 -0.209701
}

Viewpoint
{
orientation 4.273203e-2 0.997040 -6.390678e-2 0.455952
position 2.951291 1.185134 9.724634
}

Robert Lipman

2005-01-13, 12:16 pm

Lucia wrote:
> Hi,
>
> can someone provide me the formula to add two rotaions like
>
> 1 0 0 1.57 + 0 1 0 1.57=?


To add VRML rotations you have to use quaternions. At the end of this
email is some C code that converts VRML rotation to quaternions,
multiplies quaternions to add the rotations, and converts the resulting
quaternion back to a VRML rotation.

There is also a tool called Dizzy available here
http://www.vapourtech.com/dev/vrmltools.php that adds VRML rotations.

--
Bob Lipman
http://cic.nist.gov/lipman/
--

/*
* A little program to figure out the single axis+angle that
* corresponds to a series of rotations.
*
* Written by Gavin Bell.
*/

#include <stdio.h>
#include <math.h>

/*
* Convert axis/angle to quaternion form:
* Assumes axis is unit-length, angle is in radians.
*/
void
to_quaternion(float axis[3], float angle, float result[4])
{
int i;
for (i = 0; i < 3; i++) {
result[i] = axis[i]*sin(angle / 2.0);
}
result[3] = cos(angle / 2.0);
}
/*
* Convert unit-length quaternion to axis/angle.
*/
void
from_quaternion(float q[4], float axis[3], float *angle)
{
int i;
*angle = acos(q[3]) * 2.0;
for (i = 0; i < 3; i++) {
axis[i] = q[i] / sin(*angle / 2.0);
}
}

/*
* Multiply two quaternions together. Result may be the same as
* either input:
*/
void
multiply_quaternion(float q1[4], float q2[4], float result[4])
{
float tmp[4];
tmp[0] = q2[3] * q1[0] + q2[0] * q1[3] +
q2[1] * q1[2] - q2[2] * q1[1];
tmp[1] = q2[3] * q1[1] + q2[1] * q1[3] +
q2[2] * q1[0] - q2[0] * q1[2];
tmp[2] = q2[3] * q1[2] + q2[2] * q1[3] +
q2[0] * q1[1] - q2[1] * q1[0];
tmp[3] = q2[3] * q1[3] - q2[0] * q1[0] -
q2[1] * q1[1] - q2[2] * q1[2];
result[0] = tmp[0]; result[1] = tmp[1];
result[2] = tmp[2]; result[3] = tmp[3];
}

#define MAX_ROTATIONS 10

main(int argc, char **argv)
{
float axis[MAX_ROTATIONS][3], angle[MAX_ROTATIONS];
float q[4], result_axis[3], result_angle;
int num_entered = 0;
int i;

printf("\nThis program allows you to enter a series of rotations\n"
"about the X, Y, or Z axes. It will combine them into\n"
"one rotation about an arbitrary axis, suitable for\n"
"use in a VRML camera's orientation field or any other\n"
"VRML SFRotation field.\n"
"Enter rotations as if you are rotating the object or\n"
"camera (the opposite order from nested transformations in\n"
"a VRML file):\n\n");

for (i = 0; i < MAX_ROTATIONS; i++) {
char axisString[10];
int done = 0;
float angle_degrees;

axis[i][0] = 0.0;
axis[i][1] = 0.0;
axis[i][2] = 0.0;
angle[i] = 0.0;

if (i == 0) {
printf("Axis (X, Y or Z): ");
} else {
printf("Axis [XYZ or Q]: ");
}
fflush(stdout);
scanf("%s", axisString);
switch(axisString[0]) {
case 'X':
case 'x':
axis[i][0] = 1.0;
break;
case 'Y':
case 'y':
axis[i][1] = 1.0;
break;
case 'Z':
case 'z':
axis[i][2] = 1.0;
break;
default:
done = 1;
break;
}
if (done) {
num_entered = i;
break;
}

printf("Angle in degrees: ");
fflush(stdout);
scanf("%f", &angle_degrees);
angle[i] = angle_degrees * 3.141592653 / 180.0;
printf(" You entered: (%g %g %g), %g\n", axis[i][0],
axis[i][1], axis[i][2], angle[i]);
}

to_quaternion(axis[0], angle[0], q);
for (i = 1; i < num_entered; i++) {
float q1[4];

to_quaternion(axis[i], angle[i], q1);
multiply_quaternion(q, q1, q);
}
from_quaternion(q, result_axis, &result_angle);

printf("\nCombined rotation is:\n");
printf("Transform { rotation %g %g %g %g }\n\n",
result_axis[0], result_axis[1], result_axis[2],
result_angle);

return 0;
}
Richard Kennaway

2005-01-13, 12:16 pm

Joerg Scheurich aka MUFTI <rusmufti@helpdesk.rus.uni-stuttgart.de>
wrote:
> You can also use the multiply in the VRML javascript API, but unfortunalty
> the standard do not clear say, what is first and what is second rotation, so
> different browsers can give different results 8-(


Cortona and Contact are consistent with each other, and with the usual
mathematical notation (which is as good a definition of "right" as any):
if rot3 = rot1.multiply(rot2), then the following two pieces of VRML
will apply the same transformation to the children.

Transform {
rotation rot3
children [ ... ]
}

Transform {
rotation rot1
children Transform {
rotation rot2
children [ ... ]
}
}

CosmoPlayer does it the other way round (i.e. "wrong"), but it's
obsolete and can be ignored.

In some browsers (I've found this with the Mac version of Cortona), you
must make sure that the axes of the SFRotations are normalised (i.e.
unit vectors) before calling .multiply(), otherwise you get incorrect
results.

-- Richard Kennaway
simon

2005-01-13, 12:16 pm


bensmyth wrote:
> Use matrix addition? - can't remember of the top of my head..... try

Google.[color=darkred]
>
> "Lucia" <cheng_lucia@yahoo.com> wrote in message
> news:7390d0bf.0501100738.5c1a2db1@posting.google.com...

in my post "help finding fundamental 3d maths" the example i showed was
the use of vrmlmatrix to 'add' two rotations, this could have textual
output and draggable vectors added to produce a usable tool, or just
edit the example with the angles reguired.

simon.

Sponsored Links


Copyright 2003 - 2008 forum4designers.com  Software forum  Computer Hardware reviews