discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

How to translate 3 vector axis to a camera viewpoint?

A
adrian
Tue, Jan 31, 2017 5:59 PM

So, I have three orthogonal vectors and I wish to set my viewport to the 'top
view' of these vectors.  How would I go about doing that?  I'm thinking that
I would have to modify the $vpr variable, but how?

--
View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

So, I have three orthogonal vectors and I wish to set my viewport to the 'top view' of these vectors. How would I go about doing that? I'm thinking that I would have to modify the $vpr variable, but how? -- View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289.html Sent from the OpenSCAD mailing list archive at Nabble.com.
D
droftarts
Wed, Feb 1, 2017 5:06 PM

You just set the $vpt, $vpr and $vpd values in your OpenSCAD script, usually
at the beginning, or at the top-level (ie not in any module), of the main
file, eg:

$vpt = [ 0,0,0 ];
$vpr = [ 60,0,30 ];
$vpd = 500;

When you press F5, it will draw the scene from this viewpoint. For more
information, see
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Other_Language_Features#.24vpr.2C_.24vpt_and_.24vpd

When you come to animate your model, you can use $t ("time", is a value
between 0 and 1, see
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Other_Language_Features#.24t
) to move the viewport around your object, eg:

$vpt = [ 0, 0, 0 ];
$vpr = [ 90-$t30, 0.00, 30+$t720 ];
$vpd = 500;

Open the "animate" dialogue, set Time to 0, Steps to 720 and FPS to a number
greater than 0 (depends on model complexity, and how quick your PC is at to
how many FPS you can get). This should move the viewport around the object
in a spiral motion, going up, but keep the focus on the origin.

Ian

--
View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20292.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

You just set the $vpt, $vpr and $vpd values in your OpenSCAD script, usually at the beginning, or at the top-level (ie not in any module), of the main file, eg: $vpt = [ 0,0,0 ]; $vpr = [ 60,0,30 ]; $vpd = 500; When you press F5, it will draw the scene from this viewpoint. For more information, see https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Other_Language_Features#.24vpr.2C_.24vpt_and_.24vpd When you come to animate your model, you can use $t ("time", is a value between 0 and 1, see https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Other_Language_Features#.24t ) to move the viewport around your object, eg: $vpt = [ 0, 0, 0 ]; $vpr = [ 90-$t*30, 0.00, 30+$t*720 ]; $vpd = 500; Open the "animate" dialogue, set Time to 0, Steps to 720 and FPS to a number greater than 0 (depends on model complexity, and how quick your PC is at to how many FPS you can get). This should move the viewport around the object in a spiral motion, going up, but keep the focus on the origin. Ian -- View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20292.html Sent from the OpenSCAD mailing list archive at Nabble.com.
A
adrian
Thu, Feb 2, 2017 12:05 AM

Ok. Let's get a more generic example.

I have axis, represented by vectors A, B and C. I want to view that location
as if it were the origin from the top view. How would I do that?

--
View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20293.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Ok. Let's get a more generic example. I have axis, represented by vectors A, B and C. I want to view that location as if it were the origin from the top view. How would I do that? -- View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20293.html Sent from the OpenSCAD mailing list archive at Nabble.com.
D
droftarts
Thu, Feb 2, 2017 1:25 AM

$vpt sets the viewport translation, $vpr sets the rotation ( [0,0,0] sets the
view from above), $vpd sets the distance. So...

$vpt = [ A,B,C ];
$vpr = [ 0,0,0 ];

You may need to set a distance, too. The current viewport vectors are shown
in the bottom left of the OpenSCAD window, usually.

Ian

--
View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20294.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

$vpt sets the viewport translation, $vpr sets the rotation ( [0,0,0] sets the view from above), $vpd sets the distance. So... $vpt = [ A,B,C ]; $vpr = [ 0,0,0 ]; You may need to set a distance, too. The current viewport vectors are shown in the bottom left of the OpenSCAD window, usually. Ian -- View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20294.html Sent from the OpenSCAD mailing list archive at Nabble.com.
A
adrian
Thu, Feb 2, 2017 1:35 AM

