Ogre::Vector3
  CharacterController::_collideWithWorld(int recursionDepth,
      const Ogre::Vector3& pos, const Ogre::Vector3& vel,
      CollisionPacket& colData, bool gravityStep,
      const Ogre::Degree& slopeSlideThresold)
  {
    // do we need to worry?
    if (recursionDepth > 5)
      return pos;

    // Ok, we need to worry:
    colData.velocity = vel;
    colData.normalizedVelocity = vel;
    colData.normalizedVelocity.normalise();
    colData.basePoint = pos;
    colData.foundCollision = false;

    // ----------------------------
    // OgreOpcode part begin
    _doOgreOpcodeCollision(colData, mVeryCloseDistance);
    // OgreOpcode part end
    // ----------------------------

    // If no collision we just move along the velocity
    if (colData.foundCollision == false)
      {
        return pos + vel;
      }

    // *** Collision occured ***
    // The original destination point
    Ogre::Vector3 destinationPoint = pos + vel;
    Ogre::Vector3 newBasePoint = pos;

    // only update if we are not already very close
    // and if so we only move very close to intersection..not
    // to the exact spot.
    if (colData.nearestDistance >= mVeryCloseDistance)
      {
        Ogre::Vector3 V = vel;
        V.normalise();
        V = V * (colData.nearestDistance - mVeryCloseDistance);
        newBasePoint = colData.basePoint + V;
        // Adjust polygon intersection point (so sliding
        // plane will be unaffected by the fact that we
        // move slightly less than collision tells us)
        V.normalise();
        colData.intersectionPoint -= mVeryCloseDistance * V;
      }

    // Determine the sliding plane
    Ogre::Vector3 slidePlaneOrigin = colData.intersectionPoint;
    Ogre::Vector3 slidePlaneNormal = newBasePoint - colData.intersectionPoint;
    slidePlaneNormal.normalise();
    Ogre::Plane slidingPlane(slidePlaneNormal, slidePlaneOrigin);

    Ogre::Vector3 newDestinationPoint = destinationPoint
        - slidingPlane.getDistance(destinationPoint) * slidePlaneNormal;

    // Generate the slide vector, which will become our new
    // velocity vector for the next iteration
    Ogre::Vector3 newVelocityVector = newDestinationPoint
        - colData.intersectionPoint;

    // Recurse:
    // dont recurse if the new velocity is very small
    if (newVelocityVector.length() < mVeryCloseDistance)
      {
        return newBasePoint;
      }

    // simulate "friction"
    if (gravityStep)
      {
        // apply gravity only if slope is steep enough
        const Ogre::Radian tolerance = Ogre::Radian(slopeSlideThresold);
        Ogre::Vector3 gravity = vel;
        gravity.normalise();
        if (slidePlaneNormal.directionEquals(-gravity, tolerance))
          {
            return newBasePoint;
          }
      }

    return _collideWithWorld(recursionDepth++, newBasePoint, newVelocityVector,
        colData, gravityStep, slopeSlideThresold);
  }
Ejemplo n.º 2
0
core::vector3df CSceneCollisionManager::collideWithWorld(s32 recursionDepth,
	SCollisionData &colData, core::vector3df pos, core::vector3df vel)
{
	f32 veryCloseDistance = colData.slidingSpeed;

	if (recursionDepth > 5)
		return pos;

	colData.velocity = vel;
	colData.normalizedVelocity = vel;
	colData.normalizedVelocity.normalize();
	colData.basePoint = pos;
	colData.foundCollision = false;
	colData.nearestDistance = 9999999999999.0f;

	//------------------ collide with world

	// get all triangles with which we might collide
	core::aabbox3d<f32> box(colData.R3Position);
	box.addInternalPoint(colData.R3Position + colData.R3Velocity);
	box.MinEdge -= colData.eRadius;
	box.MaxEdge += colData.eRadius;

	s32 totalTriangleCnt = colData.selector->getTriangleCount();
	Triangles.set_used(totalTriangleCnt);

	core::matrix4 scaleMatrix;
	scaleMatrix.setScale(
		core::vector3df(1.0f / colData.eRadius.X, 
						1.0f / colData.eRadius.Y,
						1.0f / colData.eRadius.Z)
					);

	s32 triangleCnt = 0;
	colData.selector->getTriangles(Triangles.pointer(), totalTriangleCnt, triangleCnt, box, &scaleMatrix);
	//colData.selector->getTriangles(Triangles.pointer(), totalTriangleCnt, triangleCnt, &scaleMatrix);

	for (s32 i=0; i<triangleCnt; ++i)
		testTriangleIntersection(&colData, Triangles[i]);

	//---------------- end collide with world

	if (!colData.foundCollision)
		return pos + vel;

	// original destination point
	core::vector3df destinationPoint = pos + vel;
	core::vector3df newBasePoint = pos;

	// only update if we are not already very close
	// and if so only move very close to intersection, not to the
	// exact point
	if (colData.nearestDistance >= veryCloseDistance)
	{
		core::vector3df v = vel;
		v.setLength( colData.nearestDistance - veryCloseDistance );
		newBasePoint = colData.basePoint + v;

		v.normalize();
		colData.intersectionPoint -= (v * veryCloseDistance);
	}

	// calculate sliding plane

	core::vector3df slidePlaneOrigin = colData.intersectionPoint;
	core::vector3df slidePlaneNormal = newBasePoint - colData.intersectionPoint;
	slidePlaneNormal.normalize();
	core::plane3d<f32> slidingPlane(slidePlaneOrigin, slidePlaneNormal);

	core::vector3df newDestinationPoint =
		destinationPoint -
		(slidePlaneNormal * slidingPlane.getDistanceTo(destinationPoint));

	// generate slide vector

	core::vector3df newVelocityVector = newDestinationPoint -
		colData.intersectionPoint;

	if (newVelocityVector.getLength() < veryCloseDistance)
		return newBasePoint;

	return collideWithWorld(recursionDepth+1, colData,
		newBasePoint, newVelocityVector);
}