aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llprimitive/llprimlinkinfo.h
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/llprimitive/llprimlinkinfo.h
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 '')
-rw-r--r--linden/indra/llprimitive/llprimlinkinfo.h388
1 files changed, 388 insertions, 0 deletions
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