aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llprimitive
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llprimitive/llmaterialtable.cpp48
-rw-r--r--linden/indra/llprimitive/llmaterialtable.h57
-rw-r--r--linden/indra/llprimitive/llprimitive.cpp45
-rw-r--r--linden/indra/llprimitive/llprimitive.h54
-rw-r--r--linden/indra/llprimitive/llprimitive.vcproj15
-rw-r--r--linden/indra/llprimitive/llprimlinkinfo.h388
6 files changed, 586 insertions, 21 deletions
diff --git a/linden/indra/llprimitive/llmaterialtable.cpp b/linden/indra/llprimitive/llmaterialtable.cpp
index 537c968..5e45e44 100644
--- a/linden/indra/llprimitive/llmaterialtable.cpp
+++ b/linden/indra/llprimitive/llmaterialtable.cpp
@@ -39,6 +39,54 @@
39 39
40LLMaterialTable LLMaterialTable::basic(1); 40LLMaterialTable LLMaterialTable::basic(1);
41 41
42/*
43 Old Havok 1 constants
44
45// these are the approximately correct friction values for various materials
46// however Havok1's friction dynamics are not very correct, so the effective
47// friction coefficients that result from these numbers are approximately
48// 25-50% too low, more incorrect for the lower values.
49F32 const LLMaterialTable::FRICTION_MIN = 0.2f;
50F32 const LLMaterialTable::FRICTION_GLASS = 0.2f; // borosilicate glass
51F32 const LLMaterialTable::FRICTION_LIGHT = 0.2f; //
52F32 const LLMaterialTable::FRICTION_METAL = 0.3f; // steel
53F32 const LLMaterialTable::FRICTION_PLASTIC = 0.4f; // HDPE
54F32 const LLMaterialTable::FRICTION_WOOD = 0.6f; // southern pine
55F32 const LLMaterialTable::FRICTION_FLESH = 0.60f; // saltwater
56F32 const LLMaterialTable::FRICTION_LAND = 0.78f; // dirt
57F32 const LLMaterialTable::FRICTION_STONE = 0.8f; // concrete
58F32 const LLMaterialTable::FRICTION_RUBBER = 0.9f; //
59F32 const LLMaterialTable::FRICTION_MAX = 0.95f; //
60*/
61
62// #if LL_CURRENT_HAVOK_VERSION == LL_HAVOK_VERSION_460
63// Havok4 has more correct friction dynamics, however here we have to use
64// the "incorrect" equivalents for the legacy Havok1 behavior
65F32 const LLMaterialTable::FRICTION_MIN = 0.15f;
66F32 const LLMaterialTable::FRICTION_GLASS = 0.13f; // borosilicate glass
67F32 const LLMaterialTable::FRICTION_LIGHT = 0.14f; //
68F32 const LLMaterialTable::FRICTION_METAL = 0.22f; // steel
69F32 const LLMaterialTable::FRICTION_PLASTIC = 0.3f; // HDPE
70F32 const LLMaterialTable::FRICTION_WOOD = 0.44f; // southern pine
71F32 const LLMaterialTable::FRICTION_FLESH = 0.46f; // saltwater
72F32 const LLMaterialTable::FRICTION_LAND = 0.58f; // dirt
73F32 const LLMaterialTable::FRICTION_STONE = 0.6f; // concrete
74F32 const LLMaterialTable::FRICTION_RUBBER = 0.67f; //
75F32 const LLMaterialTable::FRICTION_MAX = 0.71f; //
76// #endif
77
78F32 const LLMaterialTable::RESTITUTION_MIN = 0.02f;
79F32 const LLMaterialTable::RESTITUTION_LAND = LLMaterialTable::RESTITUTION_MIN;
80F32 const LLMaterialTable::RESTITUTION_FLESH = 0.2f; // saltwater
81F32 const LLMaterialTable::RESTITUTION_STONE = 0.4f; // concrete
82F32 const LLMaterialTable::RESTITUTION_METAL = 0.4f; // steel
83F32 const LLMaterialTable::RESTITUTION_WOOD = 0.5f; // southern pine
84F32 const LLMaterialTable::RESTITUTION_GLASS = 0.7f; // borosilicate glass
85F32 const LLMaterialTable::RESTITUTION_PLASTIC = 0.7f; // HDPE
86F32 const LLMaterialTable::RESTITUTION_LIGHT = 0.7f; //
87F32 const LLMaterialTable::RESTITUTION_RUBBER = 0.9f; //
88F32 const LLMaterialTable::RESTITUTION_MAX = 0.95f;
89
42F32 const LLMaterialTable::DEFAULT_FRICTION = 0.5f; 90F32 const LLMaterialTable::DEFAULT_FRICTION = 0.5f;
43F32 const LLMaterialTable::DEFAULT_RESTITUTION = 0.4f; 91F32 const LLMaterialTable::DEFAULT_RESTITUTION = 0.4f;
44 92
diff --git a/linden/indra/llprimitive/llmaterialtable.h b/linden/indra/llprimitive/llmaterialtable.h
index b48c832..863fb25 100644
--- a/linden/indra/llprimitive/llmaterialtable.h
+++ b/linden/indra/llprimitive/llmaterialtable.h
@@ -33,11 +33,36 @@
33#define LL_LLMATERIALTABLE_H 33#define LL_LLMATERIALTABLE_H
34 34
35#include "lluuid.h" 35#include "lluuid.h"
36#include "linked_lists.h"
37#include "llstring.h" 36#include "llstring.h"
38 37
38#include <list>
39
39const U32 LLMATERIAL_INFO_NAME_LENGTH = 256; 40const U32 LLMATERIAL_INFO_NAME_LENGTH = 256;
40 41
42// We've moved toward more reasonable mass values for the Havok4 engine.
43// The LEGACY_DEFAULT_OBJECT_DENSITY is used to maintain support for
44// legacy scripts code (llGetMass()) and script energy consumption.
45const F32 DEFAULT_OBJECT_DENSITY = 1000.0f; // per m^3
46const F32 LEGACY_DEFAULT_OBJECT_DENSITY = 10.0f;
47
48// Avatars density depends on the collision shape used. The approximate
49// legacy volumes of avatars are:
50// Body_Length Body_Width Body_Fat Leg_Length Volume(m^3)
51// -------------------------------------------------------
52// min | min | min | min | 0.123 |
53// max | max | max | max | 0.208 |
54//
55// Either the avatar shape must be tweaked to match those volumes
56// or the DEFAULT_AVATAR_DENSITY must be adjusted to achieve the
57// legacy mass.
58//
59// The current density appears to be low because the mass and
60// inertia are computed as if the avatar were a cylinder which
61// has more volume than the actual collision shape of the avatar.
62// See the physics engine mass properties code for more info.
63const F32 DEFAULT_AVATAR_DENSITY = 445.3f; // was 444.24f;
64
65
41class LLMaterialInfo 66class LLMaterialInfo
42{ 67{
43public: 68public:
@@ -84,9 +109,33 @@ public:
84class LLMaterialTable 109class LLMaterialTable
85{ 110{
86public: 111public:
112 static const F32 FRICTION_MIN;
113 static const F32 FRICTION_GLASS;
114 static const F32 FRICTION_LIGHT;
115 static const F32 FRICTION_METAL;
116 static const F32 FRICTION_PLASTIC;
117 static const F32 FRICTION_WOOD;
118 static const F32 FRICTION_LAND;
119 static const F32 FRICTION_STONE;
120 static const F32 FRICTION_FLESH;
121 static const F32 FRICTION_RUBBER;
122 static const F32 FRICTION_MAX;
123
124 static const F32 RESTITUTION_MIN;
125 static const F32 RESTITUTION_LAND;
126 static const F32 RESTITUTION_FLESH;
127 static const F32 RESTITUTION_STONE;
128 static const F32 RESTITUTION_METAL;
129 static const F32 RESTITUTION_WOOD;
130 static const F32 RESTITUTION_GLASS;
131 static const F32 RESTITUTION_PLASTIC;
132 static const F32 RESTITUTION_LIGHT;
133 static const F32 RESTITUTION_RUBBER;
134 static const F32 RESTITUTION_MAX;
135
87 typedef std::list<LLMaterialInfo*> info_list_t; 136 typedef std::list<LLMaterialInfo*> info_list_t;
88 info_list_t mMaterialInfoList; 137 info_list_t mMaterialInfoList;
89 138
90 LLUUID *mCollisionSoundMatrix; 139 LLUUID *mCollisionSoundMatrix;
91 LLUUID *mSlidingSoundMatrix; 140 LLUUID *mSlidingSoundMatrix;
92 LLUUID *mRollingSoundMatrix; 141 LLUUID *mRollingSoundMatrix;
@@ -117,8 +166,8 @@ public:
117 char* getName(U8 mcode); 166 char* getName(U8 mcode);
118 167
119 F32 getDensity(U8 mcode); // kg/m^3, 0 if not found 168 F32 getDensity(U8 mcode); // kg/m^3, 0 if not found
120 F32 getFriction(U8 mcode); // havok values 169 F32 getFriction(U8 mcode); // physics values
121 F32 getRestitution(U8 mcode); // havok values 170 F32 getRestitution(U8 mcode); // physics values
122 F32 getHPMod(U8 mcode); 171 F32 getHPMod(U8 mcode);
123 F32 getDamageMod(U8 mcode); 172 F32 getDamageMod(U8 mcode);
124 F32 getEPMod(U8 mcode); 173 F32 getEPMod(U8 mcode);
diff --git a/linden/indra/llprimitive/llprimitive.cpp b/linden/indra/llprimitive/llprimitive.cpp
index 91d3c4e..a906926 100644
--- a/linden/indra/llprimitive/llprimitive.cpp
+++ b/linden/indra/llprimitive/llprimitive.cpp
@@ -113,9 +113,38 @@ const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE = FALSE;
113 113
114const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e"; 114const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e";
115 115
116//static
117// LEGACY: by default we use the LLVolumeMgr::gVolumeMgr global
118// TODO -- eliminate this global from the codebase!
119LLVolumeMgr* LLPrimitive::sVolumeManager = NULL;
120
121// static
122void LLPrimitive::setVolumeManager( LLVolumeMgr* volume_manager )
123{
124 if ( !volume_manager || sVolumeManager )
125 {
126 llerrs << "Unable to set LLPrimitive::sVolumeManager to NULL" << llendl;
127 }
128 sVolumeManager = volume_manager;
129}
130
131// static
132bool LLPrimitive::cleanupVolumeManager()
133{
134 BOOL res = FALSE;
135 if (sVolumeManager)
136 {
137 res = sVolumeManager->cleanup();
138 delete sVolumeManager;
139 sVolumeManager = NULL;
140 }
141 return res;
142}
143
116 144
117//=============================================================== 145//===============================================================
118LLPrimitive::LLPrimitive() 146LLPrimitive::LLPrimitive()
147: mMiscFlags(0)
119{ 148{
120 mPrimitiveCode = 0; 149 mPrimitiveCode = 0;
121 150
@@ -149,7 +178,7 @@ LLPrimitive::~LLPrimitive()
149 // Cleanup handled by volume manager 178 // Cleanup handled by volume manager
150 if (mVolumep) 179 if (mVolumep)
151 { 180 {
152 gVolumeMgr->cleanupVolume(mVolumep); 181 sVolumeManager->cleanupVolume(mVolumep);
153 } 182 }
154 mVolumep = NULL; 183 mVolumep = NULL;
155} 184}
@@ -162,7 +191,7 @@ LLPrimitive *LLPrimitive::createPrimitive(LLPCode p_code)
162 191
163 if (retval) 192 if (retval)
164 { 193 {
165 retval->init(p_code); 194 retval->init_primitive(p_code);
166 } 195 }
167 else 196 else
168 { 197 {
@@ -173,7 +202,7 @@ LLPrimitive *LLPrimitive::createPrimitive(LLPCode p_code)
173} 202}
174 203
175//=============================================================== 204//===============================================================
176void LLPrimitive::init(LLPCode p_code) 205void LLPrimitive::init_primitive(LLPCode p_code)
177{ 206{
178 if (mNumTEs) 207 if (mNumTEs)
179 { 208 {
@@ -533,6 +562,8 @@ S32 LLPrimitive::setTEGlow(const U8 te, const F32 glow)
533 562
534LLPCode LLPrimitive::legacyToPCode(const U8 legacy) 563LLPCode LLPrimitive::legacyToPCode(const U8 legacy)
535{ 564{
565 // TODO: Should this default to something valid?
566 // Maybe volume?
536 LLPCode pcode = 0; 567 LLPCode pcode = 0;
537 568
538 switch (legacy) 569 switch (legacy)
@@ -621,7 +652,7 @@ LLPCode LLPrimitive::legacyToPCode(const U8 legacy)
621 pcode = LL_PCODE_TREE_NEW; 652 pcode = LL_PCODE_TREE_NEW;
622 break; 653 break;
623 default: 654 default:
624 llwarns << "Unknown legacy code " << legacy << "!" << llendl; 655 llwarns << "Unknown legacy code " << legacy << " [" << (S32)legacy << "]!" << llendl;
625 } 656 }
626 657
627 return pcode; 658 return pcode;
@@ -904,10 +935,10 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
904 } 935 }
905 } 936 }
906 937
907 volumep = gVolumeMgr->getVolume(volume_params, detail); 938 volumep = sVolumeManager->getVolume(volume_params, detail);
908 if (volumep == mVolumep) 939 if (volumep == mVolumep)
909 { 940 {
910 gVolumeMgr->cleanupVolume( volumep ); // gVolumeMgr->getVolume() creates a reference, but we don't need a second one. 941 sVolumeManager->cleanupVolume( volumep ); // LLVolumeMgr::getVolume() creates a reference, but we don't need a second one.
911 return TRUE; 942 return TRUE;
912 } 943 }
913 } 944 }
@@ -950,7 +981,7 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
950 981
951 982
952 // build the new object 983 // build the new object
953 gVolumeMgr->cleanupVolume(mVolumep); 984 sVolumeManager->cleanupVolume(mVolumep);
954 mVolumep = volumep; 985 mVolumep = volumep;
955 986
956 U32 new_face_mask = mVolumep->mFaceMask; 987 U32 new_face_mask = mVolumep->mFaceMask;
diff --git a/linden/indra/llprimitive/llprimitive.h b/linden/indra/llprimitive/llprimitive.h
index 3b43e8f..e698a31 100644
--- a/linden/indra/llprimitive/llprimitive.h
+++ b/linden/indra/llprimitive/llprimitive.h
@@ -48,6 +48,7 @@ class LLColor4;
48class LLColor3; 48class LLColor3;
49class LLTextureEntry; 49class LLTextureEntry;
50class LLDataPacker; 50class LLDataPacker;
51class LLVolumeMgr;
51 52
52enum LLGeomType // NOTE: same vals as GL Ids 53enum LLGeomType // NOTE: same vals as GL Ids
53{ 54{
@@ -269,11 +270,32 @@ public:
269class LLPrimitive : public LLXform 270class LLPrimitive : public LLXform
270{ 271{
271public: 272public:
273
274 // HACK for removing LLPrimitive's dependency on gVolumeMgr global.
275 // If a different LLVolumeManager is instantiated and set early enough
276 // then the LLPrimitive class will use it instead of gVolumeMgr.
277 static LLVolumeMgr* getVolumeManager() { return sVolumeManager; }
278 static void setVolumeManager( LLVolumeMgr* volume_manager);
279 static bool cleanupVolumeManager();
280
281 // these flags influence how the RigidBody representation is built
282 static const U32 PRIM_FLAG_PHANTOM = 0x1 << 0;
283 static const U32 PRIM_FLAG_VOLUME_DETECT = 0x1 << 1;
284 static const U32 PRIM_FLAG_DYNAMIC = 0x1 << 2;
285 static const U32 PRIM_FLAG_AVATAR = 0x1 << 3;
286 static const U32 PRIM_FLAG_SCULPT = 0x1 << 4;
287 // not used yet, but soon
288 static const U32 PRIM_FLAG_COLLISION_CALLBACK = 0x1 << 5;
289 static const U32 PRIM_FLAG_CONVEX = 0x1 << 6;
290 static const U32 PRIM_FLAG_DEFAULT_VOLUME = 0x1 << 7;
291 static const U32 PRIM_FLAG_SITTING = 0x1 << 8;
292 static const U32 PRIM_FLAG_SITTING_ON_GROUND = 0x1 << 9; // Set along with PRIM_FLAG_SITTING
293
272 LLPrimitive(); 294 LLPrimitive();
273 virtual ~LLPrimitive(); 295 virtual ~LLPrimitive();
274 296
275 static LLPrimitive *createPrimitive(LLPCode p_code); 297 static LLPrimitive *createPrimitive(LLPCode p_code);
276 void init(LLPCode p_code); 298 void init_primitive(LLPCode p_code);
277 299
278 void setPCode(const LLPCode pcode); 300 void setPCode(const LLPCode pcode);
279 const LLVolume *getVolumeConst() const { return mVolumep; } // HACK for Windoze confusion about ostream operator in LLVolume 301 const LLVolume *getVolumeConst() const { return mVolumep; } // HACK for Windoze confusion about ostream operator in LLVolume
@@ -369,8 +391,15 @@ public:
369 391
370 void setTextureList(LLTextureEntry *listp); 392 void setTextureList(LLTextureEntry *listp);
371 393
372 inline BOOL isAvatar() const; 394 inline BOOL isAvatar() const;
373 395 inline BOOL isSittingAvatar() const;
396 inline BOOL isSittingAvatarOnGround() const;
397
398 void setFlags(U32 flags) { mMiscFlags = flags; }
399 void addFlags(U32 flags) { mMiscFlags |= flags; }
400 void removeFlags(U32 flags) { mMiscFlags &= ~flags; }
401 U32 getFlags() const { return mMiscFlags; }
402
374 static const char *pCodeToString(const LLPCode pcode); 403 static const char *pCodeToString(const LLPCode pcode);
375 static LLPCode legacyToPCode(const U8 legacy); 404 static LLPCode legacyToPCode(const U8 legacy);
376 static U8 pCodeToLegacy(const LLPCode pcode); 405 static U8 pCodeToLegacy(const LLPCode pcode);
@@ -388,11 +417,28 @@ protected:
388 LLTextureEntry *mTextureList; // list of texture GUIDs, scales, offsets 417 LLTextureEntry *mTextureList; // list of texture GUIDs, scales, offsets
389 U8 mMaterial; // Material code 418 U8 mMaterial; // Material code
390 U8 mNumTEs; // # of faces on the primitve 419 U8 mNumTEs; // # of faces on the primitve
420 U32 mMiscFlags; // home for misc bools
421
422 static LLVolumeMgr* sVolumeManager;
391}; 423};
392 424
393inline BOOL LLPrimitive::isAvatar() const 425inline BOOL LLPrimitive::isAvatar() const
394{ 426{
395 return mPrimitiveCode == LL_PCODE_LEGACY_AVATAR; 427 return ( LL_PCODE_LEGACY_AVATAR == mPrimitiveCode ) ? TRUE : FALSE;
428}
429
430inline BOOL LLPrimitive::isSittingAvatar() const
431{
432 // this is only used server-side
433 return ( LL_PCODE_LEGACY_AVATAR == mPrimitiveCode
434 && ((getFlags() & (PRIM_FLAG_SITTING | PRIM_FLAG_SITTING_ON_GROUND)) != 0) ) ? TRUE : FALSE;
435}
436
437inline BOOL LLPrimitive::isSittingAvatarOnGround() const
438{
439 // this is only used server-side
440 return ( LL_PCODE_LEGACY_AVATAR == mPrimitiveCode
441 && ((getFlags() & PRIM_FLAG_SITTING_ON_GROUND) != 0) ) ? TRUE : FALSE;
396} 442}
397 443
398// static 444// static
diff --git a/linden/indra/llprimitive/llprimitive.vcproj b/linden/indra/llprimitive/llprimitive.vcproj
index b04d938..620ace4 100644
--- a/linden/indra/llprimitive/llprimitive.vcproj
+++ b/linden/indra/llprimitive/llprimitive.vcproj
@@ -19,8 +19,8 @@
19 <Tool 19 <Tool
20 Name="VCCLCompilerTool" 20 Name="VCCLCompilerTool"
21 Optimization="0" 21 Optimization="0"
22 AdditionalIncludeDirectories="..\llxml;..\llprimitive;..\llcommon;..\llmath;..\llmessage;..\..\libraries\i686-win32\include;..\..\libraries\include\" 22 AdditionalIncludeDirectories="..\;..\llxml;..\llprimitive;..\llcommon;..\llmath;..\llmessage;..\..\libraries\i686-win32\include;..\..\libraries\include"
23 PreprocessorDefinitions="WIN32;_DEBUG;_LIB;LL_WINDOWS;LL_DEBUG" 23 PreprocessorDefinitions="WIN32;_DEBUG;_LIB;LL_WINDOWS;LL_DEBUG;LL_CURRENT_HAVOK_VERSION=460"
24 MinimalRebuild="TRUE" 24 MinimalRebuild="TRUE"
25 BasicRuntimeChecks="3" 25 BasicRuntimeChecks="3"
26 RuntimeLibrary="1" 26 RuntimeLibrary="1"
@@ -64,8 +64,8 @@
64 <Tool 64 <Tool
65 Name="VCCLCompilerTool" 65 Name="VCCLCompilerTool"
66 AdditionalOptions="/Oy-" 66 AdditionalOptions="/Oy-"
67 AdditionalIncludeDirectories="..\llxml;..\llprimitive;..\llcommon;..\llmath;..\llmessage;..\..\libraries\i686-win32\include;..\..\libraries\include\" 67 AdditionalIncludeDirectories="..\;..\llxml;..\llprimitive;..\llcommon;..\llmath;..\llmessage;..\..\libraries\i686-win32\include;..\..\libraries\include\"
68 PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;LL_RELEASE" 68 PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;LL_RELEASE;LL_CURRENT_HAVOK_VERSION=460"
69 RuntimeLibrary="0" 69 RuntimeLibrary="0"
70 StructMemberAlignment="0" 70 StructMemberAlignment="0"
71 ForceConformanceInForLoopScope="TRUE" 71 ForceConformanceInForLoopScope="TRUE"
@@ -108,8 +108,8 @@
108 Name="VCCLCompilerTool" 108 Name="VCCLCompilerTool"
109 AdditionalOptions="/Oy-" 109 AdditionalOptions="/Oy-"
110 Optimization="0" 110 Optimization="0"
111 AdditionalIncludeDirectories="..\llxml;..\llprimitive;..\llcommon;..\llmath;..\llmessage;..\..\libraries\i686-win32\include;..\..\libraries\include\" 111 AdditionalIncludeDirectories="..\;..\llxml;..\llprimitive;..\llcommon;..\llmath;..\llmessage;..\..\libraries\i686-win32\include;..\..\libraries\include"
112 PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;LL_RELEASE" 112 PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;LL_RELEASE;LL_CURRENT_HAVOK_VERSION=460"
113 RuntimeLibrary="0" 113 RuntimeLibrary="0"
114 StructMemberAlignment="0" 114 StructMemberAlignment="0"
115 ForceConformanceInForLoopScope="TRUE" 115 ForceConformanceInForLoopScope="TRUE"
@@ -186,6 +186,9 @@
186 RelativePath=".\llprimitive.h"> 186 RelativePath=".\llprimitive.h">
187 </File> 187 </File>
188 <File 188 <File
189 RelativePath=".\llprimlinkinfo.h">
190 </File>
191 <File
189 RelativePath=".\lltextureanim.h"> 192 RelativePath=".\lltextureanim.h">
190 </File> 193 </File>
191 <File 194 <File
diff --git a/linden/indra/llprimitive/llprimlinkinfo.h b/linden/indra/llprimitive/llprimlinkinfo.h
new file mode 100644
index 0000000..8de5ca0
--- /dev/null
+++ b/linden/indra/llprimitive/llprimlinkinfo.h
@@ -0,0 +1,388 @@
1/**
2 * @file llprimlinkinfo.h
3 * @author andrew@lindenlab.com
4 * @brief A template for determining which prims in a set are linkable
5 *
6 * $LicenseInfo:firstyear=2007&license=internal$
7 *
8 * Copyright (c) 2007-2008, Linden Research, Inc.
9 *
10 * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
11 * this source code is governed by the Linden Lab Source Code Disclosure
12 * Agreement ("Agreement") previously entered between you and Linden
13 * Lab. By accessing, using, copying, modifying or distributing this
14 * software, you acknowledge that you have been informed of your
15 * obligations under the Agreement and agree to abide by those obligations.
16 *
17 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
18 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
19 * COMPLETENESS OR PERFORMANCE.
20 * $/LicenseInfo$
21 */
22
23
24#ifndef LL_PRIM_LINK_INFO_H
25#define LL_PRIM_LINK_INFO_H
26
27// system includes
28#include <iostream>
29#include <map>
30#include <list>
31#include <vector>
32
33// common includes
34#include "stdtypes.h"
35#include "v3math.h"
36#include "llquaternion.h"
37#include "llsphere.h"
38
39
40const F32 MAX_OBJECT_SPAN = 54.f; // max distance from outside edge of an object to the farthest edge
41const F32 OBJECT_SPAN_BONUS = 2.f; // infinitesimally small prims can always link up to this distance
42const S32 MAX_PRIMS_PER_OBJECT = 255;
43
44
45template < typename DATA_TYPE >
46class LLPrimLinkInfo
47{
48public:
49 LLPrimLinkInfo();
50 LLPrimLinkInfo( DATA_TYPE data, const LLSphere& sphere );
51 ~LLPrimLinkInfo();
52
53 void set( DATA_TYPE data, const LLSphere& sphere );
54 void append( DATA_TYPE data, const LLSphere& sphere );
55 void getData( std::list< DATA_TYPE >& data_list ) const;
56 F32 getDiameter() const;
57 LLVector3 getCenter() const;
58
59 // returns 'true' if this info can link with other_info
60 bool canLink( const LLPrimLinkInfo< DATA_TYPE >& other_info );
61
62 S32 getPrimCount() const { return mDataMap.size(); }
63
64 void mergeLinkableSet( typename std::list< LLPrimLinkInfo < DATA_TYPE > >& unlinked );
65
66 void transform(const LLVector3& position, const LLQuaternion& rotation);
67
68private:
69 // returns number of merges made
70 S32 merge(LLPrimLinkInfo< DATA_TYPE >& other_info);
71
72 // returns number of collapses made
73 static S32 collapse(typename std::list< LLPrimLinkInfo < DATA_TYPE > >& unlinked );
74
75 void computeBoundingSphere();
76
77 // Internal utility to encapsulate the link rules
78 F32 get_max_linkable_span(const LLSphere& first, const LLSphere& second);
79 F32 get_span(const LLSphere& first, const LLSphere& second);
80
81private:
82 std::map< DATA_TYPE, LLSphere > mDataMap;
83 LLSphere mBoundingSphere;
84};
85
86
87
88template < typename DATA_TYPE >
89LLPrimLinkInfo< DATA_TYPE >::LLPrimLinkInfo()
90: mBoundingSphere( LLVector3(0.f, 0.f, 0.f), 0.f )
91{
92}
93
94template < typename DATA_TYPE >
95LLPrimLinkInfo< DATA_TYPE >::LLPrimLinkInfo( DATA_TYPE data, const LLSphere& sphere)
96: mBoundingSphere(sphere)
97{
98 mDataMap[data] = sphere;
99}
100
101template < typename DATA_TYPE >
102LLPrimLinkInfo< DATA_TYPE >::~LLPrimLinkInfo()
103{
104 mDataMap.clear();
105}
106
107template < typename DATA_TYPE >
108void LLPrimLinkInfo< DATA_TYPE>::set( DATA_TYPE data, const LLSphere& sphere )
109{
110 if (!mDataMap.empty())
111 {
112 mDataMap.clear();
113 }
114 mDataMap[data] = sphere;
115 mBoundingSphere = sphere;
116}
117
118template < typename DATA_TYPE >
119void LLPrimLinkInfo< DATA_TYPE>::append( DATA_TYPE data, const LLSphere& sphere )
120{
121 mDataMap[data] = sphere;
122 if (!mBoundingSphere.contains(sphere))
123 {
124 computeBoundingSphere();
125 }
126}
127
128template < typename DATA_TYPE >
129void LLPrimLinkInfo< DATA_TYPE >::getData( std::list< DATA_TYPE >& data_list) const
130{
131 typename std::map< DATA_TYPE, LLSphere >::const_iterator map_itr;
132 for (map_itr = mDataMap.begin(); map_itr != mDataMap.end(); ++map_itr)
133 {
134 data_list.push_back(map_itr->first);
135 }
136}
137
138template < typename DATA_TYPE >
139F32 LLPrimLinkInfo< DATA_TYPE >::getDiameter() const
140{
141 return 2.f * mBoundingSphere.getRadius();
142}
143
144template < typename DATA_TYPE >
145LLVector3 LLPrimLinkInfo< DATA_TYPE >::getCenter() const
146{
147 return mBoundingSphere.getCenter();
148}
149
150template < typename DATA_TYPE >
151F32 LLPrimLinkInfo< DATA_TYPE >::get_max_linkable_span(const LLSphere& first, const LLSphere& second)
152{
153 F32 max_span = 3.f * (first.getRadius() + second.getRadius()) + OBJECT_SPAN_BONUS;
154 if (max_span > MAX_OBJECT_SPAN)
155 {
156 max_span = MAX_OBJECT_SPAN;
157 }
158
159 return max_span;
160}
161
162template < typename DATA_TYPE >
163F32 LLPrimLinkInfo< DATA_TYPE >::get_span(const LLSphere& first, const LLSphere& second)
164{
165 F32 span = (first.getCenter() - second.getCenter()).length()
166 + first.getRadius() + second.getRadius();
167 return span;
168}
169
170// static
171// returns 'true' if this info can link with any part of other_info
172template < typename DATA_TYPE >
173bool LLPrimLinkInfo< DATA_TYPE >::canLink(const LLPrimLinkInfo& other_info)
174{
175 F32 max_span = get_max_linkable_span(mBoundingSphere, other_info.mBoundingSphere);
176
177 F32 span = get_span(mBoundingSphere, other_info.mBoundingSphere);
178
179 if (span <= max_span)
180 {
181 // The entire other_info fits inside the max span.
182 return TRUE;
183 }
184 else if (span > max_span + 2.f * other_info.mBoundingSphere.getRadius())
185 {
186 // there is no way any piece of other_info could link with this one
187 return FALSE;
188 }
189
190 // there may be a piece of other_info that is linkable
191 typename std::map< DATA_TYPE, LLSphere >::const_iterator map_itr;
192 for (map_itr = other_info.mDataMap.begin(); map_itr != other_info.mDataMap.end(); ++map_itr)
193 {
194 const LLSphere& other_sphere = (*map_itr).second;
195 max_span = get_max_linkable_span(mBoundingSphere, other_sphere);
196
197 span = get_span(mBoundingSphere, other_sphere);
198
199 if (span <= max_span)
200 {
201 // found one piece that is linkable
202 return TRUE;
203 }
204 }
205 return FALSE;
206}
207
208// merges elements of 'unlinked'
209// returns number of links made (NOT final prim count, NOR linked prim count)
210// and removes any linkable infos from 'unlinked'
211template < typename DATA_TYPE >
212void LLPrimLinkInfo< DATA_TYPE >::mergeLinkableSet(std::list< LLPrimLinkInfo< DATA_TYPE > > & unlinked)
213{
214 bool linked_something = true;
215 while (linked_something)
216 {
217 linked_something = false;
218
219 typename std::list< LLPrimLinkInfo< DATA_TYPE > >::iterator other_itr = unlinked.begin();
220 while ( other_itr != unlinked.end()
221 && getPrimCount() < MAX_PRIMS_PER_OBJECT )
222 {
223 S32 merge_count = merge(*other_itr);
224 if (merge_count > 0)
225 {
226 linked_something = true;
227 }
228 if (0 == (*other_itr).getPrimCount())
229 {
230 unlinked.erase(other_itr++);
231 }
232 else
233 {
234 ++other_itr;
235 }
236 }
237 if (!linked_something
238 && unlinked.size() > 1)
239 {
240 S32 collapse_count = collapse(unlinked);
241 if (collapse_count > 0)
242 {
243 linked_something = true;
244 }
245 }
246 }
247}
248
249// transforms all of the spheres into a new reference frame
250template < typename DATA_TYPE >
251void LLPrimLinkInfo< DATA_TYPE >::transform(const LLVector3& position, const LLQuaternion& rotation)
252{
253 typename std::map< DATA_TYPE, LLSphere >::iterator map_itr;
254 for (map_itr = mDataMap.begin(); map_itr != mDataMap.end(); ++map_itr)
255 {
256 (*map_itr).second.setCenter((*map_itr).second.getCenter() * rotation + position);
257 }
258 mBoundingSphere.setCenter(mBoundingSphere.getCenter() * rotation + position);
259}
260
261// private
262// returns number of links made
263template < typename DATA_TYPE >
264S32 LLPrimLinkInfo< DATA_TYPE >::merge(LLPrimLinkInfo& other_info)
265{
266 S32 link_count = 0;
267
268// F32 other_radius = other_info.mBoundingSphere.getRadius();
269// other_info.computeBoundingSphere();
270// if ( other_radius != other_info.mBoundingSphere.getRadius() )
271// {
272// llinfos << "Other bounding sphere changed!!" << llendl;
273// }
274
275// F32 this_radius = mBoundingSphere.getRadius();
276// computeBoundingSphere();
277// if ( this_radius != mBoundingSphere.getRadius() )
278// {
279// llinfos << "This bounding sphere changed!!" << llendl;
280// }
281
282
283 F32 max_span = get_max_linkable_span(mBoundingSphere, other_info.mBoundingSphere);
284
285 // F32 center_dist = (mBoundingSphere.getCenter() - other_info.mBoundingSphere.getCenter()).length();
286 // llinfos << "objects are " << center_dist << "m apart" << llendl;
287 F32 span = get_span(mBoundingSphere, other_info.mBoundingSphere);
288
289 F32 span_limit = max_span + (2.f * other_info.mBoundingSphere.getRadius());
290 if (span > span_limit)
291 {
292 // there is no way any piece of other_info could link with this one
293 // llinfos << "span too large: " << span << " vs. " << span_limit << llendl;
294 return 0;
295 }
296
297 bool completely_linkable = (span <= max_span) ? true : false;
298
299 typename std::map< DATA_TYPE, LLSphere >::iterator map_itr = other_info.mDataMap.begin();
300 while (map_itr != other_info.mDataMap.end()
301 && getPrimCount() < MAX_PRIMS_PER_OBJECT )
302 {
303 DATA_TYPE other_data = (*map_itr).first;
304 LLSphere& other_sphere = (*map_itr).second;
305
306 if (!completely_linkable)
307 {
308 max_span = get_max_linkable_span(mBoundingSphere, other_sphere);
309
310 F32 span = get_span(mBoundingSphere, other_sphere);
311
312 if (span > max_span)
313 {
314 ++map_itr;
315 continue;
316 }
317 }
318
319 mDataMap[other_data] = other_sphere;
320 ++link_count;
321
322 if (!mBoundingSphere.contains(other_sphere) )
323 {
324 computeBoundingSphere();
325 }
326
327 // remove from the other info
328 other_info.mDataMap.erase(map_itr++);
329 }
330
331 if (link_count > 0 && other_info.getPrimCount() > 0)
332 {
333 other_info.computeBoundingSphere();
334 }
335 return link_count;
336}
337
338// links any linkable elements of unlinked
339template < typename DATA_TYPE >
340S32 LLPrimLinkInfo< DATA_TYPE >::collapse(std::list< LLPrimLinkInfo< DATA_TYPE > > & unlinked)
341{
342 S32 link_count = 0;
343 bool linked_something = true;
344 while (linked_something)
345 {
346 linked_something = false;
347
348 typename std::list< LLPrimLinkInfo< DATA_TYPE > >::iterator this_itr = unlinked.begin();
349 typename std::list< LLPrimLinkInfo< DATA_TYPE > >::iterator other_itr = this_itr;
350 ++other_itr;
351 while ( other_itr != unlinked.end() )
352
353 {
354 S32 merge_count = (*this_itr).merge(*other_itr);
355 if (merge_count > 0)
356 {
357 linked_something = true;
358 link_count += merge_count;
359 }
360 if (0 == (*other_itr).getPrimCount())
361 {
362 unlinked.erase(other_itr++);
363 }
364 else
365 {
366 ++other_itr;
367 }
368 }
369 }
370 return link_count;
371}
372
373
374template < typename DATA_TYPE >
375void LLPrimLinkInfo< DATA_TYPE >::computeBoundingSphere()
376{
377 std::vector< LLSphere > sphere_list;
378 typename std::map< DATA_TYPE, LLSphere >::const_iterator map_itr;
379 for (map_itr = mDataMap.begin(); map_itr != mDataMap.end(); ++map_itr)
380 {
381 sphere_list.push_back(map_itr->second);
382 }
383 mBoundingSphere = LLSphere::getBoundingSphere(sphere_list);
384}
385
386
387#endif
388