/*  
    Crystal Shooter, a first person shooter game engine.
    Homepage: http://members.xoom.com/thieber/cs

    Copyright (C) 1999 Thomas Hieber (thieber@gmx.net)

    Game specific collision detection, based on some code by 
    Alex Pfaffe. (alexpf@microsoft.com)
 
    This program is free software; you can redistribute it and/or modify 
    it under the terms of the GNU General Public License as published by 
    the Free Software Foundation; either version 2 of the License, or 
    (at your option) any later version. 
 
    This program is distributed in the hope that it will be useful, 
    but WITHOUT ANY WARRANTY; without even the implied warranty of 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    GNU General Public License for more details. 
 
    You should have received a copy of the GNU General Public License 
    along with this program; if not, write to the Free Software 
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
*/

#ifndef GCOLLIDE_H
#define GCOLLIDE_H

#include "csengine/collider.h"

class csPolygonSet;
class geWorld;
class geSprite3D;
class gePhysicalObject;

/**
 * geCollider takes care of game specfic collision detection. It will only
 * handle a single Frame of a Sprite. If you need multiple Frames, you will
 * need multiple Instances of geCollider
 */
class geCollider : public csCollider
{
  typedef csCollider inherited;

 public:
  /// The sector in which the being currently resides.
  //csSector *sector;
  /** The transformation which decsribes the objects current position
   * and orienatation.
   */
  //Transform *transform;

  geCollider(geWorld* pWorld, csPolygonSet *p);
  geCollider(geWorld* pWorld, geSprite3D *pSprite);

  //Being(PolygonSet *p, csSector* s = 0, Transform *cdt = 0);
  //Being(csSprite3D *sp, csSector* s = 0, Transform *cdt = 0);

  /// Create a player bounding box.
  //static Being* playerSpawn(char* name);

  /// Initialize CD data for all sectors in the world.
  //static int init_world( csWorld* world, csCamera *camera );

  /// Free any memory held by CD system.
  //static void end_world(void);

/** Try to move the collider for a certain distance. Will move the collider only
  * in steps less or equal to MaxMoveDistance. When the collision is found, the 
  * Collider will be moved with a binary search to the last Position, that has no 
  * collision (The binary search will use 10 interation, which means, that the
  * accuracy of position afterwards will be better than 0.001*MaxMoveDistance)
  *
  * Par:
  * MoveVector:      gives the amount of distance to move the collider.
  * MaxMoveDistance: Maximum Distance to move in one step should be significantly
  *                  smaller than the size of the object, to avoid missing some
  *                  collision.
  * Moved:           The Distance that was really moved.
  * pOther:          returns a pointer to the involved collision partner, if it 
  *                  has some game object attached to it.
  * returns:         0 if ther was no collision, nonzero, if there was one.
  */
  virtual int FindFirstCollision(csVector3  MoveVector, float MaxMoveDistance, 
                                 csVector3& Moved,      gePhysicalObject*& pOther);

  /// Collide cd with all objects in the sector.
  virtual int CollisionDetect(gePhysicalObject*& pOther);

private:
  /// used internally be geCollider, to do the real work.
  virtual int CollisionDetect(csTransform*       pTransform, 
                              csSector*          pSector, 
                              gePhysicalObject*& pOther);

  int CheckCollisionInSector( csSector* s, gePhysicalObject*& pOther, csTransform *cdt);

  /// Find all sector which are near enough to intersect with this being.
  int FindSectors( csVector3 v, csVector3 d, csSector *s, csSector **sa );

  //this is needed to access other objects of the game domain.
  geWorld*    m_pWorld;  
  geSprite3D* m_pSprite;
};


#endif
