in reply to Re: Perl and Quaternions
in thread Perl and Quaternions

I apologize for the terrible formatting of the question, everyone.

I'm not used to posting here, and actually am more used to people knowing where my code is coming from(this familiarity coming from my time at Holowan Labs, at LucasForums). This is not an excuse, merely a statement about my own ignorance.

To address everything in your post, Ken, and hopefully everything else, let me try this again.

I'm trying to convert between radians and degrees from a given degree, for use in a quaternion format, particularly in translation between Quaternion values and Euler angles. I took another look at how the games I mod, Star Wars Knights of the Old Republic it's sequel, use Quaternions. And it looks like I messed up:

Z = sin (angle/2) Y = 0.0 X = 0.0 Q = cos (angle/2)

In my eyes, it was a simple mistake, though you guys might judge differently. I had always assumed that the values I needed were X and Y because that was how the game referenced them in it's files.

So, some example code was asked for. This code can be run from the commandline and will ask for an input value. Be sure to input it in degrees.

use strict; use warnings; use Math::Complex; my $pi = 4*atan2(1,1); sub deg_to_rad { ($_[0]/180) * $pi; } sub rad_to_deg { ($_[0]/$pi) * 180; } print "Enter a value: "; my $value = <STDIN>; my $radvalue = deg_to_rad($value); my $degvalue = rad_to_deg($radvalue); my $quat1 = sin($radvalue); my $quat1_deg = rad_to_deg($quat1); my $quat2 = cos($radvalue); my $quat2_deg = rad_to_deg($quat2); print "Original value: $value\n"; print "Radian value: $radvalue\n"; print "Degree value: $degvalue\n\n"; print "Quaternion first value: \t$quat1\n"; print "Quaternion first value(in degrees): \t$quat1_deg\n"; print "Quaternion fourth value: \t$quat2\n"; print "Quaternion fourth value(in degrees): \t$quat2_deg\n";

Inputting 90 degrees should bring up the radian value, 1.570796 blahblahblah, but it doesn't. I'm using the Math::Complex module, so that might be the difference between the expected results, but I'm not sure...

About the example code I posted that the game uses, yes it is NWScript. And I'm known for being accurate when I script in it, but on this occasion I didn't copy-and-paste correctly, so now feel kinda stupid for that. Also, I posted it for the sole reason of showing anybody who might care to know how the game calculates the values, which might help me do the opposite and calculate the facing from the values.

I admit that the spinbox widget isn't really optimal for this; it was more of a test on that part. It's easy enough to switch it to an entry widget with a binding to the Enter key, though, so I'm not too worried about it. However, thanks for pointing it out, Ken.

I tend to not use the strict pragma because it interferes with the TK code, in that when it forces me to put quotes around certain text, the options aren't accepted by TK... However, warnings should definitely have been used. Sorry about that, Ken.

I alternated between either value of Pi to see if there was any functional difference in the conversion subroutines.

Sorry about the clutter in the code samples. I was trying to give you guys enough info without chucking the whole script in, and without leaving out something that might be important and then get me flamed for not adding it in when it was so essential for the people answering to know that ahead of time...

Also, could you please be more specific about what you meant when you mentioned Array slices? You mentioned them, but never where in my code samples they might be used...

And I found Math::Quaternion myself while doing research, but I have no clue how to interpret it's 3x3 or 4x4 output, given that I just need four values...

I apologize, Ken, and wish I could elaborate more and get some more help, but I need to head off to school now. I'll be checking back in at lunch, see if anything's new. Thanks for the helpful comments, Ken!