I don't understand. A, B and C are 3D vectors.  $vpt is a triple of numbers.
If A = [1,0,0], B = [0,1,0] and C = [0,0,1], then what you stated was $vpt =
[[1,0,0], [0,1,0], [0,0,1]]; which is a triple of triples.  That doesn't
make sense.

--
View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20295.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

I don't understand. A, B and C are 3D vectors. $vpt is a triple of numbers. If A = [1,0,0], B = [0,1,0] and C = [0,0,1], then what you stated was $vpt = [[1,0,0], [0,1,0], [0,0,1]]; which is a triple of triples. That doesn't make sense. -- View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20295.html Sent from the OpenSCAD mailing list archive at Nabble.com.
R
Ronaldo
Thu, Feb 2, 2017 5:20 AM

Adrian,

You are right. Euler angles really sucks. It is the worst system to
represent rotations.

The rotation of $vpr should be defined by a vector of 3 Euler angles: the
rotation angles about each of the original coordinate system to be applied
to the viewport. Just like rotate(...) for children. The question, the
answer to your question, is how to find this Euler angles given an
orthogonal system for the viewport?

To solve this problem we have to solve a trigonometric system of equations.
Worst than that, there is many interpretation for the Euler angles. Even
worst, depending on the coordinate system, the system of equations has
infinite solutions!

The following code includes a function, RM2EAxyz, that solves the problem
above by converting a rotation matrix into a vector of the three Euler
angles where the rotations are supposed to be applied in the order RxRyRz.
That is what you need.

ax = unit(rands(-1,1,3));
ay = unit(cross(ax,rands(-1,1,3)));
az = unit(cross(ax,ay));

M = [ax, ay, az];
echo(M);
angs = RM2EAxyz(M);

$vpt = [0,0,0];
$vpr = angs;

color("red")  show_vector(ax);
color("green") show_vector(ay);
color("blue")  show_vector(az,t=3);

// converts a rotation matrix into the Euler angles
// with the order Rx.Ry.Rz
function RM2EAxyz(M) =
let( ang1 = 1-abs(M[0][2])<1e-12 ?
0 :
atan2(M[1][2],M[2][2]),
ang2 = 1-abs(M[0][2])<1e-12 ?
-90*sign(M[0][2]) :
-asin(M[0][2]),
ang3 = 1-abs(M[0][2])<1e-12 ?
atan2(M[2][0],M[1][0])-90 :
atan2(M[0][1],M[0][0]) )
[ang1, ang2, ang3];

// draw a cylinder with the direction of vector v
module show_vector(v,t=1) {
length = norm([v.x,v.y,v.z]);  // radial distance
b = acos(v.z/length);          // inclination angle
c = atan2(v.y,v.x);            // azimuthal angle
rotate([0, b, c])
cylinder(h=length, r=0.01*t);
}

function unit(v) = norm(v)>0 ? v/norm(v) : undef;

This code is an illustration of how to solve your problem and a test of the
function RM2EAxyz. The first 3 lines generates an orthonormal reference
system: the vectors ax, ay, az, besides being orthogonal, have unitary norm.
With them we form a rotation matrix M and convert M to the Euler angle form
with RM2EAxyz. Those Euler angles are assigned to $vpr. The following 3
lines draw the viewport axis with different colors.

If you animate this code, you will see the original coordinate system (the
system axis) rotating madly about the origin and the 3 drawn vectors
completely motionless: red to the right, green to above and blue projected
on the origin.

