PDA

View Full Version : advmath.zh - atan, acos, asin



pkmnfrk
12-30-2008, 09:52 PM
Put this in a new file called "advmath.zh" (so that if anyone else uses it in their scripts, it will have the same name)


//Code adapted from the snippet located here:
//http://discussion.forum.nokia.com/forum/showthread.php?t=72840
//The original code was placed in the public domain
//The translated code below is also public domain

//I had to truncate these constants, since ZScript uses fixed place floats.
const float sq2p1 = 2.4142; // .414213562373095048802;
const float sq2m1 = 0.4142; // .414213562373095048802;
const float p4 = 16.1536; // .1536412982230228262;
const float p3 = 268.4255; // .42548195503973794141;
const float p2 = 1153.0294; // .0293515404850115428136;
const float p1 = 1780.4063; // .40631643319697105464587;
const float p0 = 896.7860; // .78597403663861959987488;
const float q4 = 58.9570; // .95697050844462222791;
const float q3 = 536.2654; // .265374031215315104235;
const float q2 = 1666.7838; // .7838148816337184521798;
const float q1 = 2079.3350; // .33497444540981287275926;
const float q0 = 896.7860; // .78597403663861962481162;
const float PIO2 = 1.5708; // .5707963267948966135;
const float PIO1 = 3.1416;
const float iRt2 = 0.7071;
const float PIO3 = 57.2958;
const float PIO4 = 0.0175;

// reduce
float mxatan(float arg) {
float argsq = arg*arg;
float value = (((p4*argsq + p3)*argsq + p2)*argsq + p1)*argsq + p0;
value /= ((((argsq + q4)*argsq + q3)*argsq + q2)*argsq + q1)*argsq + q0;
return value*arg;
}


// reduce
float msatan(float arg) {
if(arg < sq2m1)
return mxatan(arg);
if(arg > sq2p1)
return PIO2 - mxatan(1/arg);
return PIO2/2 + mxatan((arg-1)/(arg+1));
}

// implementation of atan
float atan(float arg) {
if(arg > 0)
return msatan(arg);
return -msatan(-arg);
}

// implementation of asin
float asin(float arg) {
float temp;
int sign;

sign = 0;
if(arg < 0) {
arg = -arg;
sign++;
}
if(arg > 1)
return 0.0; //should be NaN

temp = Sqrt(1 - arg*arg);
if(arg > iRt2)
temp = PIO2 - atan(temp/arg);
else
temp = atan(arg/temp);
if(sign > 0)
temp = -temp;
return temp;
}

// implementation of acos
float acos(float arg) {
if(arg > 1 || arg < -1)
return 0.0; //should be NaN
return PIO2 - asin(arg);
}

// convert radian angle to degrees
float rad2deg(float arg) {
return arg * PIO3;
}

// convert degree angle to radians
float deg2rad(float arg) {
return arg * PIO4;
}

float findAngle(float x1, float y1, float x2, float y2) {

float ret;

float dx = x2 - x1;
float dy = y2 - y1;

ret = ArcTan(dy, dx);

return PI / 2 - ret;
}

* Implements the ATan, ACos and ASin functions (until we get built in versions of the same)
* Does not rely on std.zh
* Easily importable into any script
* As a bonus, includes two functions to convert between degrees and radians!
* As a super special bonus, includes a function to find the angle from one point to another!

Function prototypes:

See this page for what they do: http://www.xgc.com/manuals/xgclib/x940.html


float asin(float x);
float acos(float x);
float atan(float x);
//atan2 is provided by the as yet undocumented function "ArcTan(y,x)"
float deg2rad(float deg);
float rad2deg(float rad);
float findAngle(float x1, float y1, float x2, float y2);

EDIT: Hurrr. I meant to post this in Script Showcase... :(

lucas92
12-30-2008, 10:06 PM
Holy... That's awesome! Don't you know that you are a scripting god? :p

Great. :)

beefster09
12-31-2008, 01:02 AM
We already have atan2, or findangle- it's ArcTan(x,y) _L_ just added documentation for it.

The other functions are helpful, I suppose. I don't really see myself using them much, though.

pkmnfrk
12-31-2008, 12:49 PM
Well, findangle isn't directly atan2, but either way. I had no idea ArcTan existed.

Also, I've updated my post with this revalation, and with a version of the script that actually compiles.

Elmensajero
12-31-2008, 07:19 PM
Very nice job getting these scripted! I tested them, and for about half of the values they were 100% accurate (within 4 decimal places of course.) The other half was off by only 0.0001, but this is prob just due to the fifth decimal place not being considered when truncating the result to 4 decimal places.

pkmnfrk
12-31-2008, 09:14 PM
I don't know if the engine rounds or truncates the fifth decimal place, but I imagine that it doesn't matter a whole lot.

Now, if you chain these together, the imprecision will add up to larger errors, but then again, nothing that will break your game.

Gleeok
12-31-2008, 11:00 PM
Cool. :)

Y'know, my only qualm is that the variable names are too short (and thus confusing or misleading), and there needs to be longer explanations of what/how to do/use them, because something like this could be built on in the future by anyone wanting to contribute. ...Uugh, what I'm basically saying is a standard "math.zh" file is a pretty good idea. I've got some functions that come in handy, and I'm sure others have usefull ones as well. We'd just have to stick them all into one file.

pkmnfrk
12-31-2008, 11:03 PM
The variable names are 100% internal. So, bugger off ;)

Actually, the real reason is that I do not understand that code at all. I merely ported it, and that's what the original source called them. And, though I added a few new ones (also internal), I kept the names short so the constants would line up.

In short, you're welcome to use the functions (the documented ones, anyway), but leave the constants alone, I have no idea what they represent!

Din
12-31-2008, 11:15 PM
Wow, you made a SECOND scripting engine for it to draw from? Wow, nice work. I'll like using those new commands. So we just have to

import "std.zh"
import "advmath.zh"?

You're doing really nice work pkmnfrk! Stop it, you're making the rest of us look bad! ;)

pkmnfrk
12-31-2008, 11:20 PM
Wow, you made a SECOND scripting engine for it to draw from?

Er, no. That's not-

...

Actually, yes. Yes I did.


Wow, nice work. I'll like using those new commands. So we just have to

import "std.zh"
import "advmath.zh"?

Yup.


You're doing really nice work pkmnfrk! Stop it, you're making the rest of us look bad! ;)

I'm just trying to make your lives easier :)

Christian
01-01-2009, 07:17 PM
don't we can do that also though? put all scripts in a folder in zelda classic? && use:

import "std zh"
import "math.zh"
import "ffc.z"
import "item.z"
import "global.z"
?

or am I going off-topic here? and wow mike! these are awesome! your a genious mister. very well done.

pkmnfrk
01-01-2009, 09:15 PM
"import" means "take the contents of the file referenced, and stick it right here, pretending it's the same file". A good example of why you would do this with something other than std.zh (or advmath.zh) is:


//So I don't have to hit Import every time I change my script file:
import "thescriptfile.z"

pkmnfrk
03-21-2009, 09:22 PM
I've updated the header a bit, to include a bug-fixed version of findAngle. Here's a copy of the function:


float findAngle(float x1, float y1, float x2, float y2) {

float ret;

float dx = x2 - x1;
float dy = y2 - y1;

ret = ArcTan(dy, dx);

return PI / 2 - ret;
}