1 #include "bodyarch.h"
2 
BodyArch()3 BodyArch::BodyArch()
4 {
5 	settings = Settings::Instance();
6 	totalWeight = 0.0f;
7 	bodypartspacer = 2.2f;
8 }
9 
buildArch()10 void BodyArch::buildArch()
11 {
12 // 	string original;
13 // 	original.append("b 99999 box 0 75 75 200\n");
14 // 	original.append("b 99998 box 0 75 75 200\n");
15 // 	original.append("b 99997 box 0 75 75 200\n");
16 // 	original.append("m 99999 50, 50, 100\n");
17 // 	original.append("c 99999 99998 99999 1.5707 0 0 0 0 -0.25 -0.7853 99998 1.5707 0 0 0 0 0.25 0.7853\n");
18 // 	original.append("c 99997 99996 99998 1.5707 0 0 0 0 -0.25 -0.7853 99997 1.5707 0 0 0 0 0.25 0.7853\n");
19 // 	original.append("cm 99995 99994 99997 0 1.5707 0 0 0 -0.15 -0.7853 99999 0 1.5707 0 0 0 0.25 0.7853\n");
20 // 	setArch(&original);
21 
22 // 	string fourlegged;
23 // 	// body
24 // 	fourlegged.append("b 99999 box 0 200 100 400\n");
25 // 	// 4 long legs
26 // 	fourlegged.append("b 99998 box 0 150 40 40\n");
27 // 	fourlegged.append("b 99997 box 0 150 40 40\n");
28 // 	fourlegged.append("b 99996 box 0 150 40 40\n");
29 // 	fourlegged.append("b 99995 box 0 150 40 40\n");
30 // 	// mouth
31 // 	fourlegged.append("m 99999 50, 50, 100\n");
32 // 	// connections
33 // 	fourlegged.append("c 99999 99998 99999 0 0 0.7853 -0.2 0 -0.325 -0.7853 99998 0 0 0 0.25 0 0 0.7853\n");
34 // 	fourlegged.append("c 99997 99996 99999 0 0 0.7853 -0.2 0 0.325 -0.7853 99997 0 0 0 0.25 0 0 0.7853\n");
35 // 	fourlegged.append("c 99995 99994 99999 0 0 -0.7853 0.2 0 -0.325 -0.7853 99996 0 0 0 -0.25 0 0 0.7853\n");
36 // 	fourlegged.append("c 99993 99992 99999 0 0 -0.7853 0.2 0 0.325 -0.7853 99995 0 0 0 -0.25 0 0 0.7853\n");
37 // 	fourlegged.append("cm 99991 99990 99999 1.5707 0 0 0 0 -0.15 -0.3926 99999 1.5707 0 0 0 0 0.45 0.3926\n");
38 // 	setArch(&fourlegged);
39 
40 
41 
42 // 	string original;
43 // 	original.append("b 1000 box 0 200 200 200\n");
44 // 	original.append("b 1001 box 0 100 100 100\n");
45 // 	original.append("b 1002 box 0 100 100 100\n");
46 // 	original.append("b 1003 box 0 100 100 100\n");
47 // 	original.append("b 1004 box 0 100 100 100\n");
48 // 	original.append("m 99999 50, 50, 100\n");
49 //
50 // 	-x
51 // 	original.append("c 1000 1001 1000 0.5707 1.3707 0.7707 -0.3 0 0 -0.7853 1001 1.1707 0.0707 0.5707 0.15 0 0 0.7853\n");
52 // 	-z
53 // 	original.append("c 1002 1003 1000 1.5707 1.5707 1.5707 0 0 -0.3 -0.7853 1002 1.5707 1.5707 1.5707 0 0 0.15 0.7853\n");
54 // 	+z
55 // 	original.append("c 1004 1005 1000 1.5707 0 0 0 0 0.3 -0.7853 1003 1.5707 0 0 0 0 -0.15 0.7853\n");
56 // 	+x
57 // 	original.append("c 1006 1007 1000 1.5707 0 0 0.3 0 0 -0.7853 1004 1.5707 0 0 -0.15 0 0 0.7853\n");
58 // 	setArch(&original);
59 
60 	// Create a central body
61 		archBodyparts.push_back( archBodypart() );
62 		archBodypart *bp = &archBodyparts[archBodyparts.size()-1];
63 		bp->id		= 1000;
64 		bp->type	= 0;
65 		bp->materialID	= 0;
66 		bp->x		= randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") );
67 		bp->y		= randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") );
68 		bp->z		= randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") );
69 
70 	// add random more
71 		unsigned int runs = randgen->Instance()->get( 0, settings->getCVar("body_maxbodypartsatbuildtime")-1 ); // -1 -> central bodypart
72 		for ( unsigned int i=0; i < runs; i++ )
73 			addRandomBodypart();
74 
75 		addRandomMouth();
76 }
77 
removeBodypart(unsigned int id)78 void BodyArch::removeBodypart(unsigned int id)
79 {
80 // 	cerr << "requested removal of bodypart id " << id << endl;
81 
82 	// find constraints where this bodypart is id1, in order to remove connected bodyparts
83 	for ( unsigned int i = 0; i < archConstraints.size(); i++ )
84 	{
85 		archConstraint* c = &archConstraints[i];
86 		if ( c->id_1 == id )
87 		{
88 // 			cerr << " is connected to " << c->isMouthConstraint << " " << c->id_2 << endl;
89 			if ( c->isMouthConstraint )
90 				removeMouth( findMouth(c->id_2) );
91 			else
92 				removeBodypart( c->id_2 );
93 		}
94 	}
95 
96 // 	cerr << "really removing " << id << " which is " << findBodypart( id ) << endl;
97 	archBodyparts.erase( archBodyparts.begin() + findBodypart(id) );
98 }
99 
removeMouth(unsigned int id)100 void BodyArch::removeMouth(unsigned int id)
101 {
102 // 	cerr << "removing mouth " << id << endl;
103 	archMouths.erase(archMouths.begin()+id);
104 }
105 
addRandomMouth()106 void BodyArch::addRandomMouth()
107 {
108 	// Throw in a mouth
109 		archMouths.push_back( archMouth() );
110 		archMouth* mo = &archMouths[archMouths.size()-1];
111 		mo->id		= 1000;
112 		mo->x		= randgen->Instance()->get( settings->getCVar("body_minheadsize"), settings->getCVar("body_maxheadsize") );
113 		mo->y		= randgen->Instance()->get( settings->getCVar("body_minheadsize"), settings->getCVar("body_maxheadsize") );
114 		mo->z		= randgen->Instance()->get( settings->getCVar("body_minheadsize"), settings->getCVar("body_maxheadsize") );
115 
116 	// Get it connected somehow
117 
118 		unsigned int connID1 = randgen->Instance()->get( 0, archBodyparts.size()-1 );
119 		unsigned int connID2 = archMouths.size()-1;
120 
121 		addRandomConstraint(connID1, connID2, true);
122 }
123 
addRandomBodypart()124 void BodyArch::addRandomBodypart()
125 {
126 	// Throw in a bodypart
127 		archBodyparts.push_back( archBodypart() );
128 		archBodypart *bp = &archBodyparts[archBodyparts.size()-1];
129 		bp->id		= 0; // to avoid uninitialized id
130 		bp->id		= getUniqueBodypartID();
131 		bp->type	= 0;
132 		bp->materialID	= 0;
133 		bp->x		= randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") );
134 		bp->y		= randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") );
135 		bp->z		= randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") );
136 
137 	// Get it connected somehow
138 		unsigned int connID1 = randgen->Instance()->get( 0, archBodyparts.size()-1 );
139 		unsigned int connID2 = archBodyparts.size()-1;
140 		while ( connID1 == connID2 )
141 			connID1 = randgen->Instance()->get( 0, archBodyparts.size()-1 );
142 
143 		addRandomConstraint(connID1, connID2, false);
144 }
145 
addRandomConstraint(unsigned int connID1,unsigned int connID2,bool isMouth)146 void BodyArch::addRandomConstraint(unsigned int connID1, unsigned int connID2, bool isMouth)
147 {
148 		archConstraints.push_back( archConstraint() );
149 		archConstraint *co = &archConstraints[archConstraints.size()-1];
150 
151 		co->isMouthConstraint	= isMouth;
152 		// first initialize constraint id's
153 		co->constraint_id1	= 0;
154 		co->constraint_id2	= 0;
155 		co->constraint_id1	= getUniqueConstraintID();
156 		co->constraint_id2	= getUniqueConstraintID();
157 		co->id_1		= archBodyparts[ connID1 ].id;
158 		if ( isMouth )
159 			co->id_2		= archMouths[ connID2 ].id;
160 		else
161 			co->id_2		= archBodyparts[ connID2 ].id;
162 
163 		co->rot_x_1		= ((float)randgen->Instance()->get( 0, 1571 ) - 0) / 1000;
164 		co->rot_y_1		= ((float)randgen->Instance()->get( 0, 1571 ) - 0) / 1000;
165 		co->rot_z_1		= ((float)randgen->Instance()->get( 0, 1571 ) - 0) / 1000;
166 
167 		co->rot_x_2		= ((float)randgen->Instance()->get( 0, 1571 ) - 0) / 1000;
168 		co->rot_y_2		= ((float)randgen->Instance()->get( 0, 1571 ) - 0) / 1000;
169 		co->rot_z_2		= ((float)randgen->Instance()->get( 0, 1571 ) - 0) / 1000;
170 
171 		randomConstraintPosition(co, 1, connID1);
172 		randomConstraintPosition(co, 2, connID2);
173 
174 		co->limit_1		= (float)randgen->Instance()->get( 0, 7853 ) / -10000;
175 		co->limit_2		= -1.0f * co->limit_1;
176 }
177 
randomConstraintPosition(archConstraint * co,unsigned int OneOrTwo,unsigned int connID)178 void BodyArch::randomConstraintPosition(archConstraint* co, unsigned int OneOrTwo, unsigned int connID)
179 {
180 	if ( OneOrTwo == 1 )
181 	{
182 		co->XYZ = randgen->Instance()->get( 0, 2 );
183 		co->sign = randgen->Instance()->get( 0, 1 );
184 		if ( co->sign == 0 ) co->sign = -1;
185 
186 	// now we know the plane to connect to, determine positions
187 		if ( co->XYZ == 0 ) // X
188 		{
189 			// ((x / 1000.0f)  / 2)  * 1.5f * co->sign =
190 			co->pos_x_1 = (archBodyparts[connID].x / 2000.0f) * co->sign * bodypartspacer;
191 			co->pos_y_1 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].y)*2) - archBodyparts[connID].y) / 1000;
192 			co->pos_z_1 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].z)*2) - archBodyparts[connID].z) / 1000;
193 		}
194 		else if ( co->XYZ == 1 ) // Y
195 		{
196 			co->pos_x_1 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].x)*2) - archBodyparts[connID].x) / 1000;
197 			co->pos_y_1 = (archBodyparts[connID].y / 2000.0f) * co->sign * bodypartspacer;
198 			co->pos_z_1 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].z)*2) - archBodyparts[connID].z) / 1000;
199 		}
200 		else // Z
201 		{
202 			co->pos_x_1 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].x)*2) - archBodyparts[connID].x) / 1000;
203 			co->pos_y_1 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].y)*2) - archBodyparts[connID].y) / 1000;
204 			co->pos_z_1 = (archBodyparts[connID].z / 2000.0f) * co->sign * bodypartspacer;
205 		}
206 	}
207 	else
208 	{
209 		int othersign = -1 * co->sign;
210 		if ( !co->isMouthConstraint )
211 		{
212 			if ( co->XYZ == 0 ) // X
213 			{
214 				co->pos_x_2 = (archBodyparts[connID].x / 2000.0f) * othersign * bodypartspacer;
215 				co->pos_y_2 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].y)*2) - archBodyparts[connID].y) / 1000;
216 				co->pos_z_2 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].z)*2) - archBodyparts[connID].z) / 1000;
217 			}
218 			else if ( co->XYZ == 1 ) // Y
219 			{
220 				co->pos_x_2 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].x)*2) - archBodyparts[connID].x) / 1000;
221 				co->pos_y_2 = (archBodyparts[connID].y / 2000.0f) * othersign * bodypartspacer;
222 				co->pos_z_2 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].z)*2) - archBodyparts[connID].z) / 1000;
223 			}
224 			else // Z
225 			{
226 				co->pos_x_2 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].x)*2) - archBodyparts[connID].x) / 1000;
227 				co->pos_y_2 = ((float)randgen->Instance()->get( 0, (archBodyparts[connID].y)*2) - archBodyparts[connID].y) / 1000;
228 				co->pos_z_2 = (archBodyparts[connID].z / 2000.0f) * othersign * bodypartspacer;
229 			}
230 		}
231 		else
232 		{
233 			if ( co->XYZ == 0 ) // X
234 			{
235 				co->pos_x_2 = (archMouths[connID].x / 2000.0f) * othersign * bodypartspacer;
236 				co->pos_y_2 = ((float)randgen->Instance()->get( 0, (archMouths[connID].y)*2) - archMouths[connID].y) / 1000;
237 				co->pos_z_2 = ((float)randgen->Instance()->get( 0, (archMouths[connID].z)*2) - archMouths[connID].z) / 1000;
238 			}
239 			else if ( co->XYZ == 1 ) // Y
240 			{
241 				co->pos_x_2 = ((float)randgen->Instance()->get( 0, (archMouths[connID].x)*2) - archMouths[connID].x) / 1000;
242 				co->pos_y_2 = (archMouths[connID].y / 2000.0f) * othersign * bodypartspacer;
243 				co->pos_z_2 = ((float)randgen->Instance()->get( 0, (archMouths[connID].z)*2) - archMouths[connID].z) / 1000;
244 			}
245 			else // Z
246 			{
247 				co->pos_x_2 = ((float)randgen->Instance()->get( 0, (archMouths[connID].x)*2) - archMouths[connID].x) / 1000;
248 				co->pos_y_2 = ((float)randgen->Instance()->get( 0, (archMouths[connID].y)*2) - archMouths[connID].y) / 1000;
249 				co->pos_z_2 = (archMouths[connID].z / 2000.0f) * othersign * bodypartspacer;
250 			}
251 		}
252 	}
253 }
254 
mutate(unsigned int runs)255 void BodyArch::mutate(unsigned int runs)
256 {
257 	for ( unsigned int i=0; i < runs; i++ )
258 	{
259 		unsigned int tsum = 	settings->getCVar("body_percentmutateeffectchangecolor")
260 					+ settings->getCVar("body_percentmutateeffectchangecolor_slightly")
261 					+ settings->getCVar("body_percentmutateeffectaddbodypart")
262 					+ settings->getCVar("body_percentmutateeffectremovebodypart")
263 					+ settings->getCVar("body_percentmutateeffectresizebodypart")
264 					+ settings->getCVar("body_percentmutateeffectresizebodypart_slightly")
265 					+ settings->getCVar("body_percentmutateeffectresizehead")
266 					+ settings->getCVar("body_percentmutateeffectresizehead_slightly")
267 					+ settings->getCVar("body_percentmutateeffectchangeconstraintlimits")
268 					+ settings->getCVar("body_percentmutateeffectchangeconstraintlimits_slightly")
269 					+ settings->getCVar("body_percentmutateeffectchangeconstraintangles")
270 					+ settings->getCVar("body_percentmutateeffectchangeconstraintangles_slightly")
271 					+ settings->getCVar("body_percentmutateeffectchangeconstraintposition")
272 					+ settings->getCVar("body_percentmutateeffectchangeconstraintposition_slightly")
273 					+ settings->getCVar("body_percentmutateeffectrepositionhead")
274 				;
275 
276 		unsigned int mode = randgen->Instance()->get(1,tsum);
277 
278 		// CHANGE COLOR
279 			unsigned int modesum = settings->getCVar("body_percentmutateeffectchangecolor");
280 			if ( mode <= modesum )
281 			{
282 				// mutate color
283 				unsigned int ncolor = randgen->Instance()->get(0,2);
284 
285 				if ( ncolor == 0 )
286 					color.r = (float)RandGen::Instance()->get(0,100)/100.0f;
287 				else if ( ncolor == 1 )
288 					color.g = (float)RandGen::Instance()->get(0,100)/100.0f;
289 				else if ( ncolor == 2 )
290 					color.b = (float)RandGen::Instance()->get(0,100)/100.0f;
291 
292 				continue;
293 			}
294 
295 		// CHANGE COLOR SLIGHTLY
296 			modesum += settings->getCVar("body_percentmutateeffectchangecolor_slightly");
297 			if ( mode <= modesum )
298 			{
299 				// mutate color
300 				unsigned int ncolor = randgen->Instance()->get(0,2);
301 				unsigned int nweight = randgen->Instance()->get(1,10);
302 				float amount = 0.01 * nweight;
303 
304 				if ( randgen->Instance()->get(0,1) == 0 )
305 					amount *= -1;
306 
307 				if ( ncolor == 0 )
308 					color.r += amount;
309 				else if ( ncolor == 1 )
310 					color.g += amount;
311 				else if ( ncolor == 2 )
312 					color.b += amount;
313 
314 				if ( color.r < 0.1f )
315 				{
316 					float diff = 0.1f - color.r;
317 					color.r += diff; color.g += diff; color.b += diff; color.a += diff;
318 				}
319 				if ( color.g < 0.1f )
320 				{
321 					float diff = 0.1f - color.g;
322 					color.r += diff; color.g += diff; color.b += diff; color.a += diff;
323 				}
324 				if ( color.b < 0.1f )
325 				{
326 					float diff = 0.1f - color.b;
327 					color.r += diff; color.g += diff; color.b += diff; color.a += diff;
328 				}
329 
330 				if ( color.r > 1.0f && color.g > 1.0f && color.b > 1.0f )
331 					color.normalize();
332 
333 				continue;
334 			}
335 
336 		// ADD BODYPART
337 			modesum += settings->getCVar("body_percentmutateeffectaddbodypart");
338 			if ( mode <= modesum )
339 			{
340 				if ( archBodyparts.size() < settings->getCVar("body_maxbodyparts") )
341 				{
342 // 					cerr << "adding bodypart" << endl;
343 					addRandomBodypart();
344 // 					cerr << "done adding bodypart" << endl;
345 				}
346 				else
347 					runs++;
348 				continue;
349 			}
350 
351 		// REMOVE BODYPART
352 			modesum += settings->getCVar("body_percentmutateeffectremovebodypart");
353 			if ( mode <= modesum )
354 			{
355 				if ( archBodyparts.size() > 2 )
356 				{
357 					// pick a random bodypart
358 					unsigned int bid = randgen->Instance()->get( 0, archBodyparts.size()-1 );
359 
360 					// if not main body, remove it
361 					if ( archBodyparts[bid].id != 1000 )
362 					{
363 // 						cerr << "removing bodypart " << bid << " id " << archBodyparts[bid].id  << endl;
364 
365 						removeBodypart( archBodyparts[bid].id );
366 
367 // 						cerr << "removing obsolete constraints, expected errors:" << endl;
368 						for ( int i = 0; i < (int)archConstraints.size(); i++ )
369 						{
370 							archConstraint* c = &archConstraints[i];
371 							if ( findBodypart( c->id_1 ) == -1 )
372 							{
373 								archConstraints.erase(archConstraints.begin()+i);
374 								i--;
375 							}
376 							else if ( c->isMouthConstraint && findMouth( c->id_2 ) == -1 )
377 							{
378 								archConstraints.erase(archConstraints.begin()+i);
379 								i--;
380 							}
381 							else if ( !c->isMouthConstraint && findBodypart( c->id_2 ) == -1 )
382 							{
383 								archConstraints.erase(archConstraints.begin()+i);
384 								i--;
385 							}
386 						}
387 // 						cerr << "done removing obsolete constraints" << endl << endl;
388 
389 // 						cerr << "done removing bodypart" << endl;
390 
391 						// re add mouth if needed
392 						if ( archMouths.size() == 0 )
393 								addRandomMouth();
394 					}
395 					else
396 						runs++;
397 
398 				}
399 				else
400 					runs++;
401 				continue;
402 			}
403 
404 		// RESIZE BODYPART
405 			modesum += settings->getCVar("body_percentmutateeffectresizebodypart");
406 			if ( mode <= modesum )
407 			{
408 // 				cerr << "resize bodypart" << endl;
409 
410 					// pick a random bodypart
411 					unsigned int bid = randgen->Instance()->get( 0, archBodyparts.size()-1 );
412 					archBodypart *bp = &archBodyparts[bid];
413 
414 					unsigned int axismode = randgen->Instance()->get(0,2);
415 					if ( axismode == 0 )
416 						bp->x = randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") );
417 					else if ( axismode == 1 )
418 						bp->y = randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") );
419 					else
420 						bp->z = randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") );
421 
422 					// reposition the constraints back to the resized bodypart
423 					repositiontoConstraints(bp);
424 
425 // 				cerr << "done resize bodypart" << endl;
426 				continue;
427 			}
428 
429 		// RESIZE BODYPART SLIGHTLY
430 			modesum += settings->getCVar("body_percentmutateeffectresizebodypart_slightly");
431 			if ( mode <= modesum )
432 			{
433 // 				cerr << "resize bodypart slightly" << endl;
434 
435 					// pick a random bodypart
436 					unsigned int bid = randgen->Instance()->get( 0, archBodyparts.size()-1 );
437 					archBodypart* bp = &archBodyparts[bid];
438 
439 					unsigned int axismode = randgen->Instance()->get(0,2);
440 					unsigned int direction = randgen->Instance()->get(0,1);
441 					if ( axismode == 0 )
442 					{
443 						if ( direction == 0 )
444 							bp->x += randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 );
445 						else
446 							bp->x -= randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 );
447 					}
448 					else if ( axismode == 1 )
449 					{
450 						if ( direction == 0 )
451 							bp->y += randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 );
452 						else
453 							bp->y -= randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 );
454 					}
455 					else
456 					{
457 						if ( direction == 0 )
458 							bp->z += randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 );
459 						else
460 							bp->z -= randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 );
461 					}
462 
463 					// see that they didn't go over their limits
464 					if ( bp->x < settings->getCVar("body_minbodypartsize") )
465 						bp->x = settings->getCVar("body_minbodypartsize");
466 					else if ( bp->x > settings->getCVar("body_maxbodypartsize") )
467 						bp->x = settings->getCVar("body_minbodypartsize");
468 
469 					if ( bp->y < settings->getCVar("body_minbodypartsize") )
470 						bp->y = settings->getCVar("body_minbodypartsize");
471 					else if ( bp->y > settings->getCVar("body_maxbodypartsize") )
472 						bp->y = settings->getCVar("body_minbodypartsize");
473 
474 					if ( bp->z < settings->getCVar("body_minbodypartsize") )
475 						bp->z = settings->getCVar("body_minbodypartsize");
476 					else if ( bp->z > settings->getCVar("body_maxbodypartsize") )
477 						bp->z = settings->getCVar("body_minbodypartsize");
478 
479 					// reposition the constraints back to the resized bodypart
480 					repositiontoConstraints(bp);
481 
482 // 				cerr << "done resize bodypart" << endl;
483 				continue;
484 			}
485 
486 		// RESIZE HEAD
487 			modesum += settings->getCVar("body_percentmutateeffectresizehead");
488 			if ( mode <= modesum )
489 			{
490 // 				cerr << "resize mouth" << endl;
491 
492 					// pick a random head
493 					unsigned int mid = randgen->Instance()->get( 0, archMouths.size()-1 );
494 					archMouth* head = &archMouths[mid];
495 
496 					unsigned int axismode = randgen->Instance()->get(0,2);
497 					if ( axismode == 0 )
498 						head->x = randgen->Instance()->get( settings->getCVar("body_minheadsize"), settings->getCVar("body_maxheadsize") );
499 					else if ( axismode == 1 )
500 						head->y = randgen->Instance()->get( settings->getCVar("body_minheadsize"), settings->getCVar("body_maxheadsize") );
501 					else
502 						head->z = randgen->Instance()->get( settings->getCVar("body_minheadsize"), settings->getCVar("body_maxheadsize") );
503 
504 					// reposition the constraints back to the resized bodypart
505 					repositiontoConstraints(head);
506 
507 // 				cerr << "done resize head" << endl;
508 				continue;
509 			}
510 
511 		// RESIZE HEAD SLIGHTLY
512 			modesum += settings->getCVar("body_percentmutateeffectresizehead_slightly");
513 			if ( mode <= modesum )
514 			{
515 // 				cerr << "resize head slightly" << endl;
516 
517 					// pick a random head
518 					unsigned int mid = randgen->Instance()->get( 0, archMouths.size()-1 );
519 					archMouth* head = &archMouths[mid];
520 
521 					unsigned int axismode = randgen->Instance()->get(0,2);
522 					unsigned int direction = randgen->Instance()->get(0,1);
523 					if ( axismode == 0 )
524 					{
525 						if ( direction == 0 )
526 							head->x += randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 );
527 						else
528 							head->x -= randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 );
529 					}
530 					else if ( axismode == 1 )
531 					{
532 						if ( direction == 0 )
533 							head->y += randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 );
534 						else
535 							head->y -= randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 );
536 					}
537 					else
538 					{
539 						if ( direction == 0 )
540 							head->z += randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 );
541 						else
542 							head->z -= randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 );
543 					}
544 
545 					// see that they didn't go over their limits
546 					if ( head->x < settings->getCVar("body_minheadsize") )
547 						head->x = settings->getCVar("body_minheadsize");
548 					else if ( head->x > settings->getCVar("body_maxheadsize") )
549 						head->x = settings->getCVar("body_minheadsize");
550 
551 					if ( head->y < settings->getCVar("body_minheadsize") )
552 						head->y = settings->getCVar("body_minheadsize");
553 					else if ( head->y > settings->getCVar("body_maxheadsize") )
554 						head->y = settings->getCVar("body_minheadsize");
555 
556 					if ( head->z < settings->getCVar("body_minheadsize") )
557 						head->z = settings->getCVar("body_minheadsize");
558 					else if ( head->z > settings->getCVar("body_maxheadsize") )
559 						head->z = settings->getCVar("body_minheadsize");
560 
561 					// reposition the constraints back to the resized bodypart
562 					repositiontoConstraints(head);
563 
564 // 				cerr << "done resize head" << endl;
565 				continue;
566 			}
567 
568 		// CHANGE CONSTRAINT LIMITS
569 			modesum += settings->getCVar("body_percentmutateeffectchangeconstraintlimits");
570 			if ( mode <= modesum )
571 			{
572 // 				cerr << "changing constraint limits" << endl;
573 
574 				unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 );
575 				archConstraint* co = &archConstraints[cid];
576 				co->limit_1		= (float)randgen->Instance()->get( 0, 7853 ) / -10000;
577 				co->limit_2		= -1.0f * co->limit_1;
578 
579 // 				cerr << "done changing constraint limits" << endl;
580 				continue;
581 			}
582 
583 		// CHANGE CONSTRAINT LIMITS SLIGHTLY
584 			modesum += settings->getCVar("body_percentmutateeffectchangeconstraintlimits_slightly");
585 			if ( mode <= modesum )
586 			{
587 // 				cerr << "changing constraint limits" << endl;
588 
589 				unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 );
590 				archConstraint* co = &archConstraints[cid];
591 
592 				unsigned int direction = randgen->Instance()->get(0,1);
593 
594 				if ( direction == 0 )
595 					co->limit_1 += 0.01f;
596 				else
597 					co->limit_1 -= 0.01f;
598 				// check limits limits, ya
599 				if ( co->limit_1 > 0.0f )
600 					co->limit_1 = 0.0f;
601 				if ( co->limit_1 < -0.7853f )
602 					co->limit_1 = -0.7853f;
603 
604 				co->limit_2 = -1.0f * co->limit_1;
605 
606 // 				cerr << "done changing constraint limits" << endl;
607 				continue;
608 			}
609 		// CHANGE CONSTRAINT ANGLES
610 			modesum += settings->getCVar("body_percentmutateeffectchangeconstraintangles");
611 			if ( mode <= modesum )
612 			{
613 // 				cerr << "changing constraint angles" << endl;
614 
615 				unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 );
616 				archConstraint* co = &archConstraints[cid];
617 				co->rot_x_1		= ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000;
618 				co->rot_z_1		= ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000;
619 				co->rot_y_1		= ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000;
620 
621 				co->rot_x_2		= ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000;
622 				co->rot_y_2		= ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000;
623 				co->rot_z_2		= ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000;
624 
625 // 				cerr << "done changing constraint angles" << endl;
626 				continue;
627 			}
628 
629 		// CHANGE CONSTRAINT ANGLES SLIGHTLY
630 			modesum += settings->getCVar("body_percentmutateeffectchangeconstraintangles_slightly");
631 			if ( mode <= modesum )
632 			{
633 // 				cerr << "changing constraint angles" << endl;
634 
635 				unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 );
636 				archConstraint* co = &archConstraints[cid];
637 
638 				unsigned int XYZ = randgen->Instance()->get(0,2);
639 				unsigned int direction = randgen->Instance()->get(0,1);
640 				if ( direction == 0 )
641 				{
642 					if ( XYZ == 0 )
643 						co->rot_x_1 += 0.01f;
644 					else if ( XYZ == 1 )
645 						co->rot_y_1 += 0.01f;
646 					else
647 						co->rot_z_1 += 0.01f;
648 				}
649 				else
650 				{
651 					if ( XYZ == 0 )
652 						co->rot_x_1 -= 0.01f;
653 					else if ( XYZ == 1 )
654 						co->rot_y_1 -= 0.01f;
655 					else
656 						co->rot_z_1 -= 0.01f;
657 				}
658 
659 				XYZ = randgen->Instance()->get(0,2);
660 				direction = randgen->Instance()->get(0,1);
661 				if ( direction == 0 )
662 				{
663 					if ( XYZ == 0 )
664 						co->rot_x_2 += 0.01f;
665 					else if ( XYZ == 1 )
666 						co->rot_y_2 += 0.01f;
667 					else
668 						co->rot_z_2 += 0.01f;
669 				}
670 				else
671 				{
672 					if ( XYZ == 0 )
673 						co->rot_x_2 -= 0.01f;
674 					else if ( XYZ == 1 )
675 						co->rot_y_2 -= 0.01f;
676 					else
677 						co->rot_z_2 -= 0.01f;
678 				}
679 
680 				if ( co->rot_x_1 < -0.1571f )
681 					co->rot_x_1 = -0.1571f;
682 				if ( co->rot_x_1 > 0.1571f )
683 					co->rot_x_1 = 0.1571f;
684 				if ( co->rot_y_1 < -0.1571f )
685 					co->rot_y_1 = -0.1571f;
686 				if ( co->rot_y_1 > 0.1571f )
687 					co->rot_y_1 = 0.1571f;
688 				if ( co->rot_z_1 < -0.1571f )
689 					co->rot_z_1 = -0.1571f;
690 				if ( co->rot_z_1 > 0.1571f )
691 					co->rot_z_1 = 0.1571f;
692 
693 				if ( co->rot_x_2 < -0.1571f )
694 					co->rot_x_2 = -0.1571f;
695 				if ( co->rot_x_2 > 0.1571f )
696 					co->rot_x_2 = 0.1571f;
697 				if ( co->rot_y_2 < -0.1571f )
698 					co->rot_y_2 = -0.1571f;
699 				if ( co->rot_y_2 > 0.1571f )
700 					co->rot_y_2 = 0.1571f;
701 				if ( co->rot_z_2 < -0.1571f )
702 					co->rot_z_2 = -0.1571f;
703 				if ( co->rot_z_2 > 0.1571f )
704 					co->rot_z_2 = 0.1571f;
705 
706 // 				cerr << "done changing constraint angles" << endl;
707 				continue;
708 			}
709 
710 		// REPOSITION A CONSTRAINT
711 			modesum += settings->getCVar("body_percentmutateeffectchangeconstraintposition");
712 			if ( mode <= modesum )
713 			{
714 // 				cerr << "changing constraint position" << endl;
715 
716 				unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 );
717 				archConstraint* co = &archConstraints[cid];
718 
719 				int connID1 = findBodypart(co->id_1);
720 				int connID2;
721 
722 				if ( co->isMouthConstraint )
723 					connID2 = findMouth(co->id_2);
724 				else
725 					connID2 = findBodypart(co->id_2);
726 
727 				// pick one of 2 bodies to reconnect
728 				unsigned int body1or2 = randgen->Instance()->get( 1, 2 );
729 
730 				if ( body1or2 == 1 )
731 					randomConstraintPosition(co, 1, connID1);
732 				else
733 					randomConstraintPosition(co, 2, connID2);
734 
735 // 				cerr << "done changing constraint position" << endl;
736 				continue;
737 			}
738 
739 		// REPOSITION A CONSTRAINT SLIGHTLY
740 			modesum += settings->getCVar("body_percentmutateeffectchangeconstraintposition_slightly");
741 			if ( mode <= modesum )
742 			{
743 // 				cerr << "changing constraint position" << endl;
744 
745 				unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 );
746 				archConstraint* co = &archConstraints[cid];
747 
748 				int connID1 = findBodypart(co->id_1);
749 				int connID2;
750 
751 				if ( co->isMouthConstraint )
752 					connID2 = findMouth(co->id_2);
753 				else
754 					connID2 = findBodypart(co->id_2);
755 
756 				// pick one of 2 bodies to reconnect
757 				unsigned int body1or2 = randgen->Instance()->get( 1, 2 );
758 				unsigned int direction = randgen->Instance()->get( 0, 1 );
759 				unsigned int axis1or2 = randgen->Instance()->get( 0, 1 );
760 
761 				if ( body1or2 == 1 ) {
762 					// now we know the plane to connect to, determine positions
763 					if ( co->XYZ == 0 ) { // X
764 						if ( direction == 0 ) {
765 							if ( axis1or2 == 0 )	co->pos_y_1 += archBodyparts[connID1].y / 100000;
766 							else			co->pos_z_1 += archBodyparts[connID1].z / 100000;
767 						} else {
768 							if ( axis1or2 == 0 )	co->pos_y_1 -= archBodyparts[connID1].y / 100000;
769 							else			co->pos_z_1 -= archBodyparts[connID1].z / 100000;
770 						}
771 					}
772 					else if ( co->XYZ == 1 ) { // Y
773 						if ( direction == 0 ) {
774 							if ( axis1or2 == 0 )	co->pos_x_1 += archBodyparts[connID1].x / 100000;
775 							else			co->pos_z_1 += archBodyparts[connID1].z / 100000;
776 						} else {
777 							if ( axis1or2 == 0 )	co->pos_x_1 -= archBodyparts[connID1].x / 100000;
778 							else			co->pos_z_1 -= archBodyparts[connID1].z / 100000;
779 						}
780 					}
781 					else { // Z
782 						if ( direction == 0 ) {
783 							if ( axis1or2 == 0 )	co->pos_x_1 += archBodyparts[connID1].x / 100000;
784 							else			co->pos_y_1 += archBodyparts[connID1].y / 100000;
785 						} else {
786 							if ( axis1or2 == 0 )	co->pos_x_1 -= archBodyparts[connID1].x / 100000;
787 							else			co->pos_y_1 -= archBodyparts[connID1].y / 100000;
788 						}
789 					}
790 					if ( co->pos_x_1 < archBodyparts[connID1].x/-2000 )
791 						co->pos_x_1 = archBodyparts[connID1].x/-2000;
792 					if ( co->pos_x_1 > archBodyparts[connID1].x/2000 )
793 						co->pos_x_1 = archBodyparts[connID1].x/2000;
794 					if ( co->pos_y_1 < archBodyparts[connID1].y/-2000 )
795 						co->pos_y_1 = archBodyparts[connID1].y/-2000;
796 					if ( co->pos_y_1 > archBodyparts[connID1].y/2000 )
797 						co->pos_y_1 = archBodyparts[connID1].y/2000;
798 					if ( co->pos_z_1 < archBodyparts[connID1].z/-2000 )
799 						co->pos_z_1 = archBodyparts[connID1].z/-2000;
800 					if ( co->pos_z_1 > archBodyparts[connID1].z/2000 )
801 						co->pos_z_1 = archBodyparts[connID1].z/2000;
802 				}
803 				else {
804 					if ( !co->isMouthConstraint ) {
805 						// now we know the plane to connect to, determine positions
806 						if ( co->XYZ == 0 ) { // X
807 							if ( direction == 0 ) {
808 								if ( axis1or2 == 0 )	co->pos_y_2 += archBodyparts[connID2].y / 100000;
809 								else			co->pos_z_2 += archBodyparts[connID2].z / 100000;
810 							} else {
811 								if ( axis1or2 == 0 )	co->pos_y_2 -= archBodyparts[connID2].y / 100000;
812 								else			co->pos_z_2 -= archBodyparts[connID2].z / 100000;
813 							}
814 						}
815 						else if ( co->XYZ == 1 ) { // Y
816 							if ( direction == 0 ) {
817 								if ( axis1or2 == 0 )	co->pos_x_2 += archBodyparts[connID2].x / 100000;
818 								else			co->pos_z_2 += archBodyparts[connID2].z / 100000;
819 							} else {
820 								if ( axis1or2 == 0 )	co->pos_x_2 -= archBodyparts[connID2].x / 100000;
821 								else			co->pos_z_2 -= archBodyparts[connID2].z / 100000;
822 							}
823 						}
824 						else { // Z
825 							if ( direction == 0 ) {
826 								if ( axis1or2 == 0 )	co->pos_x_2 += archBodyparts[connID2].x / 100000;
827 								else			co->pos_y_2 += archBodyparts[connID2].y / 100000;
828 							} else {
829 								if ( axis1or2 == 0 )	co->pos_x_2 -= archBodyparts[connID2].x / 100000;
830 								else			co->pos_y_2 -= archBodyparts[connID2].y / 100000;
831 							}
832 						}
833 						if ( co->pos_x_2 < archBodyparts[connID2].x/-2000 )
834 							co->pos_x_2 = archBodyparts[connID2].x/-2000;
835 						if ( co->pos_x_2 > archBodyparts[connID2].x/2000 )
836 							co->pos_x_2 = archBodyparts[connID2].x/2000;
837 						if ( co->pos_y_2 < archBodyparts[connID2].y/-2000 )
838 							co->pos_y_2 = archBodyparts[connID2].y/-2000;
839 						if ( co->pos_y_2 > archBodyparts[connID2].y/2000 )
840 							co->pos_y_2 = archBodyparts[connID2].y/2000;
841 						if ( co->pos_z_2 < archBodyparts[connID2].z/-2000 )
842 							co->pos_z_2 = archBodyparts[connID2].z/-2000;
843 						if ( co->pos_z_2 > archBodyparts[connID2].z/2000 )
844 							co->pos_z_2 = archBodyparts[connID2].z/2000;
845 					}
846 					else {
847 						if ( co->XYZ == 0 ) { // X
848 							if ( direction == 0 ) {
849 								if ( axis1or2 == 0 )	co->pos_y_2 += archMouths[connID2].y / 100000;
850 								else			co->pos_z_2 += archMouths[connID2].z / 100000;
851 							} else {
852 								if ( axis1or2 == 0 )	co->pos_y_2 -= archMouths[connID2].y / 100000;
853 								else			co->pos_z_2 -= archMouths[connID2].z / 100000;
854 							}
855 						}
856 						else if ( co->XYZ == 1 ) { // Y
857 							if ( direction == 0 ) {
858 								if ( axis1or2 == 0 )	co->pos_x_2 += archMouths[connID2].x / 100000;
859 								else			co->pos_z_2 += archMouths[connID2].z / 100000;
860 							} else {
861 								if ( axis1or2 == 0 )	co->pos_x_2 -= archMouths[connID2].x / 100000;
862 								else			co->pos_z_2 -= archMouths[connID2].z / 100000;
863 							}
864 						}
865 						else { // Z
866 							if ( direction == 0 ) {
867 								if ( axis1or2 == 0 )	co->pos_x_2 += archMouths[connID2].x / 100000;
868 								else			co->pos_y_2 += archMouths[connID2].y / 100000;
869 							} else {
870 								if ( axis1or2 == 0 )	co->pos_x_2 -= archMouths[connID2].x / 100000;
871 								else			co->pos_y_2 -= archMouths[connID2].y / 100000;
872 							}
873 						}
874 						if ( co->pos_x_2 < archMouths[connID2].x/-2000 )
875 							co->pos_x_2 = archMouths[connID2].x/-2000;
876 						if ( co->pos_x_2 > archMouths[connID2].x/2000 )
877 							co->pos_x_2 = archMouths[connID2].x/2000;
878 						if ( co->pos_y_2 < archMouths[connID2].y/-2000 )
879 							co->pos_y_2 = archMouths[connID2].y/-2000;
880 						if ( co->pos_y_2 > archMouths[connID2].y/2000 )
881 							co->pos_y_2 = archMouths[connID2].y/2000;
882 						if ( co->pos_z_2 < archMouths[connID2].z/-2000 )
883 							co->pos_z_2 = archMouths[connID2].z/-2000;
884 						if ( co->pos_z_2 > archMouths[connID2].z/2000 )
885 							co->pos_z_2 = archMouths[connID2].z/2000;
886 					}
887 				}
888 
889 // 					randomConstraintPosition(co, 2, connID2);
890 
891 // 				cerr << "done changing constraint position" << endl;
892 				continue;
893 			}
894 
895 		// REMOVE AND ADD MOUTH
896 			modesum += settings->getCVar("body_percentmutateeffectrepositionhead");
897 			if ( mode <= modesum )
898 			{
899 // 				cerr << "remove and add mouth" << endl;
900 
901 				for ( int i = 0; i < (int)archConstraints.size(); i++ )
902 				{
903 					archConstraint* c = &archConstraints[i];
904 					if ( c->isMouthConstraint && c->id_2 == archMouths[0].id )
905 					{
906 						archConstraints.erase(archConstraints.begin()+i);
907 						i--;
908 					}
909 				}
910 
911 				removeMouth(0);
912 
913 				addRandomMouth();
914 
915 // 				cerr << "done remove and add mouth" << endl;
916 				continue;
917 			}
918 
919 		// if we reach here, none were processed, decrease runs by 1 to make sure we get a hit
920 			if ( modesum > 0 )
921 				runs++;
922 	}
923 }
924 
repositiontoConstraints(archBodypart * bp)925 void BodyArch::repositiontoConstraints( archBodypart* bp )
926 {
927 	// reposition the constraints back to the resized bodypart / mouth
928 	for ( int i = 0; i < (int)archConstraints.size(); i++ )
929 	{
930 		archConstraint* co = &archConstraints[i];
931 		if ( findBodypart( co->id_1 ) == (int)bp->id )
932 		{
933 			if ( co->XYZ == 0 ) // X
934 				co->pos_x_1 = (bp->x / 2000.0f) * co->sign * bodypartspacer;
935 			else if ( co->XYZ == 1 ) // Y
936 				co->pos_y_1 = (bp->y / 2000.0f) * co->sign * bodypartspacer;
937 			else if ( co->XYZ == 2 ) // Z
938 				co->pos_z_1 = (bp->z / 2000.0f) * co->sign * bodypartspacer;
939 		}
940 		else if ( !co->isMouthConstraint && findBodypart( co->id_2 ) == (int)bp->id )
941 		{
942 			int othersign = -1 * co->sign;
943 			if ( co->XYZ == 0 ) // X
944 				co->pos_x_2 = (bp->x / 2000.0f) * othersign * bodypartspacer;
945 			else if ( co->XYZ == 1 ) // Y
946 				co->pos_y_2 = (bp->y / 2000.0f) * othersign * bodypartspacer;
947 			else if ( co->XYZ == 2 ) // Z
948 				co->pos_z_2 = (bp->z / 2000.0f) * othersign * bodypartspacer;
949 		}
950 	}
951 }
952 
repositiontoConstraints(archMouth * bp)953 void BodyArch::repositiontoConstraints( archMouth* bp )
954 {
955 	// reposition the constraints back to the resized bodypart / mouth
956 	for ( int i = 0; i < (int)archConstraints.size(); i++ )
957 	{
958 		archConstraint* co = &archConstraints[i];
959 		if ( co->isMouthConstraint && findBodypart( co->id_2 ) == (int)bp->id )
960 		{
961 			int othersign = -1 * co->sign;
962 			if ( co->XYZ == 0 ) // X
963 				co->pos_x_2 = (bp->x / 2000.0f) * othersign * bodypartspacer;
964 			else if ( co->XYZ == 1 ) // Y
965 				co->pos_y_2 = (bp->y / 2000.0f) * othersign * bodypartspacer;
966 			else if ( co->XYZ == 2 ) // Z
967 				co->pos_z_2 = (bp->z / 2000.0f) * othersign * bodypartspacer;
968 		}
969 	}
970 }
971 
findBodypart(unsigned int id)972 int BodyArch::findBodypart( unsigned int id )
973 {
974 	for ( unsigned int i=0; i < archBodyparts.size(); i++ )
975 	{
976 		if ( archBodyparts[i].id == id )
977 		{
978 			return i;
979 		}
980 	}
981 // 	cerr << " NOT GOOD: cannot find a bodypart for the id " << id << endl;
982 	return -1;
983 }
984 
findMouth(unsigned int id)985 int BodyArch::findMouth( unsigned int id )
986 {
987 	for ( unsigned int i=0; i < archMouths.size(); i++ )
988 	{
989 		if ( archMouths[i].id == id )
990 		{
991 			return i;
992 		}
993 	}
994 // 	cerr << " NOT GOOD " << endl;
995 // 	cerr << " NOT GOOD: cannot find a mouth for the id " << id << endl;
996 	return -1;
997 }
998 
getUniqueBodypartID()999 unsigned int BodyArch::getUniqueBodypartID()
1000 {
1001 	unsigned int id = 1000;
1002 	bool found = true;
1003 	while ( found )
1004 	{
1005 		found = false;
1006 		for ( unsigned int i = 0; i < archBodyparts.size() && !found; i++ )
1007 			if ( archBodyparts[i].id == id )
1008 			{
1009 				found = true;
1010 				id++;
1011 			}
1012 	}
1013 	return id;
1014 }
1015 
getUniqueConstraintID()1016 unsigned int BodyArch::getUniqueConstraintID()
1017 {
1018 	unsigned int id = 1000;
1019 	bool found = true;
1020 	while ( found )
1021 	{
1022 		found = false;
1023 		for ( unsigned int i = 0; i < archConstraints.size() && !found; i++ )
1024 		{
1025 			if ( archConstraints[i].constraint_id1 == id || archConstraints[i].constraint_id2 == id )
1026 			{
1027 				found = true;
1028 				id++;
1029 			}
1030 		}
1031 	}
1032 	return id;
1033 }
1034 
copyFrom(const BodyArch * otherBody)1035 void BodyArch::copyFrom(const BodyArch* otherBody)
1036 {
1037 	color = otherBody->color;
1038 	retinasize = otherBody->retinasize;
1039 
1040 	for ( unsigned int i=0; i < otherBody->archBodyparts.size(); i++ )
1041 	{
1042 		const archBodypart *obp = &otherBody->archBodyparts[i];
1043 		archBodyparts.push_back( archBodypart() );
1044 		archBodypart *bp = &archBodyparts[archBodyparts.size()-1];
1045 
1046 		bp->id		= obp->id;
1047 		bp->type	= obp->type;
1048 		bp->materialID	= obp->materialID;
1049 		bp->x		= obp->x;
1050 		bp->y		= obp->y;
1051 		bp->z		= obp->z;
1052 	}
1053 
1054 	for ( unsigned int i=0; i < otherBody->archMouths.size(); i++ )
1055 	{
1056 		const archMouth *omo = &otherBody->archMouths[i];
1057 		archMouths.push_back( archMouth() );
1058 		archMouth *mo = &archMouths[archMouths.size()-1];
1059 
1060 		mo->id		= omo->id;
1061 		mo->x		= omo->x;
1062 		mo->y		= omo->y;
1063 		mo->z		= omo->z;
1064 	}
1065 
1066 	for ( unsigned int i=0; i < otherBody->archConstraints.size(); i++ )
1067 	{
1068 		const archConstraint *oco = &otherBody->archConstraints[i];
1069 		archConstraints.push_back( archConstraint() );
1070 		archConstraint *co = &archConstraints[archConstraints.size()-1];
1071 
1072 		co->isMouthConstraint	= oco->isMouthConstraint;
1073 		co->constraint_id1	= oco->constraint_id1;
1074 		co->constraint_id2	= oco->constraint_id2;
1075 		co->XYZ			= oco->XYZ;
1076 		co->sign		= oco->sign;
1077 		co->id_1		= oco->id_1;
1078 		co->id_2		= oco->id_2;
1079 		co->rot_x_1		= oco->rot_x_1;
1080 		co->rot_x_2		= oco->rot_x_2;
1081 		co->rot_y_1		= oco->rot_y_1;
1082 		co->rot_y_2		= oco->rot_y_2;
1083 		co->rot_z_1		= oco->rot_z_1;
1084 		co->rot_z_2		= oco->rot_z_2;
1085 		co->pos_x_1		= oco->pos_x_1;
1086 		co->pos_x_2		= oco->pos_x_2;
1087 		co->pos_y_1		= oco->pos_y_1;
1088 		co->pos_y_2		= oco->pos_y_2;
1089 		co->pos_z_1		= oco->pos_z_1;
1090 		co->pos_z_2		= oco->pos_z_2;
1091 		co->limit_1		= oco->limit_1;
1092 		co->limit_2		= oco->limit_2;
1093 	}
1094 }
1095 
setArch(string * content)1096 void BodyArch::setArch(string* content)
1097 {
1098 //	cerr << *content << endl;
1099 
1100 	string contentCopy = *content;
1101 	string line = parseH->Instance()->returnUntillStrip( "\n", contentCopy );
1102 	while ( !line.empty() )
1103 	{
1104 		if ( Parser::Instance()->beginMatchesStrip( "color=", line ) )
1105 		{
1106 			string R = Parser::Instance()->returnUntillStrip( ",", line );
1107 			string G = Parser::Instance()->returnUntillStrip( ",", line );
1108 			string B = Parser::Instance()->returnUntillStrip( ";", line );
1109 
1110 			if(EOF == sscanf(R.c_str(), "%f", &color.r)) cerr << "ERROR INSERTING CRITTER (colorR)" << endl;
1111 			if(EOF == sscanf(G.c_str(), "%f", &color.g)) cerr << "ERROR INSERTING CRITTER (colorG)" << endl;
1112 			if(EOF == sscanf(B.c_str(), "%f", &color.b)) cerr << "ERROR INSERTING CRITTER (colorB)" << endl;
1113 			color.a = 0.0f;
1114 		}
1115 		else if ( Parser::Instance()->beginMatchesStrip( "retinasize=", line ) )
1116 		{
1117 			string RES = Parser::Instance()->returnUntillStrip( ";", line );
1118 			//cerr << "RES: " << RES << endl;
1119 			if(EOF == sscanf(RES.c_str(), "%d", &retinasize)) cerr << "ERROR INSERTING CRITTER" << endl;
1120 		}
1121 		else if ( parseH->Instance()->beginMatchesStrip( "b ", line ) )
1122 		{
1123 			// b 99999 box 0 75 75 200
1124 
1125 // 			cerr << "bodypart" << endl;
1126 
1127 			archBodyparts.push_back( archBodypart() );
1128 			archBodypart *bp = &archBodyparts[archBodyparts.size()-1];
1129 
1130 			string bodypartID = Parser::Instance()->returnUntillStrip( " ", line );
1131 			if(EOF == sscanf(bodypartID.c_str(), "%d", &bp->id)) cerr << "error in parsing body" << endl;
1132 			string bodypartShape = Parser::Instance()->returnUntillStrip( " ", line );
1133 			if ( bodypartShape == "box" )
1134 			{
1135 				// type = box
1136 					bp->type = 0;
1137 
1138 				// materialID
1139 					string materialID = Parser::Instance()->returnUntillStrip( " ", line );
1140 					if(EOF == sscanf(materialID.c_str(), "%d", &bp->materialID)) cerr << "error in parsing body" << endl;
1141 
1142 				// dimesions X Y Z
1143 					string X = Parser::Instance()->returnUntillStrip( " ", line );
1144 					string Y = Parser::Instance()->returnUntillStrip( " ", line );
1145 					string Z = line;
1146 					if(EOF == sscanf(X.c_str(), "%f", &bp->x)) cerr << "error in parsing body" << endl;
1147 					if(EOF == sscanf(Y.c_str(), "%f", &bp->y)) cerr << "error in parsing body" << endl;
1148 					if(EOF == sscanf(Z.c_str(), "%f", &bp->z)) cerr << "error in parsing body" << endl;
1149 
1150 
1151 /*				cerr << endl << " id " << bp->id << endl;
1152 				cerr << " type " << bp->type << endl;
1153 				cerr << " material " << bp->materialID << endl;
1154 				cerr << " x " << bp->x << endl;
1155 				cerr << " y " << bp->y << endl;
1156 				cerr << " z " << bp->z << endl;*/
1157 			}
1158 		}
1159 		else if ( parseH->Instance()->beginMatchesStrip( "c ", line ) )
1160 		{
1161 			// c 99999 1.5707963 0 0 0 0 -0.25 99998 1.5707963 0 0 0 0 0.25
1162 // 			cm 0 1 1000 1001 1000 1.115 -0.752 -0.102 0.258 0.089 -0.133 -0.1103 1000 -1.4 -1.007 -1.287 -0.258 0.039 0.137 0.1103
1163 // 			cerr << "constraint" << endl;
1164 
1165 			archConstraint CO;
1166 			archConstraints.push_back( CO );
1167 			archConstraint *co = &archConstraints[archConstraints.size()-1];
1168 
1169 			// XYZ & sign
1170 				string XYZ = Parser::Instance()->returnUntillStrip( " ", line );
1171 				if(EOF == sscanf(XYZ.c_str(), "%d", &co->XYZ)) cerr << "error in parsing body" << endl;
1172 				string SIGN = Parser::Instance()->returnUntillStrip( " ", line );
1173 				if(EOF == sscanf(SIGN.c_str(), "%d", &co->sign)) cerr << "error in parsing body" << endl;
1174 
1175 			// CONSTRAINT IDS
1176 				string ID = Parser::Instance()->returnUntillStrip( " ", line );
1177 				if(EOF == sscanf(ID.c_str(), "%d", &co->constraint_id1)) cerr << "error in parsing body" << endl;
1178 				ID = Parser::Instance()->returnUntillStrip( " ", line );
1179 				if(EOF == sscanf(ID.c_str(), "%d", &co->constraint_id2)) cerr << "error in parsing body" << endl;
1180 
1181 			// CONNECTION TO BODYPART 1
1182 				string ID_1 = Parser::Instance()->returnUntillStrip( " ", line );
1183 				if(EOF == sscanf(ID_1.c_str(), "%d", &co->id_1)) cerr << "error in parsing body" << endl;
1184 
1185 			// ROTATION
1186 				string ROT_X_1 = Parser::Instance()->returnUntillStrip( " ", line );
1187 				if(EOF == sscanf(ROT_X_1.c_str(), "%f", &co->rot_x_1)) cerr << "error in parsing body" << endl;
1188 				string ROT_Y_1 = Parser::Instance()->returnUntillStrip( " ", line );
1189 				if(EOF == sscanf(ROT_Y_1.c_str(), "%f", &co->rot_y_1)) cerr << "error in parsing body" << endl;
1190 				string ROT_Z_1 = Parser::Instance()->returnUntillStrip( " ", line );
1191 				if(EOF == sscanf(ROT_Z_1.c_str(), "%f", &co->rot_z_1)) cerr << "error in parsing body" << endl;
1192 
1193 			// POSITION
1194 				string POS_X_1 = Parser::Instance()->returnUntillStrip( " ", line );
1195 				if(EOF == sscanf(POS_X_1.c_str(), "%f", &co->pos_x_1)) cerr << "error in parsing body" << endl;
1196 				string POS_Y_1 = Parser::Instance()->returnUntillStrip( " ", line );
1197 				if(EOF == sscanf(POS_Y_1.c_str(), "%f", &co->pos_y_1)) cerr << "error in parsing body" << endl;
1198 				string POS_Z_1 = Parser::Instance()->returnUntillStrip( " ", line );
1199 				if(EOF == sscanf(POS_Z_1.c_str(), "%f", &co->pos_z_1)) cerr << "error in parsing body" << endl;
1200 
1201 			// LIMIT
1202 				string LIMIT_1 = Parser::Instance()->returnUntillStrip( " ", line );
1203 				if(EOF == sscanf(LIMIT_1.c_str(), "%f", &co->limit_1)) cerr << "error in parsing body" << endl;
1204 
1205 			// CONNECTION TO BODYPART 2
1206 				string ID_2 = Parser::Instance()->returnUntillStrip( " ", line );
1207 				if(EOF == sscanf(ID_2.c_str(), "%d", &co->id_2)) cerr << "error in parsing body" << endl;
1208 
1209 			// ROTATION
1210 				string ROT_X_2 = Parser::Instance()->returnUntillStrip( " ", line );
1211 				if(EOF == sscanf(ROT_X_2.c_str(), "%f", &co->rot_x_2)) cerr << "error in parsing body" << endl;
1212 				string ROT_Y_2 = Parser::Instance()->returnUntillStrip( " ", line );
1213 				if(EOF == sscanf(ROT_Y_2.c_str(), "%f", &co->rot_y_2)) cerr << "error in parsing body" << endl;
1214 				string ROT_Z_2 = Parser::Instance()->returnUntillStrip( " ", line );
1215 				if(EOF == sscanf(ROT_Z_2.c_str(), "%f", &co->rot_z_2)) cerr << "error in parsing body" << endl;
1216 
1217 			// POSITION
1218 				string POS_X_2 = Parser::Instance()->returnUntillStrip( " ", line );
1219 				if(EOF == sscanf(POS_X_2.c_str(), "%f", &co->pos_x_2)) cerr << "error in parsing body" << endl;
1220 				string POS_Y_2 = Parser::Instance()->returnUntillStrip( " ", line );
1221 				if(EOF == sscanf(POS_Y_2.c_str(), "%f", &co->pos_y_2)) cerr << "error in parsing body" << endl;
1222 				string POS_Z_2 = Parser::Instance()->returnUntillStrip( " ", line );
1223 				if(EOF == sscanf(POS_Z_2.c_str(), "%f", &co->pos_z_2)) cerr << "error in parsing body" << endl;
1224 
1225 			// LIMIT
1226 				string LIMIT_2 = line;
1227 				if(EOF == sscanf(LIMIT_2.c_str(), "%f", &co->limit_2)) cerr << "error in parsing body" << endl;
1228 		}
1229 		else if ( parseH->Instance()->beginMatchesStrip( "cm ", line ) )
1230 		{
1231 			// cm 99999 1.5707963 0 0 0 0 -0.25 99998 1.5707963 0 0 0 0 0.25
1232 
1233 // 			cerr << "constraint" << endl;
1234 
1235 			archConstraint CO;
1236 			archConstraints.push_back( CO );
1237 			archConstraint *co = &archConstraints[archConstraints.size()-1];
1238 
1239 			co->isMouthConstraint = true;
1240 
1241 			// XYZ & sign
1242 				string XYZ = Parser::Instance()->returnUntillStrip( " ", line );
1243 				if(EOF == sscanf(XYZ.c_str(), "%d", &co->XYZ)) cerr << "error in parsing body" << endl;
1244 				string SIGN = Parser::Instance()->returnUntillStrip( " ", line );
1245 				if(EOF == sscanf(SIGN.c_str(), "%d", &co->sign)) cerr << "error in parsing body" << endl;
1246 
1247 			// CONSTRAINT IDS
1248 				string ID = Parser::Instance()->returnUntillStrip( " ", line );
1249 				if(EOF == sscanf(ID.c_str(), "%d", &co->constraint_id1)) cerr << "error in parsing body" << endl;
1250 				ID = Parser::Instance()->returnUntillStrip( " ", line );
1251 				if(EOF == sscanf(ID.c_str(), "%d", &co->constraint_id2)) cerr << "error in parsing body" << endl;
1252 
1253 			// CONNECTION TO BODYPART 1
1254 				string ID_1 = Parser::Instance()->returnUntillStrip( " ", line );
1255 				if(EOF == sscanf(ID_1.c_str(), "%d", &co->id_1)) cerr << "error in parsing body" << endl;
1256 
1257 			// ROTATION
1258 				string ROT_X_1 = Parser::Instance()->returnUntillStrip( " ", line );
1259 				if(EOF == sscanf(ROT_X_1.c_str(), "%f", &co->rot_x_1)) cerr << "error in parsing body" << endl;
1260 				string ROT_Y_1 = Parser::Instance()->returnUntillStrip( " ", line );
1261 				if(EOF == sscanf(ROT_Y_1.c_str(), "%f", &co->rot_y_1)) cerr << "error in parsing body" << endl;
1262 				string ROT_Z_1 = Parser::Instance()->returnUntillStrip( " ", line );
1263 				if(EOF == sscanf(ROT_Z_1.c_str(), "%f", &co->rot_z_1)) cerr << "error in parsing body" << endl;
1264 
1265 			// POSITION
1266 				string POS_X_1 = Parser::Instance()->returnUntillStrip( " ", line );
1267 				if(EOF == sscanf(POS_X_1.c_str(), "%f", &co->pos_x_1)) cerr << "error in parsing body" << endl;
1268 				string POS_Y_1 = Parser::Instance()->returnUntillStrip( " ", line );
1269 				if(EOF == sscanf(POS_Y_1.c_str(), "%f", &co->pos_y_1)) cerr << "error in parsing body" << endl;
1270 				string POS_Z_1 = Parser::Instance()->returnUntillStrip( " ", line );
1271 				if(EOF == sscanf(POS_Z_1.c_str(), "%f", &co->pos_z_1)) cerr << "error in parsing body" << endl;
1272 
1273 			// LIMIT
1274 				string LIMIT_1 = Parser::Instance()->returnUntillStrip( " ", line );
1275 				if(EOF == sscanf(LIMIT_1.c_str(), "%f", &co->limit_1)) cerr << "error in parsing body" << endl;
1276 
1277 			// CONNECTION TO BODYPART 2
1278 				string ID_2 = Parser::Instance()->returnUntillStrip( " ", line );
1279 				if(EOF == sscanf(ID_2.c_str(), "%d", &co->id_2)) cerr << "error in parsing body" << endl;
1280 
1281 			// ROTATION
1282 				string ROT_X_2 = Parser::Instance()->returnUntillStrip( " ", line );
1283 				if(EOF == sscanf(ROT_X_2.c_str(), "%f", &co->rot_x_2)) cerr << "error in parsing body" << endl;
1284 				string ROT_Y_2 = Parser::Instance()->returnUntillStrip( " ", line );
1285 				if(EOF == sscanf(ROT_Y_2.c_str(), "%f", &co->rot_y_2)) cerr << "error in parsing body" << endl;
1286 				string ROT_Z_2 = Parser::Instance()->returnUntillStrip( " ", line );
1287 				if(EOF == sscanf(ROT_Z_2.c_str(), "%f", &co->rot_z_2)) cerr << "error in parsing body" << endl;
1288 
1289 			// POSITION
1290 				string POS_X_2 = Parser::Instance()->returnUntillStrip( " ", line );
1291 				if(EOF == sscanf(POS_X_2.c_str(), "%f", &co->pos_x_2)) cerr << "error in parsing body" << endl;
1292 				string POS_Y_2 = Parser::Instance()->returnUntillStrip( " ", line );
1293 				if(EOF == sscanf(POS_Y_2.c_str(), "%f", &co->pos_y_2)) cerr << "error in parsing body" << endl;
1294 				string POS_Z_2 = Parser::Instance()->returnUntillStrip( " ", line );
1295 				if(EOF == sscanf(POS_Z_2.c_str(), "%f", &co->pos_z_2)) cerr << "error in parsing body" << endl;
1296 
1297 			// LIMIT
1298 				string LIMIT_2 = line;
1299 				if(EOF == sscanf(LIMIT_2.c_str(), "%f", &co->limit_2)) cerr << "error in parsing body" << endl;
1300 		}
1301 		else if ( parseH->Instance()->beginMatchesStrip( "m ", line ) )
1302 		{
1303 			// m 99999 50, 50, 100
1304 // 			cerr << "constraint" << endl;
1305 
1306 			archMouth MO;
1307 			archMouths.push_back( MO );
1308 			archMouth *mo = &archMouths[archMouths.size()-1];
1309 
1310 			string ID = Parser::Instance()->returnUntillStrip( " ", line );
1311 			if(EOF == sscanf(ID.c_str(), "%d", &mo->id)) cerr << "error in parsing body" << endl;
1312 
1313 			string X = Parser::Instance()->returnUntillStrip( " ", line );
1314 			if(EOF == sscanf(X.c_str(), "%f", &mo->x)) cerr << "error in parsing body" << endl;
1315 
1316 			string Y = Parser::Instance()->returnUntillStrip( " ", line );
1317 			if(EOF == sscanf(Y.c_str(), "%f", &mo->y)) cerr << "error in parsing body" << endl;
1318 
1319 			string Z = line;
1320 			if(EOF == sscanf(Z.c_str(), "%f", &mo->z)) cerr << "error in parsing body" << endl;
1321 		}
1322 		line = parseH->Instance()->returnUntillStrip( "\n", contentCopy );
1323 	}
1324 }
1325 
1326 
getArch()1327 string* BodyArch::getArch()
1328 {
1329 	stringstream buf;
1330 
1331 	// neuron info
1332 		buf << "color=" << color.r << "," << color.g << "," << color.b << ";\n";
1333 		buf << "retinasize=" << retinasize << ";\n";
1334 		for ( unsigned int i=0; i < archBodyparts.size(); i++ )
1335 		{
1336 			archBodypart *bp = &archBodyparts[i];
1337 			buf << "b" << " " << bp->id << " " << "box" << " " << bp->materialID << " " << bp->x << " " << bp->y << " " << bp->z << "\n";
1338 		}
1339 
1340 		for ( unsigned int i=0; i < archMouths.size(); i++ )
1341 		{
1342 			archMouth *mo = &archMouths[i];
1343 			buf << "m" << " " << mo->id << " " << mo->x << " " << mo->y << " " << mo->z << "\n";
1344 		}
1345 
1346 		for ( unsigned int i=0; i < archConstraints.size(); i++ )
1347 		{
1348 			archConstraint *co = &archConstraints[i];
1349 			if ( co->isMouthConstraint )
1350 				buf << "cm";
1351 			else
1352 				buf << "c";
1353 			buf << " " << co->XYZ << " " << co->sign;
1354 			buf << " " << co->constraint_id1 << " " << co->constraint_id2 << " ";
1355 			buf << co->id_1 << " " << co->rot_x_1 << " " << co->rot_y_1 << " " << co->rot_z_1 << " " << co->pos_x_1 << " " << co->pos_y_1 << " " << co->pos_z_1 << " " << co->limit_1 << " ";
1356 			buf << co->id_2 << " " << co->rot_x_2 << " " << co->rot_y_2 << " " << co->rot_z_2 << " " << co->pos_x_2 << " " << co->pos_y_2 << " " << co->pos_z_2 << " " << co->limit_2;
1357 			buf << "\n";
1358 		}
1359 
1360 	archBuffer = buf.str();
1361 	return &archBuffer;
1362 }
1363 
~BodyArch()1364 BodyArch::~BodyArch()
1365 {
1366 }
1367