--
View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20296.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Adrian, You are right. Euler angles really sucks. It is the worst system to represent rotations. The rotation of $vpr should be defined by a vector of 3 Euler angles: the rotation angles about each of the original coordinate system to be applied to the viewport. Just like rotate(...) for children. The question, the answer to your question, is how to find this Euler angles given an orthogonal system for the viewport? To solve this problem we have to solve a trigonometric system of equations. Worst than that, there is many interpretation for the Euler angles. Even worst, depending on the coordinate system, the system of equations has infinite solutions! The following code includes a function, RM2EAxyz, that solves the problem above by converting a rotation matrix into a vector of the three Euler angles where the rotations are supposed to be applied in the order Rx*Ry*Rz. That is what you need. > ax = unit(rands(-1,1,3)); > ay = unit(cross(ax,rands(-1,1,3))); > az = unit(cross(ax,ay)); > > M = [ax, ay, az]; > echo(M); > angs = RM2EAxyz(M); > > $vpt = [0,0,0]; > $vpr = angs; > > color("red") show_vector(ax); > color("green") show_vector(ay); > color("blue") show_vector(az,t=3); > > // converts a rotation matrix into the Euler angles > // with the order Rx.Ry.Rz > function RM2EAxyz(M) = > let( ang1 = 1-abs(M[0][2])<1e-12 ? > 0 : > atan2(M[1][2],M[2][2]), > ang2 = 1-abs(M[0][2])<1e-12 ? > -90*sign(M[0][2]) : > -asin(M[0][2]), > ang3 = 1-abs(M[0][2])<1e-12 ? > atan2(M[2][0],M[1][0])-90 : > atan2(M[0][1],M[0][0]) ) > [ang1, ang2, ang3]; > > // draw a cylinder with the direction of vector v > module show_vector(v,t=1) { > length = norm([v.x,v.y,v.z]); // radial distance > b = acos(v.z/length); // inclination angle > c = atan2(v.y,v.x); // azimuthal angle > rotate([0, b, c]) > cylinder(h=length, r=0.01*t); > } > > function unit(v) = norm(v)>0 ? v/norm(v) : undef; This code is an illustration of how to solve your problem and a test of the function RM2EAxyz. The first 3 lines generates an orthonormal reference system: the vectors ax, ay, az, besides being orthogonal, have unitary norm. With them we form a rotation matrix M and convert M to the Euler angle form with RM2EAxyz. Those Euler angles are assigned to $vpr. The following 3 lines draw the viewport axis with different colors. If you animate this code, you will see the original coordinate system (the system axis) rotating madly about the origin and the 3 drawn vectors completely motionless: red to the right, green to above and blue projected on the origin. -- View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20296.html Sent from the OpenSCAD mailing list archive at Nabble.com.
A
adrian
Thu, Feb 2, 2017 3:37 PM

Thanks Ronaldo, that's cool.  I'm going to have to look into this further.

Thanks again! :)

--
View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20298.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Thanks Ronaldo, that's cool. I'm going to have to look into this further. Thanks again! :) -- View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20298.html Sent from the OpenSCAD mailing list archive at Nabble.com.
RP
Ronaldo Persiano
Thu, Feb 2, 2017 7:23 PM

I have found two other methods to compute the Euler angles from a rotation
matrix:

// a version found in
// https://www.learnopencv.com/rotation-matrix-to-euler-angles/
function RM2EAxyz2(M) =
let( sy = norm([M[0][0],M[0][1]]) )
sy > 1e-6 ?
[  atan2(M[1][2],M[2][2]),
atan2(-M[0][2],sy),
atan2(M[0][1],M[0][0]) ] :
[  atan2(-M[2][1], M[1][1]),
atan2(-M[0][2],sy),
0 ];

// a version found in
// https://www.geometrictools.com/Documentation/EulerAngles.pdf
function RM2EAxyz3(M) =
M[0][2] < 1 ?
[  atan2(M[1][2],M[2][2]),
-asin(M[0][2]),
atan2(M[0][1],M[0][0]) ]
:
// Not a unique solution :
// ang3 +- ang1 = atan2(M[1][0], M[1][1])
[  -atan2(M[1][0], M[1][1]),
-90,
0 ] * sign(M[0][2]);

I have superficially checked them.

