aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/test
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:42 -0500
committerJacek Antonelli2008-08-15 23:45:42 -0500
commitce28e056c20bf2723f565bbf464b87781ec248a2 (patch)
treeef7b0501c4de4b631a916305cbc2a5fdc125e52d /linden/indra/test
parentSecond Life viewer sources 1.19.1.4b (diff)
downloadmeta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.zip
meta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.tar.gz
meta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.tar.bz2
meta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.tar.xz
Second Life viewer sources 1.20.2
Diffstat (limited to 'linden/indra/test')
-rw-r--r--linden/indra/test/files.lst2
-rw-r--r--linden/indra/test/inventory.cpp4
-rw-r--r--linden/indra/test/io.cpp2
-rw-r--r--linden/indra/test/llcontrol_tut.cpp147
-rw-r--r--linden/indra/test/llmessageconfig_tut.cpp24
-rw-r--r--linden/indra/test/llmessagetemplateparser_tut.cpp2
-rw-r--r--linden/indra/test/llnamevalue_tut.cpp550
-rwxr-xr-xlinden/indra/test/llsdmessagereader_tut.cpp2
-rw-r--r--linden/indra/test/llstreamtools_tut.cpp42
-rw-r--r--linden/indra/test/lltemplatemessagebuilder_tut.cpp2
-rw-r--r--linden/indra/test/lltut.h10
-rw-r--r--linden/indra/test/mass_properties_tut.cpp1008
-rw-r--r--linden/indra/test/math.cpp442
-rw-r--r--linden/indra/test/message_tut.cpp2
-rw-r--r--linden/indra/test/prim_linkability_tut.cpp490
-rw-r--r--linden/indra/test/test.vcproj19
-rw-r--r--linden/indra/test/test_vc8.vcproj6
-rw-r--r--linden/indra/test/test_vc9.vcproj2
18 files changed, 2198 insertions, 558 deletions
diff --git a/linden/indra/test/files.lst b/linden/indra/test/files.lst
index d923d8f..b335dbf 100644
--- a/linden/indra/test/files.lst
+++ b/linden/indra/test/files.lst
@@ -5,6 +5,7 @@ test/llapp_tut.cpp
5test/llbase64_tut.cpp 5test/llbase64_tut.cpp
6test/llblowfish_tut.cpp 6test/llblowfish_tut.cpp
7test/llbuffer_tut.cpp 7test/llbuffer_tut.cpp
8test/llcontrol_tut.cpp
8test/lldate_tut.cpp 9test/lldate_tut.cpp
9test/llerror_tut.cpp 10test/llerror_tut.cpp
10test/llhost_tut.cpp 11test/llhost_tut.cpp
@@ -38,6 +39,7 @@ test/lluuidhashmap_tut.cpp
38test/llxfer_tut.cpp 39test/llxfer_tut.cpp
39test/math.cpp 40test/math.cpp
40test/message_tut.cpp 41test/message_tut.cpp
42test/prim_linkability_tut.cpp
41test/reflection_tut.cpp 43test/reflection_tut.cpp
42test/test.cpp 44test/test.cpp
43test/v2math_tut.cpp 45test/v2math_tut.cpp
diff --git a/linden/indra/test/inventory.cpp b/linden/indra/test/inventory.cpp
index 7c81dbe..3899dfc 100644
--- a/linden/indra/test/inventory.cpp
+++ b/linden/indra/test/inventory.cpp
@@ -453,9 +453,7 @@ namespace tut
453 ensure_equals("9.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice()); 453 ensure_equals("9.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
454 ensure_equals("10.name::getName() failed", src1->getName(), src2->getName()); 454 ensure_equals("10.name::getName() failed", src1->getName(), src2->getName());
455 ensure_equals("11.description::getDescription() failed", src1->getDescription(), src2->getDescription()); 455 ensure_equals("11.description::getDescription() failed", src1->getDescription(), src2->getDescription());
456 456 //skip_fail("12.creation::getCreationDate()");
457
458 skip_fail("12.creation::getCreationDate()");
459 ensure_equals("12.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate()); 457 ensure_equals("12.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
460 } 458 }
461 459
diff --git a/linden/indra/test/io.cpp b/linden/indra/test/io.cpp
index fe8c19d..408b7c8 100644
--- a/linden/indra/test/io.cpp
+++ b/linden/indra/test/io.cpp
@@ -1151,7 +1151,7 @@ namespace tut
1151 chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi"))); 1151 chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
1152 chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client))); 1152 chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
1153 chain.push_back(LLIOPipe::ptr_t(new LLIONull)); 1153 chain.push_back(LLIOPipe::ptr_t(new LLIONull));
1154 mPump->addChain(chain, 0.2); 1154 mPump->addChain(chain, 0.2f);
1155 chain.clear(); 1155 chain.clear();
1156 1156
1157 // pump for a bit and make sure all 3 chains are running 1157 // pump for a bit and make sure all 3 chains are running
diff --git a/linden/indra/test/llcontrol_tut.cpp b/linden/indra/test/llcontrol_tut.cpp
new file mode 100644
index 0000000..aabe205
--- /dev/null
+++ b/linden/indra/test/llcontrol_tut.cpp
@@ -0,0 +1,147 @@
1/**
2 * @file llcontrol_tut.cpp
3 * @date February 2008
4 * @brief control group unit tests
5 *
6 * $LicenseInfo:firstyear=2008&license=viewergpl$
7 *
8 * Copyright (c) 2008, Linden Research, Inc.
9 *
10 * Second Life Viewer Source Code
11 * The source code in this file ("Source Code") is provided by Linden Lab
12 * to you under the terms of the GNU General Public License, version 2.0
13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
17 *
18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 *
23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above,
25 * and agree to abide by those obligations.
26 *
27 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
28 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
29 * COMPLETENESS OR PERFORMANCE.
30 * $/LicenseInfo$
31 */
32
33#include "linden_common.h"
34
35#include <tut/tut.h>
36#include "lltut.h"
37
38#include "llcontrol.h"
39#include "llsdserialize.h"
40
41namespace tut
42{
43
44 struct control_group
45 {
46 LLControlGroup* mCG;
47 LLString mTestConfigDir;
48 LLString mTestConfigFile;
49 static bool mListenerFired;
50 control_group()
51 {
52 mCG = new LLControlGroup;
53 LLUUID random;
54 random.generate();
55 // generate temp dir
56 std::ostringstream oStr;
57 oStr << "/tmp/llcontrol-test-" << random << "/";
58 mTestConfigDir = oStr.str();
59 mTestConfigFile = mTestConfigDir + "settings.xml";
60 LLFile::mkdir(mTestConfigDir.c_str());
61 LLSD config;
62 config["TestSetting"]["Comment"] = "Dummy setting used for testing";
63 config["TestSetting"]["Persist"] = 1;
64 config["TestSetting"]["Type"] = "U32";
65 config["TestSetting"]["Value"] = 12;
66 writeSettingsFile(config);
67 }
68 ~control_group()
69 {
70 //Remove test files
71 delete mCG;
72 }
73 void writeSettingsFile(const LLSD& config)
74 {
75 llofstream file(mTestConfigFile.c_str());
76 if (file.is_open())
77 {
78 LLSDSerialize::toPrettyXML(config, file);
79 }
80 file.close();
81 }
82 static bool handleListenerTest(const LLSD& newvalue)
83 {
84 control_group::mListenerFired = true;
85 return true;
86 }
87 };
88
89 bool control_group::mListenerFired = false;
90
91 typedef test_group<control_group> control_group_test;
92 typedef control_group_test::object control_group_t;
93 control_group_test tut_control_group("control_group");
94
95 //load settings from files - LLSD
96 template<> template<>
97 void control_group_t::test<1>()
98 {
99 int results = mCG->loadFromFile(mTestConfigFile.c_str());
100 ensure("number of settings", (results == 1));
101 ensure("value of setting", (mCG->getU32("TestSetting") == 12));
102 }
103
104 //save settings to files
105 template<> template<>
106 void control_group_t::test<2>()
107 {
108 int results = mCG->loadFromFile(mTestConfigFile.c_str());
109 mCG->setU32("TestSetting", 13);
110 ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13);
111 LLControlGroup test_cg;
112 LLString temp_test_file = (mTestConfigDir + "setting_llsd_temp.xml");
113 mCG->saveToFile(temp_test_file.c_str(), TRUE);
114 results = test_cg.loadFromFile(temp_test_file.c_str());
115 ensure("number of changed settings loaded", (results == 1));
116 ensure("value of changed settings loaded", (test_cg.getU32("TestSetting") == 13));
117 }
118
119 //priorities
120 template<> template<>
121 void control_group_t::test<3>()
122 {
123 int results = mCG->loadFromFile(mTestConfigFile.c_str());
124 LLControlVariable* control = mCG->getControl("TestSetting");
125 LLSD new_value = 13;
126 control->setValue(new_value, FALSE);
127 ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13);
128 LLControlGroup test_cg;
129 LLString temp_test_file = (mTestConfigDir + "setting_llsd_persist_temp.xml");
130 mCG->saveToFile(temp_test_file.c_str(), TRUE);
131 results = test_cg.loadFromFile(temp_test_file.c_str());
132 //If we haven't changed any settings, then we shouldn't have any settings to load
133 ensure("number of non-persisted changed settings loaded", (results == 0));
134 }
135
136 //listeners
137 template<> template<>
138 void control_group_t::test<4>()
139 {
140 int results = mCG->loadFromFile(mTestConfigFile.c_str());
141 ensure("number of settings", (results == 1));
142 mCG->getControl("TestSetting")->getSignal()->connect(boost::bind(&this->handleListenerTest, _1));
143 mCG->setU32("TestSetting", 13);
144 ensure("listener fired on changed setting", mListenerFired);
145 }
146
147}
diff --git a/linden/indra/test/llmessageconfig_tut.cpp b/linden/indra/test/llmessageconfig_tut.cpp
index b709bfc..e5dd328 100644
--- a/linden/indra/test/llmessageconfig_tut.cpp
+++ b/linden/indra/test/llmessageconfig_tut.cpp
@@ -35,7 +35,6 @@
35#include "lltut.h" 35#include "lltut.h"
36#include "llsdserialize.h" 36#include "llsdserialize.h"
37#include "llfile.h" 37#include "llfile.h"
38#include "lldir.h"
39#include "lltimer.h" 38#include "lltimer.h"
40#include "llframetimer.h" 39#include "llframetimer.h"
41#include "llsdutil.h" 40#include "llsdutil.h"
@@ -51,7 +50,11 @@ namespace tut
51 random.generate(); 50 random.generate();
52 // generate temp dir 51 // generate temp dir
53 std::ostringstream oStr; 52 std::ostringstream oStr;
53#if LL_WINDOWS
54 oStr << "llmessage-config-test-" << random;
55#else
54 oStr << "/tmp/llmessage-config-test-" << random; 56 oStr << "/tmp/llmessage-config-test-" << random;
57#endif
55 mTestConfigDir = oStr.str(); 58 mTestConfigDir = oStr.str();
56 LLFile::mkdir(mTestConfigDir.c_str()); 59 LLFile::mkdir(mTestConfigDir.c_str());
57 writeConfigFile(LLSD()); 60 writeConfigFile(LLSD());
@@ -199,4 +202,23 @@ namespace tut
199 LLMessageConfig::getServerDefaultFlavor(), 202 LLMessageConfig::getServerDefaultFlavor(),
200 LLMessageConfig::LLSD_FLAVOR); 203 LLMessageConfig::LLSD_FLAVOR);
201 } 204 }
205
206 template<> template<>
207 void LLMessageConfigTestObject::test<8>()
208 // tests that config changes are picked up/refreshed periodically
209 {
210 LLSD config;
211 config["serverDefaults"]["simulator"] = "template";
212 config["messages"]["msg1"]["flavor"] = "llsd";
213 config["messages"]["msg1"]["only-send-latest"] = true;
214 config["messages"]["msg2"]["flavor"] = "llsd";
215 config["messages"]["msg2"]["only-send-latest"] = false;
216 LLMessageConfig::useConfig(config);
217 ensure_equals("Ensure msg1 exists, sent latest-only",
218 LLMessageConfig::onlySendLatest("msg1"),
219 true);
220 ensure_equals("Ensure msg2 exists, sent latest-only",
221 LLMessageConfig::onlySendLatest("msg2"),
222 false);
223 }
202} 224}
diff --git a/linden/indra/test/llmessagetemplateparser_tut.cpp b/linden/indra/test/llmessagetemplateparser_tut.cpp
index fe8e34c..7634e90 100644
--- a/linden/indra/test/llmessagetemplateparser_tut.cpp
+++ b/linden/indra/test/llmessagetemplateparser_tut.cpp
@@ -56,7 +56,7 @@ namespace tut
56 56
57 char * prehash(const char * name) 57 char * prehash(const char * name)
58 { 58 {
59 return gMessageStringTable.getString(name); 59 return LLMessageStringTable::getInstance()->getString(name);
60 } 60 }
61 61
62 void ensure_block_attributes(std::string identifier, 62 void ensure_block_attributes(std::string identifier,
diff --git a/linden/indra/test/llnamevalue_tut.cpp b/linden/indra/test/llnamevalue_tut.cpp
index d38913a..f604e84 100644
--- a/linden/indra/test/llnamevalue_tut.cpp
+++ b/linden/indra/test/llnamevalue_tut.cpp
@@ -42,133 +42,7 @@ namespace tut
42 { 42 {
43 namevalue_test() 43 namevalue_test()
44 { 44 {
45 mExpectedNameValueReference.string = NULL;
46 mExpectedNameValueType = NVT_NULL;
47 mCallbackCount = 0;
48 } 45 }
49
50 ~namevalue_test()
51 {
52 reset();
53 };
54
55 void reset()
56 {
57 switch(mExpectedNameValueType)
58 {
59 case NVT_STRING:
60 case NVT_ASSET:
61 delete [] mExpectedNameValueReference.string;
62 mExpectedNameValueReference.string = NULL;
63 break;
64 case NVT_F32:
65 delete mExpectedNameValueReference.f32;
66 mExpectedNameValueReference.f32 = NULL;
67 break;
68 case NVT_S32:
69 delete mExpectedNameValueReference.s32;
70 mExpectedNameValueReference.s32 = NULL;
71 break;
72 case NVT_U32:
73 delete mExpectedNameValueReference.u32;
74 mExpectedNameValueReference.u32 = NULL;
75 break;
76 case NVT_VEC3:
77 delete mExpectedNameValueReference.vec3;
78 mExpectedNameValueReference.vec3 = NULL;
79 break;
80 case NVT_U64:
81 delete mExpectedNameValueReference.u64;
82 mExpectedNameValueReference.u64 = NULL;
83 default:
84 break;
85 }
86
87 mExpectedNameValueType = NVT_NULL;
88 mCallbackCount = 0;
89 }
90
91 void setExpectedResult(ENameValueType type, void* value)
92 {
93 reset();
94 mExpectedNameValueType = type;
95 switch(type)
96 {
97 case NVT_STRING:
98 case NVT_ASSET:
99 mExpectedNameValueReference.string = new char[strlen((const char*) value)+1];
100 strcpy(mExpectedNameValueReference.string, (const char*) value);
101 break;
102 case NVT_F32:
103 mExpectedNameValueReference.f32 = new F32(*((F32*) value));
104 break;
105 case NVT_S32:
106 mExpectedNameValueReference.s32 = new S32(*((S32*) value));
107 break;
108 case NVT_U32:
109 mExpectedNameValueReference.u32 = new U32(*((U32*) value));
110 break;
111 case NVT_VEC3:
112 mExpectedNameValueReference.vec3 = new LLVector3(*((LLVector3*) value));
113 break;
114 case NVT_U64:
115 mExpectedNameValueReference.u64 = new U64(*((U64*) value));
116 default:
117 break;
118 }
119 }
120
121 void verifyChange(LLNameValue* changed)
122 {
123 std::string str = "";
124 str += "Expected Value of type: ";
125 str += NameValueTypeStrings[mExpectedNameValueType];
126 str += "not equal";
127
128 switch(mExpectedNameValueType)
129 {
130 case NVT_STRING:
131 ensure_memory_matches(str.c_str(), changed->getString(), strlen(changed->getString()), mExpectedNameValueReference.string, strlen(mExpectedNameValueReference.string));
132 break;
133 case NVT_ASSET:
134 ensure_memory_matches(str.c_str(), changed->getAsset(), strlen(changed->getAsset()), mExpectedNameValueReference.string, strlen(mExpectedNameValueReference.string));
135 break;
136 case NVT_F32:
137 ensure(str, *(changed->getF32()) == *mExpectedNameValueReference.f32);
138 break;
139 case NVT_S32:
140 ensure(str, *(changed->getS32()) == *mExpectedNameValueReference.s32);
141 break;
142 case NVT_U32:
143 ensure(str, *(changed->getU32()) == *mExpectedNameValueReference.u32);
144 break;
145 case NVT_VEC3:
146 ensure(str, *(changed->getVec3()) == *mExpectedNameValueReference.vec3);
147 break;
148 case NVT_U64:
149 ensure(str, *(changed->getU64()) == *mExpectedNameValueReference.u64);
150 break;
151 default:
152 break;
153 }
154 }
155
156 void HandleCallback(LLNameValue* changed)
157 {
158 mCallbackCount++;
159 verifyChange(changed);
160 ensure("Callback called more than once", mCallbackCount == 1);
161 }
162
163 static void NameValueCallbackFunction(LLNameValue* changed, void** data)
164 {
165 namevalue_test* pNameValue = (namevalue_test*)data;
166 pNameValue->HandleCallback(changed);
167 }
168
169 ENameValueType mExpectedNameValueType;
170 UNameValueReference mExpectedNameValueReference;
171 int mCallbackCount;
172 }; 46 };
173 typedef test_group<namevalue_test> namevalue_t; 47 typedef test_group<namevalue_test> namevalue_t;
174 typedef namevalue_t::object namevalue_object_t; 48 typedef namevalue_t::object namevalue_object_t;
@@ -225,33 +99,33 @@ namespace tut
225 ensure("3. getS32 failed", *nValue3.getS32() == -43456787); 99 ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
226 ensure("sendToData or sendToViewer failed", nValue3.sendToData() && !nValue3.sendToViewer()); 100 ensure("sendToData or sendToViewer failed", nValue3.sendToData() && !nValue3.sendToViewer());
227 101
228 LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "CB", "SV"); 102 LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW", "SV");
229 LLVector3 llvec4(1.0, 2.0, 3.0); 103 LLVector3 llvec4(1.0, 2.0, 3.0);
230 ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3); 104 ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
231 ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_CALLBACK); 105 ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
232 ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM_VIEWER); 106 ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM_VIEWER);
233 ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4); 107 ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
234 ensure("4. sendToData or sendToViewer failed", !nValue4.sendToData() && nValue4.sendToViewer()); 108 ensure("4. sendToData or sendToViewer failed", !nValue4.sendToData() && nValue4.sendToViewer());
235 109
236 LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "CALLBACK", "SIM_VIEWER"); 110 LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW", "SIM_VIEWER");
237 LLVector3 llvec5(-1.0f, 2.4f, 3); 111 LLVector3 llvec5(-1.0f, 2.4f, 3);
238 ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3); 112 ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
239 ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_CALLBACK); 113 ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
240 ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM_VIEWER); 114 ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM_VIEWER);
241 ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5); 115 ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
242 ensure("5. sendToData or sendToViewer failed", !nValue5.sendToData() && nValue5.sendToViewer()); 116 ensure("5. sendToData or sendToViewer failed", !nValue5.sendToData() && nValue5.sendToViewer());
243 117
244 LLNameValue nValue6("SecondLife", "89764323", "U32", "CALLBACK", "DSV"); 118 LLNameValue nValue6("SecondLife", "89764323", "U32", "RW", "DSV");
245 ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32); 119 ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
246 ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_CALLBACK); 120 ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
247 ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_DATA_SIM_VIEWER); 121 ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
248 ensure("6. getU32 failed", *nValue6.getU32() == 89764323); 122 ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
249 ensure("6. sendToData or sendToViewer failed", nValue6.sendToData() && nValue6.sendToViewer()); 123 ensure("6. sendToData or sendToViewer failed", nValue6.sendToData() && nValue6.sendToViewer());
250 124
251 LLNameValue nValue7("SecondLife", "89764323323232", "U64", "CALLBACK", "SIM_SPACE_VIEWER"); 125 LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW", "SIM_SPACE_VIEWER");
252 U64 u64_7 = U64L(89764323323232); 126 U64 u64_7 = U64L(89764323323232);
253 ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64); 127 ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
254 ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_CALLBACK); 128 ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
255 ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_DATA_SIM_VIEWER); 129 ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
256 ensure("7. getU32 failed", *nValue7.getU64() == u64_7); 130 ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
257 ensure("7. sendToData or sendToViewer failed", nValue7.sendToData() && nValue7.sendToViewer()); 131 ensure("7. sendToData or sendToViewer failed", nValue7.sendToData() && nValue7.sendToViewer());
@@ -288,30 +162,30 @@ namespace tut
288 ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM); 162 ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
289 ensure("3. getS32 failed", *nValue3.getS32() == -43456787); 163 ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
290 164
291 LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "CB"); 165 LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW");
292 LLVector3 llvec4(1.0, 2.0, 3.0); 166 LLVector3 llvec4(1.0, 2.0, 3.0);
293 ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3); 167 ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
294 ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_CALLBACK); 168 ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
295 ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM); 169 ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
296 ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4); 170 ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
297 171
298 LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "CALLBACK"); 172 LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW");
299 LLVector3 llvec5(-1.0f, 2.4f, 3); 173 LLVector3 llvec5(-1.0f, 2.4f, 3);
300 ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3); 174 ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
301 ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_CALLBACK); 175 ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
302 ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM); 176 ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM);
303 ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5); 177 ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
304 178
305 LLNameValue nValue6("SecondLife", "89764323", "U32", "CALLBACK"); 179 LLNameValue nValue6("SecondLife", "89764323", "U32", "RW");
306 ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32); 180 ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
307 ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_CALLBACK); 181 ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
308 ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM); 182 ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
309 ensure("6. getU32 failed", *nValue6.getU32() == 89764323); 183 ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
310 184
311 LLNameValue nValue7("SecondLife", "89764323323232", "U64", "CALLBACK"); 185 LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW");
312 U64 u64_7 = U64L(89764323323232); 186 U64 u64_7 = U64L(89764323323232);
313 ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64); 187 ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
314 ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_CALLBACK); 188 ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
315 ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM); 189 ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
316 ensure("7. getU32 failed", *nValue7.getU64() == u64_7); 190 ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
317 } 191 }
@@ -343,208 +217,118 @@ namespace tut
343 ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY); 217 ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
344 ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM); 218 ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
345 219
346 skip_fail("NVC_CALLBACK does not parse."); 220 LLNameValue nValue4("SecondLife", "VEC3", "READ_WRITE");
347
348 LLNameValue nValue4("SecondLife", "VEC3", "CALLBACK");
349 ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3); 221 ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
350 ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_CALLBACK); 222 ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
351 ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM); 223 ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
352 224
353 LLNameValue nValue6("SecondLife", "U32", "CALLBACK"); 225 LLNameValue nValue6("SecondLife", "U32", "READ_WRITE");
354 ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32); 226 ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
355 ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_CALLBACK); 227 ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
356 ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM); 228 ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
357 229
358 LLNameValue nValue7("SecondLife", "U64", "CALLBACK"); 230 LLNameValue nValue7("SecondLife", "U64", "READ_WRITE");
359 ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64); 231 ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
360 ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_CALLBACK); 232 ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
361 ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM); 233 ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
362 } 234 }
363 235
364 template<> template<> 236 template<> template<>
365 void namevalue_object_t::test<5>() 237 void namevalue_object_t::test<5>()
366 { 238 {
367 skip_fail("callback will be called more than once."); 239 LLNameValue nValue("SecondLife", "This is a test", "STRING", "RW", "SIM");
368 LLNameValue nValue("SecondLife", "This is a test", "STRING", "CB", "SIM", NameValueCallbackFunction, (void**) this);
369 240
370 ensure("getString failed", (0 == strcmp(nValue.getString(),"This is a test"))); 241 ensure("getString failed", (0 == strcmp(nValue.getString(),"This is a test")));
371 reset();
372
373 setExpectedResult(NVT_STRING, (void*)"New Value");
374 nValue.setString("New Value");
375 ensure("String nonzero failed", nValue.nonzero() == TRUE);
376 reset();
377 setExpectedResult(NVT_STRING, (void*)"");
378 nValue.setString("");
379 ensure("String nonzero failed", nValue.nonzero() == FALSE);
380 reset();
381 } 242 }
382 243
383 template<> template<> 244 template<> template<>
384 void namevalue_object_t::test<6>() 245 void namevalue_object_t::test<6>()
385 { 246 {
386 skip_fail("callback will be called more than once."); 247 LLNameValue nValue("SecondLife", "This is a test", "ASSET", "RW", "S");
387 LLNameValue nValue("SecondLife", "This is a test", "ASSET", "CALLBACK", "S", NameValueCallbackFunction, (void**) this);
388 ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test"))); 248 ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
389 reset();
390
391 setExpectedResult(NVT_ASSET, (void*)"New Value");
392 nValue.setAsset("New Value");
393 reset();
394 } 249 }
395 250
396 template<> template<> 251 template<> template<>
397 void namevalue_object_t::test<7>() 252 void namevalue_object_t::test<7>()
398 { 253 {
399 skip_fail("callback will be called more than once."); 254 LLNameValue nValue("SecondLife", "555555", "F32", "RW", "SIM");
400 LLNameValue nValue("SecondLife", "555555", "F32", "CB", "SIM", NameValueCallbackFunction, (void**) this);
401 255
402 ensure("getF32 failed",*nValue.getF32() == 555555.f); 256 ensure("getF32 failed",*nValue.getF32() == 555555.f);
403 reset();
404
405 F32 fVal = 0.1f;
406 setExpectedResult(NVT_F32, &fVal);
407 nValue.setF32(fVal);
408
409 fVal = -11111.1f;
410 setExpectedResult(NVT_F32, &fVal);
411 nValue.setF32(fVal);
412 ensure("F32 nonzero failed", nValue.nonzero() == TRUE);
413 reset();
414
415 fVal = 0.;
416 setExpectedResult(NVT_F32, &fVal);
417 nValue.setF32(fVal);
418 ensure("F32 nonzero failed", nValue.nonzero() == FALSE);
419 reset();
420 } 257 }
421 258
422 template<> template<> 259 template<> template<>
423 void namevalue_object_t::test<8>() 260 void namevalue_object_t::test<8>()
424 { 261 {
425 skip_fail("callback will be called more than once."); 262 LLNameValue nValue("SecondLife", "-5555", "S32", "RW", "SIM");
426 LLNameValue nValue("SecondLife", "-5555", "S32", "CB", "SIM", NameValueCallbackFunction, (void**) this);
427 263
428 ensure("getS32 failed", *nValue.getS32() == -5555); 264 ensure("getS32 failed", *nValue.getS32() == -5555);
429 reset();
430 265
431 S32 sVal = 0x7FFFFFFF; 266 S32 sVal = 0x7FFFFFFF;
432 setExpectedResult(NVT_S32, &sVal);
433 nValue.setS32(sVal); 267 nValue.setS32(sVal);
268 ensure("getS32 failed", *nValue.getS32() == sVal);
434 269
435 sVal = -0x7FFFFFFF; 270 sVal = -0x7FFFFFFF;
436 setExpectedResult(NVT_S32, &sVal);
437 nValue.setS32(sVal); 271 nValue.setS32(sVal);
438 ensure("S32 nonzero failed", nValue.nonzero() == TRUE); 272 ensure("getS32 failed", *nValue.getS32() == sVal);
439 reset();
440 273
441 sVal = 0; 274 sVal = 0;
442 setExpectedResult(NVT_S32, &sVal);
443 nValue.setS32(sVal); 275 nValue.setS32(sVal);
444 ensure("S32 nonzero failed", nValue.nonzero() == FALSE); 276 ensure("getS32 failed", *nValue.getS32() == sVal);
445 reset();
446 } 277 }
447 278
448 template<> template<> 279 template<> template<>
449 void namevalue_object_t::test<9>() 280 void namevalue_object_t::test<9>()
450 { 281 {
451 LLNameValue nValue("SecondLife", "<-3, 2, 1>", "VEC3", "CB", "SIM", NameValueCallbackFunction, (void**) this); 282 LLNameValue nValue("SecondLife", "<-3, 2, 1>", "VEC3", "RW", "SIM");
452 LLVector3 vecExpected(-3, 2, 1); 283 LLVector3 vecExpected(-3, 2, 1);
453 LLVector3 vec; 284 LLVector3 vec;
454 nValue.getVec3(vec); 285 nValue.getVec3(vec);
455 ensure("getVec3 failed", vec == vecExpected); 286 ensure("getVec3 failed", vec == vecExpected);
456 reset();
457
458 vecExpected.setVec(2, -1, 0);
459 setExpectedResult(NVT_VEC3, &vecExpected);
460 nValue.setVec3(vecExpected);
461 ensure("VEC3 nonzero failed", nValue.nonzero() == TRUE);
462 reset();
463
464 vecExpected.setVec(0, 0, 0);
465 setExpectedResult(NVT_VEC3, &vecExpected);
466 nValue.setVec3(vecExpected);
467 ensure("VEC3 nonzero failed", nValue.nonzero() == FALSE);
468 reset();
469 } 287 }
470 288
471 template<> template<> 289 template<> template<>
472 void namevalue_object_t::test<10>() 290 void namevalue_object_t::test<10>()
473 { 291 {
474 LLNameValue nValue("SecondLife", "12345678", "U32", "CB", "SIM", NameValueCallbackFunction, (void**) this); 292 LLNameValue nValue("SecondLife", "12345678", "U32", "RW", "SIM");
475 293
476 ensure("getU32 failed",*nValue.getU32() == 12345678); 294 ensure("getU32 failed",*nValue.getU32() == 12345678);
477 295
478 U32 val = 0xFFFFFFFF; 296 U32 val = 0xFFFFFFFF;
479 setExpectedResult(NVT_U32, &val);
480 nValue.setU32(val); 297 nValue.setU32(val);
481 ensure("U32 nonzero failed", nValue.nonzero() == TRUE); 298 ensure("U32 max", *nValue.getU32() == val);
482 reset();
483 299
484 val = 0; 300 val = 0;
485 setExpectedResult(NVT_U32, &val);
486 nValue.setU32(val); 301 nValue.setU32(val);
487 ensure("U32 nonzero failed", nValue.nonzero() == FALSE); 302 ensure("U32 min", *nValue.getU32() == val);
488 reset();
489 } 303 }
490 304
491 template<> template<> 305 template<> template<>
492 void namevalue_object_t::test<11>() 306 void namevalue_object_t::test<11>()
493 { 307 {
494 skip_fail("incomplete support for U64."); 308 //skip_fail("incomplete support for U64.");
495 LLNameValue nValue("SecondLife", "44444444444", "U64", "CB", "SIM", NameValueCallbackFunction, (void**) this); 309 LLNameValue nValue("SecondLife", "44444444444", "U64", "RW", "SIM");
496 310
497 ensure("getU64 failed",*nValue.getU64() == U64L(44444444444)); 311 ensure("getU64 failed",*nValue.getU64() == U64L(44444444444));
498 ensure("U64 nonzero failed", nValue.nonzero() == TRUE);
499 312
500 // there is no LLNameValue::setU64() 313 // there is no LLNameValue::setU64()
501 } 314 }
502 315
503 template<> template<>
504 void namevalue_object_t::test<12>()
505 {
506 LLNameValue nValue("SecondLife F32 RW SIM -333.337600");
507 F32 val = nValue.magnitude();
508 ensure_equals("F32 magnitude failed", val, 333.337600f);
509
510 LLNameValue nValue1("SecondLife STRING RW SIM 3300");
511 val = nValue1.magnitude();
512 ensure_equals("STRING magnitude failed",val,4.0f);
513
514 LLNameValue nValue2("SecondLife S32 RW SIM -3300");
515 val = nValue2.magnitude();
516 ensure_equals("S32 magnitude failed", val, 3300.);
517
518 LLNameValue nValue3("SecondLife U32 RW SIM 3300");
519 val = nValue3.magnitude();
520 ensure_equals("U32 magnitude failed", val, 3300.);
521
522 LLNameValue nValue4("SecondLife VEC3 RW SIM <1,2,3>");
523 LLVector3 vec(1,2,3);
524 val = nValue4.magnitude();
525 ensure_equals("VEC3 magnitude failed", val, vec.magVec());
526
527 skip_fail("incomplete support for U64.");
528 LLNameValue nValue5("SecondLife U64 RW SIM 12345");
529 val = nValue5.magnitude();
530 ensure_equals("U62 magnitude failed", val, 12345);
531 }
532 316
533 template<> template<> 317 template<> template<>
534 void namevalue_object_t::test<13>() 318 void namevalue_object_t::test<12>()
535 { 319 {
536 skip_fail("incomplete support for U64."); 320 //skip_fail("incomplete support for U64.");
537 LLNameValue nValue("SecondLife U64 RW DSV 44444444444"); 321 LLNameValue nValue("SecondLife U64 RW DSV 44444444444");
538 std::string ret_str = nValue.printNameValue(); 322 std::string ret_str = nValue.printNameValue();
539 323
540 ensure_equals("1:printNameValue failed",ret_str,"SecondLife U64 RW DSV 44444444444"); 324 ensure_equals("1:printNameValue failed",ret_str,"SecondLife U64 RW DSV 44444444444");
541 325
542 LLNameValue nValue1(ret_str.c_str()); 326 LLNameValue nValue1(ret_str.c_str());
543 ensure_equals("Serialization of printNameValue failed", nValue, nValue1); 327 ensure_equals("Serialization of printNameValue failed", *nValue.getU64(), *nValue1.getU64());
544 } 328 }
545 329
546 template<> template<> 330 template<> template<>
547 void namevalue_object_t::test<14>() 331 void namevalue_object_t::test<13>()
548 { 332 {
549 LLNameValue nValue("SecondLife STRING RW DSV 44444444444"); 333 LLNameValue nValue("SecondLife STRING RW DSV 44444444444");
550 std::string ret_str = nValue.printData(); 334 std::string ret_str = nValue.printData();
@@ -556,7 +340,7 @@ namespace tut
556 } 340 }
557 341
558 template<> template<> 342 template<> template<>
559 void namevalue_object_t::test<15>() 343 void namevalue_object_t::test<14>()
560 { 344 {
561 LLNameValue nValue("SecodLife STRING RW SIM 22222"); 345 LLNameValue nValue("SecodLife STRING RW SIM 22222");
562 std::ostringstream stream1,stream2,stream3, stream4, stream5; 346 std::ostringstream stream1,stream2,stream3, stream4, stream5;
@@ -575,271 +359,39 @@ namespace tut
575 stream4<< nValue3; 359 stream4<< nValue3;
576 ensure_equals("U32 << failed",stream4.str(),"122222"); 360 ensure_equals("U32 << failed",stream4.str(),"122222");
577 361
578 skip_fail("incomplete support for U64."); 362 // I don't think we use U64 name value pairs. JC
579 LLNameValue nValue4("SecodLife U64 RW SIM 22222"); 363 //skip_fail("incomplete support for U64.");
580 stream5<< nValue4; 364 //LLNameValue nValue4("SecodLife U64 RW SIM 22222");
581 ensure("U64 << failed",0 == strcmp((stream5.str()).c_str(),"22222")); 365 //stream5<< nValue4;
582 } 366 //ensure("U64 << failed",0 == strcmp((stream5.str()).c_str(),"22222"));
583
584 template<> template<>
585 void namevalue_object_t::test<16>()
586 {
587 LLNameValue nValue1("SecondLife STRING RW DSV 44444");
588 LLNameValue nValue2("SecondLife STRING RW SIM 33333");
589 LLNameValue nValue3("SecondLife");
590 nValue3 = nValue1 + nValue2;
591 ensure("1:operator+ failed",(0==strcmp(nValue3.getString(),"4444433333")));
592
593 LLNameValue nValue4("SecondLife F32 R DSV 44444");
594 LLNameValue nValue5("SecondLife F32 RW SIM 33333");
595 LLNameValue nValue6("SecondLife");
596 nValue6 = nValue4 + nValue5;
597 ensure_equals("2:operator+ failed",*nValue6.getF32(),77777.0);
598
599 LLNameValue nValue7("SecondLife F32 R DSV 44444");
600 LLNameValue nValue8("SecondLife S32 RW SIM 33333");
601 LLNameValue nValue9("SecondLife F32");
602 nValue9 = nValue7 + nValue8;
603 ensure_equals("3:operator+ failed",*nValue9.getF32(),77777.0);
604
605 LLNameValue nValue10("SecondLife VEC3 RW SIM <4, 4, 4>");
606 LLNameValue nValue11("SecondLife VEC3 RW SV <3, 3, 3>");
607 LLNameValue nValue12("SecondLife VEC3");
608 nValue12 = nValue10 + nValue11;
609 LLVector3 vec(7,7,7);
610 ensure_equals("4:operator+ failed",*nValue12.getVec3(), vec);
611 }
612
613 template<> template<>
614 void namevalue_object_t::test<17>()
615 {
616 LLNameValue nValue7(" SecondLife S32 RW SIM 22222");
617 LLNameValue nValue8(" SecondLife F32 RW SIM 33333");
618 LLNameValue nValue9(" SecondLife F32");
619 nValue9 = nValue7 - nValue8;
620 ensure_equals("1:operator- failed",*nValue9.getF32(),-11111.f);
621
622 LLNameValue nValue10(" SecondLife VEC3 RW SIM <2, 2, 2>");
623 LLNameValue nValue11(" SecondLife VEC3 RW SIM <3, 3, 3>");
624 LLNameValue nValue12(" SecondLife VEC3");
625 LLVector3 vec(-1,-1,-1);
626 nValue12 = nValue10 - nValue11;
627 ensure_equals("2:operator- failed",*nValue12.getVec3(), vec);
628 }
629
630 template<> template<>
631 void namevalue_object_t::test<18>()
632 {
633
634 LLNameValue nValue1(" SecondLife F32 RW SIM 22222");
635 LLNameValue nValue2(" SecondLife F32 RW SIM 33333");
636 LLNameValue nValue3(" SecondLife F32");
637 nValue3 = nValue1 * nValue2;
638 ensure_equals("1:operator* failed",*nValue3.getF32(),740725926.f);
639
640 LLNameValue nValue4(" SecondLife S32 RW SIM 22222");
641 LLNameValue nValue5(" SecondLife F32 RW SIM 33333");
642 LLNameValue nValue6(" SecondLife F32");
643 nValue6 = nValue4 * nValue5;
644 ensure_equals("2:operator* failed",*nValue6.getF32(),740725926.f);
645
646 LLNameValue nValue10(" SecondLife VEC3 RW SIM <2, 2, 2>");
647 LLNameValue nValue11(" SecondLife VEC3 RW SIM <3, 3, 3>");
648 LLNameValue nValue12(" SecondLife F32");
649 LLVector3 vec1(2,2,2);
650 LLVector3 vec2(3,3,3);
651 nValue12 = nValue10 * nValue11;
652 ensure_equals("2:operator* failed",*nValue12.getF32(), (vec1 * vec2));
653 } 367 }
654 368
655 template<> template<> 369 template<> template<>
656 void namevalue_object_t::test<19>() 370 void namevalue_object_t::test<15>()
657 {
658 LLNameValue nValue1(" SecondLife S32 RW SIM 22222");
659 LLNameValue nValue2(" Virtual F32 RW SIM 44444");
660 LLNameValue nValue3(" SecondLife F32");
661 nValue3 = nValue1 / nValue2;
662 ensure_equals("1:operator/ failed",*nValue3.getF32(),0.5);
663
664 LLNameValue nValue4(" SecondLife F32 RW SIM 33333");
665 LLNameValue nValue5(" SecondLife S32 RW SIM 22222");
666 LLNameValue nValue6(" SecondLife F32");
667 nValue6 = nValue4 / nValue5;
668 ensure_equals("2:operator/ failed",*nValue6.getF32(),1.5);
669 }
670
671 template<> template<>
672 void namevalue_object_t::test<20>()
673 {
674 LLNameValue nValue1(" SecondLife S32 RW SIM 22222");
675 LLNameValue nValue2(" Virtual S32 RW SIM 33333");
676 LLNameValue nValue3(" SecondLife S32");
677 nValue3 = nValue1 % nValue2;
678 ensure_equals("1:operator% failed",*nValue3.getS32(),22222);
679
680 LLNameValue nValue4(" SecondLife U32 RW SIM 3");
681 LLNameValue nValue5(" SecondLife S32 RW SIM 2");
682 LLNameValue nValue6(" SecondLife S32");
683 nValue6 = nValue4 % nValue5;
684 ensure_equals("2:operator% failed",*nValue6.getS32(),1);
685
686 LLNameValue nValue10(" SecondLife VEC3 RW SIM <4, 5, 6>");
687 LLNameValue nValue11(" SecondLife VEC3 RW SIM <1, 2, 3>");
688 LLNameValue nValue12(" SecondLife VEC3");
689 LLVector3 vec1(4,5,6);
690 LLVector3 vec2(1,2,3);
691 LLVector3 vec3(vec1 % vec2);
692 nValue12 = nValue10 % nValue11;
693 ensure_equals("5:operator% failed",*nValue12.getVec3(), vec3);
694 }
695
696 template<> template<>
697 void namevalue_object_t::test<21>()
698 {
699 LLNameValue nValue1(" SecondLife STRING RW SIM 22222");
700 LLNameValue nValue2(" Virtual STRING RW SIM 22222");
701 ensure("1:operator== failed", nValue1 == nValue2);
702
703 LLNameValue nValue3(" SecondLife F32 RW SIM 33333");
704 LLNameValue nValue4(" Virtual F32 RW SIM 22222");
705 ensure("2:operator== failed",!(nValue3 == nValue4));
706
707 LLNameValue nValue5(" SecondLife STRING RW SIM 22222");
708 LLNameValue nValue6(" Virtual STRING RW SIM 33333");
709 ensure("3:operator== failed",!(nValue5 == nValue6));
710
711 LLNameValue nValue7(" SecondLife VEC3 RW SIM <2, 2, 2>");
712 LLNameValue nValue8(" Virtual VEC3 RW SIM <2, 2, 2>");
713 ensure("4:operator== failed",(nValue7 == nValue8));
714 }
715
716 template<> template<>
717 void namevalue_object_t::test<22>()
718 {
719 LLNameValue nValue1(" SecondLife STRING RW SIM 22222");
720 LLNameValue nValue2(" Virtual STRING RW SIM 33333");
721 bool b_ret = (nValue1 <= nValue2) ? 1 : 0;
722 ensure("1:operator<= failed",(1==b_ret));
723
724 LLNameValue nValue3(" SecondLife F32 RW SIM 33333");
725 LLNameValue nValue4(" Virtual F32 RW SIM 22222");
726 b_ret = (nValue3 <= nValue4) ? 1 : 0;
727 ensure("2:operator<= failed",(0==b_ret));
728 }
729
730 template<> template<>
731 void namevalue_object_t::test<23>()
732 {
733 LLNameValue nValue1(" SecondLife STRING RW SIM 22222");
734 LLNameValue nValue2(" Virtual STRING RW SIM 33333");
735 bool b_ret = (nValue1 >= nValue2) ? 1 : 0;
736 ensure("operator>= failed",!b_ret);
737
738 LLNameValue nValue3(" SecondLife F32 RW SIM 33333");
739 LLNameValue nValue4(" Virtual F32 RW SIM 22222");
740 b_ret = (nValue3 >= nValue4) ? 1 : 0;
741 ensure("2:operator<= failed",b_ret);
742
743 }
744
745 template<> template<>
746 void namevalue_object_t::test<24>()
747 {
748 LLNameValue nValue1(" SecondLife STRING RW SIM 33333");
749 LLNameValue nValue2(" Virtual STRING RW SIM 33333");
750 bool b_ret = (nValue1 < nValue2) ? 1 : 0;
751 ensure("operator< failed",!b_ret);
752
753 LLNameValue nValue3(" SecondLife F32 RW SIM 11111");
754 LLNameValue nValue4(" Virtual F32 RW SIM 22222");
755 b_ret = (nValue3 < nValue4) ? 1 : 0;
756 ensure("2:operator< failed",b_ret);
757
758 }
759
760 template<> template<>
761 void namevalue_object_t::test<25>()
762 {
763 LLNameValue nValue1(" SecondLife STRING RW SIM 33333");
764 LLNameValue nValue2(" Virtual STRING RW SIM 33333");
765 bool b_ret = (nValue1 > nValue2) ? 1 : 0;
766 ensure("1:operator> failed",!b_ret);
767
768 LLNameValue nValue3(" SecondLife F32 RW SIM 11111");
769 LLNameValue nValue4(" Virtual F32 RW SIM 22222");
770 b_ret = (nValue3 > nValue4) ? 1 : 0;
771 ensure("2:operator> failed",!b_ret);
772
773 LLNameValue nValue5(" SecondLife S32 RW SIM 22222");
774 LLNameValue nValue6(" Virtual F32 RW SIM 11111");
775 b_ret = (nValue5 > nValue6) ? 1 : 0;
776 ensure("3:operator> failed",b_ret);
777 }
778
779 template<> template<>
780 void namevalue_object_t::test<26>()
781 {
782 LLNameValue nValue1(" SecondLife STRING RW SIM 33333");
783 LLNameValue nValue2(" Virtual STRING RW SIM 33333");
784 bool b_ret = (nValue1 != nValue2) ? 1 : 0;
785 ensure("1:operator!= failed",!b_ret);
786
787 LLNameValue nValue3(" SecondLife F32 RW SIM 11111");
788 LLNameValue nValue4(" Virtual F32 RW SIM 22222");
789 b_ret = (nValue3 != nValue4) ? 1 : 0;
790 ensure("2:operator!= failed",b_ret);
791
792 }
793
794
795 template<> template<>
796 void namevalue_object_t::test<27>()
797 {
798 LLNameValue nValue1(" SecondLife F32 RW SIM 33333");
799 LLNameValue nValue2("Virtual");
800 nValue2 = -nValue1;
801 ensure_equals("1:operator unary- failed",*nValue2.getF32(), -33333.f);
802
803 LLNameValue nValue3(" SecondLife U32 RW SIM 11111");
804 LLNameValue nValue4("Virtual S32");
805 nValue4 = -nValue3;
806 ensure_equals("2:operator unary- failed",*nValue4.getS32(), -11111);
807
808 LLNameValue nValue5(" SecondLife VEC3 RW SIM <1, 1, 1>");
809 LLNameValue nValue6("Virtual VEC3");
810 LLVector3 vec(-1, -1, -1);
811 nValue6 = -nValue5;
812 ensure_equals("3:operator unary- failed",*nValue6.getVec3(), vec);
813 }
814
815 template<> template<>
816 void namevalue_object_t::test<28>()
817 { 371 {
818 LLNameValue nValue("SecondLife", "This is a test", "ASSET", "R", "S", NameValueCallbackFunction, (void**) this); 372 LLNameValue nValue("SecondLife", "This is a test", "ASSET", "R", "S");
819 373
820 ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test"))); 374 ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
821 // this should not have updated as it is read only. 375 // this should not have updated as it is read only.
822 nValue.setAsset("New Value should not be updated"); 376 nValue.setAsset("New Value should not be updated");
823 ensure("setAsset on ReadOnly failed", (0 == strcmp(nValue.getAsset(),"This is a test"))); 377 ensure("setAsset on ReadOnly failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
824 378
825 LLNameValue nValue1("SecondLife", "1234", "U32", "R", "S", NameValueCallbackFunction, (void**) this); 379 LLNameValue nValue1("SecondLife", "1234", "U32", "R", "S");
826 // this should not have updated as it is read only. 380 // this should not have updated as it is read only.
827 nValue1.setU32(4567); 381 nValue1.setU32(4567);
828 ensure("setU32 on ReadOnly failed", *nValue1.getU32() == 1234); 382 ensure("setU32 on ReadOnly failed", *nValue1.getU32() == 1234);
829 383
830 LLNameValue nValue2("SecondLife", "1234", "S32", "R", "S", NameValueCallbackFunction, (void**) this); 384 LLNameValue nValue2("SecondLife", "1234", "S32", "R", "S");
831 // this should not have updated as it is read only. 385 // this should not have updated as it is read only.
832 nValue2.setS32(4567); 386 nValue2.setS32(4567);
833 ensure("setS32 on ReadOnly failed", *nValue2.getS32() == 1234); 387 ensure("setS32 on ReadOnly failed", *nValue2.getS32() == 1234);
834 388
835 LLNameValue nValue3("SecondLife", "1234", "F32", "R", "S", NameValueCallbackFunction, (void**) this); 389 LLNameValue nValue3("SecondLife", "1234", "F32", "R", "S");
836 // this should not have updated as it is read only. 390 // this should not have updated as it is read only.
837 nValue3.setF32(4567); 391 nValue3.setF32(4567);
838 ensure("setF32 on ReadOnly failed", *nValue3.getF32() == 1234); 392 ensure("setF32 on ReadOnly failed", *nValue3.getF32() == 1234);
839 nValue3 = nValue3 * 2;
840 ensure("setF32 on ReadOnly failed", *nValue3.getF32() == 1234);
841 393
842 LLNameValue nValue4("SecondLife", "<1,2,3>", "VEC3", "R", "S", NameValueCallbackFunction, (void**) this); 394 LLNameValue nValue4("SecondLife", "<1,2,3>", "VEC3", "R", "S");
843 // this should not have updated as it is read only. 395 // this should not have updated as it is read only.
844 LLVector3 vec(4,5,6); 396 LLVector3 vec(4,5,6);
845 nValue3.setVec3(vec); 397 nValue3.setVec3(vec);
diff --git a/linden/indra/test/llsdmessagereader_tut.cpp b/linden/indra/test/llsdmessagereader_tut.cpp
index e52809f..04861c4 100755
--- a/linden/indra/test/llsdmessagereader_tut.cpp
+++ b/linden/indra/test/llsdmessagereader_tut.cpp
@@ -46,7 +46,7 @@ namespace tut
46 const std::string& expected_name) 46 const std::string& expected_name)
47 { 47 {
48 LLSDMessageReader msg; 48 LLSDMessageReader msg;
49 msg.setMessage(gMessageStringTable.getString(msg_name.c_str()), msg_data); 49 msg.setMessage(LLMessageStringTable::getInstance()->getString(msg_name.c_str()), msg_data);
50 ensure_equals("Ensure name", std::string(msg.getMessageName()), 50 ensure_equals("Ensure name", std::string(msg.getMessageName()),
51 expected_name); 51 expected_name);
52 } 52 }
diff --git a/linden/indra/test/llstreamtools_tut.cpp b/linden/indra/test/llstreamtools_tut.cpp
index 3e89282..c360cc1 100644
--- a/linden/indra/test/llstreamtools_tut.cpp
+++ b/linden/indra/test/llstreamtools_tut.cpp
@@ -491,7 +491,7 @@ namespace tut
491 is.str(str = "First Second \t \r\n Third Fourth-ShouldThisBePartOfFourth IsThisFifth\n"); 491 is.str(str = "First Second \t \r\n Third Fourth-ShouldThisBePartOfFourth IsThisFifth\n");
492 actual_result = ""; 492 actual_result = "";
493 ret = get_line(actual_result, is); 493 ret = get_line(actual_result, is);
494 expected_result = "First Second \t \n"; 494 expected_result = "First Second \t \r\n";
495 ensure_equals("get_line: 1", actual_result, expected_result); 495 ensure_equals("get_line: 1", actual_result, expected_result);
496 496
497 actual_result = ""; 497 actual_result = "";
@@ -545,7 +545,6 @@ namespace tut
545 template<> template<> 545 template<> template<>
546 void streamtools_object::test<12>() 546 void streamtools_object::test<12>()
547 { 547 {
548 skip_fail("get_line() incorrectly handles lone carriage return.");
549 std::string str; 548 std::string str;
550 std::string expected_result; 549 std::string expected_result;
551 std::string actual_result; 550 std::string actual_result;
@@ -554,10 +553,10 @@ namespace tut
554 553
555 // need to be check if this test case is wrong or the implementation is wrong. 554 // need to be check if this test case is wrong or the implementation is wrong.
556 is.clear(); 555 is.clear();
557 is.str(str = "Should not skip \r unless they are followed with newline .\r\n"); 556 is.str(str = "Should not skip lone \r.\r\n");
558 actual_result = ""; 557 actual_result = "";
559 ret = get_line(actual_result, is); 558 ret = get_line(actual_result, is);
560 expected_result = "Should not skip \r unless they are followed with newline .\n"; 559 expected_result = "Should not skip lone \r.\r\n";
561 ensure_equals("get_line: carriage return skipped even though not followed by newline", actual_result, expected_result); 560 ensure_equals("get_line: carriage return skipped even though not followed by newline", actual_result, expected_result);
562 } 561 }
563 562
@@ -804,37 +803,6 @@ namespace tut
804 template<> template<> 803 template<> template<>
805 void streamtools_object::test<21>() 804 void streamtools_object::test<21>()
806 { 805 {
807 skip_fail("get_brace_count() has bugs.");
808
809 std::string str;
810 std::string expected_result;
811 int count;
812
813 str = " { ";
814 count = get_brace_count(str);
815 ensure("get_brace_count: 1 for {", count == 1);
816
817 str = "\t}\t\t \n";
818 count = get_brace_count(str);
819 ensure("get_brace_count: 1 for {", count == -1);
820
821 str = "\t\t\t \n";
822 count = get_brace_count(str);
823 ensure("get_brace_count: 0 for no braces", count == 0);
824
825 str = "{ Remaining line not empty\n";
826 count = get_brace_count(str);
827 ensure("get_brace_count: 0 for remainign line not empty", count == 0);
828
829 /* shouldn't this return 1? */
830 str = "{ /*Remaining line in comment*/\n";
831 count = get_brace_count(str);
832 ensure("get_brace_count: 1 for { with remaining line in comment", count == 1);
833
834 /* shouldn't this return -1? */
835 str = " } //Remaining line in comment \n";
836 count = get_brace_count(str);
837 ensure("get_brace_count: -1 for } with remaining line in comment", count == -1);
838 } 806 }
839 807
840 //testcases for get_keyword_and_value() 808 //testcases for get_keyword_and_value()
@@ -860,8 +828,6 @@ namespace tut
860 template<> template<> 828 template<> template<>
861 void streamtools_object::test<23>() 829 void streamtools_object::test<23>()
862 { 830 {
863 skip_fail("get_keyword_and_value() has bugs.");
864
865 std::string s; 831 std::string s;
866 std::string keyword = "SOME PRIOR KEYWORD"; 832 std::string keyword = "SOME PRIOR KEYWORD";
867 std::string value = "SOME PRIOR VALUE"; 833 std::string value = "SOME PRIOR VALUE";
@@ -875,8 +841,6 @@ namespace tut
875 template<> template<> 841 template<> template<>
876 void streamtools_object::test<24>() 842 void streamtools_object::test<24>()
877 { 843 {
878 skip_fail("get_keyword_and_value() has bugs.");
879
880 std::string s; 844 std::string s;
881 std::string keyword = "SOME PRIOR KEYWORD"; 845 std::string keyword = "SOME PRIOR KEYWORD";
882 std::string value = "SOME PRIOR VALUE"; 846 std::string value = "SOME PRIOR VALUE";
diff --git a/linden/indra/test/lltemplatemessagebuilder_tut.cpp b/linden/indra/test/lltemplatemessagebuilder_tut.cpp
index 1b3d600..86b1fbd 100644
--- a/linden/indra/test/lltemplatemessagebuilder_tut.cpp
+++ b/linden/indra/test/lltemplatemessagebuilder_tut.cpp
@@ -65,7 +65,7 @@ namespace tut
65 LL_VERSION_PATCH, 65 LL_VERSION_PATCH,
66 FALSE, 66 FALSE,
67 "notasharedsecret"); 67 "notasharedsecret");
68 init_prehash_data(); 68 //init_prehash_data();
69 init = true; 69 init = true;
70 } 70 }
71 return LLMessageTemplate(_PREHASH_TestMessage, 1, MFT_HIGH); 71 return LLMessageTemplate(_PREHASH_TestMessage, 1, MFT_HIGH);
diff --git a/linden/indra/test/lltut.h b/linden/indra/test/lltut.h
index e5c2419..4e4af73 100644
--- a/linden/indra/test/lltut.h
+++ b/linden/indra/test/lltut.h
@@ -44,6 +44,16 @@ class LLSD;
44 44
45namespace tut 45namespace tut
46{ 46{
47 inline void ensure_approximately_equals(const char* msg, F64 actual, F64 expected, U32 frac_bits)
48 {
49 if(!is_approx_equal_fraction(actual, expected, frac_bits))
50 {
51 std::stringstream ss;
52 ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected;
53 throw tut::failure(ss.str().c_str());
54 }
55 }
56
47 inline void ensure_approximately_equals(const char* msg, F32 actual, F32 expected, U32 frac_bits) 57 inline void ensure_approximately_equals(const char* msg, F32 actual, F32 expected, U32 frac_bits)
48 { 58 {
49 if(!is_approx_equal_fraction(actual, expected, frac_bits)) 59 if(!is_approx_equal_fraction(actual, expected, frac_bits))
diff --git a/linden/indra/test/mass_properties_tut.cpp b/linden/indra/test/mass_properties_tut.cpp
new file mode 100644
index 0000000..08cfeac
--- /dev/null
+++ b/linden/indra/test/mass_properties_tut.cpp
@@ -0,0 +1,1008 @@
1/**
2 * @file mass_properties.cpp
3 * @author andrew@lindenlab.com
4 * @date 2007-12-20
5 * @brief Tests for the LLPrimMassProperties and LLObjectMassProperties classes
6 *
7 * $LicenseInfo:firstyear=2007&license=internal$
8 *
9 * Copyright (c) 2007-2008, Linden Research, Inc.
10 *
11 * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
12 * this source code is governed by the Linden Lab Source Code Disclosure
13 * Agreement ("Agreement") previously entered between you and Linden
14 * Lab. By accessing, using, copying, modifying or distributing this
15 * software, you acknowledge that you have been informed of your
16 * obligations under the Agreement and agree to abide by those obligations.
17 *
18 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
19 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
20 * COMPLETENESS OR PERFORMANCE.
21 * $/LicenseInfo$
22 */
23
24#include "linden_common.h"
25#include "lltut.h"
26#include <llmath/v3math.h>
27#include <llmath/llquaternion.h>
28#include <llphysics/abstract/utils/llinertiatensorutils.h>
29#include <llphysics/abstract/utils/llobjectmassproperties.h>
30#include <llphysics/abstract/utils/llprimmassproperties.h>
31#include <llphysics/abstract/utils/llphysicsvolumemanager.h>
32#include <llprimitive/llmaterialtable.h>
33#include <llprimitive/llprimitive.h>
34
35
36const F32 SMALL_RELATIVE_ERROR = 0.001f; // 0.1%
37const F32 SQRT_THREE = 1.732050808f;
38const F32 SQRT_SIX = 2.449489743f;
39
40namespace tut
41{
42 struct mass_properties_data
43 {
44 LLPrimMassProperties prim_properties;
45 LLObjectMassProperties object_properties;
46 };
47
48 typedef test_group<mass_properties_data> mass_properties_group;
49 typedef mass_properties_group::object mass_properties;
50 tut::mass_properties_group mp_test_group("mass properties");
51
52 template<> template<>
53 void mass_properties::test<1>()
54 {
55 // test SPHERE mass properties
56 LLPrimMassProperties prim_sphere;
57 prim_sphere.setUnitSphere();
58
59 F32 density = 1000.f;
60 F32 radius = 5.f;
61 F32 diameter = 2.f * radius;
62 LLVector3 scale(diameter, diameter, diameter);
63 LLObjectMassProperties obj_sphere(prim_sphere, scale, density);
64
65 F32 computed_mass = obj_sphere.getMass();
66 //LLVector3 center_of_mass
67 //obj_sphere.getCenterOfMass(center_of_mass);
68 LLMatrix3 inertia;
69 obj_sphere.getInertiaLocal(inertia);
70 F32 computed_inertia_eigenvalue = inertia.mMatrix[0][0];
71
72
73 // volume is normalized for scale = <1,1,1>
74 // V = 4/3 * PI * r^3
75 // inertia_eigenvalue = (2/5) * M * r^2
76 F32 volume = ( 4.f / 3.f ) * radius * radius * radius * F_PI;
77 F32 expected_mass = density * volume;
78 F32 expected_inertia_eigenvalue = ( 2.f / 5.f ) * expected_mass * radius * radius;
79
80 F32 error = fabs(computed_mass - expected_mass) / expected_mass;
81 ensure("expected sphere mass should match computed", error < SMALL_RELATIVE_ERROR);
82
83 error = fabs(computed_inertia_eigenvalue - expected_inertia_eigenvalue) / expected_inertia_eigenvalue;
84 ensure("expected sphere inertia should match computed", error < SMALL_RELATIVE_ERROR);
85 }
86
87 template<> template<>
88 void mass_properties::test<2>()
89 {
90 // test LLInertiaTensorUtils
91
92 // define a known inertia tensor in the center of mass frame
93 // from the numerical example in this paper:
94 // http://www.journaldatabase.org/articles/87064/Explicit_Exact_Formulas_f.html
95 F32 known_mass = 1873.23f;
96 LLVector3 known_center( 0.f, 0.f, 0.f );
97 LLMatrix3 known_inertia;
98 known_inertia.mMatrix[0][0] = 43520.33257f;
99 known_inertia.mMatrix[1][1] = 194711.28938f;
100 known_inertia.mMatrix[2][2] = 191168.76173f;
101
102 known_inertia.mMatrix[0][1] = -11996.20119f;
103 known_inertia.mMatrix[1][0] = -11996.20119f;
104
105 known_inertia.mMatrix[0][2] = 46343.16662f;
106 known_inertia.mMatrix[2][0] = 46343.16662f;
107
108 known_inertia.mMatrix[2][1] = -4417.66150f;
109 known_inertia.mMatrix[1][2] = -4417.66150f;
110
111 // the following two shifts should have null effect
112 {
113 LLVector3 first_shift(2.f, 3.f, 4.f);
114 LLVector3 second_shift = - first_shift;
115 LLMatrix3 inertia = known_inertia;
116
117 LLInertiaTensorUtils::shiftCenteredInertiaTensor(inertia, first_shift, known_mass);
118 LLInertiaTensorUtils::centerInertiaTensor(inertia, second_shift, known_mass);
119
120 // we should now have the same inertia with which we started
121 for (S32 i=0; i<3; ++i)
122 {
123 for (S32 j=0; j<3; ++j)
124 {
125 F32 error = fabs(1.f - inertia.mMatrix[i][j] / known_inertia.mMatrix[i][j]);
126 ensure("LLInertiaTensorUtils shift+sclae-shift-scale should be no-op", error < SMALL_RELATIVE_ERROR);
127 }
128 }
129 }
130
131 // the following series operations should have null effect
132 {
133 LLVector3 first_shift(1.f, 5.f, 10.f);
134 LLVector3 second_scale(2.f, 3.f, 4.f);
135 LLVector3 third_shift;
136 LLVector3 fourth_scale;
137 for (S32 i = 0; i < 3; ++i)
138 {
139 third_shift.mV[i] = -first_shift.mV[i] * second_scale.mV[i];
140 fourth_scale.mV[i] = 1.f / second_scale.mV[i];
141 }
142
143 F32 mass = known_mass;
144 LLVector3 center = known_center;
145 LLMatrix3 inertia = known_inertia;
146
147 // first
148 LLInertiaTensorUtils::shiftCenteredInertiaTensor(inertia, first_shift, mass);
149 center += first_shift;
150
151 // second
152 LLInertiaTensorUtils::scaleInertiaTensor(inertia, second_scale);
153 mass *= second_scale.mV[VX] * second_scale.mV[VY] * second_scale.mV[VZ];
154 for (S32 i = 0; i < 3; ++i)
155 {
156 center.mV[i] *= second_scale.mV[i];
157 }
158
159 // third
160 LLInertiaTensorUtils::centerInertiaTensor(inertia, third_shift, mass);
161 center -= third_shift;
162
163 // foruth
164 LLInertiaTensorUtils::scaleInertiaTensor(inertia, fourth_scale);
165
166 // we should now have the same inertia with which we started
167 for (S32 i=0; i<3; ++i)
168 {
169 for (S32 j=0; j<3; ++j)
170 {
171 F32 error = fabs(1.f - inertia.mMatrix[i][j] / known_inertia.mMatrix[i][j]);
172 ensure("LLInertiaTensorUtils shift+sclae-shift-scale should be no-op", error < SMALL_RELATIVE_ERROR);
173 }
174 }
175 }
176 }
177
178 template<> template<>
179 void mass_properties::test<3>()
180 {
181 // test tetrahedral decomposition of unit tetrahedron centered on origin
182 std::vector< LLVector3 > points;
183 points.push_back( LLVector3( 0.f, 0.f, 0.f ) );
184 points.push_back( LLVector3( 1.f, 0.f, 0.f ) );
185 points.push_back( LLVector3( 0.5f, 0.5f * SQRT_THREE, 0.f) );
186 points.push_back( LLVector3( 0.5f, SQRT_THREE / 6.f, SQRT_SIX / 3.f) );
187
188 // compute the center
189 LLVector3 center;
190 for (S32 i = 0; i < (S32)points.size(); ++i)
191 {
192 center += points[i];
193 }
194 center *= ( 1.f / F32(points.size()) );
195
196 // shift all points to center of mass frame
197 for (S32 i = 0; i < (S32)points.size(); ++i)
198 {
199 points[i] -= center;
200 }
201
202 LLPrimMassProperties tetrahedron;
203 tetrahedron.addSignedTetrahedron(1.0, points[0], points[1], points[2], points[3]);
204 // we must manually center the inertia tensor here
205 // since addSignedTetrahedron() does not do it automatically
206 tetrahedron.centerInertiaTensor();
207
208 F32 density = 1.0f;
209 LLVector3 scale(1.f, 1.f, 1.f);
210 LLMatrix3 analytic_inertia;
211 tetrahedron.getScaledInertiaTensor(analytic_inertia, scale, density);
212
213 // compute the mesh
214 std::vector< S32 > triangle_indices;
215 triangle_indices.push_back(0);
216 triangle_indices.push_back(2);
217 triangle_indices.push_back(1);
218
219 triangle_indices.push_back(0);
220 triangle_indices.push_back(1);
221 triangle_indices.push_back(3);
222
223 triangle_indices.push_back(0);
224 triangle_indices.push_back(3);
225 triangle_indices.push_back(2);
226
227 triangle_indices.push_back(1);
228 triangle_indices.push_back(2);
229 triangle_indices.push_back(3);
230
231 // compute the same inertia using a mesh
232 {
233 LLPrimMassProperties mesh;
234 mesh.setUnitMesh(points, triangle_indices);
235
236 // the two properties should agree
237 F32 error = ( tetrahedron.getVolume() - mesh.getVolume() ) / tetrahedron.getVolume();
238 ensure("tetrahedron and mesh volume should match", error < SMALL_RELATIVE_ERROR);
239
240 error = ( tetrahedron.getCenterOfMass() - mesh.getCenterOfMass() ).length();
241 ensure("tetrahedron and mesh centers should match", error < SMALL_RELATIVE_ERROR);
242
243 LLMatrix3 mesh_inertia;
244 mesh.getScaledInertiaTensor(mesh_inertia, scale, density);
245
246 for (S32 i=0; i<3; ++i)
247 {
248 for (S32 j=0; j<3; ++j)
249 {
250 // only verify the non-small elements
251 if (analytic_inertia.mMatrix[i][j] > SMALL_RELATIVE_ERROR)
252 {
253 error = fabs(1.f - mesh_inertia.mMatrix[i][j] / analytic_inertia.mMatrix[i][j]);
254 ensure("LLPrimMassProperties::setUnitMesh() inertia ", error < SMALL_RELATIVE_ERROR);
255 }
256 }
257 }
258 }
259
260 // shift the whole tetrahedron away from the center of mass and recompute the mesh
261 {
262 LLVector3 shift(11.f, 7.f, 3.f);
263 for (S32 i = 0; i < (S32)points.size(); ++i)
264 {
265 points[i] += shift;
266 }
267 LLPrimMassProperties mesh;
268 mesh.setUnitMesh(points, triangle_indices);
269
270 // the two properties should agree
271 F32 error = ( tetrahedron.getVolume() - mesh.getVolume() ) / tetrahedron.getVolume();
272 ensure("tetrahedron and mesh volume should match", error < SMALL_RELATIVE_ERROR);
273
274 LLMatrix3 mesh_inertia;
275 mesh.getScaledInertiaTensor(mesh_inertia, scale, density);
276
277 for (S32 i=0; i<3; ++i)
278 {
279 for (S32 j=0; j<3; ++j)
280 {
281 // only verify the non-small elements
282 if (analytic_inertia.mMatrix[i][j] > SMALL_RELATIVE_ERROR)
283 {
284 error = fabs(1.f - mesh_inertia.mMatrix[i][j] / analytic_inertia.mMatrix[i][j]);
285 ensure("LLPrimMassProperties::setUnitMesh() inertia ", error < SMALL_RELATIVE_ERROR);
286 }
287 }
288 }
289 }
290 }
291
292 template<> template<>
293 void mass_properties::test<4>()
294 {
295 // test tetrahedron utilities
296
297 // from the paper described here:
298 // from the numerical example in this paper:
299 // http://www.journaldatabase.org/articles/87064/Explicit_Exact_Formulas_f.html
300
301 // initialize info about the tetrahedron
302 std::vector< LLVector3 > points;
303 points.push_back( LLVector3( 8.33220f, -11.86875f, 0.93355f) );
304 points.push_back( LLVector3( 0.75523f, 5.00000f, 16.37072f) );
305 points.push_back( LLVector3( 52.61236f, 5.00000f, - 5.38580f) );
306 points.push_back( LLVector3( 2.00000f, 5.00000f, 3.00000f) );
307
308 LLVector3 expected_center( 15.92492f, 0.78281f, 3.732962f);
309
310 LLMatrix3 expected_inertia;
311 expected_inertia.mMatrix[0][0] = 43520.33257f;
312 expected_inertia.mMatrix[1][1] = 194711.28938f;
313 expected_inertia.mMatrix[2][2] = 191168.76173f;
314
315 expected_inertia.mMatrix[0][1] = -11996.20119f;
316 expected_inertia.mMatrix[1][0] = -11996.20119f;
317
318 expected_inertia.mMatrix[0][2] = 46343.16662f;
319 expected_inertia.mMatrix[2][0] = 46343.16662f;
320
321 expected_inertia.mMatrix[2][1] = -4417.66150f;
322 expected_inertia.mMatrix[1][2] = -4417.66150f;
323
324 // measure tetrahedron bounding box max dimension
325 // for relative error estimates
326 LLVector3 box_min(FLT_MAX, FLT_MAX, FLT_MAX);
327 LLVector3 box_max(-FLT_MAX, -FLT_MAX, -FLT_MAX);
328 for (S32 point_index = 0; point_index < (S32)points.size(); ++point_index)
329 {
330 for (S32 i = 0; i < 3; ++i)
331 {
332 if (points[point_index].mV[i] < box_min.mV[i])
333 {
334 box_min.mV[i] = points[point_index].mV[i];
335 }
336 if (points[point_index].mV[i] > box_max.mV[i])
337 {
338 box_max.mV[i] = points[point_index].mV[i];
339 }
340 }
341 }
342 F32 tetrahedron_max_dimension = (box_max - box_min).length();
343
344
345 // test LLPrimMassProperties::addSignedTetrahedron()
346 {
347 LLPrimMassProperties tetrahedron;
348 tetrahedron.addSignedTetrahedron(1.f, points[0], points[1], points[2], points[3]);
349 // we must manually center the inertia tensor here
350 // since addSignedTetrahedron() does not do it automatically
351 tetrahedron.centerInertiaTensor();
352
353 // check the center of mass
354 LLVector3 center = tetrahedron.getCenterOfMass();
355 F32 error = (center - expected_center).length() / tetrahedron_max_dimension;
356
357 ensure("LLPrimMassProperties::addSignedTetrahedron() center of mass ", error < SMALL_RELATIVE_ERROR);
358
359 // check the inertia tensor
360 LLMatrix3 computed_inertia;
361 LLVector3 scale(1.f, 1.f, 1.f);
362 F32 density = 1.f;
363 tetrahedron.getScaledInertiaTensor(computed_inertia, scale, density);
364
365 for (S32 i=0; i<3; ++i)
366 {
367 for (S32 j=0; j<3; ++j)
368 {
369 error = fabs(1.f - computed_inertia.mMatrix[i][j] / expected_inertia.mMatrix[i][j]);
370 ensure("LLPrimMassProperties::addSignedTetrahedron inertia ", error < SMALL_RELATIVE_ERROR);
371 }
372 }
373 }
374
375 // test LLPrimMassProperties::addUnitMesh()
376 {
377 std::vector< S32 > triangle_indices;
378 triangle_indices.push_back(0);
379 triangle_indices.push_back(2);
380 triangle_indices.push_back(1);
381
382 triangle_indices.push_back(1);
383 triangle_indices.push_back(3);
384 triangle_indices.push_back(0);
385
386 triangle_indices.push_back(2);
387 triangle_indices.push_back(0);
388 triangle_indices.push_back(3);
389
390 triangle_indices.push_back(3);
391 triangle_indices.push_back(1);
392 triangle_indices.push_back(2);
393
394 LLPrimMassProperties mesh;
395 mesh.setUnitMesh(points, triangle_indices);
396
397 // check the center of mass
398 LLVector3 center = mesh.getCenterOfMass();
399 F32 error = (center - expected_center).length() / tetrahedron_max_dimension;
400
401 ensure("LLPrimMassProperties::setUnitMesh() center of mass ", error < SMALL_RELATIVE_ERROR);
402
403 // check the inertia tensor
404 LLMatrix3 computed_inertia;
405 LLVector3 scale(1.f, 1.f, 1.f);
406 F32 density = 1.f;
407 mesh.getScaledInertiaTensor(computed_inertia, scale, density);
408
409 for (S32 i=0; i<3; ++i)
410 {
411 for (S32 j=0; j<3; ++j)
412 {
413 error = fabs(1.f - computed_inertia.mMatrix[i][j] / expected_inertia.mMatrix[i][j]);
414 ensure("LLPrimMassProperties::setUnitMesh() inertia diagonal elements mismatch", error < SMALL_RELATIVE_ERROR);
415 }
416 }
417 }
418 }
419
420 template<> template<>
421 void mass_properties::test<5>()
422 {
423 // test LLPrimMassProperties
424
425 // unit shape box
426 LLPrimMassProperties box;
427 box.setUnitBox();
428
429 // unit shape mesh -- box
430
431 //
432 // 4-----------0
433 // z /| /|
434 // | / | / |
435 // | / | / |
436 // | 6-----------2 |
437 // | | | | |
438 // | | 5-------|---1
439 // | | / | /
440 // | | / | /
441 // | y |/ |/
442 // |/ 7-----------3
443 // +------------------------ x
444
445 std::vector< LLVector3 > points;
446 points.push_back( LLVector3( 0.5f, 0.5f, 0.5f) );
447 points.push_back( LLVector3( 0.5f, 0.5f, -0.5f) );
448 points.push_back( LLVector3( 0.5f, -0.5f, 0.5f) );
449 points.push_back( LLVector3( 0.5f, -0.5f, -0.5f) );
450 points.push_back( LLVector3(-0.5f, 0.5f, 0.5f) );
451 points.push_back( LLVector3(-0.5f, 0.5f, -0.5f) );
452 points.push_back( LLVector3(-0.5f, -0.5f, 0.5f) );
453 points.push_back( LLVector3(-0.5f, -0.5f, -0.5f) );
454
455 std::vector< S32 > triangle_indices;
456 // +x
457 triangle_indices.push_back(1);
458 triangle_indices.push_back(0);
459 triangle_indices.push_back(2);
460
461 triangle_indices.push_back(1);
462 triangle_indices.push_back(2);
463 triangle_indices.push_back(3);
464
465 // -y
466 triangle_indices.push_back(3);
467 triangle_indices.push_back(2);
468 triangle_indices.push_back(7);
469
470 triangle_indices.push_back(7);
471 triangle_indices.push_back(2);
472 triangle_indices.push_back(6);
473
474 // -x
475 triangle_indices.push_back(7);
476 triangle_indices.push_back(6);
477 triangle_indices.push_back(4);
478
479 triangle_indices.push_back(7);
480 triangle_indices.push_back(4);
481 triangle_indices.push_back(5);
482
483 // +y
484 triangle_indices.push_back(5);
485 triangle_indices.push_back(4);
486 triangle_indices.push_back(1);
487
488 triangle_indices.push_back(1);
489 triangle_indices.push_back(4);
490 triangle_indices.push_back(0);
491
492 // +z
493 triangle_indices.push_back(0);
494 triangle_indices.push_back(4);
495 triangle_indices.push_back(6);
496
497 triangle_indices.push_back(0);
498 triangle_indices.push_back(6);
499 triangle_indices.push_back(2);
500
501 // -z
502 triangle_indices.push_back(7);
503 triangle_indices.push_back(5);
504 triangle_indices.push_back(3);
505
506 triangle_indices.push_back(3);
507 triangle_indices.push_back(5);
508 triangle_indices.push_back(1);
509
510 LLPrimMassProperties mesh;
511 mesh.setUnitMesh(points, triangle_indices);
512
513 // the unit box and unit mesh mass properties should be nearly the same
514
515 // volume should agree
516 F32 error = fabs(box.getVolume() - mesh.getVolume()) / box.getVolume();
517 ensure("UnitBox and UnitMesh(box) should have same volume", error < SMALL_RELATIVE_ERROR);
518
519 // center of mass should agree
520 LLVector3 box_center = box.getCenterOfMass();
521 LLVector3 mesh_center = mesh.getCenterOfMass();
522 error = fabs( (box_center - mesh_center).length() );
523 ensure("UnitBox and UnitMesh(box) centers of mass should agree", error < SMALL_RELATIVE_ERROR );
524
525 LLVector3 scale(1.f, 1.f, 1.f);
526 F32 density = 1.f;
527 LLMatrix3 box_inertia, mesh_inertia;
528 box.getScaledInertiaTensor(box_inertia, scale, density);
529 mesh.getScaledInertiaTensor(mesh_inertia, scale, density);
530
531 // mesh eigenvalues should be uniform
532 for (S32 i = 0; i < 2; ++i)
533 {
534 error = fabs(mesh_inertia.mMatrix[i][i] - mesh_inertia.mMatrix[i+1][i+1]) / mesh_inertia.mMatrix[i][i];
535 ensure("UnitMesh(box) should have uniform eigenvalues", error < SMALL_RELATIVE_ERROR);
536 }
537 // inertias should agree
538 for (S32 i = 0; i < 3; ++i)
539 {
540 for (S32 j = 0; j < 3; ++j)
541 {
542 error = fabs(box_inertia.mMatrix[i][j] - mesh_inertia.mMatrix[i][j]);
543 if (error > 0.f
544 && box_inertia.mMatrix[i][j] != 0.f)
545 {
546 error /= box_inertia.mMatrix[i][j];
547 }
548 ensure("UnitBox and UnitMesh(box) should have same inertia", error < SMALL_RELATIVE_ERROR);
549 }
550 }
551
552 // Here we test the boundary of the LLPrimLinkInfo::canLink() method
553 // between semi-random middle-sized objects.
554 }
555
556 template<> template<>
557 void mass_properties::test<6>()
558 {
559 // test LLObjectMassProperties
560
561 // we make a large single-prim box, then a similarly shaped object
562 // that is multiple prims, and compare their mass properties
563
564 LLPrimMassProperties box;
565 box.setUnitBox();
566
567 F32 density = 3.7f;
568 LLVector3 big_scale(1.f, 2.f, 3.f);
569 LLObjectMassProperties big_box(box, big_scale, density);
570
571 LLObjectMassProperties multiple_box;
572 LLVector3 position;
573 LLQuaternion rotation;
574 rotation.loadIdentity();
575
576 F32 small_box_size = 0.5f;
577 LLVector3 small_scale( small_box_size, small_box_size, small_box_size);
578 S32 num_boxes_x = S32(big_scale.mV[VX] / small_box_size);
579 S32 num_boxes_y = S32(big_scale.mV[VY] / small_box_size);
580 S32 num_boxes_z = S32(big_scale.mV[VZ] / small_box_size);
581 LLVector3 start_pos = 0.5f * (small_scale - big_scale);
582 for (S32 x = 0; x < num_boxes_x; ++x)
583 {
584 for (S32 y = 0; y < num_boxes_y; ++y)
585 {
586 for (S32 z = 0; z < num_boxes_z; ++z)
587 {
588 position.set( F32(x) * small_box_size, F32(y) * small_box_size, F32(z) * small_box_size );
589 position += start_pos;
590
591 multiple_box.add(box, small_scale, density, position, rotation);
592 }
593 }
594 }
595
596 // the mass properties of the two boxes should match
597
598 // mass
599 F32 big_mass = big_box.getMass();
600 F32 multiple_mass = multiple_box.getMass();
601 F32 error = (big_mass - multiple_mass) / big_mass;
602 ensure("Big box and equivalent multi-prim box should have same mass", error < SMALL_RELATIVE_ERROR);
603
604 // center of mass
605 LLVector3 big_center, multiple_center;
606 big_box.getCenterOfMass(big_center);
607 multiple_box.getCenterOfMass(multiple_center);
608 error = (big_center - multiple_center).length();
609 ensure("Big box and equivalent multi-prim box should have same center", error < SMALL_RELATIVE_ERROR);
610
611 // inertia
612 LLMatrix3 big_inertia, multiple_inertia;
613 big_box.getInertiaLocal(big_inertia);
614 multiple_box.getInertiaLocal(multiple_inertia);
615 for (S32 i = 0; i < 3; ++i)
616 {
617 for (S32 j = 0; j < 3; ++j)
618 {
619 error = fabs(big_inertia.mMatrix[i][j] - multiple_inertia.mMatrix[i][j]);
620 if (error > 0.f
621 && big_inertia.mMatrix[i][j] != 0.f)
622 {
623 error /= big_inertia.mMatrix[i][j];
624 }
625 ensure("UnitBox and UnitMesh(box) should have same inertia", error < SMALL_RELATIVE_ERROR);
626 }
627 }
628 }
629
630 template<> template<>
631 void mass_properties::test<7>()
632 {
633 // test LLObjectMassProperties with rotations
634
635 // we make a large single-prim box via mesh, then a similarly shaped
636 // object that is multiple prims (implicit boxes), and compare their
637 // mass properties
638
639 //
640 // 4-----------0
641 // z /| /|
642 // | / | / |
643 // | / | / |
644 // | 6-----------2 |
645 // | | | | |
646 // | | 5-------|---1
647 // | | / | /
648 // | | / | /
649 // | y |/ |/
650 // |/ 7-----------3
651 // +------------------------ x
652
653 std::vector< LLVector3 > points;
654 points.push_back( LLVector3( 0.5f, 0.5f, 0.5f) );
655 points.push_back( LLVector3( 0.5f, 0.5f, -0.5f) );
656 points.push_back( LLVector3( 0.5f, -0.5f, 0.5f) );
657 points.push_back( LLVector3( 0.5f, -0.5f, -0.5f) );
658 points.push_back( LLVector3(-0.5f, 0.5f, 0.5f) );
659 points.push_back( LLVector3(-0.5f, 0.5f, -0.5f) );
660 points.push_back( LLVector3(-0.5f, -0.5f, 0.5f) );
661 points.push_back( LLVector3(-0.5f, -0.5f, -0.5f) );
662
663 std::vector< S32 > triangle_indices;
664 // +x
665 triangle_indices.push_back(1);
666 triangle_indices.push_back(0);
667 triangle_indices.push_back(2);
668
669 triangle_indices.push_back(1);
670 triangle_indices.push_back(2);
671 triangle_indices.push_back(3);
672
673 // -y
674 triangle_indices.push_back(3);
675 triangle_indices.push_back(2);
676 triangle_indices.push_back(7);
677
678 triangle_indices.push_back(7);
679 triangle_indices.push_back(2);
680 triangle_indices.push_back(6);
681
682 // -x
683 triangle_indices.push_back(7);
684 triangle_indices.push_back(6);
685 triangle_indices.push_back(4);
686
687 triangle_indices.push_back(7);
688 triangle_indices.push_back(4);
689 triangle_indices.push_back(5);
690
691 // +y
692 triangle_indices.push_back(5);
693 triangle_indices.push_back(4);
694 triangle_indices.push_back(1);
695
696 triangle_indices.push_back(1);
697 triangle_indices.push_back(4);
698 triangle_indices.push_back(0);
699
700 // +z
701 triangle_indices.push_back(0);
702 triangle_indices.push_back(4);
703 triangle_indices.push_back(6);
704
705 triangle_indices.push_back(0);
706 triangle_indices.push_back(6);
707 triangle_indices.push_back(2);
708
709 // -z
710 triangle_indices.push_back(7);
711 triangle_indices.push_back(5);
712 triangle_indices.push_back(3);
713
714 triangle_indices.push_back(3);
715 triangle_indices.push_back(5);
716 triangle_indices.push_back(1);
717
718 F32 angle_step = F_PI / (2.f * 3.f);
719 for (F32 angle = 0.f; angle < 0.51f * F_PI; angle += angle_step)
720 {
721 // scale and rotate mesh points
722 LLVector3 axis(0.f, 0.f, angle);
723 LLQuaternion mesh_rotation(angle, axis);
724 LLVector3 big_scale(3.f, 5.f, 7.f);
725 std::vector< LLVector3 > new_points;
726 for (S32 p = 0; p < (S32)points.size(); ++p)
727 {
728 LLVector3 new_point = points[p];
729 for (S32 i = 0; i < 3; ++i)
730 {
731 new_point.mV[i] *= big_scale.mV[i];
732 }
733 new_points.push_back( new_point * mesh_rotation );
734 }
735
736 // build the big mesh box
737 LLPrimMassProperties mesh_box;
738 mesh_box.setUnitMesh(new_points, triangle_indices);
739
740 F32 density = 3.7f;
741 LLVector3 unit_scale(1.f, 1.f, 1.f);
742 LLObjectMassProperties big_box(mesh_box, unit_scale, density);
743
744 // build the multiple_box
745 LLPrimMassProperties box;
746 box.setUnitBox();
747
748 LLObjectMassProperties multiple_box;
749 LLVector3 position;
750
751 F32 small_box_size = 0.5f;
752 LLVector3 small_scale( small_box_size, small_box_size, small_box_size);
753 S32 num_boxes_x = S32(big_scale.mV[VX] / small_box_size);
754 S32 num_boxes_y = S32(big_scale.mV[VY] / small_box_size);
755 S32 num_boxes_z = S32(big_scale.mV[VZ] / small_box_size);
756 LLVector3 start_pos = (0.5f * (small_scale - big_scale)) * mesh_rotation;
757 for (S32 x = 0; x < num_boxes_x; ++x)
758 {
759 for (S32 y = 0; y < num_boxes_y; ++y)
760 {
761 for (S32 z = 0; z < num_boxes_z; ++z)
762 {
763 position.set( F32(x) * small_box_size, F32(y) * small_box_size, F32(z) * small_box_size );
764 position *= mesh_rotation;
765 position += start_pos;
766 multiple_box.add(box, small_scale, density, position, mesh_rotation);
767 }
768 }
769 }
770
771 // the mass properties of the two boxes should match
772
773 // mass
774 F32 big_mass = big_box.getMass();
775 F32 multiple_mass = multiple_box.getMass();
776 F32 error = (big_mass - multiple_mass) / big_mass;
777 ensure("Big box and equivalent multi-prim box should have same mass", error < SMALL_RELATIVE_ERROR);
778
779 // center of mass
780 LLVector3 big_center, multiple_center;
781 big_box.getCenterOfMass(big_center);
782 multiple_box.getCenterOfMass(multiple_center);
783 error = (big_center - multiple_center).length();
784 ensure("Big box and equivalent multi-prim box should have same center", error < SMALL_RELATIVE_ERROR);
785
786 LLMatrix3 big_inertia, multiple_inertia;
787 big_box.getInertiaLocal(big_inertia);
788 multiple_box.getInertiaLocal(multiple_inertia);
789
790 for (S32 i = 0; i < 3; ++i)
791 {
792 for (S32 j = 0; j < 3; ++j)
793 {
794 error = fabs(big_inertia.mMatrix[i][j] - multiple_inertia.mMatrix[i][j]);
795 if (error > 0.f
796 && big_inertia.mMatrix[i][j] > SMALL_RELATIVE_ERROR)
797 {
798 error /= big_inertia.mMatrix[i][j];
799 }
800 ensure("UnitBox and UnitMesh(box) should have same inertia", error < SMALL_RELATIVE_ERROR);
801 }
802 }
803 }
804 }
805
806 template<> template<>
807 void mass_properties::test<8>()
808 {
809 // test LLPhysicsVolumeManager
810
811 // we make a large single-prim box, then a similarly shaped object
812 // that is multiple prims, and compare their mass properties
813
814 // first we make the single-prim giant
815 //
816 // 4-----------0
817 // z /| /|
818 // | / | / |
819 // | / | / |
820 // | 6-----------2 |
821 // | | | | |
822 // | | 5-------|---1
823 // | | / | /
824 // | | / | /
825 // | y |/ |/
826 // |/ 7-----------3
827 // +------------------------ x
828
829 std::vector< LLVector3 > points;
830 points.push_back( LLVector3( 0.5f, 0.5f, 0.5f) );
831 points.push_back( LLVector3( 0.5f, 0.5f, -0.5f) );
832 points.push_back( LLVector3( 0.5f, -0.5f, 0.5f) );
833 points.push_back( LLVector3( 0.5f, -0.5f, -0.5f) );
834 points.push_back( LLVector3(-0.5f, 0.5f, 0.5f) );
835 points.push_back( LLVector3(-0.5f, 0.5f, -0.5f) );
836 points.push_back( LLVector3(-0.5f, -0.5f, 0.5f) );
837 points.push_back( LLVector3(-0.5f, -0.5f, -0.5f) );
838
839 std::vector< S32 > triangle_indices;
840 // +x
841 triangle_indices.push_back(1);
842 triangle_indices.push_back(0);
843 triangle_indices.push_back(2);
844
845 triangle_indices.push_back(1);
846 triangle_indices.push_back(2);
847 triangle_indices.push_back(3);
848
849 // -y
850 triangle_indices.push_back(3);
851 triangle_indices.push_back(2);
852 triangle_indices.push_back(7);
853
854 triangle_indices.push_back(7);
855 triangle_indices.push_back(2);
856 triangle_indices.push_back(6);
857
858 // -x
859 triangle_indices.push_back(7);
860 triangle_indices.push_back(6);
861 triangle_indices.push_back(4);
862
863 triangle_indices.push_back(7);
864 triangle_indices.push_back(4);
865 triangle_indices.push_back(5);
866
867 // +y
868 triangle_indices.push_back(5);
869 triangle_indices.push_back(4);
870 triangle_indices.push_back(1);
871
872 triangle_indices.push_back(1);
873 triangle_indices.push_back(4);
874 triangle_indices.push_back(0);
875
876 // +z
877 triangle_indices.push_back(0);
878 triangle_indices.push_back(4);
879 triangle_indices.push_back(6);
880
881 triangle_indices.push_back(0);
882 triangle_indices.push_back(6);
883 triangle_indices.push_back(2);
884
885 // -z
886 triangle_indices.push_back(7);
887 triangle_indices.push_back(5);
888 triangle_indices.push_back(3);
889
890 triangle_indices.push_back(3);
891 triangle_indices.push_back(5);
892 triangle_indices.push_back(1);
893
894 // scale the mesh points
895 LLVector3 big_scale(1.f, 2.f, 3.f);
896 std::vector< LLVector3 > new_points;
897 for (S32 p = 0; p < (S32)points.size(); ++p)
898 {
899 LLVector3 new_point = points[p];
900 for (S32 i = 0; i < 3; ++i)
901 {
902 new_point.mV[i] *= big_scale.mV[i];
903 }
904 new_points.push_back( new_point );
905 }
906
907 // build the big mesh box (primitive)
908 LLPrimMassProperties mesh_box;
909 mesh_box.setUnitMesh(new_points, triangle_indices);
910
911 F32 density = DEFAULT_OBJECT_DENSITY;
912 LLVector3 unit_scale(1.f, 1.f, 1.f);
913 LLObjectMassProperties big_box(mesh_box, unit_scale, density);
914
915 // build the multi-prim box (object)
916 S32 TEST_VOLUME_DETAIL = 1;
917
918 LLVolumeParams volume_params;
919 volume_params.setCube();
920
921 LLObjectMassProperties multiple_box;
922 F32 small_box_size = 0.5f;
923 LLVector3 small_scale( small_box_size, small_box_size, small_box_size);
924 {
925 // hijack the volume manager used by LLPrimitive
926 LLPhysicsVolumeManager* volume_manager = new LLPhysicsVolumeManager();
927 //volume_manager->setThreadSafe(false);
928 LLPrimitive::setVolumeManager(volume_manager);
929
930 std::vector< const LLPrimitive* > prim_list;
931
932 F32 angle = 0.f;
933 LLVector3 axis(0.f, 0.f, angle);
934 LLVector3 position;
935 LLQuaternion rotation(angle, axis);
936 S32 num_boxes_x = S32(big_scale.mV[VX] / small_box_size);
937 S32 num_boxes_y = S32(big_scale.mV[VY] / small_box_size);
938 S32 num_boxes_z = S32(big_scale.mV[VZ] / small_box_size);
939
940 for (S32 x = 0; x < num_boxes_x; ++x)
941 {
942 for (S32 y = 0; y < num_boxes_y; ++y)
943 {
944 for (S32 z = 0; z < num_boxes_z; ++z)
945 {
946 LLPrimitive* primp = new LLPrimitive();
947 primp->setVolume( volume_params, TEST_VOLUME_DETAIL);
948
949 position.set( F32(x) * small_box_size, F32(y) * small_box_size, F32(z) * small_box_size );
950 position *= rotation;
951
952 primp->setPosition(position);
953 primp->setRotation(rotation);
954 primp->setScale(small_scale);
955
956 prim_list.push_back(primp);
957 }
958 }
959 }
960
961 volume_manager->getObjectMassProperties(multiple_box, prim_list);
962
963 for (S32 i = 0; i < (S32)prim_list.size(); ++i)
964 {
965 delete prim_list[i];
966 prim_list[i] = NULL;
967 }
968 LLPrimitive::cleanupVolumeManager();
969 }
970
971 // mass
972 F32 big_mass = big_box.getMass();
973 F32 multiple_mass = multiple_box.getMass();
974 F32 error = (big_mass - multiple_mass) / big_mass;
975 ensure("Big box and equivalent multi-prim box should have same mass", error < SMALL_RELATIVE_ERROR);
976
977 // center of mass
978 LLVector3 big_center, multiple_center;
979 big_box.getCenterOfMass(big_center);
980 multiple_box.getCenterOfMass(multiple_center);
981 LLVector3 expected_shift = 0.5f * ( big_scale - small_scale );
982 error = ( big_center - (multiple_center - expected_shift) ).length();
983 ensure("Big box and equivalent multi-prim box should have same center", error < SMALL_RELATIVE_ERROR);
984
985 // inertia
986 LLMatrix3 big_inertia, multiple_inertia;
987 big_box.getInertiaLocal(big_inertia);
988 multiple_box.getInertiaLocal(multiple_inertia);
989
990 for (S32 i = 0; i < 3; ++i)
991 {
992 for (S32 j = 0; j < 3; ++j)
993 {
994 error = fabs(big_inertia.mMatrix[i][j] - multiple_inertia.mMatrix[i][j]);
995 if (error > 0.f
996 && big_inertia.mMatrix[i][j] > SMALL_RELATIVE_ERROR)
997 {
998 error /= big_inertia.mMatrix[i][j];
999 }
1000 bool ok = error < SMALL_RELATIVE_ERROR
1001 || (i != j
1002 && error < SMALL_RELATIVE_ERROR);
1003 ensure("UnitBox and UnitMesh(box) should have same inertia", ok );
1004 }
1005 }
1006 }
1007}
1008
diff --git a/linden/indra/test/math.cpp b/linden/indra/test/math.cpp
index 9cab3fe..405b8a3 100644
--- a/linden/indra/test/math.cpp
+++ b/linden/indra/test/math.cpp
@@ -34,9 +34,13 @@
34#include "linden_common.h" 34#include "linden_common.h"
35#include "lltut.h" 35#include "lltut.h"
36 36
37#include "llcrc.h"
38#include "llline.h"
37#include "llmath.h" 39#include "llmath.h"
40#include "llrand.h"
41#include "llsphere.h"
38#include "lluuid.h" 42#include "lluuid.h"
39#include "llcrc.h" 43#include "v3math.h"
40 44
41namespace tut 45namespace tut
42{ 46{
@@ -277,3 +281,439 @@ namespace tut
277 ensure_equals("crc update 2", c1.getCRC(), c2.getCRC()); 281 ensure_equals("crc update 2", c1.getCRC(), c2.getCRC());
278 } 282 }
279} 283}
284
285namespace tut
286{
287 struct sphere_data
288 {
289 };
290 typedef test_group<sphere_data> sphere_test;
291 typedef sphere_test::object sphere_object;
292 tut::sphere_test tsphere("LLSphere");
293
294 template<> template<>
295 void sphere_object::test<1>()
296 {
297 // test LLSphere::contains() and ::overlaps()
298 S32 number_of_tests = 10;
299 for (S32 test = 0; test < number_of_tests; ++test)
300 {
301 LLVector3 first_center(1.f, 1.f, 1.f);
302 F32 first_radius = 3.f;
303 LLSphere first_sphere( first_center, first_radius );
304
305 F32 half_millimeter = 0.0005f;
306 LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
307 direction.normalize();
308
309 F32 distance = ll_frand(first_radius - 2.f * half_millimeter);
310 LLVector3 second_center = first_center + distance * direction;
311 F32 second_radius = first_radius - distance - half_millimeter;
312 LLSphere second_sphere( second_center, second_radius );
313 ensure("first sphere should contain the second", first_sphere.contains(second_sphere));
314 ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere));
315
316 distance = first_radius + ll_frand(first_radius);
317 second_center = first_center + distance * direction;
318 second_radius = distance - first_radius + half_millimeter;
319 second_sphere.set( second_center, second_radius );
320 ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere));
321 ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere));
322
323 distance = first_radius + ll_frand(first_radius) + half_millimeter;
324 second_center = first_center + distance * direction;
325 second_radius = distance - first_radius - half_millimeter;
326 second_sphere.set( second_center, second_radius );
327 ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere));
328 ensure("first sphere should NOT overlap the second", !first_sphere.overlaps(second_sphere));
329 }
330 }
331
332 template<> template<>
333 void sphere_object::test<2>()
334 {
335 // test LLSphere::getBoundingSphere()
336 S32 number_of_tests = 100;
337 S32 number_of_spheres = 10;
338 F32 sphere_center_range = 32.f;
339 F32 sphere_radius_range = 5.f;
340
341 for (S32 test = 0; test < number_of_tests; ++test)
342 {
343 // gegnerate a bunch of random sphere
344 std::vector< LLSphere > sphere_list;
345 for (S32 sphere_count=0; sphere_count < number_of_spheres; ++sphere_count)
346 {
347 LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
348 direction.normalize();
349 F32 distance = ll_frand(sphere_center_range);
350 LLVector3 center = distance * direction;
351 F32 radius = ll_frand(sphere_radius_range);
352 LLSphere sphere( center, radius );
353 sphere_list.push_back(sphere);
354 }
355
356 // compute the bounding sphere
357 LLSphere bounding_sphere = LLSphere::getBoundingSphere(sphere_list);
358
359 // make sure all spheres are inside the bounding sphere
360 {
361 std::vector< LLSphere >::const_iterator sphere_itr;
362 for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
363 {
364 ensure("sphere should be contained by the bounding sphere", bounding_sphere.contains(*sphere_itr));
365 }
366 }
367
368 // TODO -- improve LLSphere::getBoundingSphere() to the point where
369 // we can reduce the 'expansion' in the two tests below to about
370 // 2 mm or less
371
372 F32 expansion = 0.005f;
373 // move all spheres out a little bit
374 // and count how many are NOT contained
375 {
376 std::vector< LLVector3 > uncontained_directions;
377 std::vector< LLSphere >::iterator sphere_itr;
378 for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
379 {
380 LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter();
381 direction.normalize();
382
383 sphere_itr->setCenter( sphere_itr->getCenter() + expansion * direction );
384 if (! bounding_sphere.contains( *sphere_itr ) )
385 {
386 uncontained_directions.push_back(direction);
387 }
388 }
389 ensure("when moving spheres out there should be at least two uncontained spheres",
390 uncontained_directions.size() > 1);
391
392 /* TODO -- when the bounding sphere algorithm is improved we can open up this test
393 * at the moment it occasionally fails when the sphere collection is tight and small
394 * (2 meters or less)
395 if (2 == uncontained_directions.size() )
396 {
397 // if there were only two uncontained spheres then
398 // the two directions should be nearly opposite
399 F32 dir_dot = uncontained_directions[0] * uncontained_directions[1];
400 ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f);
401 }
402 */
403 }
404
405 // compute the new bounding sphere
406 bounding_sphere = LLSphere::getBoundingSphere(sphere_list);
407
408 // increase the size of all spheres a little bit
409 // and count how many are NOT contained
410 {
411 std::vector< LLVector3 > uncontained_directions;
412 std::vector< LLSphere >::iterator sphere_itr;
413 for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
414 {
415 LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter();
416 direction.normalize();
417
418 sphere_itr->setRadius( sphere_itr->getRadius() + expansion );
419 if (! bounding_sphere.contains( *sphere_itr ) )
420 {
421 uncontained_directions.push_back(direction);
422 }
423 }
424 ensure("when boosting sphere radii there should be at least two uncontained spheres",
425 uncontained_directions.size() > 1);
426
427 /* TODO -- when the bounding sphere algorithm is improved we can open up this test
428 * at the moment it occasionally fails when the sphere collection is tight and small
429 * (2 meters or less)
430 if (2 == uncontained_directions.size() )
431 {
432 // if there were only two uncontained spheres then
433 // the two directions should be nearly opposite
434 F32 dir_dot = uncontained_directions[0] * uncontained_directions[1];
435 ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f);
436 }
437 */
438 }
439 }
440 }
441}
442
443namespace tut
444{
445 F32 SMALL_RADIUS = 1.0f;
446 F32 MEDIUM_RADIUS = 5.0f;
447 F32 LARGE_RADIUS = 10.0f;
448
449 struct line_data
450 {
451 };
452 typedef test_group<line_data> line_test;
453 typedef line_test::object line_object;
454 tut::line_test tline("LLLine");
455
456 template<> template<>
457 void line_object::test<1>()
458 {
459 // this is a test for LLLine::intersects(point) which returns TRUE
460 // if the line passes within some tolerance of point
461
462 // these tests will have some floating point error,
463 // so we need to specify how much error is ok
464 F32 allowable_relative_error = 0.00001f;
465 S32 number_of_tests = 100;
466 for (S32 test = 0; test < number_of_tests; ++test)
467 {
468 // generate some random point to be on the line
469 LLVector3 point_on_line( ll_frand(2.f) - 1.f,
470 ll_frand(2.f) - 1.f,
471 ll_frand(2.f) - 1.f);
472 point_on_line.normalize();
473 point_on_line *= ll_frand(LARGE_RADIUS);
474
475 // generate some random point to "intersect"
476 LLVector3 random_direction ( ll_frand(2.f) - 1.f,
477 ll_frand(2.f) - 1.f,
478 ll_frand(2.f) - 1.f);
479 random_direction.normalize();
480
481 LLVector3 random_offset( ll_frand(2.f) - 1.f,
482 ll_frand(2.f) - 1.f,
483 ll_frand(2.f) - 1.f);
484 random_offset.normalize();
485 random_offset *= ll_frand(SMALL_RADIUS);
486
487 LLVector3 point = point_on_line + MEDIUM_RADIUS * random_direction
488 + random_offset;
489
490 // compute the axis of approach (a unit vector between the points)
491 LLVector3 axis_of_approach = point - point_on_line;
492 axis_of_approach.normalize();
493
494 // compute the direction of the the first line (perp to axis_of_approach)
495 LLVector3 first_dir( ll_frand(2.f) - 1.f,
496 ll_frand(2.f) - 1.f,
497 ll_frand(2.f) - 1.f);
498 first_dir.normalize();
499 F32 dot = first_dir * axis_of_approach;
500 first_dir -= dot * axis_of_approach; // subtract component parallel to axis
501 first_dir.normalize();
502
503 // construct the line
504 LLVector3 another_point_on_line = point_on_line + ll_frand(LARGE_RADIUS) * first_dir;
505 LLLine line(another_point_on_line, point_on_line);
506
507 // test that the intersection point is within MEDIUM_RADIUS + SMALL_RADIUS
508 F32 test_radius = MEDIUM_RADIUS + SMALL_RADIUS;
509 test_radius += (LARGE_RADIUS * allowable_relative_error);
510 ensure("line should pass near intersection point", line.intersects(point, test_radius));
511
512 test_radius = allowable_relative_error * (point - point_on_line).length();
513 ensure("line should intersect point used to define it", line.intersects(point_on_line, test_radius));
514 }
515 }
516
517 template<> template<>
518 void line_object::test<2>()
519 {
520 // this is a test for LLLine::nearestApproach(LLLIne) method
521 // which computes the point on a line nearest another line
522
523 // these tests will have some floating point error,
524 // so we need to specify how much error is ok
525 // TODO -- make nearestApproach() algorithm more accurate so
526 // we can tighten the allowable_error. Most tests are tighter
527 // than one milimeter, however when doing randomized testing
528 // you can walk into inaccurate cases.
529 F32 allowable_relative_error = 0.001f;
530 S32 number_of_tests = 100;
531 for (S32 test = 0; test < number_of_tests; ++test)
532 {
533 // generate two points to be our known nearest approaches
534 LLVector3 some_point( ll_frand(2.f) - 1.f,
535 ll_frand(2.f) - 1.f,
536 ll_frand(2.f) - 1.f);
537 some_point.normalize();
538 some_point *= ll_frand(LARGE_RADIUS);
539
540 LLVector3 another_point( ll_frand(2.f) - 1.f,
541 ll_frand(2.f) - 1.f,
542 ll_frand(2.f) - 1.f);
543 another_point.normalize();
544 another_point *= ll_frand(LARGE_RADIUS);
545
546 // compute the axis of approach (a unit vector between the points)
547 LLVector3 axis_of_approach = another_point - some_point;
548 axis_of_approach.normalize();
549
550 // compute the direction of the the first line (perp to axis_of_approach)
551 LLVector3 first_dir( ll_frand(2.f) - 1.f,
552 ll_frand(2.f) - 1.f,
553 ll_frand(2.f) - 1.f);
554 F32 dot = first_dir * axis_of_approach;
555 first_dir -= dot * axis_of_approach; // subtract component parallel to axis
556 first_dir.normalize(); // normalize
557
558 // compute the direction of the the second line
559 LLVector3 second_dir( ll_frand(2.f) - 1.f,
560 ll_frand(2.f) - 1.f,
561 ll_frand(2.f) - 1.f);
562 dot = second_dir * axis_of_approach;
563 second_dir -= dot * axis_of_approach;
564 second_dir.normalize();
565
566 // make sure the lines aren't too parallel,
567 dot = fabsf(first_dir * second_dir);
568 if (dot > 0.99f)
569 {
570 // skip this test, we're not interested in testing
571 // the intractible cases
572 continue;
573 }
574
575 // construct the lines
576 LLVector3 first_point = some_point + ll_frand(LARGE_RADIUS) * first_dir;
577 LLLine first_line(first_point, some_point);
578
579 LLVector3 second_point = another_point + ll_frand(LARGE_RADIUS) * second_dir;
580 LLLine second_line(second_point, another_point);
581
582 // compute the points of nearest approach
583 LLVector3 some_computed_point = first_line.nearestApproach(second_line);
584 LLVector3 another_computed_point = second_line.nearestApproach(first_line);
585
586 // compute the error
587 F32 first_error = (some_point - some_computed_point).length();
588 F32 scale = llmax((some_point - another_point).length(), some_point.length());
589 scale = llmax(scale, another_point.length());
590 scale = llmax(scale, 1.f);
591 F32 first_relative_error = first_error / scale;
592
593 F32 second_error = (another_point - another_computed_point).length();
594 F32 second_relative_error = second_error / scale;
595
596 //if (first_relative_error > allowable_relative_error)
597 //{
598 // std::cout << "first_error = " << first_error
599 // << " first_relative_error = " << first_relative_error
600 // << " scale = " << scale
601 // << " dir_dot = " << (first_dir * second_dir)
602 // << std::endl;
603 //}
604 //if (second_relative_error > allowable_relative_error)
605 //{
606 // std::cout << "second_error = " << second_error
607 // << " second_relative_error = " << second_relative_error
608 // << " scale = " << scale
609 // << " dist = " << (some_point - another_point).length()
610 // << " dir_dot = " << (first_dir * second_dir)
611 // << std::endl;
612 //}
613
614 // test that the errors are small
615 ensure("first line should accurately compute its closest approach",
616 first_relative_error <= allowable_relative_error);
617 ensure("second line should accurately compute its closest approach",
618 second_relative_error <= allowable_relative_error);
619 }
620 }
621
622 F32 ALMOST_PARALLEL = 0.99f;
623 template<> template<>
624 void line_object::test<3>()
625 {
626 // this is a test for LLLine::getIntersectionBetweenTwoPlanes() method
627
628 // first some known tests
629 LLLine xy_plane(LLVector3(0.f, 0.f, 2.f), LLVector3(0.f, 0.f, 3.f));
630 LLLine yz_plane(LLVector3(2.f, 0.f, 0.f), LLVector3(3.f, 0.f, 0.f));
631 LLLine zx_plane(LLVector3(0.f, 2.f, 0.f), LLVector3(0.f, 3.f, 0.f));
632
633 LLLine x_line;
634 LLLine y_line;
635 LLLine z_line;
636
637 bool x_success = LLLine::getIntersectionBetweenTwoPlanes(x_line, xy_plane, zx_plane);
638 bool y_success = LLLine::getIntersectionBetweenTwoPlanes(y_line, yz_plane, xy_plane);
639 bool z_success = LLLine::getIntersectionBetweenTwoPlanes(z_line, zx_plane, yz_plane);
640
641 ensure("xy and zx planes should intersect", x_success);
642 ensure("yz and xy planes should intersect", y_success);
643 ensure("zx and yz planes should intersect", z_success);
644
645 LLVector3 direction = x_line.getDirection();
646 ensure("x_line should be parallel to x_axis", fabs(direction.mV[VX]) == 1.f
647 && 0.f == direction.mV[VY]
648 && 0.f == direction.mV[VZ] );
649 direction = y_line.getDirection();
650 ensure("y_line should be parallel to y_axis", 0.f == direction.mV[VX]
651 && fabs(direction.mV[VY]) == 1.f
652 && 0.f == direction.mV[VZ] );
653 direction = z_line.getDirection();
654 ensure("z_line should be parallel to z_axis", 0.f == direction.mV[VX]
655 && 0.f == direction.mV[VY]
656 && fabs(direction.mV[VZ]) == 1.f );
657
658 // next some random tests
659 F32 allowable_relative_error = 0.0001f;
660 S32 number_of_tests = 20;
661 for (S32 test = 0; test < number_of_tests; ++test)
662 {
663 // generate the known line
664 LLVector3 some_point( ll_frand(2.f) - 1.f,
665 ll_frand(2.f) - 1.f,
666 ll_frand(2.f) - 1.f);
667 some_point.normalize();
668 some_point *= ll_frand(LARGE_RADIUS);
669 LLVector3 another_point( ll_frand(2.f) - 1.f,
670 ll_frand(2.f) - 1.f,
671 ll_frand(2.f) - 1.f);
672 another_point.normalize();
673 another_point *= ll_frand(LARGE_RADIUS);
674 LLLine known_intersection(some_point, another_point);
675
676 // compute a plane that intersect the line
677 LLVector3 point_on_plane( ll_frand(2.f) - 1.f,
678 ll_frand(2.f) - 1.f,
679 ll_frand(2.f) - 1.f);
680 point_on_plane.normalize();
681 point_on_plane *= ll_frand(LARGE_RADIUS);
682 LLVector3 plane_normal = (point_on_plane - some_point) % known_intersection.getDirection();
683 plane_normal.normalize();
684 LLLine first_plane(point_on_plane, point_on_plane + plane_normal);
685
686 // compute a different plane that intersect the line
687 LLVector3 point_on_different_plane( ll_frand(2.f) - 1.f,
688 ll_frand(2.f) - 1.f,
689 ll_frand(2.f) - 1.f);
690 point_on_different_plane.normalize();
691 point_on_different_plane *= ll_frand(LARGE_RADIUS);
692 LLVector3 different_plane_normal = (point_on_different_plane - another_point) % known_intersection.getDirection();
693 different_plane_normal.normalize();
694 LLLine second_plane(point_on_different_plane, point_on_different_plane + different_plane_normal);
695
696 if (fabs(plane_normal * different_plane_normal) > ALMOST_PARALLEL)
697 {
698 // the two planes are approximately parallel, so we won't test this case
699 continue;
700 }
701
702 LLLine measured_intersection;
703 bool success = LLLine::getIntersectionBetweenTwoPlanes(
704 measured_intersection,
705 first_plane,
706 second_plane);
707
708 ensure("plane intersection should succeed", success);
709
710 F32 dot = fabs(known_intersection.getDirection() * measured_intersection.getDirection());
711 ensure("measured intersection should be parallel to known intersection",
712 dot > ALMOST_PARALLEL);
713
714 ensure("measured intersection should pass near known point",
715 measured_intersection.intersects(some_point, LARGE_RADIUS * allowable_relative_error));
716 }
717 }
718}
719
diff --git a/linden/indra/test/message_tut.cpp b/linden/indra/test/message_tut.cpp
index 60a249c..b619d38 100644
--- a/linden/indra/test/message_tut.cpp
+++ b/linden/indra/test/message_tut.cpp
@@ -62,7 +62,7 @@ namespace tut
62 if(! init) 62 if(! init)
63 { 63 {
64 ll_init_apr(); 64 ll_init_apr();
65 init_prehash_data(); 65 //init_prehash_data();
66 init = true; 66 init = true;
67 } 67 }
68 68
diff --git a/linden/indra/test/prim_linkability_tut.cpp b/linden/indra/test/prim_linkability_tut.cpp
new file mode 100644
index 0000000..c5f2958
--- /dev/null
+++ b/linden/indra/test/prim_linkability_tut.cpp
@@ -0,0 +1,490 @@
1/**
2 * @file linkability.cpp
3 * @author andrew@lindenlab.com
4 * @date 2007-04-23
5 * @brief Tests for the LLPrimLinkInfo template which computes the linkability of prims
6 *
7 * $LicenseInfo:firstyear=2007&license=internal$
8 *
9 * Copyright (c) 2007-2008, Linden Research, Inc.
10 *
11 * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
12 * this source code is governed by the Linden Lab Source Code Disclosure
13 * Agreement ("Agreement") previously entered between you and Linden
14 * Lab. By accessing, using, copying, modifying or distributing this
15 * software, you acknowledge that you have been informed of your
16 * obligations under the Agreement and agree to abide by those obligations.
17 *
18 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
19 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
20 * COMPLETENESS OR PERFORMANCE.
21 * $/LicenseInfo$
22 */
23
24#include "linden_common.h"
25#include "lltut.h"
26#include "llprimlinkinfo.h"
27#include "llrand.h"
28
29
30// helper function
31void randomize_sphere(LLSphere& sphere, F32 center_range, F32 radius_range)
32{
33 F32 radius = ll_frand(2.f * radius_range) - radius_range;
34 LLVector3 center;
35 for (S32 i=0; i<3; ++i)
36 {
37 center.mV[i] = ll_frand(2.f * center_range) - center_range;
38 }
39 sphere.setRadius(radius);
40 sphere.setCenter(center);
41}
42
43// helper function. Same as above with a min and max radius.
44void randomize_sphere(LLSphere& sphere, F32 center_range, F32 minimum_radius, F32 maximum_radius)
45{
46 F32 radius = ll_frand(maximum_radius - minimum_radius) + minimum_radius;
47 LLVector3 center;
48 for (S32 i=0; i<3; ++i)
49 {
50 center.mV[i] = ll_frand(2.f * center_range) - center_range;
51 }
52 sphere.setRadius(radius);
53 sphere.setCenter(center);
54}
55
56// helper function
57bool random_sort( const LLPrimLinkInfo< S32 >&, const LLPrimLinkInfo< S32 >& b)
58{
59 return (ll_rand(64) < 32);
60}
61
62namespace tut
63{
64 struct linkable_data
65 {
66 LLPrimLinkInfo<S32> info;
67 };
68
69 typedef test_group<linkable_data> linkable_test;
70 typedef linkable_test::object linkable_object;
71 tut::linkable_test wtf("prim linkability");
72
73 template<> template<>
74 void linkable_object::test<1>()
75 {
76 // Here we test the boundary of the LLPrimLinkInfo::canLink() method
77 // between semi-random middle-sized objects.
78
79 S32 number_of_tests = 100;
80 for (S32 test = 0; test < number_of_tests; ++test)
81 {
82 // compute the radii that would provide the above max link distance
83 F32 first_radius = 0.f;
84 F32 second_radius = 0.f;
85
86 // compute a random center for the first sphere
87 // compute some random max link distance
88 F32 max_link_span = ll_frand(MAX_OBJECT_SPAN);
89 if (max_link_span < OBJECT_SPAN_BONUS)
90 {
91 max_link_span += OBJECT_SPAN_BONUS;
92 }
93 LLVector3 first_center(
94 ll_frand(2.f * max_link_span) - max_link_span,
95 ll_frand(2.f * max_link_span) - max_link_span,
96 ll_frand(2.f * max_link_span) - max_link_span);
97
98 // put the second sphere at the right distance from the origin
99 // such that it is within the max_link_distance of the first
100 LLVector3 direction(ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
101 direction.normalize();
102 F32 half_milimeter = 0.0005f;
103 LLVector3 second_center;
104
105 // max_span = 3 * (first_radius + second_radius) + OBJECT_SPAN_BONUS
106 // make sure they link at short distances
107 {
108 second_center = first_center + (OBJECT_SPAN_BONUS - half_milimeter) * direction;
109 LLPrimLinkInfo<S32> first_info(0, LLSphere(first_center, first_radius) );
110 LLPrimLinkInfo<S32> second_info(1, LLSphere(second_center, second_radius) );
111 ensure("these nearby objects should link", first_info.canLink(second_info) );
112 }
113
114 // make sure they fail to link if we move them apart just a little bit
115 {
116 second_center = first_center + (OBJECT_SPAN_BONUS + half_milimeter) * direction;
117 LLPrimLinkInfo<S32> first_info(0, LLSphere(first_center, first_radius) );
118 LLPrimLinkInfo<S32> second_info(1, LLSphere(second_center, second_radius) );
119 ensure("these nearby objects should NOT link", !first_info.canLink(second_info) );
120 }
121
122 // make sure the objects link or not at medium distances
123 {
124 first_radius = 0.3f * ll_frand(max_link_span - OBJECT_SPAN_BONUS);
125
126 // This is the exact second radius that will link at exactly our random max_link_distance
127 second_radius = ((max_link_span - OBJECT_SPAN_BONUS) / 3.f) - first_radius;
128 second_center = first_center + (max_link_span - first_radius - second_radius - half_milimeter) * direction;
129
130 LLPrimLinkInfo<S32> first_info(0, LLSphere(first_center, first_radius) );
131 LLPrimLinkInfo<S32> second_info(1, LLSphere(second_center, second_radius) );
132
133 ensure("these objects should link", first_info.canLink(second_info) );
134 }
135
136 // make sure they fail to link if we move them apart just a little bit
137 {
138 // move the second sphere such that it is a little too far from the first
139 second_center += (2.f * half_milimeter) * direction;
140 LLPrimLinkInfo<S32> first_info(0, LLSphere(first_center, first_radius) );
141 LLPrimLinkInfo<S32> second_info(1, LLSphere(second_center, second_radius) );
142
143 ensure("these objects should NOT link", !first_info.canLink(second_info) );
144 }
145
146 // make sure things don't link at far distances
147 {
148 second_center = first_center + (MAX_OBJECT_SPAN + 2.f * half_milimeter) * direction;
149 second_radius = 0.3f * MAX_OBJECT_SPAN;
150 LLPrimLinkInfo<S32> first_info(0, LLSphere(first_center, first_radius) );
151 LLPrimLinkInfo<S32> second_info(1, LLSphere(second_center, second_radius) );
152 ensure("these objects should NOT link", !first_info.canLink(second_info) );
153 }
154
155 }
156 }
157
158 template<> template<>
159 void linkable_object::test<2>()
160 {
161
162 // Consider a row of eight spheres in a row, each 10m in diameter and centered
163 // at 10m intervals: 01234567.
164
165 F32 radius = 5.f;
166 F32 spacing = 10.f;
167
168 LLVector3 line_direction(ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
169 line_direction.normalize();
170
171 LLVector3 first_center(ll_frand(2.f * spacing) -spacing, ll_frand(2.f * spacing) - spacing, ll_frand(2.f * spacing) - spacing);
172
173 LLPrimLinkInfo<S32> infos[8];
174
175 for (S32 index = 0; index < 8; ++index)
176 {
177 LLVector3 center = first_center + ((F32)(index) * spacing) * line_direction;
178 infos[index].set(index, LLSphere(center, radius));
179 }
180
181 // Max span for 2 spheres of 5m radius is 3 * (5 + 5) + 1 = 31m
182 // spheres 0&2 have a 30m span (from outside edge to outside edge) and should link
183 {
184 LLPrimLinkInfo<S32> root_info = infos[0];
185 std::list< LLPrimLinkInfo<S32> > info_list;
186 info_list.push_back(infos[2]);
187 root_info.mergeLinkableSet(info_list);
188 S32 prim_count = root_info.getPrimCount();
189 ensure_equals("0&2 prim count should be 2", prim_count, 2);
190 ensure_equals("0&2 unlinkable list should have length 0", (S32) info_list.size(), 0);
191 }
192
193
194 // spheres 0&3 have a 40 meter span and should NOT link outright
195 {
196 LLPrimLinkInfo<S32> root_info = infos[0];
197 std::list< LLPrimLinkInfo<S32> > info_list;
198 info_list.push_back(infos[3]);
199 root_info.mergeLinkableSet(info_list);
200 S32 prim_count = root_info.getPrimCount();
201 ensure_equals("0&4 prim count should be 1", prim_count, 1);
202 ensure_equals("0&4 unlinkable list should have length 1", (S32) info_list.size(), 1);
203 }
204
205
206 // spheres 0-4 should link no matter what order : 01234
207 // Total span = 50m, 012 link with a r=15.5 giving max span of 3 * (15.5 + 5) + 1 = 62.5, but the cap is 54m
208 {
209 LLPrimLinkInfo<S32> root_info = infos[0];
210 std::list< LLPrimLinkInfo<S32> > info_list;
211 for (S32 index = 1; index < 5; ++index)
212 {
213 info_list.push_back(infos[index]);
214 }
215 root_info.mergeLinkableSet(info_list);
216 S32 prim_count = root_info.getPrimCount();
217 ensure_equals("01234 prim count should be 5", prim_count, 5);
218 ensure_equals("01234 unlinkable list should have length 0", (S32) info_list.size(), 0);
219 }
220
221
222 // spheres 0-5 should link no matter what order : 04321
223 {
224 LLPrimLinkInfo<S32> root_info = infos[0];
225 std::list< LLPrimLinkInfo<S32> > info_list;
226 for (S32 index = 4; index > 0; --index)
227 {
228 info_list.push_back(infos[index]);
229 }
230 root_info.mergeLinkableSet(info_list);
231 S32 prim_count = root_info.getPrimCount();
232 ensure_equals("04321 prim count should be 5", prim_count, 5);
233 ensure_equals("04321 unlinkable list should have length 0", (S32) info_list.size(), 0);
234 }
235
236 // spheres 0-4 should link no matter what order : 01423
237 {
238 LLPrimLinkInfo<S32> root_info = infos[0];
239 std::list< LLPrimLinkInfo<S32> > info_list;
240 info_list.push_back(infos[1]);
241 info_list.push_back(infos[4]);
242 info_list.push_back(infos[2]);
243 info_list.push_back(infos[3]);
244 root_info.mergeLinkableSet(info_list);
245 S32 prim_count = root_info.getPrimCount();
246 ensure_equals("01423 prim count should be 5", prim_count, 5);
247 ensure_equals("01423 unlinkable list should have length 0", (S32) info_list.size(), 0);
248 }
249
250 // spheres 0-5 should NOT fully link, only 0-4
251 {
252 LLPrimLinkInfo<S32> root_info = infos[0];
253 std::list< LLPrimLinkInfo<S32> > info_list;
254 for (S32 index = 1; index < 6; ++index)
255 {
256 info_list.push_back(infos[index]);
257 }
258 root_info.mergeLinkableSet(info_list);
259 S32 prim_count = root_info.getPrimCount();
260 ensure_equals("012345 prim count should be 5", prim_count, 5);
261 ensure_equals("012345 unlinkable list should have length 1", (S32) info_list.size(), 1);
262 std::list< LLPrimLinkInfo<S32> >::iterator info_itr = info_list.begin();
263 if (info_itr != info_list.end())
264 {
265 // examine the contents of the unlinked info
266 std::list<S32> unlinked_indecies;
267 info_itr->getData(unlinked_indecies);
268 // make sure there is only one index in the unlinked_info
269 ensure_equals("012345 unlinkable index count should be 1", (S32) unlinked_indecies.size(), 1);
270 // make sure its value is 6
271 std::list<S32>::iterator unlinked_index_itr = unlinked_indecies.begin();
272 S32 unlinkable_index = *unlinked_index_itr;
273 ensure_equals("012345 unlinkable index should be 5", (S32) unlinkable_index, 5);
274 }
275 }
276
277 // spheres 0-7 should NOT fully link, only 0-5
278 {
279 LLPrimLinkInfo<S32> root_info = infos[0];
280 std::list< LLPrimLinkInfo<S32> > info_list;
281 for (S32 index = 1; index < 8; ++index)
282 {
283 info_list.push_back(infos[index]);
284 }
285 root_info.mergeLinkableSet(info_list);
286 S32 prim_count = root_info.getPrimCount();
287 ensure_equals("01234567 prim count should be 5", prim_count, 5);
288 // Should be 1 linkinfo on unlinkable that has 2 prims
289 ensure_equals("01234567 unlinkable list should have length 1", (S32) info_list.size(), 1);
290 std::list< LLPrimLinkInfo<S32> >::iterator info_itr = info_list.begin();
291 if (info_itr != info_list.end())
292 {
293 // make sure there is only one index in the unlinked_info
294 std::list<S32> unlinked_indecies;
295 info_itr->getData(unlinked_indecies);
296 ensure_equals("0123456 unlinkable index count should be 3", (S32) unlinked_indecies.size(), 3);
297
298 // make sure its values are 6 and 7
299 std::list<S32>::iterator unlinked_index_itr = unlinked_indecies.begin();
300 S32 unlinkable_index = *unlinked_index_itr;
301 ensure_equals("0123456 first unlinkable index should be 5", (S32) unlinkable_index, 5);
302 ++unlinked_index_itr;
303 unlinkable_index = *unlinked_index_itr;
304 ensure_equals("0123456 second unlinkable index should be 6", (S32) unlinkable_index, 6);
305 ++unlinked_index_itr;
306 unlinkable_index = *unlinked_index_itr;
307 ensure_equals("0123456 third unlinkable index should be 7", (S32) unlinkable_index, 7);
308
309 }
310 }
311 }
312
313 template<> template<>
314 void linkable_object::test<3>()
315 {
316 // Here we test the link results between an LLPrimLinkInfo and a set of
317 // randomized LLPrimLinkInfos where the expected results are known.
318 S32 number_of_tests = 5;
319 for (S32 test = 0; test < number_of_tests; ++test)
320 {
321 // the radii are known
322 F32 first_radius = 1.f;
323 F32 second_radius = 2.f;
324 F32 third_radius = 3.f;
325
326 // compute the distances
327 F32 half_milimeter = 0.0005f;
328 F32 max_first_second_span = 3.f * (first_radius + second_radius) + OBJECT_SPAN_BONUS;
329 F32 linkable_distance = max_first_second_span - first_radius - second_radius - half_milimeter;
330
331 F32 max_full_span = 3.f * (0.5f * max_first_second_span + third_radius) + OBJECT_SPAN_BONUS;
332 F32 unlinkable_distance = max_full_span - 0.5f * linkable_distance - third_radius + half_milimeter;
333
334 // compute some random directions
335 LLVector3 first_direction(ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
336 first_direction.normalize();
337 LLVector3 second_direction(ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
338 second_direction.normalize();
339 LLVector3 third_direction(ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
340 third_direction.normalize();
341
342 // compute the centers
343 LLVector3 first_center = ll_frand(10.f) * first_direction;
344 LLVector3 second_center = first_center + ll_frand(linkable_distance) * second_direction;
345 LLVector3 first_join_center = 0.5f * (first_center + second_center);
346 LLVector3 third_center = first_join_center + unlinkable_distance * third_direction;
347
348 // make sure the second info links and the third does not
349 {
350 // initialize the infos
351 S32 index = 0;
352 LLPrimLinkInfo<S32> first_info(index++, LLSphere(first_center, first_radius));
353 LLPrimLinkInfo<S32> second_info(index++, LLSphere(second_center, second_radius));
354 LLPrimLinkInfo<S32> third_info(index++, LLSphere(third_center, third_radius));
355
356 // put the second and third infos in a list
357 std::list< LLPrimLinkInfo<S32> > info_list;
358 info_list.push_back(second_info);
359 info_list.push_back(third_info);
360
361 // merge the list with the first_info
362 first_info.mergeLinkableSet(info_list);
363 S32 prim_count = first_info.getPrimCount();
364
365 ensure_equals("prim count should be 2", prim_count, 2);
366 ensure_equals("unlinkable list should have length 1", (S32) info_list.size(), 1);
367 }
368
369 // reverse the order and make sure we get the same results
370 {
371 // initialize the infos
372 S32 index = 0;
373 LLPrimLinkInfo<S32> first_info(index++, LLSphere(first_center, first_radius));
374 LLPrimLinkInfo<S32> second_info(index++, LLSphere(second_center, second_radius));
375 LLPrimLinkInfo<S32> third_info(index++, LLSphere(third_center, third_radius));
376
377 // build the list in the reverse order
378 std::list< LLPrimLinkInfo<S32> > info_list;
379 info_list.push_back(third_info);
380 info_list.push_back(second_info);
381
382 // merge the list with the first_info
383 first_info.mergeLinkableSet(info_list);
384 S32 prim_count = first_info.getPrimCount();
385
386 ensure_equals("prim count should be 2", prim_count, 2);
387 ensure_equals("unlinkable list should have length 1", (S32) info_list.size(), 1);
388 }
389 }
390 }
391
392 template<> template<>
393 void linkable_object::test<4>()
394 {
395 // Here we test whether linkability is invarient under permutations
396 // of link order. To do this we generate a bunch of random spheres
397 // and then try to link them in different ways.
398 //
399 // NOTE: the linkability will only be invarient if there is only one
400 // linkable solution. Multiple solutions will exist if the set of
401 // candidates are larger than the maximum linkable distance, or more
402 // numerous than a single linked object can contain. This is easily
403 // understood by considering a very large set of link candidates,
404 // and first linking preferentially to the left until linking fails,
405 // then doing the same to the right -- the final solutions will differ.
406 // Hence for this test we must generate candidate sets that lie within
407 // the linkability envelope of a single object.
408 //
409 // NOTE: a random set of objects will tend to either be totally linkable
410 // or totally not. That is, the random orientations that
411
412 F32 root_center_range = 0.f;
413 F32 min_prim_radius = 0.1f;
414 F32 max_prim_radius = 2.f;
415
416 // Linkability is min(MAX_OBJECT_SPAN,3 *( R1 + R2 ) + BONUS)
417 // 3 * (min_prim_radius + min_prim_radius) + OBJECT_SPAN_BONUS = 6 * min_prim_radius + OBJECT_SPAN_BONUS;
418 // Use .45 instead of .5 to gaurantee objects are within the minimum span.
419 F32 child_center_range = 0.45f * ( (6*min_prim_radius) + OBJECT_SPAN_BONUS );
420
421 S32 number_of_tests = 100;
422 S32 number_of_spheres = 10;
423 S32 number_of_scrambles = 10;
424 S32 number_of_random_bubble_sorts = 10;
425
426 for (S32 test = 0; test < number_of_tests; ++test)
427 {
428 LLSphere sphere;
429 S32 sphere_index = 0;
430
431 // build the root piece
432 randomize_sphere(sphere, root_center_range, min_prim_radius, max_prim_radius);
433 info.set( sphere_index++, sphere );
434
435 // build the unlinked pieces
436 std::list< LLPrimLinkInfo<S32> > info_list;
437 for (; sphere_index < number_of_spheres; ++sphere_index)
438 {
439 randomize_sphere(sphere, child_center_range, min_prim_radius, max_prim_radius);
440 LLPrimLinkInfo<S32> child_info( sphere_index, sphere );
441 info_list.push_back(child_info);
442 }
443
444 // declare the variables used to store the results
445 std::list<S32> first_linked_list;
446
447 {
448 // the link attempt will modify our original info's, so we
449 // have to make copies of the originals for testing
450 LLPrimLinkInfo<S32> test_info( 0, LLSphere(info.getCenter(), 0.5f * info.getDiameter()) );
451 std::list< LLPrimLinkInfo<S32> > test_list;
452 test_list.assign(info_list.begin(), info_list.end());
453
454 // try to link
455 test_info.mergeLinkableSet(test_list);
456
457 ensure("All prims should link, but did not.",test_list.empty());
458
459 // store the results
460 test_info.getData(first_linked_list);
461 first_linked_list.sort();
462 }
463
464 // try to link the spheres in various random orders
465 for (S32 scramble = 0; scramble < number_of_scrambles; ++scramble)
466 {
467 LLPrimLinkInfo<S32> test_info(0, LLSphere(info.getCenter(), 0.5f * info.getDiameter()) );
468
469 // scramble the order of the info_list
470 std::list< LLPrimLinkInfo<S32> > test_list;
471 test_list.assign(info_list.begin(), info_list.end());
472 for (S32 i = 0; i < number_of_random_bubble_sorts; i++)
473 {
474 test_list.sort(random_sort);
475 }
476
477 // try to link
478 test_info.mergeLinkableSet(test_list);
479
480 // get the results
481 std::list<S32> linked_list;
482 test_info.getData(linked_list);
483 linked_list.sort();
484
485 ensure_equals("linked set size should be order independent",linked_list.size(),first_linked_list.size());
486 }
487 }
488 }
489}
490
diff --git a/linden/indra/test/test.vcproj b/linden/indra/test/test.vcproj
index 4476c2e..f720d9a 100644
--- a/linden/indra/test/test.vcproj
+++ b/linden/indra/test/test.vcproj
@@ -20,7 +20,7 @@
20 <Tool 20 <Tool
21 Name="VCCLCompilerTool" 21 Name="VCCLCompilerTool"
22 Optimization="0" 22 Optimization="0"
23 AdditionalIncludeDirectories="..\llcharacter;..\llcommon;..\lldatabase;..\llinventory;..\llmath;..\llmessage;..\llxml;&quot;..\..\libraries\i686-win32\include&quot;;..\..\libraries\include" 23 AdditionalIncludeDirectories="..\;..\llcharacter;..\llcommon;..\lldatabase;..\llinventory;..\llmath;..\llmessage;..\llprimitive;..\llxml;&quot;..\..\libraries\i686-win32\include&quot;;..\..\libraries\include"
24 PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;LL_WINDOWS;LL_DEBUG" 24 PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;LL_WINDOWS;LL_DEBUG"
25 MinimalRebuild="FALSE" 25 MinimalRebuild="FALSE"
26 BasicRuntimeChecks="3" 26 BasicRuntimeChecks="3"
@@ -35,7 +35,7 @@
35 <Tool 35 <Tool
36 Name="VCLinkerTool" 36 Name="VCLinkerTool"
37 AdditionalOptions="/FORCE:MULTIPLE" 37 AdditionalOptions="/FORCE:MULTIPLE"
38 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr8.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc71-mt-s.lib libcurld.lib libeay32.lib libexpatMT.lib llcommon.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib psapi.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib" 38 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr8.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc71-mt-sgd-1_34_1.lib libcurld.lib libeay32.lib libexpatMT.lib llcommon.lib llphysics.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib psapi.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib"
39 OutputFile="$(OutDir)/test.exe" 39 OutputFile="$(OutDir)/test.exe"
40 LinkIncremental="2" 40 LinkIncremental="2"
41 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_debug&quot;" 41 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_debug&quot;"
@@ -74,7 +74,7 @@
74 <Tool 74 <Tool
75 Name="VCCLCompilerTool" 75 Name="VCCLCompilerTool"
76 Optimization="0" 76 Optimization="0"
77 AdditionalIncludeDirectories="..\llcharacter;..\llcommon;..\lldatabase;..\llinventory;..\llmath;..\llmessage;..\llxml;&quot;..\..\libraries\i686-win32\include&quot;;..\..\libraries\include" 77 AdditionalIncludeDirectories="..\;..\llcharacter;..\llcommon;..\lldatabase;..\llinventory;..\llmath;..\llmessage;..\llprimitive;..\llxml;&quot;..\..\libraries\i686-win32\include&quot;;..\..\libraries\include"
78 PreprocessorDefinitions="WIN32;__WIN32;NDEBUG;_WINDOWS;LL_WINDOWS;LL_RELEASE;APR_DECLARE_STATIC;LL_HTTPD=1" 78 PreprocessorDefinitions="WIN32;__WIN32;NDEBUG;_WINDOWS;LL_WINDOWS;LL_RELEASE;APR_DECLARE_STATIC;LL_HTTPD=1"
79 MinimalRebuild="FALSE" 79 MinimalRebuild="FALSE"
80 BasicRuntimeChecks="3" 80 BasicRuntimeChecks="3"
@@ -90,7 +90,7 @@
90 <Tool 90 <Tool
91 Name="VCLinkerTool" 91 Name="VCLinkerTool"
92 AdditionalOptions="/FORCE:MULTIPLE" 92 AdditionalOptions="/FORCE:MULTIPLE"
93 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr8.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc71-mt-s.lib libcurl.lib libeay32.lib libexpatMT.lib llcommon.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib psapi.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib" 93 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr8.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc71-mt-s-1_34_1.lib libcurl.lib libeay32.lib libexpatMT.lib llcommon.lib llphysics.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib psapi.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib"
94 OutputFile="$(OutDir)/test.exe" 94 OutputFile="$(OutDir)/test.exe"
95 LinkIncremental="2" 95 LinkIncremental="2"
96 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_release&quot;" 96 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_release&quot;"
@@ -130,7 +130,7 @@
130 <Tool 130 <Tool
131 Name="VCCLCompilerTool" 131 Name="VCCLCompilerTool"
132 Optimization="0" 132 Optimization="0"
133 AdditionalIncludeDirectories="..\llcharacter;..\llcommon;..\lldatabase;..\llinventory;..\llmath;..\llmessage;..\llxml;&quot;..\..\libraries\i686-win32\include&quot;;..\..\libraries\include" 133 AdditionalIncludeDirectories="..\;..\llcharacter;..\llcommon;..\lldatabase;..\llinventory;..\llmath;..\llmessage;..\llprimitive;..\llxml;&quot;..\..\libraries\i686-win32\include&quot;;..\..\libraries\include"
134 PreprocessorDefinitions="WIN32;__WIN32;NDEBUG;_WINDOWS;LL_WINDOWS;LL_RELEASE;APR_DECLARE_STATIC;LL_HTTPD=1" 134 PreprocessorDefinitions="WIN32;__WIN32;NDEBUG;_WINDOWS;LL_WINDOWS;LL_RELEASE;APR_DECLARE_STATIC;LL_HTTPD=1"
135 MinimalRebuild="FALSE" 135 MinimalRebuild="FALSE"
136 BasicRuntimeChecks="3" 136 BasicRuntimeChecks="3"
@@ -145,7 +145,7 @@
145 Name="VCCustomBuildTool"/> 145 Name="VCCustomBuildTool"/>
146 <Tool 146 <Tool
147 Name="VCLinkerTool" 147 Name="VCLinkerTool"
148 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib gdi32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc71-mt-s.lib libcurl.lib libeay32.lib libexpatMT.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib psapi.lib shell32.lib ssleay32.lib user32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib" 148 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib gdi32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc71-mt-s-1_34_1.lib libcurl.lib libeay32.lib libexpatMT.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib psapi.lib shell32.lib ssleay32.lib user32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib"
149 OutputFile="$(OutDir)/test.exe" 149 OutputFile="$(OutDir)/test.exe"
150 LinkIncremental="2" 150 LinkIncremental="2"
151 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_release&quot;" 151 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_release&quot;"
@@ -219,6 +219,9 @@
219 RelativePath=".\lljoint_tut.cpp"> 219 RelativePath=".\lljoint_tut.cpp">
220 </File> 220 </File>
221 <File 221 <File
222 RelativePath=".\llmessageconfig_tut.cpp">
223 </File>
224 <File
222 RelativePath=".\llmime_tut.cpp"> 225 RelativePath=".\llmime_tut.cpp">
223 </File> 226 </File>
224 <File 227 <File
@@ -281,10 +284,14 @@
281 <File 284 <File
282 RelativePath=".\lluuidhashmap_tut.cpp"> 285 RelativePath=".\lluuidhashmap_tut.cpp">
283 </File> 286 </File>
287
284 <File 288 <File
285 RelativePath=".\math.cpp"> 289 RelativePath=".\math.cpp">
286 </File> 290 </File>
287 <File 291 <File
292 RelativePath=".\prim_linkability_tut.cpp">
293 </File>
294 <File
288 RelativePath=".\reflection_tut.cpp"> 295 RelativePath=".\reflection_tut.cpp">
289 </File> 296 </File>
290 <File 297 <File
diff --git a/linden/indra/test/test_vc8.vcproj b/linden/indra/test/test_vc8.vcproj
index 2f607cb..6d47de8 100644
--- a/linden/indra/test/test_vc8.vcproj
+++ b/linden/indra/test/test_vc8.vcproj
@@ -65,7 +65,7 @@
65 <Tool 65 <Tool
66 Name="VCLinkerTool" 66 Name="VCLinkerTool"
67 AdditionalOptions="/FORCE:MULTIPLE" 67 AdditionalOptions="/FORCE:MULTIPLE"
68 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr8.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc80-mt-s.lib libcurl.lib libeay32.lib libexpatMT.lib llcommon.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib" 68 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr8.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc80-mt-sgd-1_34_1.lib libboost_signals-vc80-mt-sgd-1_34_1.lib libcurl.lib libeay32.lib libexpatMT.lib llcommon.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib"
69 OutputFile="$(OutDir)/test.exe" 69 OutputFile="$(OutDir)/test.exe"
70 LinkIncremental="2" 70 LinkIncremental="2"
71 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_debug&quot;" 71 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_debug&quot;"
@@ -155,7 +155,7 @@
155 <Tool 155 <Tool
156 Name="VCLinkerTool" 156 Name="VCLinkerTool"
157 AdditionalOptions="/FORCE:MULTIPLE" 157 AdditionalOptions="/FORCE:MULTIPLE"
158 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr8.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc80-mt-s.lib libcurl.lib libeay32.lib libexpatMT.lib llcommon.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib" 158 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr8.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc80-mt-s-1_34_1.lib libboost_signals-vc80-mt-s-1_34_1.lib libcurl.lib libeay32.lib libexpatMT.lib llcommon.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib"
159 OutputFile="$(OutDir)/test.exe" 159 OutputFile="$(OutDir)/test.exe"
160 LinkIncremental="2" 160 LinkIncremental="2"
161 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_release&quot;" 161 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_release&quot;"
@@ -243,7 +243,7 @@
243 /> 243 />
244 <Tool 244 <Tool
245 Name="VCLinkerTool" 245 Name="VCLinkerTool"
246 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr8.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc80-mt-s.lib libcurl.lib libeay32.lib libexpatMT.lib llcommon.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib" 246 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr8.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc80-mt-s-1_34_1.lib libboost_signals-vc80-mt-s-1_34_1.lib libcurl.lib libeay32.lib libexpatMT.lib llcommon.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib"
247 OutputFile="$(OutDir)/test.exe" 247 OutputFile="$(OutDir)/test.exe"
248 LinkIncremental="2" 248 LinkIncremental="2"
249 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_release&quot;" 249 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_release&quot;"
diff --git a/linden/indra/test/test_vc9.vcproj b/linden/indra/test/test_vc9.vcproj
index 7230df4..d7fcfae 100644
--- a/linden/indra/test/test_vc9.vcproj
+++ b/linden/indra/test/test_vc9.vcproj
@@ -242,7 +242,7 @@
242 /> 242 />
243 <Tool 243 <Tool
244 Name="VCLinkerTool" 244 Name="VCLinkerTool"
245 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr8.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc80-mt-s.lib libcurl.lib libeay32.lib libexpatMT.lib llcommon.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib" 245 AdditionalDependencies="advapi32.lib apr-1.lib aprutil-1.lib comdlg32.lib dinput8.lib dsound.lib dxerr.lib dxguid.lib freetype.lib gdi32.lib glu32.lib jpeglib_6b.lib kernel32.lib libboost_regex-vc80-mt-s.lib libcurl.lib libeay32.lib libexpatMT.lib llcommon.lib llprimitive.lib llvfs.lib llxml.lib lscript_library.lib mswsock.lib netapi32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib opengl32.lib shell32.lib ssleay32.lib user32.lib Vfw32.lib winmm.lib winspool.lib ws2_32.lib xmlrpcepi.lib zlib.lib"
246 OutputFile="$(OutDir)/test.exe" 246 OutputFile="$(OutDir)/test.exe"
247 LinkIncremental="2" 247 LinkIncremental="2"
248 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_release&quot;" 248 AdditionalLibraryDirectories="&quot;../lib_$(ConfigurationName)/i686-win32&quot;;&quot;../../libraries/i686-win32/lib_release&quot;"