void BodyArch::removeBodypart(unsigned int id) { // cerr << "requested removal of bodypart id " << id << endl; // find constraints where this bodypart is id1, in order to remove connected bodyparts for ( unsigned int i = 0; i < archConstraints.size(); i++ ) { archConstraint* c = &archConstraints[i]; if ( c->id_1 == id ) { // cerr << " is connected to " << c->isMouthConstraint << " " << c->id_2 << endl; if ( c->isMouthConstraint ) removeMouth( findMouth(c->id_2) ); else removeBodypart( c->id_2 ); } } // cerr << "really removing " << id << " which is " << findBodypart( id ) << endl; archBodyparts.erase( archBodyparts.begin() + findBodypart(id) ); }
std::vector<float> FeatureVectorBuilder::detectFeatures(const cv::Mat& input) { //For saving puropse static int imgNumber = 0; assert(input.data != NULL); //Finding face size int rightFace, leftFace; int size = faceSize(input, leftFace, rightFace); //Eyes section int eyeLine = findEyesLine(input); cv::Mat rEye, lEye; cv::Rect rEyeRect, lEyeRect; findEyes(input, eyeLine, rEye, lEye, rEyeRect, lEyeRect); if(rEye.data == NULL || lEye.data == NULL) { return std::vector<float>(7); } cv::Point rEyeCenter, lEyeCenter; int rEyeRadius, lEyeRadius; findEyeCenter(rEye, rEyeCenter, rEyeRadius); findEyeCenter(lEye, lEyeCenter, lEyeRadius); transformPoint(rEyeCenter, rEyeRect); transformPoint(lEyeCenter, lEyeRect); //nose cv::Mat nose; cv::Rect noseRect = findNose(input); input(noseRect).copyTo(nose); if((noseRect.width <= 0 && noseRect.height <= 0) || nose.data == NULL) { return std::vector<float>(7); } cv::Point noseLeft, noseRight; findNosePoints(nose, noseLeft, noseRight); transformPoint(noseLeft, noseRect); transformPoint(noseRight, noseRect); //mouth cv::Mat mouth; cv::Point left, right, up, down; cv::Rect mouthRect = findMouth(input); input(mouthRect).copyTo(mouth); if((mouthRect.width <= 0 && mouthRect.height <= 0) || mouth.data == NULL) { return std::vector<float>(7); } findMouthPoints(mouth, left, right, up, down); transformPoint(left, mouthRect); transformPoint(right, mouthRect); transformPoint(up, mouthRect); transformPoint(down, mouthRect); #ifdef _DEBUG cv::Mat cpy; input.copyTo(cpy); cv::circle(cpy, lEyeCenter, 4, cv::Scalar(0, 0, 255)); cv::circle(cpy, rEyeCenter, 4, cv::Scalar(0, 0, 255)); cv::circle(cpy, noseLeft, 4, cv::Scalar(0, 255, 0)); cv::circle(cpy, noseRight, 4, cv::Scalar(0, 255, 0)); cv::circle(cpy, left, 4, cv::Scalar(255, 0, 255)); cv::circle(cpy, right, 4, cv::Scalar(255, 0, 255)); cv::circle(cpy, up, 4, cv::Scalar(255, 0, 255)); cv::circle(cpy, down, 4, cv::Scalar(255, 0, 255)); std::stringstream ss; ss << "debug//img" << imgNumber << ".jpg"; cv::imwrite(ss.str(), cpy); imgNumber++; #endif //wektor cech float x1, x2, x3, x4, x5, x6, x7; //odlegosc miedzy srodkami oczy x1 = distance(lEyeCenter, rEyeCenter); //szerokosc nosa x2 = distance(noseLeft, noseRight); //szerokosc ust x3 = distance(left, right); //wysokosc ust x4 = distance(up, down); //szerokosc twarzy x5 = (float)size; //odgleglosc miedzy linia oczu a lina nosa float tmp1, tmp2; tmp1 = distance(lEyeCenter, noseLeft); tmp2 = distance(rEyeCenter, noseRight); x6 = (tmp1 + tmp2) / 2.0f; //odleglosc miedzy linia oczu a linia ust tmp1 = distance(lEyeCenter, left); tmp2 = distance(rEyeCenter, right); x7 = (tmp1 + tmp2) / 2.0f; std::vector<float> characteristic; characteristic.push_back(x1/x2); characteristic.push_back(x1/x3); characteristic.push_back(x2/x3); characteristic.push_back(x1/x5); characteristic.push_back(x1/x6); characteristic.push_back(x1/x7); characteristic.push_back(x4/x5); return characteristic; }
void BodyArch::mutate(unsigned int runs) { for ( unsigned int i=0; i < runs; i++ ) { unsigned int tsum = settings->getCVar("body_percentmutateeffectchangecolor") + settings->getCVar("body_percentmutateeffectchangecolor_slightly") + settings->getCVar("body_percentmutateeffectaddbodypart") + settings->getCVar("body_percentmutateeffectremovebodypart") + settings->getCVar("body_percentmutateeffectresizebodypart") + settings->getCVar("body_percentmutateeffectresizebodypart_slightly") + settings->getCVar("body_percentmutateeffectresizehead") + settings->getCVar("body_percentmutateeffectresizehead_slightly") + settings->getCVar("body_percentmutateeffectchangeconstraintlimits") + settings->getCVar("body_percentmutateeffectchangeconstraintlimits_slightly") + settings->getCVar("body_percentmutateeffectchangeconstraintangles") + settings->getCVar("body_percentmutateeffectchangeconstraintangles_slightly") + settings->getCVar("body_percentmutateeffectchangeconstraintposition") + settings->getCVar("body_percentmutateeffectchangeconstraintposition_slightly") + settings->getCVar("body_percentmutateeffectrepositionhead") ; unsigned int mode = randgen->Instance()->get(1,tsum); // CHANGE COLOR unsigned int modesum = settings->getCVar("body_percentmutateeffectchangecolor"); if ( mode <= modesum ) { // mutate color unsigned int ncolor = randgen->Instance()->get(0,2); if ( ncolor == 0 ) color.r = (float)RandGen::Instance()->get(0,100)/100.0f; else if ( ncolor == 1 ) color.g = (float)RandGen::Instance()->get(0,100)/100.0f; else if ( ncolor == 2 ) color.b = (float)RandGen::Instance()->get(0,100)/100.0f; continue; } // CHANGE COLOR SLIGHTLY modesum += settings->getCVar("body_percentmutateeffectchangecolor_slightly"); if ( mode <= modesum ) { // mutate color unsigned int ncolor = randgen->Instance()->get(0,2); unsigned int nweight = randgen->Instance()->get(1,10); float amount = 0.01 * nweight; if ( randgen->Instance()->get(0,1) == 0 ) amount *= -1; if ( ncolor == 0 ) color.r += amount; else if ( ncolor == 1 ) color.g += amount; else if ( ncolor == 2 ) color.b += amount; if ( color.r < 0.1f ) { float diff = 0.1f - color.r; color.r += diff; color.g += diff; color.b += diff; color.a += diff; } if ( color.g < 0.1f ) { float diff = 0.1f - color.g; color.r += diff; color.g += diff; color.b += diff; color.a += diff; } if ( color.b < 0.1f ) { float diff = 0.1f - color.b; color.r += diff; color.g += diff; color.b += diff; color.a += diff; } if ( color.r > 1.0f && color.g > 1.0f && color.b > 1.0f ) color.normalize(); continue; } // ADD BODYPART modesum += settings->getCVar("body_percentmutateeffectaddbodypart"); if ( mode <= modesum ) { if ( archBodyparts.size() < settings->getCVar("body_maxbodyparts") ) { // cerr << "adding bodypart" << endl; addRandomBodypart(); // cerr << "done adding bodypart" << endl; } else runs++; continue; } // REMOVE BODYPART modesum += settings->getCVar("body_percentmutateeffectremovebodypart"); if ( mode <= modesum ) { if ( archBodyparts.size() > 2 ) { // pick a random bodypart unsigned int bid = randgen->Instance()->get( 0, archBodyparts.size()-1 ); // if not main body, remove it if ( archBodyparts[bid].id != 1000 ) { // cerr << "removing bodypart " << bid << " id " << archBodyparts[bid].id << endl; removeBodypart( archBodyparts[bid].id ); // cerr << "removing obsolete constraints, expected errors:" << endl; for ( int i = 0; i < (int)archConstraints.size(); i++ ) { archConstraint* c = &archConstraints[i]; if ( findBodypart( c->id_1 ) == -1 ) { archConstraints.erase(archConstraints.begin()+i); i--; } else if ( c->isMouthConstraint && findMouth( c->id_2 ) == -1 ) { archConstraints.erase(archConstraints.begin()+i); i--; } else if ( !c->isMouthConstraint && findBodypart( c->id_2 ) == -1 ) { archConstraints.erase(archConstraints.begin()+i); i--; } } // cerr << "done removing obsolete constraints" << endl << endl; // cerr << "done removing bodypart" << endl; // re add mouth if needed if ( archMouths.size() == 0 ) addRandomMouth(); } else runs++; } else runs++; continue; } // RESIZE BODYPART modesum += settings->getCVar("body_percentmutateeffectresizebodypart"); if ( mode <= modesum ) { // cerr << "resize bodypart" << endl; // pick a random bodypart unsigned int bid = randgen->Instance()->get( 0, archBodyparts.size()-1 ); archBodypart *bp = &archBodyparts[bid]; unsigned int axismode = randgen->Instance()->get(0,2); if ( axismode == 0 ) bp->x = randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") ); else if ( axismode == 1 ) bp->y = randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") ); else bp->z = randgen->Instance()->get( settings->getCVar("body_minbodypartsize"), settings->getCVar("body_maxbodypartsize") ); // reposition the constraints back to the resized bodypart repositiontoConstraints(bp); // cerr << "done resize bodypart" << endl; continue; } // RESIZE BODYPART SLIGHTLY modesum += settings->getCVar("body_percentmutateeffectresizebodypart_slightly"); if ( mode <= modesum ) { // cerr << "resize bodypart slightly" << endl; // pick a random bodypart unsigned int bid = randgen->Instance()->get( 0, archBodyparts.size()-1 ); archBodypart* bp = &archBodyparts[bid]; unsigned int axismode = randgen->Instance()->get(0,2); unsigned int direction = randgen->Instance()->get(0,1); if ( axismode == 0 ) { if ( direction == 0 ) bp->x += randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 ); else bp->x -= randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 ); } else if ( axismode == 1 ) { if ( direction == 0 ) bp->y += randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 ); else bp->y -= randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 ); } else { if ( direction == 0 ) bp->z += randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 ); else bp->z -= randgen->Instance()->get( 1, settings->getCVar("body_maxbodypartsize") / 10 ); } // see that they didn't go over their limits if ( bp->x < settings->getCVar("body_minbodypartsize") ) bp->x = settings->getCVar("body_minbodypartsize"); else if ( bp->x > settings->getCVar("body_maxbodypartsize") ) bp->x = settings->getCVar("body_minbodypartsize"); if ( bp->y < settings->getCVar("body_minbodypartsize") ) bp->y = settings->getCVar("body_minbodypartsize"); else if ( bp->y > settings->getCVar("body_maxbodypartsize") ) bp->y = settings->getCVar("body_minbodypartsize"); if ( bp->z < settings->getCVar("body_minbodypartsize") ) bp->z = settings->getCVar("body_minbodypartsize"); else if ( bp->z > settings->getCVar("body_maxbodypartsize") ) bp->z = settings->getCVar("body_minbodypartsize"); // reposition the constraints back to the resized bodypart repositiontoConstraints(bp); // cerr << "done resize bodypart" << endl; continue; } // RESIZE HEAD modesum += settings->getCVar("body_percentmutateeffectresizehead"); if ( mode <= modesum ) { // cerr << "resize mouth" << endl; // pick a random head unsigned int mid = randgen->Instance()->get( 0, archMouths.size()-1 ); archMouth* head = &archMouths[mid]; unsigned int axismode = randgen->Instance()->get(0,2); if ( axismode == 0 ) head->x = randgen->Instance()->get( settings->getCVar("body_minheadsize"), settings->getCVar("body_maxheadsize") ); else if ( axismode == 1 ) head->y = randgen->Instance()->get( settings->getCVar("body_minheadsize"), settings->getCVar("body_maxheadsize") ); else head->z = randgen->Instance()->get( settings->getCVar("body_minheadsize"), settings->getCVar("body_maxheadsize") ); // reposition the constraints back to the resized bodypart repositiontoConstraints(head); // cerr << "done resize head" << endl; continue; } // RESIZE HEAD SLIGHTLY modesum += settings->getCVar("body_percentmutateeffectresizehead_slightly"); if ( mode <= modesum ) { // cerr << "resize head slightly" << endl; // pick a random head unsigned int mid = randgen->Instance()->get( 0, archMouths.size()-1 ); archMouth* head = &archMouths[mid]; unsigned int axismode = randgen->Instance()->get(0,2); unsigned int direction = randgen->Instance()->get(0,1); if ( axismode == 0 ) { if ( direction == 0 ) head->x += randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 ); else head->x -= randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 ); } else if ( axismode == 1 ) { if ( direction == 0 ) head->y += randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 ); else head->y -= randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 ); } else { if ( direction == 0 ) head->z += randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 ); else head->z -= randgen->Instance()->get( 1, settings->getCVar("body_maxheadsize") / 10 ); } // see that they didn't go over their limits if ( head->x < settings->getCVar("body_minheadsize") ) head->x = settings->getCVar("body_minheadsize"); else if ( head->x > settings->getCVar("body_maxheadsize") ) head->x = settings->getCVar("body_minheadsize"); if ( head->y < settings->getCVar("body_minheadsize") ) head->y = settings->getCVar("body_minheadsize"); else if ( head->y > settings->getCVar("body_maxheadsize") ) head->y = settings->getCVar("body_minheadsize"); if ( head->z < settings->getCVar("body_minheadsize") ) head->z = settings->getCVar("body_minheadsize"); else if ( head->z > settings->getCVar("body_maxheadsize") ) head->z = settings->getCVar("body_minheadsize"); // reposition the constraints back to the resized bodypart repositiontoConstraints(head); // cerr << "done resize head" << endl; continue; } // CHANGE CONSTRAINT LIMITS modesum += settings->getCVar("body_percentmutateeffectchangeconstraintlimits"); if ( mode <= modesum ) { // cerr << "changing constraint limits" << endl; unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 ); archConstraint* co = &archConstraints[cid]; co->limit_1 = (float)randgen->Instance()->get( 0, 7853 ) / -10000; co->limit_2 = -1.0f * co->limit_1; // cerr << "done changing constraint limits" << endl; continue; } // CHANGE CONSTRAINT LIMITS SLIGHTLY modesum += settings->getCVar("body_percentmutateeffectchangeconstraintlimits_slightly"); if ( mode <= modesum ) { // cerr << "changing constraint limits" << endl; unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 ); archConstraint* co = &archConstraints[cid]; unsigned int direction = randgen->Instance()->get(0,1); if ( direction == 0 ) co->limit_1 += 0.01f; else co->limit_1 -= 0.01f; // check limits limits, ya if ( co->limit_1 > 0.0f ) co->limit_1 = 0.0f; if ( co->limit_1 < -0.7853f ) co->limit_1 = -0.7853f; co->limit_2 = -1.0f * co->limit_1; // cerr << "done changing constraint limits" << endl; continue; } // CHANGE CONSTRAINT ANGLES modesum += settings->getCVar("body_percentmutateeffectchangeconstraintangles"); if ( mode <= modesum ) { // cerr << "changing constraint angles" << endl; unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 ); archConstraint* co = &archConstraints[cid]; co->rot_x_1 = ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000; co->rot_z_1 = ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000; co->rot_y_1 = ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000; co->rot_x_2 = ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000; co->rot_y_2 = ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000; co->rot_z_2 = ((float)randgen->Instance()->get( 0, 3141 ) - 1571) / 1000; // cerr << "done changing constraint angles" << endl; continue; } // CHANGE CONSTRAINT ANGLES SLIGHTLY modesum += settings->getCVar("body_percentmutateeffectchangeconstraintangles_slightly"); if ( mode <= modesum ) { // cerr << "changing constraint angles" << endl; unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 ); archConstraint* co = &archConstraints[cid]; unsigned int XYZ = randgen->Instance()->get(0,2); unsigned int direction = randgen->Instance()->get(0,1); if ( direction == 0 ) { if ( XYZ == 0 ) co->rot_x_1 += 0.01f; else if ( XYZ == 1 ) co->rot_y_1 += 0.01f; else co->rot_z_1 += 0.01f; } else { if ( XYZ == 0 ) co->rot_x_1 -= 0.01f; else if ( XYZ == 1 ) co->rot_y_1 -= 0.01f; else co->rot_z_1 -= 0.01f; } XYZ = randgen->Instance()->get(0,2); direction = randgen->Instance()->get(0,1); if ( direction == 0 ) { if ( XYZ == 0 ) co->rot_x_2 += 0.01f; else if ( XYZ == 1 ) co->rot_y_2 += 0.01f; else co->rot_z_2 += 0.01f; } else { if ( XYZ == 0 ) co->rot_x_2 -= 0.01f; else if ( XYZ == 1 ) co->rot_y_2 -= 0.01f; else co->rot_z_2 -= 0.01f; } if ( co->rot_x_1 < -0.1571f ) co->rot_x_1 = -0.1571f; if ( co->rot_x_1 > 0.1571f ) co->rot_x_1 = 0.1571f; if ( co->rot_y_1 < -0.1571f ) co->rot_y_1 = -0.1571f; if ( co->rot_y_1 > 0.1571f ) co->rot_y_1 = 0.1571f; if ( co->rot_z_1 < -0.1571f ) co->rot_z_1 = -0.1571f; if ( co->rot_z_1 > 0.1571f ) co->rot_z_1 = 0.1571f; if ( co->rot_x_2 < -0.1571f ) co->rot_x_2 = -0.1571f; if ( co->rot_x_2 > 0.1571f ) co->rot_x_2 = 0.1571f; if ( co->rot_y_2 < -0.1571f ) co->rot_y_2 = -0.1571f; if ( co->rot_y_2 > 0.1571f ) co->rot_y_2 = 0.1571f; if ( co->rot_z_2 < -0.1571f ) co->rot_z_2 = -0.1571f; if ( co->rot_z_2 > 0.1571f ) co->rot_z_2 = 0.1571f; // cerr << "done changing constraint angles" << endl; continue; } // REPOSITION A CONSTRAINT modesum += settings->getCVar("body_percentmutateeffectchangeconstraintposition"); if ( mode <= modesum ) { // cerr << "changing constraint position" << endl; unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 ); archConstraint* co = &archConstraints[cid]; int connID1 = findBodypart(co->id_1); int connID2; if ( co->isMouthConstraint ) connID2 = findMouth(co->id_2); else connID2 = findBodypart(co->id_2); // pick one of 2 bodies to reconnect unsigned int body1or2 = randgen->Instance()->get( 1, 2 ); if ( body1or2 == 1 ) randomConstraintPosition(co, 1, connID1); else randomConstraintPosition(co, 2, connID2); // cerr << "done changing constraint position" << endl; continue; } // REPOSITION A CONSTRAINT SLIGHTLY modesum += settings->getCVar("body_percentmutateeffectchangeconstraintposition_slightly"); if ( mode <= modesum ) { // cerr << "changing constraint position" << endl; unsigned int cid = randgen->Instance()->get( 0, archConstraints.size()-1 ); archConstraint* co = &archConstraints[cid]; int connID1 = findBodypart(co->id_1); int connID2; if ( co->isMouthConstraint ) connID2 = findMouth(co->id_2); else connID2 = findBodypart(co->id_2); // pick one of 2 bodies to reconnect unsigned int body1or2 = randgen->Instance()->get( 1, 2 ); unsigned int direction = randgen->Instance()->get( 0, 1 ); unsigned int axis1or2 = randgen->Instance()->get( 0, 1 ); if ( body1or2 == 1 ) { // now we know the plane to connect to, determine positions if ( co->XYZ == 0 ) { // X if ( direction == 0 ) { if ( axis1or2 == 0 ) co->pos_y_1 += archBodyparts[connID1].y / 100000; else co->pos_z_1 += archBodyparts[connID1].z / 100000; } else { if ( axis1or2 == 0 ) co->pos_y_1 -= archBodyparts[connID1].y / 100000; else co->pos_z_1 -= archBodyparts[connID1].z / 100000; } } else if ( co->XYZ == 1 ) { // Y if ( direction == 0 ) { if ( axis1or2 == 0 ) co->pos_x_1 += archBodyparts[connID1].x / 100000; else co->pos_z_1 += archBodyparts[connID1].z / 100000; } else { if ( axis1or2 == 0 ) co->pos_x_1 -= archBodyparts[connID1].x / 100000; else co->pos_z_1 -= archBodyparts[connID1].z / 100000; } } else { // Z if ( direction == 0 ) { if ( axis1or2 == 0 ) co->pos_x_1 += archBodyparts[connID1].x / 100000; else co->pos_y_1 += archBodyparts[connID1].y / 100000; } else { if ( axis1or2 == 0 ) co->pos_x_1 -= archBodyparts[connID1].x / 100000; else co->pos_y_1 -= archBodyparts[connID1].y / 100000; } } if ( co->pos_x_1 < archBodyparts[connID1].x/-2000 ) co->pos_x_1 = archBodyparts[connID1].x/-2000; if ( co->pos_x_1 > archBodyparts[connID1].x/2000 ) co->pos_x_1 = archBodyparts[connID1].x/2000; if ( co->pos_y_1 < archBodyparts[connID1].y/-2000 ) co->pos_y_1 = archBodyparts[connID1].y/-2000; if ( co->pos_y_1 > archBodyparts[connID1].y/2000 ) co->pos_y_1 = archBodyparts[connID1].y/2000; if ( co->pos_z_1 < archBodyparts[connID1].z/-2000 ) co->pos_z_1 = archBodyparts[connID1].z/-2000; if ( co->pos_z_1 > archBodyparts[connID1].z/2000 ) co->pos_z_1 = archBodyparts[connID1].z/2000; } else { if ( !co->isMouthConstraint ) { // now we know the plane to connect to, determine positions if ( co->XYZ == 0 ) { // X if ( direction == 0 ) { if ( axis1or2 == 0 ) co->pos_y_2 += archBodyparts[connID2].y / 100000; else co->pos_z_2 += archBodyparts[connID2].z / 100000; } else { if ( axis1or2 == 0 ) co->pos_y_2 -= archBodyparts[connID2].y / 100000; else co->pos_z_2 -= archBodyparts[connID2].z / 100000; } } else if ( co->XYZ == 1 ) { // Y if ( direction == 0 ) { if ( axis1or2 == 0 ) co->pos_x_2 += archBodyparts[connID2].x / 100000; else co->pos_z_2 += archBodyparts[connID2].z / 100000; } else { if ( axis1or2 == 0 ) co->pos_x_2 -= archBodyparts[connID2].x / 100000; else co->pos_z_2 -= archBodyparts[connID2].z / 100000; } } else { // Z if ( direction == 0 ) { if ( axis1or2 == 0 ) co->pos_x_2 += archBodyparts[connID2].x / 100000; else co->pos_y_2 += archBodyparts[connID2].y / 100000; } else { if ( axis1or2 == 0 ) co->pos_x_2 -= archBodyparts[connID2].x / 100000; else co->pos_y_2 -= archBodyparts[connID2].y / 100000; } } if ( co->pos_x_2 < archBodyparts[connID2].x/-2000 ) co->pos_x_2 = archBodyparts[connID2].x/-2000; if ( co->pos_x_2 > archBodyparts[connID2].x/2000 ) co->pos_x_2 = archBodyparts[connID2].x/2000; if ( co->pos_y_2 < archBodyparts[connID2].y/-2000 ) co->pos_y_2 = archBodyparts[connID2].y/-2000; if ( co->pos_y_2 > archBodyparts[connID2].y/2000 ) co->pos_y_2 = archBodyparts[connID2].y/2000; if ( co->pos_z_2 < archBodyparts[connID2].z/-2000 ) co->pos_z_2 = archBodyparts[connID2].z/-2000; if ( co->pos_z_2 > archBodyparts[connID2].z/2000 ) co->pos_z_2 = archBodyparts[connID2].z/2000; } else { if ( co->XYZ == 0 ) { // X if ( direction == 0 ) { if ( axis1or2 == 0 ) co->pos_y_2 += archMouths[connID2].y / 100000; else co->pos_z_2 += archMouths[connID2].z / 100000; } else { if ( axis1or2 == 0 ) co->pos_y_2 -= archMouths[connID2].y / 100000; else co->pos_z_2 -= archMouths[connID2].z / 100000; } } else if ( co->XYZ == 1 ) { // Y if ( direction == 0 ) { if ( axis1or2 == 0 ) co->pos_x_2 += archMouths[connID2].x / 100000; else co->pos_z_2 += archMouths[connID2].z / 100000; } else { if ( axis1or2 == 0 ) co->pos_x_2 -= archMouths[connID2].x / 100000; else co->pos_z_2 -= archMouths[connID2].z / 100000; } } else { // Z if ( direction == 0 ) { if ( axis1or2 == 0 ) co->pos_x_2 += archMouths[connID2].x / 100000; else co->pos_y_2 += archMouths[connID2].y / 100000; } else { if ( axis1or2 == 0 ) co->pos_x_2 -= archMouths[connID2].x / 100000; else co->pos_y_2 -= archMouths[connID2].y / 100000; } } if ( co->pos_x_2 < archMouths[connID2].x/-2000 ) co->pos_x_2 = archMouths[connID2].x/-2000; if ( co->pos_x_2 > archMouths[connID2].x/2000 ) co->pos_x_2 = archMouths[connID2].x/2000; if ( co->pos_y_2 < archMouths[connID2].y/-2000 ) co->pos_y_2 = archMouths[connID2].y/-2000; if ( co->pos_y_2 > archMouths[connID2].y/2000 ) co->pos_y_2 = archMouths[connID2].y/2000; if ( co->pos_z_2 < archMouths[connID2].z/-2000 ) co->pos_z_2 = archMouths[connID2].z/-2000; if ( co->pos_z_2 > archMouths[connID2].z/2000 ) co->pos_z_2 = archMouths[connID2].z/2000; } } // randomConstraintPosition(co, 2, connID2); // cerr << "done changing constraint position" << endl; continue; } // REMOVE AND ADD MOUTH modesum += settings->getCVar("body_percentmutateeffectrepositionhead"); if ( mode <= modesum ) { // cerr << "remove and add mouth" << endl; for ( int i = 0; i < (int)archConstraints.size(); i++ ) { archConstraint* c = &archConstraints[i]; if ( c->isMouthConstraint && c->id_2 == archMouths[0].id ) { archConstraints.erase(archConstraints.begin()+i); i--; } } removeMouth(0); addRandomMouth(); // cerr << "done remove and add mouth" << endl; continue; } // if we reach here, none were processed, decrease runs by 1 to make sure we get a hit if ( modesum > 0 ) runs++; } }