I have found two other methods to compute the Euler angles from a rotation matrix: // a version found in // https://www.learnopencv.com/rotation-matrix-to-euler-angles/ function RM2EAxyz2(M) = let( sy = norm([M[0][0],M[0][1]]) ) sy > 1e-6 ? [ atan2(M[1][2],M[2][2]), atan2(-M[0][2],sy), atan2(M[0][1],M[0][0]) ] : [ atan2(-M[2][1], M[1][1]), atan2(-M[0][2],sy), 0 ]; // a version found in // https://www.geometrictools.com/Documentation/EulerAngles.pdf function RM2EAxyz3(M) = M[0][2] < 1 ? [ atan2(M[1][2],M[2][2]), -asin(M[0][2]), atan2(M[0][1],M[0][0]) ] : // Not a unique solution : // ang3 +- ang1 = atan2(M[1][0], M[1][1]) [ -atan2(M[1][0], M[1][1]), -90, 0 ] * sign(M[0][2]); I have superficially checked them.
DM
doug moen
Thu, Feb 2, 2017 7:58 PM

Ronaldo said: "Euler angles really sucks. It is the worst system to
represent rotations."

Haha, that's a pretty strong statement. I am considering to use quaternions
to represent 3D rotations in my new geometry engine. The upside is no
gimbal lock, normalization, and the slerp function, which are real
benefits. The downside is that the 4 numbers stored in a quaternion are
incomprehensible to ordinary humans, so you need to use library functions
to manipulate quaternions. Euler angles are at least easier to understand.

It seems you can convert between quaternions and euler angles using matrix
multiplication.
https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

An OpenSCAD quaternion library might be worthwhile.

On 2 February 2017 at 00:20, Ronaldo rcmpersiano@gmail.com wrote:

Adrian,

You are right. Euler angles really sucks. It is the worst system to
represent rotations.

The rotation of $vpr should be defined by a vector of 3 Euler angles: the
rotation angles about each of the original coordinate system to be applied
to the viewport. Just like rotate(...) for children. The question, the
answer to your question, is how to find this Euler angles given an
orthogonal system for the viewport?

To solve this problem we have to solve a trigonometric system of equations.
Worst than that, there is many interpretation for the Euler angles. Even
worst, depending on the coordinate system, the system of equations has
infinite solutions!

The following code includes a function, RM2EAxyz, that solves the problem
above by converting a rotation matrix into a vector of the three Euler
angles where the rotations are supposed to be applied in the order
RxRyRz.
That is what you need.

ax = unit(rands(-1,1,3));
ay = unit(cross(ax,rands(-1,1,3)));
az = unit(cross(ax,ay));

M = [ax, ay, az];
echo(M);
angs = RM2EAxyz(M);

$vpt = [0,0,0];
$vpr = angs;

color("red")  show_vector(ax);
color("green") show_vector(ay);
color("blue")  show_vector(az,t=3);

// converts a rotation matrix into the Euler angles
// with the order Rx.Ry.Rz
function RM2EAxyz(M) =
let( ang1 = 1-abs(M[0][2])<1e-12 ?
0 :
atan2(M[1][2],M[2][2]),
ang2 = 1-abs(M[0][2])<1e-12 ?
-90*sign(M[0][2]) :
-asin(M[0][2]),
ang3 = 1-abs(M[0][2])<1e-12 ?
atan2(M[2][0],M[1][0])-90 :
atan2(M[0][1],M[0][0]) )
[ang1, ang2, ang3];

// draw a cylinder with the direction of vector v
module show_vector(v,t=1) {
length = norm([v.x,v.y,v.z]);  // radial distance
b = acos(v.z/length);          // inclination angle
c = atan2(v.y,v.x);            // azimuthal angle
rotate([0, b, c])
cylinder(h=length, r=0.01*t);
}

function unit(v) = norm(v)>0 ? v/norm(v) : undef;

This code is an illustration of how to solve your problem and a test of the
function RM2EAxyz. The first 3 lines generates an orthonormal reference
system: the vectors ax, ay, az, besides being orthogonal, have unitary
norm.
With them we form a rotation matrix M and convert M to the Euler angle form
with RM2EAxyz. Those Euler angles are assigned to $vpr. The following 3
lines draw the viewport axis with different colors.

If you animate this code, you will see the original coordinate system (the
system axis) rotating madly about the origin and the 3 drawn vectors
completely motionless: red to the right, green to above and blue projected
on the origin.

