diff options
Diffstat (limited to 'linden/indra/newview/llgenepool.cpp')
-rw-r--r-- | linden/indra/newview/llgenepool.cpp | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/linden/indra/newview/llgenepool.cpp b/linden/indra/newview/llgenepool.cpp new file mode 100644 index 0000000..33cb70d --- /dev/null +++ b/linden/indra/newview/llgenepool.cpp | |||
@@ -0,0 +1,386 @@ | |||
1 | /** | ||
2 | * @file llgenepool.cpp | ||
3 | * @brief LLGenePool class implementation | ||
4 | * | ||
5 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "llviewerprecompiledheaders.h" | ||
29 | |||
30 | #include "llgenepool.h" | ||
31 | #include "llxmltree.h" | ||
32 | #include "llvoavatar.h" | ||
33 | #include "lluuid.h" | ||
34 | #include "llagent.h" | ||
35 | #include "llviewervisualparam.h" | ||
36 | #include "llxmltree.h" | ||
37 | #include "llviewerimagelist.h" | ||
38 | #include "llappearance.h" | ||
39 | |||
40 | #include "lldir.h" | ||
41 | |||
42 | LLGenePool::LLGenePool() | ||
43 | : | ||
44 | mLoaded( FALSE ) | ||
45 | { | ||
46 | } | ||
47 | |||
48 | LLGenePool::~LLGenePool() | ||
49 | { | ||
50 | for( S32 i = 0; i < mArchetypes.count(); i++ ) | ||
51 | { | ||
52 | delete mArchetypes[i]; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | |||
57 | BOOL LLGenePool::load() | ||
58 | { | ||
59 | char filename[MAX_PATH]; | ||
60 | |||
61 | strcpy(filename,gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"genepool.xml").c_str()); | ||
62 | |||
63 | if( mLoaded ) | ||
64 | { | ||
65 | return TRUE; | ||
66 | } | ||
67 | |||
68 | LLXmlTree xml_tree; | ||
69 | BOOL success = xml_tree.parseFile( filename, FALSE ); | ||
70 | if( !success ) | ||
71 | { | ||
72 | return FALSE; | ||
73 | } | ||
74 | |||
75 | LLXmlTreeNode* root = xml_tree.getRoot(); | ||
76 | if( !root ) | ||
77 | { | ||
78 | return FALSE; | ||
79 | } | ||
80 | |||
81 | //------------------------------------------------------------------------- | ||
82 | // <linden_genepool version="1.0"> (root) | ||
83 | //------------------------------------------------------------------------- | ||
84 | if( !root->hasName( "linden_genepool" ) ) | ||
85 | { | ||
86 | llwarns << "Invalid linden_genepool file header: " << filename << llendl; | ||
87 | return FALSE; | ||
88 | } | ||
89 | |||
90 | LLString version; | ||
91 | static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); | ||
92 | if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) | ||
93 | { | ||
94 | llwarns << "Invalid linden_genepool file version: " << version << llendl; | ||
95 | return FALSE; | ||
96 | } | ||
97 | |||
98 | //------------------------------------------------------------------------- | ||
99 | // <archetype> | ||
100 | //------------------------------------------------------------------------- | ||
101 | for (LLXmlTreeNode* child = root->getChildByName( "archetype" ); | ||
102 | child; | ||
103 | child = root->getNextNamedChild()) | ||
104 | { | ||
105 | if( !loadNodeArchetype( child ) ) | ||
106 | { | ||
107 | return FALSE; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | mLoaded = TRUE; | ||
112 | return TRUE; | ||
113 | } | ||
114 | |||
115 | |||
116 | //----------------------------------------------------------------------------- | ||
117 | // loadNodeArchetype(): loads <archetype> node from XML tree | ||
118 | //----------------------------------------------------------------------------- | ||
119 | BOOL LLGenePool::loadNodeArchetype( LLXmlTreeNode* node ) | ||
120 | { | ||
121 | llassert( node->hasName( "archetype" ) ); | ||
122 | |||
123 | LLAppearance* archetype = new LLAppearance(); | ||
124 | BOOL success = TRUE; | ||
125 | |||
126 | LLVOAvatar* avatar = gAgent.getAvatarObject(); | ||
127 | if( !avatar ) | ||
128 | { | ||
129 | return FALSE; | ||
130 | } | ||
131 | |||
132 | LLXmlTreeNode* child; | ||
133 | for (child = node->getChildByName( "param" ); | ||
134 | child; | ||
135 | child = node->getNextNamedChild()) | ||
136 | { | ||
137 | F32 value; | ||
138 | static LLStdStringHandle value_string = LLXmlTree::addAttributeString("value"); | ||
139 | if( !child->getFastAttributeF32( value_string, value ) ) | ||
140 | { | ||
141 | llwarns << "avatar genepool file: <param> missing value attribute" << llendl; | ||
142 | success = FALSE; | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | S32 id; | ||
147 | static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id"); | ||
148 | if( !child->getFastAttributeS32( id_string, id ) ) | ||
149 | { | ||
150 | llwarns << "avatar genepool file: <param> missing id attribute" << llendl; | ||
151 | success = FALSE; | ||
152 | break; | ||
153 | } | ||
154 | |||
155 | LLVisualParam* param = avatar->getVisualParam( id ); | ||
156 | if( param ) | ||
157 | { | ||
158 | archetype->addParam( id, value ); | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | llwarns << "avatar genepool file: ignoring invalid <param> with id: " << id << llendl; | ||
163 | } | ||
164 | } | ||
165 | for (child = node->getChildByName( "texture" ); | ||
166 | child; | ||
167 | child = node->getNextNamedChild()) | ||
168 | { | ||
169 | LLUUID uuid; | ||
170 | static LLStdStringHandle uuid_string = LLXmlTree::addAttributeString("uuid"); | ||
171 | if( !child->getFastAttributeUUID( uuid_string, uuid ) ) | ||
172 | { | ||
173 | llwarns << "avatar genepool file: <texture> missing uuid attribute" << llendl; | ||
174 | success = FALSE; | ||
175 | break; | ||
176 | } | ||
177 | |||
178 | S32 te; | ||
179 | static LLStdStringHandle te_string = LLXmlTree::addAttributeString("te"); | ||
180 | if( !child->getFastAttributeS32( te_string, te ) ) | ||
181 | { | ||
182 | llwarns << "avatar genepool file: <texture> missing te attribute" << llendl; | ||
183 | success = FALSE; | ||
184 | break; | ||
185 | } | ||
186 | |||
187 | archetype->addTexture( te, uuid ); | ||
188 | } | ||
189 | |||
190 | if( success ) | ||
191 | { | ||
192 | mArchetypes.put( archetype ); | ||
193 | } | ||
194 | else | ||
195 | { | ||
196 | delete archetype; | ||
197 | } | ||
198 | return success; | ||
199 | } | ||
200 | |||
201 | // Creates new parameters for the given wearable and applies them to the avatar. | ||
202 | void LLGenePool::spawn( EWearableType type ) | ||
203 | { | ||
204 | LLVOAvatar* avatar = gAgent.getAvatarObject(); | ||
205 | if( !avatar ) | ||
206 | { | ||
207 | return; | ||
208 | } | ||
209 | |||
210 | if( !mLoaded ) | ||
211 | { | ||
212 | if( !load() ) | ||
213 | { | ||
214 | return; | ||
215 | } | ||
216 | } | ||
217 | |||
218 | if( mArchetypes.count() < 1 ) | ||
219 | { | ||
220 | return; | ||
221 | } | ||
222 | |||
223 | // Only consider archetypes that have the same sex as you have already. | ||
224 | LLVisualParam* male_param = avatar->getVisualParam( "male" ); | ||
225 | S32 male_param_id = male_param->getID(); | ||
226 | F32 sex_weight = male_param->getWeight(); | ||
227 | |||
228 | S32 i = 0; | ||
229 | S32 j = 0; | ||
230 | S32 k = 0; | ||
231 | const S32 MAX_CYCLES = 1000; | ||
232 | S32 cycles = 0; | ||
233 | |||
234 | F32 cur_sex_weight = 0.f; | ||
235 | do | ||
236 | { | ||
237 | i = rand() % mArchetypes.count(); | ||
238 | cur_sex_weight = *(mArchetypes[i]->mParamMap[ male_param_id ]); | ||
239 | cycles++; | ||
240 | if (cur_sex_weight != sex_weight) | ||
241 | { | ||
242 | break; | ||
243 | } | ||
244 | } while((cycles < MAX_CYCLES)); | ||
245 | |||
246 | if( cycles >= MAX_CYCLES ) | ||
247 | { | ||
248 | return; | ||
249 | } | ||
250 | |||
251 | LLAppearance* arch1 = mArchetypes[i]; | ||
252 | LLAppearance* arch2 = NULL; | ||
253 | LLAppearance* arch3 = NULL; | ||
254 | |||
255 | if( mArchetypes.count() > 1 ) | ||
256 | { | ||
257 | cycles = 0; | ||
258 | do | ||
259 | { | ||
260 | j = rand() % mArchetypes.count(); | ||
261 | cur_sex_weight = *(mArchetypes[j]->mParamMap[ male_param_id ]); | ||
262 | |||
263 | cycles++; | ||
264 | } while( | ||
265 | (cycles < MAX_CYCLES) && | ||
266 | ( (i == j) || (cur_sex_weight != sex_weight) ) | ||
267 | ); | ||
268 | |||
269 | if( cycles >= MAX_CYCLES ) | ||
270 | { | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | arch2 = mArchetypes[j]; | ||
275 | } | ||
276 | |||
277 | if( mArchetypes.count() > 2 ) | ||
278 | { | ||
279 | cycles = 0; | ||
280 | do | ||
281 | { | ||
282 | k = rand() % mArchetypes.count(); | ||
283 | cur_sex_weight = *(mArchetypes[k]->mParamMap[ male_param_id ]); | ||
284 | cycles++; | ||
285 | } while( | ||
286 | (cycles < MAX_CYCLES) && | ||
287 | ( (i == k) || (j == k) || (cur_sex_weight != sex_weight) ) | ||
288 | ); | ||
289 | |||
290 | if( cycles >= MAX_CYCLES ) | ||
291 | { | ||
292 | return; | ||
293 | } | ||
294 | |||
295 | arch3 = mArchetypes[k]; | ||
296 | } | ||
297 | |||
298 | // Lame generation of barycentric coordinates | ||
299 | F32 b1 = F32( rand() ) / RAND_MAX; | ||
300 | F32 b2 = (F32( rand() ) / RAND_MAX) * (1.f - b1); | ||
301 | F32 b3 = 1.f - b1 - b2; | ||
302 | |||
303 | // ESex old_sex = avatar->getSex(); | ||
304 | |||
305 | // Pull params | ||
306 | for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() ) | ||
307 | { | ||
308 | if( (((LLViewerVisualParam*)param)->getWearableType() == type) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) ) | ||
309 | { | ||
310 | S32 param_id = param->getID(); | ||
311 | |||
312 | // don't try to blend male/female param...as fp innaccuracy will break the [0 | 1] semantics | ||
313 | if (param_id != male_param_id) | ||
314 | { | ||
315 | |||
316 | F32* weight1p = arch1->getParam( param_id ); | ||
317 | F32 weight1 = weight1p ? *weight1p : param->getDefaultWeight(); | ||
318 | F32 net_weight = weight1; | ||
319 | |||
320 | if( arch2 && arch3 ) | ||
321 | { | ||
322 | F32* weight2p = arch2->getParam( param_id ); | ||
323 | F32 weight2 = weight2p ? *weight2p : param->getDefaultWeight(); | ||
324 | |||
325 | F32* weight3p = arch3->getParam( param_id ); | ||
326 | F32 weight3 = weight3p ? *weight3p : param->getDefaultWeight(); | ||
327 | |||
328 | net_weight = b1 * weight1 + b2 * weight2 + b3 * weight3; | ||
329 | } | ||
330 | |||
331 | param->setAnimationTarget(net_weight, TRUE); | ||
332 | } | ||
333 | } | ||
334 | } | ||
335 | |||
336 | // Find the archetype with the greatest influence | ||
337 | LLAppearance* dominant_arch = arch1; | ||
338 | if( (b2 > b1) && (b2 > b3) ) | ||
339 | { | ||
340 | dominant_arch = arch2; | ||
341 | } | ||
342 | else | ||
343 | if( (b3 > b1) && (b3 > b2) ) | ||
344 | { | ||
345 | dominant_arch = arch3; | ||
346 | } | ||
347 | |||
348 | |||
349 | // Pull Textures from the dominant archetype | ||
350 | for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ ) | ||
351 | { | ||
352 | if( LLVOAvatar::isTextureIndexBaked( te ) ) | ||
353 | { | ||
354 | continue; | ||
355 | } | ||
356 | |||
357 | if( LLVOAvatar::getTEWearableType( te ) == type ) | ||
358 | { | ||
359 | LLUUID image_id = dominant_arch->getTexture( te ); | ||
360 | if( image_id.isNull() ) | ||
361 | { | ||
362 | image_id = LLVOAvatar::getDefaultTEImageID( te ); | ||
363 | } | ||
364 | |||
365 | LLViewerImage* image = gImageList.getImage( image_id ); | ||
366 | if( image ) | ||
367 | { | ||
368 | avatar->setLocTexTE( te, image, TRUE ); | ||
369 | } | ||
370 | } | ||
371 | } | ||
372 | |||
373 | // avatar->setVisualParamWeight( "male", sex_weight ); | ||
374 | |||
375 | avatar->startAppearanceAnimation(TRUE, TRUE); | ||
376 | avatar->updateVisualParams(); | ||
377 | |||
378 | // ESex new_sex = avatar->getSex(); | ||
379 | // if( old_sex != new_sex ) | ||
380 | // { | ||
381 | // avatar->updateSexDependentLayerSets( TRUE ); | ||
382 | // } | ||
383 | |||
384 | avatar->updateMeshTextures(); | ||
385 | gAgent.sendAgentSetAppearance(); | ||
386 | } | ||