OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
LSL_ApiTest.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System.Collections.Generic;
29 using NUnit.Framework;
30 using OpenSim.Framework;
31 using OpenSim.Tests.Common;
32 using OpenSim.Region.ScriptEngine.Shared;
33 using OpenSim.Region.Framework.Scenes;
34 using Nini.Config;
35 using OpenSim.Region.ScriptEngine.Shared.Api;
36 using OpenSim.Region.ScriptEngine.Shared.Instance;
37 using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
38 using OpenMetaverse;
39 using System;
40 
41 namespace OpenSim.Region.ScriptEngine.Shared.Tests
42 {
46  [TestFixture, LongRunning]
47  public class LSL_ApiTest
48  {
49  private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
50  private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
51  private LSL_Api m_lslApi;
52 
53  [SetUp]
54  public void SetUp()
55  {
56  IConfigSource initConfigSource = new IniConfigSource();
57  IConfig config = initConfigSource.AddConfig("XEngine");
58  config.Set("Enabled", "true");
59 
60  Scene scene = new SceneHelpers().SetupScene();
61  SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart;
62 
63  XEngine.XEngine engine = new XEngine.XEngine();
64  engine.Initialise(initConfigSource);
65  engine.AddRegion(scene);
66 
67  m_lslApi = new LSL_Api();
68  m_lslApi.Initialize(engine, part, null);
69  }
70 
71  [Test]
72  public void TestllAngleBetween()
73  {
74  TestHelpers.InMethod();
75 
76  CheckllAngleBetween(new Vector3(1, 0, 0), 0, 1, 1);
77  CheckllAngleBetween(new Vector3(1, 0, 0), 90, 1, 1);
78  CheckllAngleBetween(new Vector3(1, 0, 0), 180, 1, 1);
79 
80  CheckllAngleBetween(new Vector3(0, 1, 0), 0, 1, 1);
81  CheckllAngleBetween(new Vector3(0, 1, 0), 90, 1, 1);
82  CheckllAngleBetween(new Vector3(0, 1, 0), 180, 1, 1);
83 
84  CheckllAngleBetween(new Vector3(0, 0, 1), 0, 1, 1);
85  CheckllAngleBetween(new Vector3(0, 0, 1), 90, 1, 1);
86  CheckllAngleBetween(new Vector3(0, 0, 1), 180, 1, 1);
87 
88  CheckllAngleBetween(new Vector3(1, 1, 1), 0, 1, 1);
89  CheckllAngleBetween(new Vector3(1, 1, 1), 90, 1, 1);
90  CheckllAngleBetween(new Vector3(1, 1, 1), 180, 1, 1);
91 
92  CheckllAngleBetween(new Vector3(1, 0, 0), 0, 1.6f, 1.8f);
93  CheckllAngleBetween(new Vector3(1, 0, 0), 90, 0.3f, 3.9f);
94  CheckllAngleBetween(new Vector3(1, 0, 0), 180, 8.8f, 7.4f);
95 
96  CheckllAngleBetween(new Vector3(0, 1, 0), 0, 9.8f, -9.4f);
97  CheckllAngleBetween(new Vector3(0, 1, 0), 90, 8.4f, -8.2f);
98  CheckllAngleBetween(new Vector3(0, 1, 0), 180, 0.4f, -5.8f);
99 
100  CheckllAngleBetween(new Vector3(0, 0, 1), 0, -6.8f, 3.4f);
101  CheckllAngleBetween(new Vector3(0, 0, 1), 90, -3.6f, 5.6f);
102  CheckllAngleBetween(new Vector3(0, 0, 1), 180, -3.8f, 1.1f);
103 
104  CheckllAngleBetween(new Vector3(1, 1, 1), 0, -7.7f, -2.0f);
105  CheckllAngleBetween(new Vector3(1, 1, 1), 90, -3.0f, -9.1f);
106  CheckllAngleBetween(new Vector3(1, 1, 1), 180, -7.9f, -8.0f);
107  }
108 
109  private void CheckllAngleBetween(Vector3 axis,float originalAngle, float denorm1, float denorm2)
110  {
111  Quaternion rotation1 = Quaternion.CreateFromAxisAngle(axis, 0);
112  Quaternion rotation2 = Quaternion.CreateFromAxisAngle(axis, ToRadians(originalAngle));
113  rotation1 *= denorm1;
114  rotation2 *= denorm2;
115 
116  double deducedAngle = FromLslFloat(m_lslApi.llAngleBetween(ToLslQuaternion(rotation2), ToLslQuaternion(rotation1)));
117 
118  Assert.That(deducedAngle, Is.EqualTo(ToRadians(originalAngle)).Within(ANGLE_ACCURACY_IN_RADIANS), "TestllAngleBetween check fail");
119  }
120 
121  #region Conversions to and from LSL_Types
122 
123  private float ToRadians(double degrees)
124  {
125  return (float)(Math.PI * degrees / 180);
126  }
127 
128  // private double FromRadians(float radians)
129  // {
130  // return radians * 180 / Math.PI;
131  // }
132 
133  private double FromLslFloat(LSL_Types.LSLFloat lslFloat)
134  {
135  return lslFloat.value;
136  }
137 
138  // private LSL_Types.LSLFloat ToLslFloat(double value)
139  // {
140  // return new LSL_Types.LSLFloat(value);
141  // }
142 
143  // private Quaternion FromLslQuaternion(LSL_Types.Quaternion lslQuaternion)
144  // {
145  // return new Quaternion((float)lslQuaternion.x, (float)lslQuaternion.y, (float)lslQuaternion.z, (float)lslQuaternion.s);
146  // }
147 
148  private LSL_Types.Quaternion ToLslQuaternion(Quaternion quaternion)
149  {
150  return new LSL_Types.Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
151  }
152 
153  #endregion
154 
155  [Test]
156  // llRot2Euler test.
157  public void TestllRot2Euler()
158  {
159  TestHelpers.InMethod();
160 
161  // 180, 90 and zero degree rotations.
162  CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 0.0f, 1.0f));
163  CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 0.707107f, 0.707107f));
164  CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 1.0f, 0.0f));
165  CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 0.707107f, -0.707107f));
166  CheckllRot2Euler(new LSL_Types.Quaternion(0.707107f, 0.0f, 0.0f, 0.707107f));
167  CheckllRot2Euler(new LSL_Types.Quaternion(0.5f, -0.5f, 0.5f, 0.5f));
168  CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, 0.707107f, 0.0f));
169  CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, 0.5f, -0.5f));
170  CheckllRot2Euler(new LSL_Types.Quaternion(1.0f, 0.0f, 0.0f, 0.0f));
171  CheckllRot2Euler(new LSL_Types.Quaternion(0.707107f, -0.707107f, 0.0f, 0.0f));
172  CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -1.0f, 0.0f, 0.0f));
173  CheckllRot2Euler(new LSL_Types.Quaternion(-0.707107f, -0.707107f, 0.0f, 0.0f));
174  CheckllRot2Euler(new LSL_Types.Quaternion(0.707107f, 0.0f, 0.0f, -0.707107f));
175  CheckllRot2Euler(new LSL_Types.Quaternion(0.5f, -0.5f, -0.5f, -0.5f));
176  CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, -0.707107f, 0.0f));
177  CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, -0.5f, 0.5f));
178  CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, 0.0f, 0.707107f));
179  CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, 0.5f, 0.5f));
180  CheckllRot2Euler(new LSL_Types.Quaternion(-0.707107f, 0.0f, 0.707107f, 0.0f));
181  CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, 0.5f, 0.5f, -0.5f));
182  CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, 0.0f, -0.707107f));
183  CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, -0.5f, -0.5f));
184  CheckllRot2Euler(new LSL_Types.Quaternion(-0.707107f, 0.0f, -0.707107f, 0.0f));
185  CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, 0.5f, -0.5f, 0.5f));
186 
187  // A couple of messy rotations.
188  CheckllRot2Euler(new LSL_Types.Quaternion(1.0f, 5.651f, -3.1f, 67.023f));
189  CheckllRot2Euler(new LSL_Types.Quaternion(0.719188f, -0.408934f, -0.363998f, -0.427841f));
190 
191  // Some deliberately malicious rotations (intended on provoking singularity errors)
192  // The "f" suffexes are deliberately omitted.
193  CheckllRot2Euler(new LSL_Types.Quaternion(0.50001f, 0.50001f, 0.50001f, 0.50001f));
194  // More malice. The "f" suffixes are deliberately omitted.
195  CheckllRot2Euler(new LSL_Types.Quaternion(-0.701055, 0.092296, 0.701055, -0.092296));
196  CheckllRot2Euler(new LSL_Types.Quaternion(-0.183005, -0.683010, 0.183005, 0.683010));
197  CheckllRot2Euler(new LSL_Types.Quaternion(-0.430460, -0.560982, 0.430460, 0.560982));
198  CheckllRot2Euler(new LSL_Types.Quaternion(-0.701066, 0.092301, -0.701066, 0.092301));
199  CheckllRot2Euler(new LSL_Types.Quaternion(-0.183013, -0.683010, 0.183013, 0.683010));
200  CheckllRot2Euler(new LSL_Types.Quaternion(-0.183005, -0.683014, -0.183005, -0.683014));
201  CheckllRot2Euler(new LSL_Types.Quaternion(-0.353556, 0.612375, 0.353556, -0.612375));
202  CheckllRot2Euler(new LSL_Types.Quaternion(0.353554, -0.612385, -0.353554, 0.612385));
203  CheckllRot2Euler(new LSL_Types.Quaternion(-0.560989, 0.430450, 0.560989, -0.430450));
204  CheckllRot2Euler(new LSL_Types.Quaternion(-0.183013, 0.683009, -0.183013, 0.683009));
205  CheckllRot2Euler(new LSL_Types.Quaternion(0.430457, -0.560985, -0.430457, 0.560985));
206  CheckllRot2Euler(new LSL_Types.Quaternion(0.353552, 0.612360, -0.353552, -0.612360));
207  CheckllRot2Euler(new LSL_Types.Quaternion(-0.499991, 0.500003, 0.499991, -0.500003));
208  CheckllRot2Euler(new LSL_Types.Quaternion(-0.353555, -0.612385, -0.353555, -0.612385));
209  CheckllRot2Euler(new LSL_Types.Quaternion(0.701066, -0.092301, -0.701066, 0.092301));
210  CheckllRot2Euler(new LSL_Types.Quaternion(-0.499991, 0.500007, 0.499991, -0.500007));
211  CheckllRot2Euler(new LSL_Types.Quaternion(-0.683002, 0.183016, -0.683002, 0.183016));
212  CheckllRot2Euler(new LSL_Types.Quaternion(0.430458, 0.560982, 0.430458, 0.560982));
213  CheckllRot2Euler(new LSL_Types.Quaternion(0.499991, -0.500003, -0.499991, 0.500003));
214  CheckllRot2Euler(new LSL_Types.Quaternion(-0.183009, 0.683011, -0.183009, 0.683011));
215  CheckllRot2Euler(new LSL_Types.Quaternion(0.560975, -0.430457, 0.560975, -0.430457));
216  CheckllRot2Euler(new LSL_Types.Quaternion(0.701055, 0.092300, 0.701055, 0.092300));
217  CheckllRot2Euler(new LSL_Types.Quaternion(-0.560990, 0.430459, -0.560990, 0.430459));
218  CheckllRot2Euler(new LSL_Types.Quaternion(-0.092302, -0.701059, -0.092302, -0.701059));
219  }
220 
241  private void CheckllRot2Euler(LSL_Types.Quaternion rot)
242  {
243  // Call LSL function to convert quaternion rotaion to euler radians.
244  LSL_Types.Vector3 eulerCalc = m_lslApi.llRot2Euler(rot);
245  // Now use the euler radians to recalculate a new quaternion rotation
246  LSL_Types.Quaternion newRot = m_lslApi.llEuler2Rot(eulerCalc);
247  // Multiple original quaternion by conjugate of quaternion calculated with angles.
248  LSL_Types.Quaternion check = rot * new LSL_Types.Quaternion(-newRot.x, -newRot.y, -newRot.z, newRot.s);
249 
250  Assert.AreEqual(0.0, check.x, VECTOR_COMPONENT_ACCURACY, "TestllRot2Euler X bounds check fail");
251  Assert.AreEqual(0.0, check.y, VECTOR_COMPONENT_ACCURACY, "TestllRot2Euler Y bounds check fail");
252  Assert.AreEqual(0.0, check.z, VECTOR_COMPONENT_ACCURACY, "TestllRot2Euler Z bounds check fail");
253  }
254 
255  [Test]
256  public void TestllVecNorm()
257  {
258  TestHelpers.InMethod();
259 
260  // Check special case for normalizing zero vector.
261  CheckllVecNorm(new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), new LSL_Types.Vector3(0.0d, 0.0d, 0.0d));
262  // Check various vectors.
263  CheckllVecNorm(new LSL_Types.Vector3(10.0d, 25.0d, 0.0d), new LSL_Types.Vector3(0.371391d, 0.928477d, 0.0d));
264  CheckllVecNorm(new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), new LSL_Types.Vector3(1.0d, 0.0d, 0.0d));
265  CheckllVecNorm(new LSL_Types.Vector3(-90.0d, 55.0d, 2.0d), new LSL_Types.Vector3(-0.853128d, 0.521356d, 0.018958d));
266  CheckllVecNorm(new LSL_Types.Vector3(255.0d, 255.0d, 255.0d), new LSL_Types.Vector3(0.577350d, 0.577350d, 0.577350d));
267  }
268 
269  public void CheckllVecNorm(LSL_Types.Vector3 vec, LSL_Types.Vector3 vecNormCheck)
270  {
271  // Call LSL function to normalize the vector.
272  LSL_Types.Vector3 vecNorm = m_lslApi.llVecNorm(vec);
273  // Check each vector component against expected result.
274  Assert.AreEqual(vecNorm.x, vecNormCheck.x, VECTOR_COMPONENT_ACCURACY, "TestllVecNorm vector check fail on x component");
275  Assert.AreEqual(vecNorm.y, vecNormCheck.y, VECTOR_COMPONENT_ACCURACY, "TestllVecNorm vector check fail on y component");
276  Assert.AreEqual(vecNorm.z, vecNormCheck.z, VECTOR_COMPONENT_ACCURACY, "TestllVecNorm vector check fail on z component");
277  }
278  }
279 }
Contains all LSL ll-functions. This class will be in Default AppDomain.
Definition: LSL_Api.cs:95
void CheckllVecNorm(LSL_Types.Vector3 vec, LSL_Types.Vector3 vecNormCheck)
Definition: LSL_ApiTest.cs:269
Helpers for setting up scenes.
Definition: SceneHelpers.cs:60