--
View this message in context: http://forum.openscad.org/How-
to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20296.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Ronaldo said: "Euler angles really sucks. It is the worst system to represent rotations." Haha, that's a pretty strong statement. I am considering to use quaternions to represent 3D rotations in my new geometry engine. The upside is no gimbal lock, normalization, and the slerp function, which are real benefits. The downside is that the 4 numbers stored in a quaternion are incomprehensible to ordinary humans, so you need to use library functions to manipulate quaternions. Euler angles are at least easier to understand. It seems you can convert between quaternions and euler angles using matrix multiplication. https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles An OpenSCAD quaternion library might be worthwhile. On 2 February 2017 at 00:20, Ronaldo <rcmpersiano@gmail.com> wrote: > Adrian, > > You are right. Euler angles really sucks. It is the worst system to > represent rotations. > > The rotation of $vpr should be defined by a vector of 3 Euler angles: the > rotation angles about each of the original coordinate system to be applied > to the viewport. Just like rotate(...) for children. The question, the > answer to your question, is how to find this Euler angles given an > orthogonal system for the viewport? > > To solve this problem we have to solve a trigonometric system of equations. > Worst than that, there is many interpretation for the Euler angles. Even > worst, depending on the coordinate system, the system of equations has > infinite solutions! > > The following code includes a function, RM2EAxyz, that solves the problem > above by converting a rotation matrix into a vector of the three Euler > angles where the rotations are supposed to be applied in the order > Rx*Ry*Rz. > That is what you need. > > > ax = unit(rands(-1,1,3)); > > ay = unit(cross(ax,rands(-1,1,3))); > > az = unit(cross(ax,ay)); > > > > M = [ax, ay, az]; > > echo(M); > > angs = RM2EAxyz(M); > > > > $vpt = [0,0,0]; > > $vpr = angs; > > > > color("red") show_vector(ax); > > color("green") show_vector(ay); > > color("blue") show_vector(az,t=3); > > > > // converts a rotation matrix into the Euler angles > > // with the order Rx.Ry.Rz > > function RM2EAxyz(M) = > > let( ang1 = 1-abs(M[0][2])<1e-12 ? > > 0 : > > atan2(M[1][2],M[2][2]), > > ang2 = 1-abs(M[0][2])<1e-12 ? > > -90*sign(M[0][2]) : > > -asin(M[0][2]), > > ang3 = 1-abs(M[0][2])<1e-12 ? > > atan2(M[2][0],M[1][0])-90 : > > atan2(M[0][1],M[0][0]) ) > > [ang1, ang2, ang3]; > > > > // draw a cylinder with the direction of vector v > > module show_vector(v,t=1) { > > length = norm([v.x,v.y,v.z]); // radial distance > > b = acos(v.z/length); // inclination angle > > c = atan2(v.y,v.x); // azimuthal angle > > rotate([0, b, c]) > > cylinder(h=length, r=0.01*t); > > } > > > > function unit(v) = norm(v)>0 ? v/norm(v) : undef; > > This code is an illustration of how to solve your problem and a test of the > function RM2EAxyz. The first 3 lines generates an orthonormal reference > system: the vectors ax, ay, az, besides being orthogonal, have unitary > norm. > With them we form a rotation matrix M and convert M to the Euler angle form > with RM2EAxyz. Those Euler angles are assigned to $vpr. The following 3 > lines draw the viewport axis with different colors. > > If you animate this code, you will see the original coordinate system (the > system axis) rotating madly about the origin and the 3 drawn vectors > completely motionless: red to the right, green to above and blue projected > on the origin. > > > > > > -- > View this message in context: http://forum.openscad.org/How- > to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20296.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > >
A
adrian
Thu, Feb 2, 2017 10:59 PM

Thanks for that.  Now that I know what to look for, I've found the wiki that
states matrices that do the same thing:

https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix

--
View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20301.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Thanks for that. Now that I know what to look for, I've found the wiki that states matrices that do the same thing: https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix -- View this message in context: http://forum.openscad.org/How-to-translate-3-vector-axis-to-a-camera-viewpoint-tp20289p20301.html Sent from the OpenSCAD mailing list archive at Nabble.com.