From fd360406b9be5ac8d32586e0142cde449ee53ee7 Mon Sep 17 00:00:00 2001 From: Charles Krinke Date: Sat, 15 Dec 2007 16:26:32 +0000 Subject: [PATCH] Thanks again to Alondria for adding: math support for rot * rot, vec / rot, == and != overriders for Rotations and Vectors. Also: llRotBetween(), llGetRegionTimeDilation(). And fixing: Error in LSL2CSConverter that botched a variable with a type name in it (ex: rotationCenter) Fixed: Error in LSL2CSConverter that parsed which() loops incorrectly. Fixed: Changed definition of Quaternion to from (As per LSL) Finished: llEuler2Rot() --- .../Region/ScriptEngine/Common/LSL_Types.cs | 193 ++++++++++++++---- .../Compiler/LSL/LSL2CSConverter.cs | 11 +- .../Server_API/LSL_BuiltIn_Commands.cs | 40 ++-- 3 files changed, 181 insertions(+), 63 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs index 5618db64b0..e0cf1e55f8 100644 --- a/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs @@ -53,59 +53,53 @@ namespace OpenSim.Region.ScriptEngine.Common y = Y; z = Z; } - public string ToString() + + #region Overriders + + public override string ToString() { return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ">"; } - public static Vector3 operator *(Vector3 v, float f) + public static bool operator ==(Vector3 lhs, Vector3 rhs) { - v.x = v.x * f; - v.y = v.y * f; - v.z = v.z * f; - return v; + return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); } - public static Vector3 operator /(Vector3 v, float f) + public static bool operator !=(Vector3 lhs, Vector3 rhs) { - v.x = v.x / f; - v.y = v.y / f; - v.z = v.z / f; - return v; + return !(lhs == rhs); } - public static Vector3 operator /(float f, Vector3 v) + public override int GetHashCode() { - v.x = v.x / f; - v.y = v.y / f; - v.z = v.z / f; - return v; + return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode()); } - public static Vector3 operator *(float f, Vector3 v) + + + public override bool Equals(object o) { - v.x = v.x * f; - v.y = v.y * f; - v.z = v.z * f; - return v; + if (!(o is Vector3)) return false; + + Vector3 vector = (Vector3)o; + + return (x == vector.x && x == vector.x && z == vector.z); } - public static Vector3 operator *(Vector3 v1, Vector3 v2) + + #endregion + + #region Vector & Vector Math + // Vector-Vector Math + public static Vector3 operator +(Vector3 lhs, Vector3 rhs) { - v1.x = v1.x * v2.x; - v1.y = v1.y * v2.y; - v1.z = v1.z * v2.z; - return v1; - } - public static Vector3 operator +(Vector3 v1, Vector3 v2) + return new Vector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); + } + public static Vector3 operator -(Vector3 lhs, Vector3 rhs) { - v1.x = v1.x + v2.x; - v1.y = v1.y + v2.y; - v1.z = v1.z + v2.z; - return v1; + return new Vector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); } - public static Vector3 operator -(Vector3 v1, Vector3 v2) + public static Vector3 operator *(Vector3 lhs, Vector3 rhs) { - v1.x = v1.x - v2.x; - v1.y = v1.y - v2.y; - v1.z = v1.z - v2.z; - return v1; + return new Vector3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); } + public static Vector3 operator %(Vector3 v1, Vector3 v2) { //Cross product @@ -115,6 +109,79 @@ namespace OpenSim.Region.ScriptEngine.Common tv.z = (v1.x * v2.y) - (v1.y * v2.x); return tv; } + + #endregion + + #region Vector & Float Math + // Vector-Float and Float-Vector Math + public static Vector3 operator *(Vector3 vec, float val) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator *(float val, Vector3 vec) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator /(Vector3 v, float f) + { + v.x = v.x / f; + v.y = v.y / f; + v.z = v.z / f; + return v; + } + + #endregion + + #region Vector & Rotation Math + // Vector-Rotation Math + public static Vector3 operator *(Vector3 v, Quaternion r) + { + Quaternion vq = new Quaternion(v.x, v.y, v.z, 0); + Quaternion nq = new Quaternion(-r.x, -r.y, -r.z, r.s); + + Quaternion result = (r * vq) * nq; + + return new Vector3(result.x, result.y, result.z); + } + // I *think* this is how it works.... + public static Vector3 operator /(Vector3 vec, Quaternion quat) + { + quat.s = -quat.s; + Quaternion vq = new Quaternion(vec.x, vec.y, vec.z, 0); + Quaternion nq = new Quaternion(-quat.x, -quat.y, -quat.z, quat.s); + + Quaternion result = (quat * vq) * nq; + + return new Vector3(result.x, result.y, result.z); + } + #endregion + + #region Static Helper Functions + public static double Dot(Vector3 v1, Vector3 v2) + { + return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z); + } + public static Vector3 Cross(Vector3 v1, Vector3 v2) + { + return new Vector3 + ( + v1.y * v2.z - v1.z * v2.y, + v1.z * v2.x - v1.x * v2.z, + v1.x * v2.y - v1.y * v2.x + ); + } + public static float Mag(Vector3 v) + { + return (float)Math.Sqrt(v.x * v.y + v.y * v.y + v.z * v.z); + } + public static Vector3 Norm(Vector3 vector) + { + float mag = Mag(vector); + return new Vector3(vector.x / mag, vector.y / mag, vector.z / mag); + } + #endregion } [Serializable] @@ -123,26 +190,66 @@ namespace OpenSim.Region.ScriptEngine.Common public double x; public double y; public double z; - public double r; + public double s; public Quaternion(Quaternion Quat) { x = (float) Quat.x; y = (float) Quat.y; z = (float) Quat.z; - r = (float) Quat.r; + s = (float) Quat.s; } - public Quaternion(double X, double Y, double Z, double R) + public Quaternion(double X, double Y, double Z, double S) { x = X; y = Y; z = Z; - r = R; + s = S; } - public string ToString() + + #region Overriders + + public override int GetHashCode() { - return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ", " + r.ToString() + ">"; + return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ s.GetHashCode()); + } + + + public override bool Equals(object o) + { + if (!(o is Quaternion)) return false; + + Quaternion quaternion = (Quaternion)o; + + return x == quaternion.x && y == quaternion.y && z == quaternion.z && s == quaternion.s; + } + public override string ToString() + { + return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ", " + s.ToString() + ">"; + } + + public static bool operator ==(Quaternion lhs, Quaternion rhs) + { + // Return true if the fields match: + return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.s == rhs.s; + } + + public static bool operator !=(Quaternion lhs, Quaternion rhs) + { + return !(lhs == rhs); + } + + #endregion + + public static Quaternion operator *(Quaternion a, Quaternion b) + { + Quaternion c; + c.x = a.s * b.x + a.x * b.s + a.y * b.z - a.z * b.y; + c.y = a.s * b.y + a.y * b.s + a.z * b.x - a.x * b.z; + c.z = a.s * b.z + a.z * b.s + a.x * b.y - a.y * b.x; + c.s = a.s * b.s - a.x * b.x - a.y * b.y - a.z * b.z; + return c; } } } diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs index d9ebd14308..00ddbba7ba 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs @@ -47,7 +47,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL dataTypes.Add("key", "string"); dataTypes.Add("vector", "LSL_Types.Vector3"); dataTypes.Add("rotation", "LSL_Types.Quaternion"); - dataTypes.Add("list", "List"); + dataTypes.Add("list", "List"); dataTypes.Add("null", "null"); } @@ -203,7 +203,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL //Console.WriteLine("Replacing using statename: " + current_statename); cache = Regex.Replace(cache, - @"^(\s*)((?!(if|switch|for)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", + @"^(\s*)((?!(if|switch|for|while)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", @"$1public " + current_statename + "_event_$2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); } @@ -236,7 +236,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL RegexOptions.Compiled | RegexOptions.Multiline); // Replace return types and function variables - integer a() and f(integer a, integer a) Script = - Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)", @"$1$2" + val + "$3", + Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s+)", @"$1$2" + val + "$3", + RegexOptions.Compiled | RegexOptions.Multiline); + Script = + Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)[,]", @"$1$2" + val + "$3,", RegexOptions.Compiled | RegexOptions.Multiline); } @@ -281,7 +284,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL // Add namespace, class name and inheritance Return = "" + - "using OpenSim.Region.ScriptEngine.Common;"; + "using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic;"; //"using System; " + //"using System.Collections.Generic; " + //"using System.Text; " + diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs index 8563694dcf..00e79c03d8 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs @@ -191,19 +191,19 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r) { //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke - LSL_Types.Quaternion t = new LSL_Types.Quaternion(r.x*r.x, r.y*r.y, r.z*r.z, r.r*r.r); - double m = (t.x + t.y + t.z + t.r); + LSL_Types.Quaternion t = new LSL_Types.Quaternion(r.x*r.x, r.y*r.y, r.z*r.z, r.s*r.s); + double m = (t.x + t.y + t.z + t.s); if (m == 0) return new LSL_Types.Vector3(); - double n = 2*(r.y*r.r + r.x*r.z); + double n = 2*(r.y*r.s + r.x*r.z); double p = m*m - n*n; if (p > 0) - return new LSL_Types.Vector3(Math.Atan2(2.0*(r.x*r.r - r.y*r.z), (-t.x - t.y + t.z + t.r)), + return new LSL_Types.Vector3(Math.Atan2(2.0*(r.x*r.s - r.y*r.z), (-t.x - t.y + t.z + t.s)), Math.Atan2(n, Math.Sqrt(p)), - Math.Atan2(2.0*(r.z*r.r - r.x*r.y), (t.x - t.y - t.z + t.r))); + Math.Atan2(2.0*(r.z*r.s - r.x*r.y), (t.x - t.y - t.z + t.s))); else if (n > 0) - return new LSL_Types.Vector3(0.0, Math.PI/2, Math.Atan2((r.z*r.r + r.x*r.y), 0.5 - t.x - t.z)); + return new LSL_Types.Vector3(0.0, Math.PI/2, Math.Atan2((r.z*r.s + r.x*r.y), 0.5 - t.x - t.z)); else - return new LSL_Types.Vector3(0.0, -Math.PI/2, Math.Atan2((r.z*r.r + r.x*r.y), 0.5 - t.x - t.z)); + return new LSL_Types.Vector3(0.0, -Math.PI/2, Math.Atan2((r.z*r.s + r.x*r.y), 0.5 - t.x - t.z)); } public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v) @@ -219,6 +219,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler LSL_Types.Quaternion a1 = new LSL_Types.Quaternion(0.0, 0.0, cz, cw); LSL_Types.Quaternion a2 = new LSL_Types.Quaternion(0.0, by, 0.0, bw); LSL_Types.Quaternion a3 = new LSL_Types.Quaternion(ax, 0.0, 0.0, aw); + LSL_Types.Quaternion a = (a1 * a2) * a3; //This multiplication doesnt compile, yet. a = a1 * a2 * a3; LSL_Types.Quaternion b = new LSL_Types.Quaternion(ax*bw*cw + aw*by*cz, aw*by*cw - ax*bw*cz, aw*bw*cz + ax*by*cw, @@ -230,13 +231,14 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler if ((Math.Abs(c.x) > err && Math.Abs(d.x) > err) || (Math.Abs(c.y) > err && Math.Abs(d.y) > err) || (Math.Abs(c.z) > err && Math.Abs(d.z) > err) || - (Math.Abs(c.r) > err && Math.Abs(d.r) > err)) + (Math.Abs(c.s) > err && Math.Abs(d.s) > err)) { + return b; //return a new Quaternion that is null until I figure this out // return b; // return a; } - return new LSL_Types.Quaternion(); + return a; } public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up) @@ -258,12 +260,19 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler { return new LSL_Types.Vector3(); } - - public LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 start, LSL_Types.Vector3 end) + public LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 a, LSL_Types.Vector3 b) { - return new LSL_Types.Quaternion(); - } + //A and B should both be normalized + double dotProduct = LSL_Types.Vector3.Dot(a, b); + LSL_Types.Vector3 crossProduct = LSL_Types.Vector3.Cross(a, b); + double magProduct = LSL_Types.Vector3.Mag(a) * LSL_Types.Vector3.Mag(b); + double angle = Math.Acos(dotProduct / magProduct); + LSL_Types.Vector3 axis = LSL_Types.Vector3.Norm(crossProduct); + double s = Math.Sin(angle / 2); + + return new LSL_Types.Quaternion(axis.x * s, axis.y * s, axis.z * s, (float)Math.Cos(angle / 2)); + } public void llWhisper(int channelID, string text) { World.SimChat(Helpers.StringToField(text), @@ -629,7 +638,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler } if (face == -1) { - LLObject.TextureEntryFace texface; for (int i = 0; i < 32; i++) { if (tex.FaceTextures[i] != null) @@ -729,7 +737,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler public void llSetRot(LSL_Types.Quaternion rot) { - m_host.UpdateRotation(new LLQuaternion((float) rot.x, (float) rot.y, (float) rot.z, (float) rot.r)); + m_host.UpdateRotation(new LLQuaternion((float) rot.x, (float) rot.y, (float) rot.z, (float) rot.s)); } public LSL_Types.Quaternion llGetRot() @@ -1778,7 +1786,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler public double llGetRegionTimeDilation() { - return 1.0f; + return (double)World.TimeDilation; } public double llGetRegionFPS()