Morrowind Mod:Math Functions
Overview[edit]
Morrowind comes with a very limited math library. By limited, we mean square root (GetSquareRoot) and distance (GetDistance) from one object to another (with some substantial limitations). Occasionally, there's a need for something more.
For anyone writing a script in a mod using MWSE, the basic trig functions are built in. So xArcTan is a simple extended function call. Degree/Radian conversions, Distance calculations, and the 6 basic trig functions. No power function though.
Ghan Buri Ghan's Scripting for Dummies mentions Soralis' Math Mod, available at Planet Elder Scrolls: Math Mod. This contains the following functions: SquareRoot Sine Cosine Tangent NaturalLog Log intPower intRoot Modulus Antiln Antilog AbsoluteValue Power
The math mod can either be included with your mod or you can use the scripts as a basis for your own.
LN by Taylor Expansion[edit]
LN can be expressed in a series similar to the SIN example, though it is slightly more complex:
x1 = ( Value - 1 ) / ( Value + 1 ) x3 = x1*x1*x1 x5 = x3*x1*x1 x7 = x5*x1*x1 x9 = x9*x1*x1 LNValue = 2 * ( x1 + x3/3 + x5/5 + x7/7 + x9/9 + ... )
You'd likely have to use more values than in the SIN case to get a similar accuracy (though I haven't checked). There are similar expansions for any trig/math function.
Modulo[edit]
Modulo gives you the remainder of division operation.
short divXY float modXY set divXY to ( X / Y ) set modXY to ( X - ( divXY * Y ) )
Sin/Cos Approximation[edit]
Here's a very simple example script which assumes the existence of 4 global floats: SinIN, SinOUT, CosIN, CosOUT. All the script does is take the sin of what's in SinIN and set SinOUT to the result, then take cos of what's in CosIN and set CosOUT to the result of that. It also prints out the results in a message box
begin SinScript ;Global float SinIN ;Global float SinOUT ;Global float CosIN ;Global float CosOUT float IN float OUT short DEBUG set IN to SinIN ;================================================== ; Simple Sin ; By: Matt (Simpleton) Edlefsen ; Remember to declare IN and OUT!! ;================================================== while ( IN > 270 ) set IN to IN - 360 endwhile while ( IN < -90 ) set IN to IN + 360 endwhile if ( IN > 90 ) set IN to 180 - IN endif set IN to IN * 3.14159265 / 180 set OUT to IN * IN set OUT to IN * ( ( -0.16605 * OUT) + ( 0.00761 * OUT * OUT) + 1 ) ;================================================== if ( DEBUG == 1 ) if ( OUT != SinOUT) MessageBox, "Sin(%.4f) = %.4f", SinIN, OUT endif endif set SinOUT to OUT set IN to CosIN ; subtracting IN from 90 right before the sin will make it do cos instead set IN to 90 - IN ;================================================== ; Simple Sin ; By: Matt (Simpleton) Edlefsen ; Remember to declare IN and OUT!! ;================================================== while ( IN > 270 ) set IN to IN - 360 endwhile while ( IN < -90 ) set IN to IN + 360 endwhile if ( IN > 90 ) set IN to 180 - IN endif set IN to IN * 3.14159265 / 180 set OUT to IN * IN set OUT to IN * ( ( -0.16605 * OUT) + ( 0.00761 * OUT * OUT) + 1 ) ;================================================== if ( DEBUG == 1 ) if ( OUT != CosOUT) MessageBox, "Cos(%.4f) = %.4f", CosIN, OUT endif endif set CosOUT to OUT end
If you want to test it out, just make sure to have the 4 globals declared and add the script to the start scripts
Sin by Taylor Expansion[edit]
Sin/Cosine can be easily computed to a reasonable degree of accuracy using Taylor series (I did this really fast so ignore any obvious errors):
begin SinTaylor float X float X2 float X4 float X5 float X7 float X8 float X9 float SinResult float Angle float Mult set Angle to 45; Angle you want in degrees ; We get a few more digits accuracy with large angles if we do this... if ( Angle >= 270 ) then set Angle to 360 - Angle set Mult to -1 else if ( Angle >= 180 ) then set Angle to 270 - Angle set Mult to -1 else if ( Angle >= 90 ) then set Angle to 180 - Angle set Mult to 1 else set Mult to 1 endif set X to Angle / 57.2957792; Convert angle to radians set X2 to X*X set X4 to X2*X2 set X5 to X4*X set X7 to X5*X2 set X8 to X4*X4 set X9 to X4*X4*X set SinResult to X - X2*X/6 + X5/120 - X7/5040 + X9/362880 - X9*X2/39916800 + X9*X4/6227020800 - X8*X7/1.307674368e12 set SinResult to SinResult * Mult end
This will give you a sin of any angle 0-360deg to at least 10 digits of accuracy. You can remove some of the end terms if you need less (really 3-4 digits is fine for most things you'd do in Morrowind anyways which means you can remove 3-4 terms).
Cos, Tan, ArcCin, SinH, exp, log etc... can be computed in a similar manner.