Example #1
0
void Body::stepPhysics ()
{
    WorldObject::stepPhysics();
    dBodyID bodyID = getMainOdeObject()->getBodyID();
    if (userDriver)
    {
        double moveZ = System::get()->axisMap[getIDKeyboardKey(SDLK_BACKSPACE)]->getValue() * 50000;
        moveZ += System::get()->axisMap[getIDKeyboardKey(SDLK_RETURN)]->getValue() * 12200;
        moveZ -= System::get()->axisMap[getIDKeyboardKey(SDLK_RSHIFT)]->getValue() * 10000;
        dBodyAddForce (bodyID, 0, 0, moveZ);
    }
    
    // apply simple air drag forces:
    const double airDensity = 1.225;
    //  f = Cx              * 0.5 * airDensity * v^2     * area;
    //  f = dragCoefficient * 0.5 * 1.225      * vel*vel * frontalArea;
    Vector3d velocity (dBodyGetLinearVel (bodyID));
    double velModule = velocity.distance();
    Vector3d normalizedVel (velocity);
    normalizedVel.scalarDivide(velModule);
    normalizedVel.scalarMultiply(-1);
    Vector3d force (normalizedVel);
    force.scalarMultiply (0.5 * dragCoefficient * airDensity * frontalArea * velModule * velModule);

    dBodyAddForce (bodyID, force.x, force.y, force.z);

    //log->__format(LOG_DEVELOPER, "Body air drag force = (%f, %f, %f)", force.x, force.y, force.z);
}
Example #2
0
/**
Tries to find a (high-level) path from sourcePos in sourcePoly to destPos in destPoly.

@param sourcePos	The source position
@param sourcePoly	The source nav polygon
@param destPos		The destination position
@param destPoly		The destination nav polygon
@param path			Used to return the path (if found) to the caller
@return				true, if a path was found, or false otherwise
*/
bool GlobalPathfinder::find_path(const Vector3d& sourcePos, int sourcePoly,
								 const Vector3d& destPos, int destPoly,
								 std::list<int>& path) const
{
	// Step 1:	If the source position and dest position are both in the same nav polygon,
	//			the high-level path is empty (the entity just needs to go in a straight line).
	if(sourcePoly == destPoly)
	{
		return true;
	}

	// Step 2:	Find the shortest unblocked path-table path from a source navlink to a dest navlink.
	//			If such a path is found, and it's no more than (say) 25% longer than the optimal path
	//			we'd have if we ignored blocks, then use it.
	const std::vector<NavLink_Ptr>& links = m_navMesh->links();
	const std::vector<NavPolygon_Ptr>& polygons = m_navMesh->polygons();
	const std::vector<int>& sourceLinkIndices = polygons[sourcePoly]->out_links();
	const std::vector<int>& destLinkIndices = polygons[destPoly]->in_links();

	// Work out the costs of all the possible paths and get them ready to be processed in ascending order of cost.
	std::priority_queue<PathDescriptor, std::vector<PathDescriptor>, std::greater<PathDescriptor> > pq;
	int sourceLinkCount = static_cast<int>(sourceLinkIndices.size());
	int destLinkCount = static_cast<int>(destLinkIndices.size());
	for(int i=0; i<sourceLinkCount; ++i)
	{
		int sourceLinkIndex = sourceLinkIndices[i];
		const NavLink_Ptr& sourceLink = links[sourceLinkIndex];
		float sourceCost = static_cast<float>(sourcePos.distance(sourceLink->source_position()));

		for(int j=0; j<destLinkCount; ++j)
		{
			// The cost of going from sourcePos to destPos via the shortest path-table path
			// between the two navlinks is the sum of the cost of going to the source navlink,
			// the cost of going from the source navlink to the dest navlink, and the cost of
			// going from the dest navlink to destPos.
			int destLinkIndex = destLinkIndices[j];
			const NavLink_Ptr& destLink = links[destLinkIndex];
			float destCost = static_cast<float>(destPos.distance(destLink->dest_position()));
			float interlinkCost = m_pathTable->cost(sourceLinkIndex, destLinkIndex);
			pq.push(PathDescriptor(sourceCost + interlinkCost + destCost, sourceLinkIndex, destLinkIndex));
		}
	}

	// Starting from the least costly path (if any), construct it and see whether it's blocked or not. If not, use it.
	if(!pq.empty())
	{
		// We accept path-table paths which are no more than 25% longer than the shortest
		// path-table path we found without considering blocks: they are "good enough",
		// and are MUCH quicker to calculate than paths we might find using A*.
		const float WORST_ACCEPTABLE_COST = 1.25f * pq.top().cost;

		while(!pq.empty())
		{
			PathDescriptor desc = pq.top();
			if(desc.cost > WORST_ACCEPTABLE_COST) break;
			pq.pop();

			path = m_pathTable->construct_path(desc.sourceLink, desc.destLink);

			if(!is_blocked(sourcePos, path, destPos))
				return true;	// note that the path to be returned has already been stored in the out parameter
		}
	}

	// Step 3:	If a reasonable unblocked path-table path does not exist, do an A* search on
	//			the adjacency list representation of the navigation graph. Use a temporary node
	//			in both the source and destination polygons to represent the actual position of
	//			the player.
	// TODO

	// Step 4:	If an A* path was found, use it. Otherwise, no valid path exists.
	// TODO

	// NYI
	return false;
}