aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorCharles Krinke2007-12-15 16:26:32 +0000
committerCharles Krinke2007-12-15 16:26:32 +0000
commitfd360406b9be5ac8d32586e0142cde449ee53ee7 (patch)
tree5e1593c2a046dd07d5c528ff3230729b2ad3cace /OpenSim
parent* some work on not storing the circuitPack (bad thing if we're going to reuse... (diff)
downloadopensim-SC_OLD-fd360406b9be5ac8d32586e0142cde449ee53ee7.zip
opensim-SC_OLD-fd360406b9be5ac8d32586e0142cde449ee53ee7.tar.gz
opensim-SC_OLD-fd360406b9be5ac8d32586e0142cde449ee53ee7.tar.bz2
opensim-SC_OLD-fd360406b9be5ac8d32586e0142cde449ee53ee7.tar.xz
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 <x, y, z, r> from <x, y, z, t> (As per LSL) Finished: llEuler2Rot()
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/LSL_Types.cs193
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs40
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 5618db6..e0cf1e5 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
53 y = Y; 53 y = Y;
54 z = Z; 54 z = Z;
55 } 55 }
56 public string ToString() 56
57 #region Overriders
58
59 public override string ToString()
57 { 60 {
58 return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ">"; 61 return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ">";
59 } 62 }
60 public static Vector3 operator *(Vector3 v, float f) 63 public static bool operator ==(Vector3 lhs, Vector3 rhs)
61 { 64 {
62 v.x = v.x * f; 65 return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
63 v.y = v.y * f;
64 v.z = v.z * f;
65 return v;
66 } 66 }
67 public static Vector3 operator /(Vector3 v, float f) 67 public static bool operator !=(Vector3 lhs, Vector3 rhs)
68 { 68 {
69 v.x = v.x / f; 69 return !(lhs == rhs);
70 v.y = v.y / f;
71 v.z = v.z / f;
72 return v;
73 } 70 }
74 public static Vector3 operator /(float f, Vector3 v) 71 public override int GetHashCode()
75 { 72 {
76 v.x = v.x / f; 73 return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode());
77 v.y = v.y / f;
78 v.z = v.z / f;
79 return v;
80 } 74 }
81 public static Vector3 operator *(float f, Vector3 v) 75
76
77 public override bool Equals(object o)
82 { 78 {
83 v.x = v.x * f; 79 if (!(o is Vector3)) return false;
84 v.y = v.y * f; 80
85 v.z = v.z * f; 81 Vector3 vector = (Vector3)o;
86 return v; 82
83 return (x == vector.x && x == vector.x && z == vector.z);
87 } 84 }
88 public static Vector3 operator *(Vector3 v1, Vector3 v2) 85
86 #endregion
87
88 #region Vector & Vector Math
89 // Vector-Vector Math
90 public static Vector3 operator +(Vector3 lhs, Vector3 rhs)
89 { 91 {
90 v1.x = v1.x * v2.x; 92 return new Vector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z);
91 v1.y = v1.y * v2.y; 93 }
92 v1.z = v1.z * v2.z; 94 public static Vector3 operator -(Vector3 lhs, Vector3 rhs)
93 return v1;
94 }
95 public static Vector3 operator +(Vector3 v1, Vector3 v2)
96 { 95 {
97 v1.x = v1.x + v2.x; 96 return new Vector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z);
98 v1.y = v1.y + v2.y;
99 v1.z = v1.z + v2.z;
100 return v1;
101 } 97 }
102 public static Vector3 operator -(Vector3 v1, Vector3 v2) 98 public static Vector3 operator *(Vector3 lhs, Vector3 rhs)
103 { 99 {
104 v1.x = v1.x - v2.x; 100 return new Vector3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z);
105 v1.y = v1.y - v2.y;
106 v1.z = v1.z - v2.z;
107 return v1;
108 } 101 }
102
109 public static Vector3 operator %(Vector3 v1, Vector3 v2) 103 public static Vector3 operator %(Vector3 v1, Vector3 v2)
110 { 104 {
111 //Cross product 105 //Cross product
@@ -115,6 +109,79 @@ namespace OpenSim.Region.ScriptEngine.Common
115 tv.z = (v1.x * v2.y) - (v1.y * v2.x); 109 tv.z = (v1.x * v2.y) - (v1.y * v2.x);
116 return tv; 110 return tv;
117 } 111 }
112
113 #endregion
114
115 #region Vector & Float Math
116 // Vector-Float and Float-Vector Math
117 public static Vector3 operator *(Vector3 vec, float val)
118 {
119 return new Vector3(vec.x * val, vec.y * val, vec.z * val);
120 }
121
122 public static Vector3 operator *(float val, Vector3 vec)
123 {
124 return new Vector3(vec.x * val, vec.y * val, vec.z * val);
125 }
126
127 public static Vector3 operator /(Vector3 v, float f)
128 {
129 v.x = v.x / f;
130 v.y = v.y / f;
131 v.z = v.z / f;
132 return v;
133 }
134
135 #endregion
136
137 #region Vector & Rotation Math
138 // Vector-Rotation Math
139 public static Vector3 operator *(Vector3 v, Quaternion r)
140 {
141 Quaternion vq = new Quaternion(v.x, v.y, v.z, 0);
142 Quaternion nq = new Quaternion(-r.x, -r.y, -r.z, r.s);
143
144 Quaternion result = (r * vq) * nq;
145
146 return new Vector3(result.x, result.y, result.z);
147 }
148 // I *think* this is how it works....
149 public static Vector3 operator /(Vector3 vec, Quaternion quat)
150 {
151 quat.s = -quat.s;
152 Quaternion vq = new Quaternion(vec.x, vec.y, vec.z, 0);
153 Quaternion nq = new Quaternion(-quat.x, -quat.y, -quat.z, quat.s);
154
155 Quaternion result = (quat * vq) * nq;
156
157 return new Vector3(result.x, result.y, result.z);
158 }
159 #endregion
160
161 #region Static Helper Functions
162 public static double Dot(Vector3 v1, Vector3 v2)
163 {
164 return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
165 }
166 public static Vector3 Cross(Vector3 v1, Vector3 v2)
167 {
168 return new Vector3
169 (
170 v1.y * v2.z - v1.z * v2.y,
171 v1.z * v2.x - v1.x * v2.z,
172 v1.x * v2.y - v1.y * v2.x
173 );
174 }
175 public static float Mag(Vector3 v)
176 {
177 return (float)Math.Sqrt(v.x * v.y + v.y * v.y + v.z * v.z);
178 }
179 public static Vector3 Norm(Vector3 vector)
180 {
181 float mag = Mag(vector);
182 return new Vector3(vector.x / mag, vector.y / mag, vector.z / mag);
183 }
184 #endregion
118 } 185 }
119 186
120 [Serializable] 187 [Serializable]
@@ -123,26 +190,66 @@ namespace OpenSim.Region.ScriptEngine.Common
123 public double x; 190 public double x;
124 public double y; 191 public double y;
125 public double z; 192 public double z;
126 public double r; 193 public double s;
127 194
128 public Quaternion(Quaternion Quat) 195 public Quaternion(Quaternion Quat)
129 { 196 {
130 x = (float) Quat.x; 197 x = (float) Quat.x;
131 y = (float) Quat.y; 198 y = (float) Quat.y;
132 z = (float) Quat.z; 199 z = (float) Quat.z;
133 r = (float) Quat.r; 200 s = (float) Quat.s;
134 } 201 }
135 202
136 public Quaternion(double X, double Y, double Z, double R) 203 public Quaternion(double X, double Y, double Z, double S)
137 { 204 {
138 x = X; 205 x = X;
139 y = Y; 206 y = Y;
140 z = Z; 207 z = Z;
141 r = R; 208 s = S;
142 } 209 }
143 public string ToString() 210
211 #region Overriders
212
213 public override int GetHashCode()
214 {
215 return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ s.GetHashCode());
216 }
217
218
219 public override bool Equals(object o)
220 {
221 if (!(o is Quaternion)) return false;
222
223 Quaternion quaternion = (Quaternion)o;
224
225 return x == quaternion.x && y == quaternion.y && z == quaternion.z && s == quaternion.s;
226 }
227 public override string ToString()
228 {
229 return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ", " + s.ToString() + ">";
230 }
231
232 public static bool operator ==(Quaternion lhs, Quaternion rhs)
233 {
234 // Return true if the fields match:
235 return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.s == rhs.s;
236 }
237
238 public static bool operator !=(Quaternion lhs, Quaternion rhs)
239 {
240 return !(lhs == rhs);
241 }
242
243 #endregion
244
245 public static Quaternion operator *(Quaternion a, Quaternion b)
144 { 246 {
145 return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ", " + r.ToString() + ">"; 247 Quaternion c;
248 c.x = a.s * b.x + a.x * b.s + a.y * b.z - a.z * b.y;
249 c.y = a.s * b.y + a.y * b.s + a.z * b.x - a.x * b.z;
250 c.z = a.s * b.z + a.z * b.s + a.x * b.y - a.y * b.x;
251 c.s = a.s * b.s - a.x * b.x - a.y * b.y - a.z * b.z;
252 return c;
146 } 253 }
147 } 254 }
148 } 255 }
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs
index d9ebd14..00ddbba 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
47 dataTypes.Add("key", "string"); 47 dataTypes.Add("key", "string");
48 dataTypes.Add("vector", "LSL_Types.Vector3"); 48 dataTypes.Add("vector", "LSL_Types.Vector3");
49 dataTypes.Add("rotation", "LSL_Types.Quaternion"); 49 dataTypes.Add("rotation", "LSL_Types.Quaternion");
50 dataTypes.Add("list", "List"); 50 dataTypes.Add("list", "List<string>");
51 dataTypes.Add("null", "null"); 51 dataTypes.Add("null", "null");
52 } 52 }
53 53
@@ -203,7 +203,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
203 //Console.WriteLine("Replacing using statename: " + current_statename); 203 //Console.WriteLine("Replacing using statename: " + current_statename);
204 cache = 204 cache =
205 Regex.Replace(cache, 205 Regex.Replace(cache,
206 @"^(\s*)((?!(if|switch|for)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", 206 @"^(\s*)((?!(if|switch|for|while)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)",
207 @"$1public " + current_statename + "_event_$2", 207 @"$1public " + current_statename + "_event_$2",
208 RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); 208 RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
209 } 209 }
@@ -236,7 +236,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
236 RegexOptions.Compiled | RegexOptions.Multiline); 236 RegexOptions.Compiled | RegexOptions.Multiline);
237 // Replace return types and function variables - integer a() and f(integer a, integer a) 237 // Replace return types and function variables - integer a() and f(integer a, integer a)
238 Script = 238 Script =
239 Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)", @"$1$2" + val + "$3", 239 Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s+)", @"$1$2" + val + "$3",
240 RegexOptions.Compiled | RegexOptions.Multiline);
241 Script =
242 Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)[,]", @"$1$2" + val + "$3,",
240 RegexOptions.Compiled | RegexOptions.Multiline); 243 RegexOptions.Compiled | RegexOptions.Multiline);
241 } 244 }
242 245
@@ -281,7 +284,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
281 // Add namespace, class name and inheritance 284 // Add namespace, class name and inheritance
282 285
283 Return = "" + 286 Return = "" +
284 "using OpenSim.Region.ScriptEngine.Common;"; 287 "using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic;";
285 //"using System; " + 288 //"using System; " +
286 //"using System.Collections.Generic; " + 289 //"using System.Collections.Generic; " +
287 //"using System.Text; " + 290 //"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 8563694..00e79c0 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
191 public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r) 191 public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r)
192 { 192 {
193 //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke 193 //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke
194 LSL_Types.Quaternion t = new LSL_Types.Quaternion(r.x*r.x, r.y*r.y, r.z*r.z, r.r*r.r); 194 LSL_Types.Quaternion t = new LSL_Types.Quaternion(r.x*r.x, r.y*r.y, r.z*r.z, r.s*r.s);
195 double m = (t.x + t.y + t.z + t.r); 195 double m = (t.x + t.y + t.z + t.s);
196 if (m == 0) return new LSL_Types.Vector3(); 196 if (m == 0) return new LSL_Types.Vector3();
197 double n = 2*(r.y*r.r + r.x*r.z); 197 double n = 2*(r.y*r.s + r.x*r.z);
198 double p = m*m - n*n; 198 double p = m*m - n*n;
199 if (p > 0) 199 if (p > 0)
200 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)), 200 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)),
201 Math.Atan2(n, Math.Sqrt(p)), 201 Math.Atan2(n, Math.Sqrt(p)),
202 Math.Atan2(2.0*(r.z*r.r - r.x*r.y), (t.x - t.y - t.z + t.r))); 202 Math.Atan2(2.0*(r.z*r.s - r.x*r.y), (t.x - t.y - t.z + t.s)));
203 else if (n > 0) 203 else if (n > 0)
204 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)); 204 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));
205 else 205 else
206 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)); 206 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));
207 } 207 }
208 208
209 public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v) 209 public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v)
@@ -219,6 +219,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
219 LSL_Types.Quaternion a1 = new LSL_Types.Quaternion(0.0, 0.0, cz, cw); 219 LSL_Types.Quaternion a1 = new LSL_Types.Quaternion(0.0, 0.0, cz, cw);
220 LSL_Types.Quaternion a2 = new LSL_Types.Quaternion(0.0, by, 0.0, bw); 220 LSL_Types.Quaternion a2 = new LSL_Types.Quaternion(0.0, by, 0.0, bw);
221 LSL_Types.Quaternion a3 = new LSL_Types.Quaternion(ax, 0.0, 0.0, aw); 221 LSL_Types.Quaternion a3 = new LSL_Types.Quaternion(ax, 0.0, 0.0, aw);
222 LSL_Types.Quaternion a = (a1 * a2) * a3;
222 //This multiplication doesnt compile, yet. a = a1 * a2 * a3; 223 //This multiplication doesnt compile, yet. a = a1 * a2 * a3;
223 LSL_Types.Quaternion b = new LSL_Types.Quaternion(ax*bw*cw + aw*by*cz, 224 LSL_Types.Quaternion b = new LSL_Types.Quaternion(ax*bw*cw + aw*by*cz,
224 aw*by*cw - ax*bw*cz, aw*bw*cz + ax*by*cw, 225 aw*by*cw - ax*bw*cz, aw*bw*cz + ax*by*cw,
@@ -230,13 +231,14 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
230 if ((Math.Abs(c.x) > err && Math.Abs(d.x) > err) || 231 if ((Math.Abs(c.x) > err && Math.Abs(d.x) > err) ||
231 (Math.Abs(c.y) > err && Math.Abs(d.y) > err) || 232 (Math.Abs(c.y) > err && Math.Abs(d.y) > err) ||
232 (Math.Abs(c.z) > err && Math.Abs(d.z) > err) || 233 (Math.Abs(c.z) > err && Math.Abs(d.z) > err) ||
233 (Math.Abs(c.r) > err && Math.Abs(d.r) > err)) 234 (Math.Abs(c.s) > err && Math.Abs(d.s) > err))
234 { 235 {
236 return b;
235 //return a new Quaternion that is null until I figure this out 237 //return a new Quaternion that is null until I figure this out
236 // return b; 238 // return b;
237 // return a; 239 // return a;
238 } 240 }
239 return new LSL_Types.Quaternion(); 241 return a;
240 } 242 }
241 243
242 public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up) 244 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
258 { 260 {
259 return new LSL_Types.Vector3(); 261 return new LSL_Types.Vector3();
260 } 262 }
261 263 public LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 a, LSL_Types.Vector3 b)
262 public LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 start, LSL_Types.Vector3 end)
263 { 264 {
264 return new LSL_Types.Quaternion(); 265 //A and B should both be normalized
265 }
266 266
267 double dotProduct = LSL_Types.Vector3.Dot(a, b);
268 LSL_Types.Vector3 crossProduct = LSL_Types.Vector3.Cross(a, b);
269 double magProduct = LSL_Types.Vector3.Mag(a) * LSL_Types.Vector3.Mag(b);
270 double angle = Math.Acos(dotProduct / magProduct);
271 LSL_Types.Vector3 axis = LSL_Types.Vector3.Norm(crossProduct);
272 double s = Math.Sin(angle / 2);
273
274 return new LSL_Types.Quaternion(axis.x * s, axis.y * s, axis.z * s, (float)Math.Cos(angle / 2));
275 }
267 public void llWhisper(int channelID, string text) 276 public void llWhisper(int channelID, string text)
268 { 277 {
269 World.SimChat(Helpers.StringToField(text), 278 World.SimChat(Helpers.StringToField(text),
@@ -629,7 +638,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
629 } 638 }
630 if (face == -1) 639 if (face == -1)
631 { 640 {
632 LLObject.TextureEntryFace texface;
633 for (int i = 0; i < 32; i++) 641 for (int i = 0; i < 32; i++)
634 { 642 {
635 if (tex.FaceTextures[i] != null) 643 if (tex.FaceTextures[i] != null)
@@ -729,7 +737,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
729 737
730 public void llSetRot(LSL_Types.Quaternion rot) 738 public void llSetRot(LSL_Types.Quaternion rot)
731 { 739 {
732 m_host.UpdateRotation(new LLQuaternion((float) rot.x, (float) rot.y, (float) rot.z, (float) rot.r)); 740 m_host.UpdateRotation(new LLQuaternion((float) rot.x, (float) rot.y, (float) rot.z, (float) rot.s));
733 } 741 }
734 742
735 public LSL_Types.Quaternion llGetRot() 743 public LSL_Types.Quaternion llGetRot()
@@ -1778,7 +1786,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
1778 1786
1779 public double llGetRegionTimeDilation() 1787 public double llGetRegionTimeDilation()
1780 { 1788 {
1781 return 1.0f; 1789 return (double)World.TimeDilation;
1782 } 1790 }
1783 1791
1784 public double llGetRegionFPS() 1792 public double llGetRegionFPS()