Exemplo n.º 1
0
void AvatarVoxelSystem::computeBoneIndicesAndWeights(const glm::vec3& vertex, BoneIndices& indices, glm::vec4& weights) const {
    // transform into joint space
    glm::vec3 jointVertex = (vertex - glm::vec3(0.5f, 0.5f, 0.5f)) * AVATAR_TREE_SCALE;
    
    // find the nearest four joints (TODO: use a better data structure for the pose positions to speed this up)
    IndexDistance nearest[BONE_ELEMENTS_PER_VERTEX];
    const Skeleton& skeleton = _avatar->getSkeleton();
    for (int i = 0; i < NUM_AVATAR_JOINTS; i++) {
        AvatarJointID parent = skeleton.joint[i].parent;
        float distance = glm::length(computeVectorFromPointToSegment(jointVertex,
            skeleton.joint[parent == AVATAR_JOINT_NULL ? i : parent].absoluteBindPosePosition,
            skeleton.joint[i].absoluteBindPosePosition));
        if (!MODES[_mode].includeBonesOutsideBindRadius && distance > skeleton.joint[i].bindRadius) {
            continue;
        }
        for (int j = 0; j < BONE_ELEMENTS_PER_VERTEX; j++) {
            if (distance < nearest[j].distance) {
                // move the rest of the indices down
                for (int k = BONE_ELEMENTS_PER_VERTEX - 1; k > j; k--) {
                    nearest[k] = nearest[k - 1];
                }       
                nearest[j] = IndexDistance(i, distance);
                break;
            }
        }
    } 
    
    // compute the weights based on inverse distance
    float totalWeight = 0.0f;
    for (int i = 0; i < MODES[_mode].maxBonesPerBind; i++) {
        indices[i] = nearest[i].index;
        if (nearest[i].distance != FLT_MAX) {
            weights[i] = 1.0f / glm::max(nearest[i].distance, EPSILON);
            totalWeight += weights[i];
        
        } else {
            weights[i] = 0.0f;
        }
    }
    
    // if it's not attached to anything, consider it attached to the hip
    if (totalWeight == 0.0f) {
        weights[0] = 1.0f;
        return;
    }
    
    // ortherwise, normalize the weights
    for (int i = 0; i < BONE_ELEMENTS_PER_VERTEX; i++) {
        weights[i] /= totalWeight;
    }
}
Exemplo n.º 2
0
void AIHeroesAddedTask(Heroes & hero)
{
    AIHero & ai_hero = AIHeroes::Get(hero);
    AIKingdom & ai_kingdom = AIKingdoms::Get(hero.GetColor());

    Queue & task = ai_hero.sheduled_visit;
    IndexObjectMap & ai_objects = ai_kingdom.scans;

    // load minimal distance tasks
    std::vector<IndexDistance> objs;
    objs.reserve(ai_objects.size());

    for(std::map<s32, int>::const_iterator
	it = ai_objects.begin(); it != ai_objects.end(); ++it)
    {
	const Maps::Tiles & tile = world.GetTiles((*it).first);

	if(hero.isShipMaster())
	{
	    if(MP2::OBJ_COAST != tile.GetObject() &&
		! tile.isWater()) continue;

	    // check previous positions
	    if(MP2::OBJ_COAST == (*it).second &&
		hero.isVisited(world.GetTiles((*it).first))) continue;
	}
	else
	{
	    if(tile.isWater() && MP2::OBJ_BOAT != tile.GetObject()) continue;
	}

	objs.push_back(IndexDistance((*it).first,
			    Maps::GetApproximateDistance(hero.GetIndex(), (*it).first)));
    }

    DEBUG(DBG_AI, DBG_INFO, Color::String(hero.GetColor()) <<
		    ", hero: " << hero.GetName() << ", task prepare: " << objs.size());

    std::sort(objs.begin(), objs.end(), IndexDistance::Shortest);

    for(std::vector<IndexDistance>::const_iterator
	it = objs.begin(); it != objs.end(); ++it)
    {
	if(task.size() >= HERO_MAX_SHEDULED_TASK) break;
	const bool validobj = AI::HeroesValidObject(hero, (*it).first);

	if(validobj &&
	    hero.GetPath().Calculate((*it).first))
	{
	    DEBUG(DBG_AI, DBG_INFO, Color::String(hero.GetColor()) <<
		    ", hero: " << hero.GetName() << ", added tasks: " <<
		    MP2::StringObject(ai_objects[(*it).first]) << ", index: " << (*it).first <<
		    ", distance: " << (*it).second);

	    task.push_back((*it).first);
	    ai_objects.erase((*it).first);
	}
	else
	{
	    DEBUG(DBG_AI, DBG_TRACE, Color::String(hero.GetColor()) <<
		    ", hero: " << hero.GetName() << (!validobj ? ", invalid: " : ", impossible: ") <<
		    MP2::StringObject(ai_objects[(*it).first]) << ", index: " << (*it).first <<
		    ", distance: " << (*it).second);
	}
    }

    if(task.empty())
	AIHeroesAddedRescueTask(hero);
}