Replies are listed 'Best First'.
Re^3: Perl and Quaternions
by kcott (Archbishop) on May 09, 2014 at 03:54 UTC
    "So, some example code was asked for. This code can be run from the commandline and will ask for an input value. Be sure to input it in degrees."

    Thanks. That looks like a much better sample that we can work with.

    "Inputting 90 degrees should bring up the radian value, 1.570796 blahblahblah, but it doesn't."

    Actually, it does when I run it.

    Enter a value: 90 Original value: 90 Radian value: 1.5707963267949 Degree value: 90 Quaternion first value: 1 Quaternion first value(in degrees): 57.2957795130823 Quaternion fourth value: 6.12323399573677e-17 Quaternion fourth value(in degrees): 3.50835464926744e-15

    And, just to confirm that's the correct result:

    $ perl -E 'say(4*atan2(1,1) / 2)' 1.5707963267949

    I suggest you run this again and check the output. Also check that you're running exactly the same code that you posted.

    "I'm using the Math::Complex module, so that might be the difference between the expected results, but I'm not sure..."

    Although you've loaded the Math::Complex module, I don't see any code that uses its functionality. In fact, if I comment out "use Math::Complex;", the output remains exactly the same.

    However, even if you were using Math::Complex's constants or functions, I can't see how you'd get anything different. Here's some fragments from its source code:

    ... sub pi () { 4 * CORE::atan2(1, 1) } ... sub cos { my ($z) = @_ ? @_ : $_; return CORE::cos($z) unless ref $z; ... } ... sub sin { my ($z) = @_ ? @_ : $_; return CORE::sin($z) unless ref $z; ... } ...

    And repeating the confirmation using pi from Math::Complex:

    $ perl -MMath::Complex -E 'say(pi / 2)' 1.5707963267949
    "I tend to not use the strict pragma because it interferes with the TK code, in that when it forces me to put quotes around certain text, the options aren't accepted by TK..."

    Frankly, that's a poor reason to remove all strictures from your entire script. If quoting right and x in

    ...->pack(-side=>right); ... ...->pack(-expand=>1, -fill=>x);

    is really such a burden, write them like this:

    ...->pack(qw{-side right}); ... ...->pack(qw{-expand 1 -fill x});

    On the rare occasions when you really do need to turn off a stricture, turn off just one and do it the smallest scope possible. For example

    use strict; ... # all strictures on here { no strict 'refs'; # 'vars' and 'subs' strictures still on here ...; # <--- minimal code requiring "no strict 'refs'" } # all strictures on here ...
    "However, warnings should definitely have been used."

    I'm not certain whether you're saying they weren't used or weren't shown. Had they been used, you would have received multiple messages like this:

    $ perl -Mwarnings -E 'my @x = qw{1 2 3}; my $y = @x[1]' Scalar value @x[1] better written as $x[1] at -e line 1.

    This is what I was referring to in my previous post with: "I can see four places in your posted code where you'll not only receive a warning but also actual code to replace what you've written (e.g. "your_code" better written as "better_code")."; although, I've now spotted two more.

    "Also, could you please be more specific about what you meant when you mentioned Array slices? You mentioned them, but never where in my code samples they might be used..."

    Don't use slices like this (as per my previous point):

    my $qx = @cam_quats[0]; my $qy = @cam_quats[1];

    You didn't show how you were intending to use $qx or $qy. If they were just for their values, you don't need them at all: you can use $cam_quats[0] and $cam_quats[1]. If, on the other hand, you wanted to modify these values without changing @cam_quats, you could have used a slice like this:

    my ($qx, $qy) = @cam_quats[0,1];

    However, when I originally made that point, I was thinking more about this code:

    my $cam_ori1 = @cam_ori[0]; # X-orientation my $cam_ori2 = @cam_ori[1]; # Always 0 my $cam_ori3 = @cam_ori[2]; # Always 0 my $cam_ori4 = @cam_ori[3]; # Y-orientation # Debugging print-out print "Orientation:\n\t$cam_ori1\n\t$cam_ori2\n\t$cam_ori3\n\t$cam +_ori4\n\n"; # The orientation values are stored as radians, so # calc_quatcam returns the degree equivalent, or should... my @cam_quats = calc_quatcam($cam_ori1, $cam_ori4);

    which you could've written like this using slices:

    # Debugging print-out print join("\n\t", 'Orientation:', @cam_ori[0..3]), "\n\n"; # The orientation values are stored as radians, so # calc_quatcam returns the degree equivalent, or should... my @cam_quats = calc_quatcam(@cam_ori[0,3]);

    As you can see, you no longer need any of: $cam_ori1, $cam_ori2, $cam_ori3 or $cam_ori4. Refer back to the dot point following the one about slices.

    Regarding "am more used to people knowing where my code is coming from", "Sorry about the clutter in the code samples." (and a few other related points), take a look at "I know what I mean. Why don't you?" which should address most of these.

    This is only your second post so don't concern yourself too much about mistakes you've made. Mistakes are good: we all make them and, hopefully, all learn from them. :-)

    -- Ken