Index: trunk/src/defs/class_id.h
===================================================================
--- trunk/src/defs/class_id.h	(revision 8719)
+++ trunk/src/defs/class_id.h	(revision 8724)
@@ -196,4 +196,5 @@
   CL_SPECTATOR                  =    0x00000360,
   CL_COLLISION_PROBE            =    0x00000361,
+  CL_FPS_PLAYER                 =    0x00000362,
 
   // Powerups
@@ -223,4 +224,5 @@
   CL_NPC_TEST1                  =    0x00000401,
   CL_NPC_TEST2                  =    0x00000402,
+  CL_GENERIC_NPC                =    0x00000403,
 
   // Testing Entities
@@ -280,4 +282,6 @@
   CL_OBB                        =    0x00720000,
   CL_BOUNDING_SPHERE            =    0x00740000,
+  CL_AABB_TREE_NODE             =    0x00000724,                //FIXME: is this correct? AABB_TREE_NODE isA BV_TREE_NODE
+  CL_AABB                       =    0x00780000,                //FIXME: is this correct? AABB isA BOUNDING_VOLUME
 
 
Index: trunk/src/lib/collision_detection/Makefile.am
===================================================================
--- trunk/src/lib/collision_detection/Makefile.am	(revision 8719)
+++ trunk/src/lib/collision_detection/Makefile.am	(revision 8724)
@@ -11,5 +11,7 @@
                      bv_tree_node.cc \
                      bounding_volume.cc \
-                     bounding_sphere.cc
+                     bounding_sphere.cc \
+                     aabb_tree_node.cc \
+                     aabb.cc
 
 
@@ -22,4 +24,6 @@
                      bv_tree_node.h \
                      bounding_volume.h \
-                     bounding_sphere.h
+                     bounding_sphere.h \
+                     aabb_tree_node.h \
+                     aabb.h
 
Index: trunk/src/lib/collision_detection/aabb.cc
===================================================================
--- trunk/src/lib/collision_detection/aabb.cc	(revision 8724)
+++ trunk/src/lib/collision_detection/aabb.cc	(revision 8724)
@@ -0,0 +1,52 @@
+/*
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 orx
+
+   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, or (at your option)
+   any later version.
+
+   ### File Specific:
+   main-programmer: Patrick Boenzli
+   co-programmer: ...
+*/
+
+#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_COLLISION_DETECTION
+
+#include "aabb.h"
+#include "vector.h"
+
+using namespace std;
+
+
+/**
+ *  standard constructor
+*/
+AABB::AABB ()
+{
+   this->setClassID(CL_OBB, "AABB");
+   this->halfLength[0] = this->halfLength[1] = this->halfLength[2] = 0.0f;
+   this->bCollided = false;
+}
+
+
+/**
+ *  standard deconstructor
+
+*/
+AABB::~AABB ()
+{
+}
+
+
+
+void AABB::mergeWith(const BoundingVolume &bv)
+{}
+
+
+void AABB::drawBV(int currentDepth, int drawMode) const
+{}
+
+
Index: trunk/src/lib/collision_detection/aabb.h
===================================================================
--- trunk/src/lib/collision_detection/aabb.h	(revision 8724)
+++ trunk/src/lib/collision_detection/aabb.h	(revision 8724)
@@ -0,0 +1,44 @@
+/*!
+ * @file aabb.h
+  *  Definition of an AABB (Axix Aligned Bounding Box)
+
+*/
+
+#ifndef _AABB_H
+#define _AABB_H
+
+#include "base_object.h"
+#include "bounding_volume.h"
+
+template<class T> class tList;
+
+//! A class representing an extended bounding volume tree: an obb tree
+class AABB : public BoundingVolume {
+
+ public:
+  AABB();
+  virtual ~AABB();
+
+
+  inline Vector getAxisX () const { return this->axis[0]; }
+  inline Vector getAxisY () const { return this->axis[1]; }
+  inline Vector getAxisZ () const { return this->axis[2]; }
+
+  inline const float* getHalfLength() const { return this->halfLength; }
+
+  virtual void mergeWith(const BoundingVolume &bv);
+
+  virtual void drawBV(int currentDepth, int drawMode) const;
+
+
+
+ public:
+  Vector           axis[3];                    //!< Axes of oriented box [x,y,z]
+  float            halfLength[3];              //!< Half lengths of the box along the axis
+  float            covarianceMatrix[3][3];     //!< the covariance matrix
+
+  bool             bCollided;                  //!< is true if this obb has collided
+
+};
+
+#endif /* _AABB_H */
Index: trunk/src/lib/collision_detection/aabb_tree_node.cc
===================================================================
--- trunk/src/lib/collision_detection/aabb_tree_node.cc	(revision 8724)
+++ trunk/src/lib/collision_detection/aabb_tree_node.cc	(revision 8724)
@@ -0,0 +1,943 @@
+/*
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 orx
+
+   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, or (at your option)
+   any later version.
+
+### File Specific:
+   main-programmer: Patrick Boenzli
+*/
+
+#define DEBUG_SPECIAL_MODULE 3/* DEBUG_MODULE_COLLISION_DETECTION*/
+
+#include "aabb_tree_node.h"
+#include "aabb.h"
+
+#include "bv_tree.h"
+
+#include "matrix.h"
+#include "model.h"
+#include "world_entity.h"
+#include "plane.h"
+
+#include "color.h"
+#include "glincl.h"
+
+#include <list>
+#include <vector>
+#include "debug.h"
+
+
+
+using namespace std;
+
+
+GLUquadricObj* AABBTreeNode_sphereObj = NULL;
+
+
+/**
+ *  standard constructor
+ * @param tree: reference to the obb tree
+ * @param depth: the depth of the obb tree to generate
+ */
+AABBTreeNode::AABBTreeNode (const OBBTree& tree, AABBTreeNode* prev, int depth)
+    : BVTreeNode()
+{
+  this->setClassID(CL_OBB_TREE_NODE, "AABBTreeNode");
+
+  this->obbTree = &tree;
+  this->nodePrev = prev;
+  this->depth = depth;
+  this->nextID = 0;
+
+  this->init();
+}
+
+
+/**
+ *  standard constructor
+ * @param depth: the depth of the obb tree to generate
+ */
+AABBTreeNode::AABBTreeNode(int depth)
+{
+  this->depth = depth;
+}
+
+/**
+ *  init funciton
+ */
+void AABBTreeNode::init()
+{
+  this->nodeLeft = NULL;
+  this->nodeRight = NULL;
+  this->bvElement = NULL;
+
+  this->triangleIndexList1 = NULL;
+  this->triangleIndexList2 = NULL;
+
+  this->modelInf = NULL;
+  this->triangleIndexes = NULL;
+
+  if( AABBTreeNode_sphereObj == NULL)
+    AABBTreeNode_sphereObj = gluNewQuadric();
+
+  this->owner = NULL;
+
+  /* debug ids */
+  if( this->nodePrev)
+    this->treeIndex = 100 * this->depth + this->nodePrev->getID();
+  else
+    this->treeIndex = 0;
+}
+
+/**
+ *  standard deconstructor
+ */
+AABBTreeNode::~AABBTreeNode ()
+{
+  if( this->nodeLeft)
+    delete this->nodeLeft;
+  if( this->nodeRight)
+    delete this->nodeRight;
+
+  if( this->bvElement)
+    delete this->bvElement;
+}
+
+
+
+void AABBTreeNode::spawnBVTree(Model* model)
+{
+
+  const modelInfo* modelInf = model->getModelInfo();
+
+  int* triangleIndexes = new int[modelInf->numTriangles];
+  for(unsigned int i = 0; i < modelInf->numTriangles; ++i)
+    triangleIndexes[i] = i;
+
+  this->spawnBVTree(*modelInf, triangleIndexes, modelInf->numTriangles);
+}
+
+
+/**
+ *  creates a new BVTree or BVTree partition
+ * @param depth: how much more depth-steps to go: if == 1 don't go any deeper!
+ * @param modInfo: model informations from the abstrac model
+ *
+ * this function creates the Bounding Volume tree from a modelInfo struct and bases its calculations
+ * on the triangle informations (triangle soup not polygon soup)
+ */
+void AABBTreeNode::spawnBVTree(const modelInfo& modelInf, const int* triangleIndexes, int length)
+{
+  PRINTF(4)("\n==============================Creating AABB Tree Node==================\n");
+  PRINT(4)(" AABB Tree Infos: \n");
+  PRINT(4)("\tDepth: %i \n\tTree Index: %i \n\tNumber of Triangles: %i\n", depth, this->treeIndex, length);
+  this->depth = depth;
+
+  this->bvElement = new AABB();
+  this->bvElement->modelInf = &modelInf;
+  this->bvElement->triangleIndexes = triangleIndexes;
+  this->bvElement->triangleIndexesLength = length;
+
+  /* create the bounding boxes in three steps */
+  this->calculateBoxCovariance(*this->bvElement, modelInf, triangleIndexes, length);
+  this->calculateBoxEigenvectors(*this->bvElement, modelInf, triangleIndexes, length);
+  this->calculateBoxAxis(*this->bvElement, modelInf, triangleIndexes, length);
+
+  /* do we need to descent further in the obb tree?*/
+  if( likely( this->depth > 0))
+  {
+    this->forkBox(*this->bvElement);
+
+    if( this->triangleIndexLength1 >= 3)
+    {
+      this->nodeLeft = new AABBTreeNode(*this->obbTree, this, depth - 1);
+      this->nodeLeft->spawnBVTree(modelInf, this->triangleIndexList1, this->triangleIndexLength1);
+    }
+    if( this->triangleIndexLength2 >= 3)
+    {
+      this->nodeRight = new AABBTreeNode(*this->obbTree, this, depth - 1);
+      this->nodeRight->spawnBVTree(modelInf, this->triangleIndexList2, this->triangleIndexLength2);
+    }
+  }
+}
+
+
+
+/**
+ *  calculate the box covariance matrix
+ * @param box: reference to the box
+ * @param modelInf: the model info structure of the model
+ * @param tirangleIndexes: an array with the indexes of the triangles inside this
+ * @param length: the length of the indexes array
+ */
+void AABBTreeNode::calculateBoxCovariance(AABB& box, const modelInfo& modelInf, const int* triangleIndexes, int length)
+{
+  float     facelet[length];                         //!< surface area of the i'th triangle of the convex hull
+  float     face = 0.0f;                             //!< surface area of the entire convex hull
+  Vector    centroid[length];                        //!< centroid of the i'th convex hull
+  Vector    center;                                  //!< the center of the entire hull
+  Vector    p, q, r;                                 //!< holder of the polygon data, much more conveniant to work with Vector than sVec3d
+  Vector    t1, t2;                                  //!< temporary values
+  float     covariance[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}};//!< the covariance matrix
+
+  /* fist compute all the convex hull face/facelets and centroids */
+  for( int i = 0; i < length ; ++i)
+  {
+    p = &modelInf.pVertices[modelInf.pTriangles[triangleIndexes[i]].indexToVertices[0]];
+    q = &modelInf.pVertices[modelInf.pTriangles[triangleIndexes[i]].indexToVertices[1]];
+    r = &modelInf.pVertices[modelInf.pTriangles[triangleIndexes[i]].indexToVertices[2]];
+
+    /* finding the facelet surface via cross-product */
+    t1 = p - q;
+    t2 = p - r;
+    facelet[i] = 0.5f * /*fabs*/( t1.cross(t2).len() );
+    /* update the entire convex hull surface */
+    face += facelet[i];
+
+    /* calculate the cetroid of the hull triangles */
+    centroid[i] = (p + q + r) / 3.0f;
+    /* now calculate the centroid of the entire convex hull, weighted average of triangle centroids */
+    center += centroid[i] * facelet[i];
+    /* the arithmetical center */
+  }
+  /* take the average of the centroid sum */
+  center /= face;
+
+
+  /* now calculate the covariance matrix - if not written in three for-loops,
+     it would compute faster: minor */
+  for( int j = 0; j < 3; ++j)
+  {
+    for( int k = 0; k < 3; ++k)
+    {
+      for( int i = 0; i < length; ++i)
+      {
+        p = (&modelInf.pVertices[modelInf.pTriangles[triangleIndexes[i]].indexToVertices[0]]);
+        q = (&modelInf.pVertices[modelInf.pTriangles[triangleIndexes[i]].indexToVertices[1]]);
+        r = (&modelInf.pVertices[modelInf.pTriangles[triangleIndexes[i]].indexToVertices[2]]);
+
+        covariance[j][k] = facelet[i] * (9.0f * centroid[i][j] * centroid[i][k] + p[j] * p[k] +
+                           q[j] * q[k] + r[j] * r[k]);
+      }
+      covariance[j][k] = covariance[j][k] / (12.0f * face) - center[j] * center[k];
+    }
+  }
+  for( int i = 0; i < 3; ++i)
+  {
+    box.covarianceMatrix[i][0] = covariance[i][0];
+    box.covarianceMatrix[i][1] = covariance[i][1];
+    box.covarianceMatrix[i][2] = covariance[i][2];
+  }
+  box.center = center;
+
+  /* debug output section*/
+  PRINTF(4)("\nOBB Covariance Matrix:\n");
+  for(int j = 0; j < 3; ++j)
+  {
+    PRINT(4)("\t\t");
+    for(int k = 0; k < 3; ++k)
+    {
+      PRINT(4)("%11.4f\t", covariance[j][k]);
+    }
+    PRINT(4)("\n");
+  }
+  PRINTF(4)("\nWeighteed AABB Center:\n\t\t%11.4f\t %11.4f\t %11.4f\n", center.x, center.y, center.z);
+}
+
+
+
+/**
+ *  calculate the eigenvectors for the object oriented box
+ * @param box: reference to the box
+ * @param modelInf: the model info structure of the model
+ * @param tirangleIndexes: an array with the indexes of the triangles inside this
+ * @param length: the length of the indexes array
+ */
+void AABBTreeNode::calculateBoxEigenvectors(AABB& box, const modelInfo& modelInf,
+    const int* triangleIndexes, int length)
+{
+
+  Vector         axis[3];                            //!< the references to the obb axis
+  Matrix         covMat(  box.covarianceMatrix  );   //!< covariance matrix (in the matrix dataform)
+
+  /*
+  now getting spanning vectors of the sub-space:
+  the eigenvectors of a symmertric matrix, such as the
+  covarience matrix are mutually orthogonal.
+  after normalizing them, they can be used as a the basis
+  vectors
+  */
+
+
+  // this is for axis aligned bouning boxes only
+   box.axis[0] = Vector(1,0,0);
+   box.axis[1] = Vector(0,1,0);
+   box.axis[2] = Vector(0,0,1);
+
+   PRINTF(4)("Eigenvectors:\n");
+   PRINT(4)("\t\t%11.2f \t%11.2f \t%11.2f\n", box.axis[0].x, box.axis[0].y, box.axis[0].z);
+   PRINT(4)("\t\t%11.2f \t%11.2f \t%11.2f\n", box.axis[1].x, box.axis[1].y, box.axis[1].z);
+   PRINT(4)("\t\t%11.2f \t%11.2f \t%11.2f\n", box.axis[2].x, box.axis[2].y, box.axis[2].z);
+}
+
+
+
+
+/**
+ *  calculate the eigenvectors for the object oriented box
+ * @param box: reference to the box
+ * @param modelInf: the model info structure of the model
+ * @param tirangleIndexes: an array with the indexes of the triangles inside this
+ * @param length: the length of the indexes array
+ */
+void AABBTreeNode::calculateBoxAxis(AABB& box, const modelInfo& modelInf, const int* triangleIndexes, int length)
+{
+
+  PRINTF(4)("Calculate Box Axis\n");
+  /* now get the axis length */
+  float               tmpLength;                             //!< tmp save point for the length
+  Plane               p0(box.axis[0], box.center);           //!< the axis planes
+  Plane               p1(box.axis[1], box.center);           //!< the axis planes
+  Plane               p2(box.axis[2], box.center);           //!< the axis planes
+  float               maxLength[3];                          //!< maximal lenth of the axis
+  float               minLength[3];                          //!< minimal length of the axis
+  const float*        tmpVec;                                //!< variable taking tmp vectors
+  float               centerOffset[3];
+
+  /* get the maximal dimensions of the body in all directions */
+  /* for the initialisation the value just has to be inside of the polygon soup -> first vertices (rand) */
+  for( int k = 0; k  < 3; k++)
+  {
+    tmpVec = (&modelInf.pVertices[modelInf.pTriangles[triangleIndexes[0]].indexToVertices[0]]);
+    Plane* p;
+    if( k == 0)
+      p = &p0;
+    else if( k == 1)
+      p = &p1;
+    else
+      p = &p2;
+    maxLength[k] = p->distancePoint(tmpVec);
+    minLength[k] = p->distancePoint(tmpVec);
+
+    for( int j = 0; j < length; ++j) {
+      for( int i = 0; i < 3; ++i) {
+        tmpVec = &modelInf.pVertices[modelInf.pTriangles[triangleIndexes[j]].indexToVertices[i]];
+        tmpLength = p->distancePoint(tmpVec);
+
+        if( tmpLength > maxLength[k])
+          maxLength[k] = tmpLength;
+        else if( tmpLength < minLength[k])
+          minLength[k] = tmpLength;
+      }
+    }
+  }
+
+
+
+  /* calculate the real centre of the body by using the axis length */
+  for( int i = 0; i < 3; ++i)
+  {
+    if( maxLength[i] > 0.0f && minLength[i] > 0.0f)  // both axis positiv
+      centerOffset[i] = minLength[i] + (maxLength[i] - minLength[i]) / 2.0f;
+    else if( maxLength[i] > 0.0f && maxLength[i] < 0.0f) // positiv and negativ
+      centerOffset[i] = (maxLength[i] + minLength[i]) / 2.0f;
+    else //both negativ
+     centerOffset[i] = minLength[i] + (maxLength[i] - minLength[i]) / 2.0f;
+
+    box.halfLength[i] = (maxLength[i] - minLength[i]) / 2.0f;
+  }
+
+  box.center += (box.axis[0] * centerOffset[0]);
+  box.center += (box.axis[1] * centerOffset[1]);
+  box.center += (box.axis[2] * centerOffset[2]);
+
+
+  PRINTF(4)("\n");
+  PRINT(4)("\tAxis halflength x: %11.2f (max: %11.2f, \tmin: %11.2f), offset: %11.2f\n", box.halfLength[0], maxLength[0], minLength[0], centerOffset[0]);
+  PRINT(4)("\tAxis halflength y: %11.2f (max: %11.2f, \tmin: %11.2f), offset: %11.2f\n", box.halfLength[1], maxLength[1], minLength[1], centerOffset[1] );
+  PRINT(4)("\tAxis halflength z: %11.2f (max: %11.2f, \tmin: %11.2f), offset: %11.2f\n", box.halfLength[2], maxLength[2], minLength[2], centerOffset[2]);
+}
+
+
+
+/**
+ *  this separates an ob-box in the middle
+ * @param box: the box to separate
+ *
+ * this will separate the box into to smaller boxes. the separation is done along the middle of the longest axis
+ */
+void AABBTreeNode::forkBox(AABB& box)
+{
+
+  PRINTF(4)("Fork Box\n");
+  PRINTF(4)("Calculating the longest Axis\n");
+  /* get the longest axis of the box */
+  float               longestAxis = -1.0f;                 //!< the length of the longest axis
+  int                 longestAxisIndex = 0;                //!< this is the nr of the longest axis
+
+
+  /* now get the longest axis of the three exiting */
+  for( int i = 0; i < 3; ++i)
+  {
+    if( longestAxis < box.halfLength[i])
+    {
+      longestAxis = box.halfLength[i];
+      longestAxisIndex = i;
+    }
+  }
+  PRINTF(4)("\nLongest Axis is: Nr %i with a half-length of:%11.2f\n", longestAxisIndex, longestAxis);
+
+
+  PRINTF(4)("Separating along the longest axis\n");
+  /* get the closest vertex near the center */
+  float               tmpDist;                             //!< variable to save diverse distances temporarily
+  Plane               middlePlane(box.axis[longestAxisIndex], box.center); //!< the middle plane
+
+
+  /* now definin the separation plane through this specified nearest point and partition
+  the points depending on which side they are located
+  */
+  std::list<int>           partition1;                           //!< the vertex partition 1
+  std::list<int>           partition2;                           //!< the vertex partition 2
+  float*                   triangleCenter = new float[3];        //!< the center of the triangle
+  const float*             a;                                    //!< triangle  edge a
+  const float*             b;                                    //!< triangle  edge b
+  const float*             c;                                    //!< triangle  edge c
+
+
+  /* find the center of the box */
+  this->separationPlane = Plane(box.axis[longestAxisIndex], box.center);
+  this->sepPlaneCenter[0] = box.center.x;
+  this->sepPlaneCenter[1] = box.center.y;
+  this->sepPlaneCenter[2] = box.center.z;
+  this->longestAxisIndex = longestAxisIndex;
+
+  for( int i = 0; i < box.triangleIndexesLength; ++i)
+  {
+    /* first calculate the middle of the triangle */
+    a = &box.modelInf->pVertices[box.modelInf->pTriangles[box.triangleIndexes[i]].indexToVertices[0]];
+    b = &box.modelInf->pVertices[box.modelInf->pTriangles[box.triangleIndexes[i]].indexToVertices[1]];
+    c = &box.modelInf->pVertices[box.modelInf->pTriangles[box.triangleIndexes[i]].indexToVertices[2]];
+
+    triangleCenter[0] = (a[0] + b[0] + c[0]) / 3.0f;
+    triangleCenter[1] = (a[1] + b[1] + c[1]) / 3.0f;
+    triangleCenter[2] = (a[2] + b[2] + c[2]) / 3.0f;
+    tmpDist = this->separationPlane.distancePoint(*((sVec3D*)triangleCenter));
+
+    if( tmpDist > 0.0f)
+      partition1.push_back(box.triangleIndexes[i]); /* positive numbers plus zero */
+    else if( tmpDist < 0.0f)
+      partition2.push_back(box.triangleIndexes[i]); /* negatice numbers */
+    else {
+      partition1.push_back(box.triangleIndexes[i]); /* 0.0f? unprobable... */
+      partition2.push_back(box.triangleIndexes[i]);
+    }
+  }
+  PRINTF(4)("\nPartition1: got \t%i Vertices \nPartition2: got \t%i Vertices\n", partition1.size(), partition2.size());
+
+
+  /* now comes the separation into two different sVec3D arrays */
+  int                index;                                //!< index storage place
+  int*               triangleIndexList1;                   //!< the vertex list 1
+  int*               triangleIndexList2;                   //!< the vertex list 2
+  std::list<int>::iterator element;                        //!< the list iterator
+
+  triangleIndexList1 = new int[partition1.size()];
+  triangleIndexList2 = new int[partition2.size()];
+
+  for( element = partition1.begin(), index = 0; element != partition1.end(); element++, index++)
+    triangleIndexList1[index] = (*element);
+
+  for( element = partition2.begin(), index = 0; element != partition2.end(); element++, index++)
+    triangleIndexList2[index] = (*element);
+
+  if( this->triangleIndexList1!= NULL)
+    delete[] this->triangleIndexList1;
+  this->triangleIndexList1 = triangleIndexList1;
+  this->triangleIndexLength1 = partition1.size();
+
+  if( this->triangleIndexList2 != NULL)
+    delete[] this->triangleIndexList2;
+  this->triangleIndexList2 = triangleIndexList2;
+  this->triangleIndexLength2 = partition2.size();
+}
+
+
+
+/**
+ * collides one tree with an other
+ *  @param treeNode the other bv tree node
+ *  @param nodeA  the worldentity belonging to this bv
+ *  @param nodeB the worldentity belonging to treeNode
+ */
+void AABBTreeNode::collideWith(BVTreeNode* treeNode, WorldEntity* nodeA, WorldEntity* nodeB)
+{
+  if( unlikely(treeNode == NULL || nodeA == NULL || nodeB == NULL))
+    return;
+
+  PRINTF(4)("collideWith\n");
+  PRINTF(5)("Checking AABB %i vs %i: ", this->getIndex(), treeNode->getIndex());
+
+  // for now only collide with AABBTreeNodes
+  this->collideWithOBB((AABBTreeNode*)treeNode, nodeA, nodeB);
+}
+
+
+
+/**
+ * collides one obb tree with an other
+ *  @param treeNode the other bv tree node
+ *  @param nodeA  the worldentity belonging to this bv
+ *  @param nodeB the worldentity belonging to treeNode
+ */
+void AABBTreeNode::collideWithOBB(AABBTreeNode* treeNode, WorldEntity* nodeA, WorldEntity* nodeB)
+{
+
+  if( this->overlapTest(this->bvElement, treeNode->bvElement, nodeA, nodeB))
+  {
+    PRINTF(5)("collision @ lvl %i, object %s vs. %s, (%p, %p)\n", this->depth, nodeA->getClassName(), nodeB->getClassName(), this->nodeLeft, this->nodeRight);
+
+
+    // left node
+    if( this->nodeLeft != NULL )
+    {
+      if( this->overlapTest(this->nodeLeft->bvElement, treeNode->bvElement, nodeA, nodeB))
+      {
+        if( treeNode->nodeLeft != NULL)
+          this->nodeLeft->collideWith(treeNode->nodeLeft, nodeA, nodeB);
+        if( treeNode->nodeRight != NULL)
+          this->nodeLeft->collideWith(treeNode->nodeRight, nodeA, nodeB);
+      }
+    }
+
+    // right node
+    if( this->nodeRight != NULL )
+    {
+      if( this->overlapTest(this->nodeRight->bvElement, treeNode->bvElement, nodeA, nodeB))
+      {
+        if( treeNode->nodeLeft != NULL)
+          this->nodeRight->collideWith(treeNode->nodeLeft, nodeA, nodeB);
+        if( treeNode->nodeRight != NULL)
+          this->nodeRight->collideWith(treeNode->nodeRight, nodeA, nodeB);
+      }
+    }
+
+
+    // hybrid mode: we reached the end of this obbtree, now reach the end of the other tree
+    if( this->nodeLeft == NULL && this->nodeRight == NULL)
+    {
+      if( treeNode->nodeLeft != NULL)
+        this->collideWith(treeNode->nodeLeft, nodeA, nodeB);
+      if( treeNode->nodeRight != NULL)
+        this->collideWith(treeNode->nodeRight, nodeA, nodeB);
+    }
+
+
+    // now check if we reached the end of both trees
+    if( unlikely((this->nodeRight == NULL && this->nodeLeft == NULL) &&
+        (treeNode->nodeRight == NULL && treeNode->nodeLeft == NULL)) )
+    {
+      nodeA->registerCollision(nodeA, nodeB, (BoundingVolume*)this->bvElement, (BoundingVolume*)treeNode->bvElement);
+    }
+
+  }
+}
+
+
+/**
+ * this actualy checks if one obb box touches the other
+ * @param boxA the box from nodeA
+ * @param boxB the box from nodeB
+ * @param nodeA the node itself
+ * @param nodeB the node itself
+ */
+bool AABBTreeNode::overlapTest(AABB* boxA, AABB* boxB, WorldEntity* nodeA, WorldEntity* nodeB)
+{
+  //HACK remove this again
+  this->owner = nodeA;
+  //   if( boxB == NULL || boxA == NULL)
+  //     return false;
+
+  /* first check all axis */
+  Vector      t;
+  float       rA = 0.0f;
+  float       rB = 0.0f;
+  Vector      l;
+  Vector      rotAxisA[3];
+  Vector      rotAxisB[3];
+
+  rotAxisA[0] =  nodeA->getAbsDir().apply(boxA->axis[0]);
+  rotAxisA[1] =  nodeA->getAbsDir().apply(boxA->axis[1]);
+  rotAxisA[2] =  nodeA->getAbsDir().apply(boxA->axis[2]);
+
+  rotAxisB[0] =  nodeB->getAbsDir().apply(boxB->axis[0]);
+  rotAxisB[1] =  nodeB->getAbsDir().apply(boxB->axis[1]);
+  rotAxisB[2] =  nodeB->getAbsDir().apply(boxB->axis[2]);
+
+  t = nodeA->getAbsCoor() + nodeA->getAbsDir().apply(boxA->center) - ( nodeB->getAbsCoor() + nodeB->getAbsDir().apply(boxB->center));
+
+  /* All 3 axis of the object A */
+  for( int j = 0; j < 3; ++j)
+  {
+    rA = 0.0f;
+    rB = 0.0f;
+    l = rotAxisA[j];
+
+    rA += fabs(boxA->halfLength[0] * rotAxisA[0].dot(l));
+    rA += fabs(boxA->halfLength[1] * rotAxisA[1].dot(l));
+    rA += fabs(boxA->halfLength[2] * rotAxisA[2].dot(l));
+
+    rB += fabs(boxB->halfLength[0] * rotAxisB[0].dot(l));
+    rB += fabs(boxB->halfLength[1] * rotAxisB[1].dot(l));
+    rB += fabs(boxB->halfLength[2] * rotAxisB[2].dot(l));
+
+    PRINTF(5)("s = %f, rA+rB = %f\n", fabs(t.dot(l)), rA+rB);
+
+    if( (rA + rB) < fabs(t.dot(l)))
+    {
+      PRINTF(4)("no Collision\n");
+      return false;
+    }
+  }
+
+  /* All 3 axis of the object B */
+  for( int j = 0; j < 3; ++j)
+  {
+    rA = 0.0f;
+    rB = 0.0f;
+    l = rotAxisB[j];
+
+    rA += fabs(boxA->halfLength[0] * rotAxisA[0].dot(l));
+    rA += fabs(boxA->halfLength[1] * rotAxisA[1].dot(l));
+    rA += fabs(boxA->halfLength[2] * rotAxisA[2].dot(l));
+
+    rB += fabs(boxB->halfLength[0] * rotAxisB[0].dot(l));
+    rB += fabs(boxB->halfLength[1] * rotAxisB[1].dot(l));
+    rB += fabs(boxB->halfLength[2] * rotAxisB[2].dot(l));
+
+    PRINTF(5)("s = %f, rA+rB = %f\n", fabs(t.dot(l)), rA+rB);
+
+    if( (rA + rB) < fabs(t.dot(l)))
+    {
+      PRINTF(4)("no Collision\n");
+      return false;
+    }
+  }
+
+
+  /* Now check for all face cross products */
+
+  for( int j = 0; j < 3; ++j)
+  {
+    for(int k = 0; k < 3; ++k )
+    {
+      rA = 0.0f;
+      rB = 0.0f;
+      l = rotAxisA[j].cross(rotAxisB[k]);
+
+      rA += fabs(boxA->halfLength[0] * rotAxisA[0].dot(l));
+      rA += fabs(boxA->halfLength[1] * rotAxisA[1].dot(l));
+      rA += fabs(boxA->halfLength[2] * rotAxisA[2].dot(l));
+
+      rB += fabs(boxB->halfLength[0] * rotAxisB[0].dot(l));
+      rB += fabs(boxB->halfLength[1] * rotAxisB[1].dot(l));
+      rB += fabs(boxB->halfLength[2] * rotAxisB[2].dot(l));
+
+      PRINTF(5)("s = %f, rA+rB = %f\n", fabs(t.dot(l)), rA+rB);
+
+      if( (rA + rB) < fabs(t.dot(l)))
+      {
+        PRINTF(4)("keine Kollision\n");
+        return false;
+      }
+    }
+  }
+
+  /* FIXME: there is no collision mark set now */
+     boxA->bCollided = true; /* use this ONLY(!!!!) for drawing operations */
+     boxB->bCollided = true;
+
+
+  PRINTF(4)("Kollision!\n");
+  return true;
+}
+
+
+/**
+ *
+ * draw the BV tree - debug mode
+ */
+void AABBTreeNode::drawBV(int depth, int drawMode, const Vector& color,  bool top) const
+{
+  /* this function can be used to draw the triangles and/or the points only  */
+  if( 1 /*drawMode & DRAW_MODEL || drawMode & DRAW_ALL*/)
+  {
+    if( depth == 0/*!(drawMode & DRAW_SINGLE && depth != 0)*/)
+    {
+      if( 1 /*drawMode & DRAW_POINTS*/)
+      {
+        glBegin(GL_POINTS);
+        glColor3f(0.3, 0.8, 0.54);
+        for(unsigned int i = 0; i < this->bvElement->modelInf->numVertices*3; i+=3)
+          glVertex3f(this->bvElement->modelInf->pVertices[i],
+                     this->bvElement->modelInf->pVertices[i+1],
+                     this->bvElement->modelInf->pVertices[i+2]);
+        glEnd();
+      }
+    }
+  }
+
+  if (top)
+  {
+    glPushAttrib(GL_ENABLE_BIT);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_TEXTURE_2D);
+  }
+  glColor3f(color.x, color.y, color.z);
+
+
+  /* draw world axes */
+  if( 1 /*drawMode & DRAW_BV_AXIS*/)
+  {
+    glBegin(GL_LINES);
+    glColor3f(1.0, 0.0, 0.0);
+    glVertex3f(0.0, 0.0, 0.0);
+    glVertex3f(3.0, 0.0, 0.0);
+
+    glColor3f(0.0, 1.0, 0.0);
+    glVertex3f(0.0, 0.0, 0.0);
+    glVertex3f(0.0, 3.0, 0.0);
+
+    glColor3f(0.0, 0.0, 1.0);
+    glVertex3f(0.0, 0.0, 0.0);
+    glVertex3f(0.0, 0.0, 3.0);
+    glEnd();
+  }
+
+
+  if( 1/*drawMode & DRAW_BV_AXIS || drawMode & DRAW_ALL*/)
+  {
+    if( 1/*drawMode & DRAW_SINGLE && depth != 0*/)
+    {
+      /* draw the obb axes */
+      glBegin(GL_LINES);
+      glColor3f(1.0, 0.0, 0.0);
+      glVertex3f(this->bvElement->center.x, this->bvElement->center.y, this->bvElement->center.z);
+      glVertex3f(this->bvElement->center.x + this->bvElement->axis[0].x * this->bvElement->halfLength[0],
+                 this->bvElement->center.y + this->bvElement->axis[0].y * this->bvElement->halfLength[0],
+                 this->bvElement->center.z + this->bvElement->axis[0].z * this->bvElement->halfLength[0]);
+
+      glColor3f(0.0, 1.0, 0.0);
+      glVertex3f(this->bvElement->center.x, this->bvElement->center.y, this->bvElement->center.z);
+      glVertex3f(this->bvElement->center.x + this->bvElement->axis[1].x * this->bvElement->halfLength[1],
+                 this->bvElement->center.y + this->bvElement->axis[1].y * this->bvElement->halfLength[1],
+                 this->bvElement->center.z + this->bvElement->axis[1].z * this->bvElement->halfLength[1]);
+
+      glColor3f(0.0, 0.0, 1.0);
+      glVertex3f(this->bvElement->center.x, this->bvElement->center.y, this->bvElement->center.z);
+      glVertex3f(this->bvElement->center.x + this->bvElement->axis[2].x * this->bvElement->halfLength[2],
+                 this->bvElement->center.y + this->bvElement->axis[2].y * this->bvElement->halfLength[2],
+                 this->bvElement->center.z + this->bvElement->axis[2].z * this->bvElement->halfLength[2]);
+      glEnd();
+    }
+  }
+
+
+  /* DRAW POLYGONS */
+  if( drawMode & DRAW_BV_POLYGON || drawMode & DRAW_ALL || drawMode & DRAW_BV_BLENDED)
+  {
+    if (top)
+    {
+      glEnable(GL_BLEND);
+      glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+    }
+
+    if( this->nodeLeft == NULL && this->nodeRight == NULL)
+      depth = 0;
+
+    if( depth == 0 /*!(drawMode & DRAW_SINGLE && depth != 0)*/)
+    {
+
+
+      Vector cen = this->bvElement->center;
+      Vector* axis = this->bvElement->axis;
+      float* len = this->bvElement->halfLength;
+
+      if( this->bvElement->bCollided)
+      {
+        glColor4f(1.0, 1.0, 1.0, .5); // COLLISION COLOR
+      }
+      else if( drawMode & DRAW_BV_BLENDED)
+      {
+        glColor4f(color.x, color.y, color.z, .5);
+      }
+
+
+      /* draw bounding box */
+      if( drawMode & DRAW_BV_BLENDED)
+        glBegin(GL_QUADS);
+      else
+        glBegin(GL_LINE_LOOP);
+      glVertex3f(cen.x + axis[0].x * len[0] + axis[1].x * len[1] + axis[2].x * len[2],
+                 cen.y + axis[0].y * len[0] + axis[1].y * len[1] + axis[2].y * len[2],
+                 cen.z + axis[0].z * len[0] + axis[1].z * len[1] + axis[2].z * len[2]);
+      glVertex3f(cen.x + axis[0].x * len[0] + axis[1].x * len[1] - axis[2].x * len[2],
+                 cen.y + axis[0].y * len[0] + axis[1].y * len[1] - axis[2].y * len[2],
+                 cen.z + axis[0].z * len[0] + axis[1].z * len[1] - axis[2].z * len[2]);
+      glVertex3f(cen.x + axis[0].x * len[0] - axis[1].x * len[1] - axis[2].x * len[2],
+                 cen.y + axis[0].y * len[0] - axis[1].y * len[1] - axis[2].y * len[2],
+                 cen.z + axis[0].z * len[0] - axis[1].z * len[1] - axis[2].z * len[2]);
+      glVertex3f(cen.x + axis[0].x * len[0] - axis[1].x * len[1] + axis[2].x * len[2],
+                 cen.y + axis[0].y * len[0] - axis[1].y * len[1] + axis[2].y * len[2],
+                 cen.z + axis[0].z * len[0] - axis[1].z * len[1] + axis[2].z * len[2]);
+      glEnd();
+
+      if( drawMode & DRAW_BV_BLENDED)
+        glBegin(GL_QUADS);
+      else
+        glBegin(GL_LINE_LOOP);
+      glVertex3f(cen.x + axis[0].x * len[0] - axis[1].x * len[1] + axis[2].x * len[2],
+                 cen.y + axis[0].y * len[0] - axis[1].y * len[1] + axis[2].y * len[2],
+                 cen.z + axis[0].z * len[0] - axis[1].z * len[1] + axis[2].z * len[2]);
+      glVertex3f(cen.x + axis[0].x * len[0] - axis[1].x * len[1] - axis[2].x * len[2],
+                 cen.y + axis[0].y * len[0] - axis[1].y * len[1] - axis[2].y * len[2],
+                 cen.z + axis[0].z * len[0] - axis[1].z * len[1] - axis[2].z * len[2]);
+      glVertex3f(cen.x - axis[0].x * len[0] - axis[1].x * len[1] - axis[2].x * len[2],
+                 cen.y - axis[0].y * len[0] - axis[1].y * len[1] - axis[2].y * len[2],
+                 cen.z - axis[0].z * len[0] - axis[1].z * len[1] - axis[2].z * len[2]);
+      glVertex3f(cen.x - axis[0].x * len[0] - axis[1].x * len[1] + axis[2].x * len[2],
+                 cen.y - axis[0].y * len[0] - axis[1].y * len[1] + axis[2].y * len[2],
+                 cen.z - axis[0].z * len[0] - axis[1].z * len[1] + axis[2].z * len[2]);
+      glEnd();
+
+      if( drawMode & DRAW_BV_BLENDED)
+        glBegin(GL_QUADS);
+      else
+        glBegin(GL_LINE_LOOP);
+      glVertex3f(cen.x - axis[0].x * len[0] - axis[1].x * len[1] + axis[2].x * len[2],
+                 cen.y - axis[0].y * len[0] - axis[1].y * len[1] + axis[2].y * len[2],
+                 cen.z - axis[0].z * len[0] - axis[1].z * len[1] + axis[2].z * len[2]);
+      glVertex3f(cen.x - axis[0].x * len[0] - axis[1].x * len[1] - axis[2].x * len[2],
+                 cen.y - axis[0].y * len[0] - axis[1].y * len[1] - axis[2].y * len[2],
+                 cen.z - axis[0].z * len[0] - axis[1].z * len[1] - axis[2].z * len[2]);
+      glVertex3f(cen.x - axis[0].x * len[0] + axis[1].x * len[1] - axis[2].x * len[2],
+                 cen.y - axis[0].y * len[0] + axis[1].y * len[1] - axis[2].y * len[2],
+                 cen.z - axis[0].z * len[0] + axis[1].z * len[1] - axis[2].z * len[2]);
+      glVertex3f(cen.x - axis[0].x * len[0] + axis[1].x * len[1] + axis[2].x * len[2],
+                 cen.y - axis[0].y * len[0] + axis[1].y * len[1] + axis[2].y * len[2],
+                 cen.z - axis[0].z * len[0] + axis[1].z * len[1] + axis[2].z * len[2]);
+      glEnd();
+
+      if( drawMode & DRAW_BV_BLENDED)
+        glBegin(GL_QUADS);
+      else
+        glBegin(GL_LINE_LOOP);
+      glVertex3f(cen.x - axis[0].x * len[0] + axis[1].x * len[1] - axis[2].x * len[2],
+                 cen.y - axis[0].y * len[0] + axis[1].y * len[1] - axis[2].y * len[2],
+                 cen.z - axis[0].z * len[0] + axis[1].z * len[1] - axis[2].z * len[2]);
+      glVertex3f(cen.x - axis[0].x * len[0] + axis[1].x * len[1] + axis[2].x * len[2],
+                 cen.y - axis[0].y * len[0] + axis[1].y * len[1] + axis[2].y * len[2],
+                 cen.z - axis[0].z * len[0] + axis[1].z * len[1] + axis[2].z * len[2]);
+      glVertex3f(cen.x + axis[0].x * len[0] + axis[1].x * len[1] + axis[2].x * len[2],
+                 cen.y + axis[0].y * len[0] + axis[1].y * len[1] + axis[2].y * len[2],
+                 cen.z + axis[0].z * len[0] + axis[1].z * len[1] + axis[2].z * len[2]);
+      glVertex3f(cen.x + axis[0].x * len[0] + axis[1].x * len[1] - axis[2].x * len[2],
+                 cen.y + axis[0].y * len[0] + axis[1].y * len[1] - axis[2].y * len[2],
+                 cen.z + axis[0].z * len[0] + axis[1].z * len[1] - axis[2].z * len[2]);
+      glEnd();
+
+
+      if( drawMode & DRAW_BV_BLENDED)
+      {
+        glBegin(GL_QUADS);
+        glVertex3f(cen.x - axis[0].x * len[0] + axis[1].x * len[1] - axis[2].x * len[2],
+                   cen.y - axis[0].y * len[0] + axis[1].y * len[1] - axis[2].y * len[2],
+                   cen.z - axis[0].z * len[0] + axis[1].z * len[1] - axis[2].z * len[2]);
+        glVertex3f(cen.x + axis[0].x * len[0] + axis[1].x * len[1] - axis[2].x * len[2],
+                   cen.y + axis[0].y * len[0] + axis[1].y * len[1] - axis[2].y * len[2],
+                   cen.z + axis[0].z * len[0] + axis[1].z * len[1] - axis[2].z * len[2]);
+        glVertex3f(cen.x + axis[0].x * len[0] - axis[1].x * len[1] - axis[2].x * len[2],
+                   cen.y + axis[0].y * len[0] - axis[1].y * len[1] - axis[2].y * len[2],
+                   cen.z + axis[0].z * len[0] - axis[1].z * len[1] - axis[2].z * len[2]);
+        glVertex3f(cen.x - axis[0].x * len[0] - axis[1].x * len[1] - axis[2].x * len[2],
+                   cen.y - axis[0].y * len[0] - axis[1].y * len[1] - axis[2].y * len[2],
+                   cen.z - axis[0].z * len[0] - axis[1].z * len[1] - axis[2].z * len[2]);
+        glEnd();
+
+        glBegin(GL_QUADS);
+        glVertex3f(cen.x - axis[0].x * len[0] + axis[1].x * len[1] + axis[2].x * len[2],
+                   cen.y - axis[0].y * len[0] + axis[1].y * len[1] + axis[2].y * len[2],
+                   cen.z - axis[0].z * len[0] + axis[1].z * len[1] + axis[2].z * len[2]);
+        glVertex3f(cen.x + axis[0].x * len[0] + axis[1].x * len[1] + axis[2].x * len[2],
+                   cen.y + axis[0].y * len[0] + axis[1].y * len[1] + axis[2].y * len[2],
+                   cen.z + axis[0].z * len[0] + axis[1].z * len[1] + axis[2].z * len[2]);
+        glVertex3f(cen.x + axis[0].x * len[0] - axis[1].x * len[1] + axis[2].x * len[2],
+                   cen.y + axis[0].y * len[0] - axis[1].y * len[1] + axis[2].y * len[2],
+                   cen.z + axis[0].z * len[0] - axis[1].z * len[1] + axis[2].z * len[2]);
+        glVertex3f(cen.x - axis[0].x * len[0] - axis[1].x * len[1] + axis[2].x * len[2],
+                   cen.y - axis[0].y * len[0] - axis[1].y * len[1] + axis[2].y * len[2],
+                   cen.z - axis[0].z * len[0] - axis[1].z * len[1] + axis[2].z * len[2]);
+        glEnd();
+      }
+
+      if( drawMode & DRAW_BV_BLENDED)
+        glColor3f(color.x, color.y, color.z);
+    }
+  }
+
+  /* DRAW SEPARATING PLANE */
+  if( drawMode & DRAW_SEPARATING_PLANE || drawMode & DRAW_ALL)
+  {
+    if( !(drawMode & DRAW_SINGLE && depth != 0))
+    {
+      if( drawMode & DRAW_BV_BLENDED)
+        glColor4f(color.x, color.y, color.z, .6);
+
+      /* now draw the separation plane */
+      Vector a1 = this->bvElement->axis[(this->longestAxisIndex + 1)%3];
+      Vector a2 = this->bvElement->axis[(this->longestAxisIndex + 2)%3];
+      Vector c = this->bvElement->center;
+      float l1 = this->bvElement->halfLength[(this->longestAxisIndex + 1)%3];
+      float l2 = this->bvElement->halfLength[(this->longestAxisIndex + 2)%3];
+      glBegin(GL_QUADS);
+      glVertex3f(c.x + a1.x * l1 + a2.x * l2, c.y + a1.y * l1+ a2.y * l2, c.z + a1.z * l1 + a2.z * l2);
+      glVertex3f(c.x - a1.x * l1 + a2.x * l2, c.y - a1.y * l1+ a2.y * l2, c.z - a1.z * l1 + a2.z * l2);
+      glVertex3f(c.x - a1.x * l1 - a2.x * l2, c.y - a1.y * l1- a2.y * l2, c.z - a1.z * l1 - a2.z * l2);
+      glVertex3f(c.x + a1.x * l1 - a2.x * l2, c.y + a1.y * l1- a2.y * l2, c.z + a1.z * l1 - a2.z * l2);
+      glEnd();
+
+      if( drawMode & DRAW_BV_BLENDED)
+        glColor4f(color.x, color.y, color.z, 1.0);
+
+    }
+  }
+
+
+
+  if (depth > 0)
+  {
+    if( this->nodeLeft != NULL)
+      this->nodeLeft->drawBV(depth - 1, drawMode, Color::HSVtoRGB(Color::RGBtoHSV(color)+Vector(15.0,0.0,0.0)), false);
+    if( this->nodeRight != NULL)
+      this->nodeRight->drawBV(depth - 1, drawMode, Color::HSVtoRGB(Color::RGBtoHSV(color)+Vector(30.0,0.0,0.0)), false);
+  }
+  this->bvElement->bCollided = false;
+
+  if (top)
+    glPopAttrib();
+}
+
+
+
+void AABBTreeNode::debug() const
+{
+  PRINT(0)("========AABBTreeNode::debug()=====\n");
+  PRINT(0)(" Current depth: %i", this->depth);
+  PRINT(0)(" ");
+  PRINT(0)("=================================\n");
+}
Index: trunk/src/lib/collision_detection/aabb_tree_node.h
===================================================================
--- trunk/src/lib/collision_detection/aabb_tree_node.h	(revision 8724)
+++ trunk/src/lib/collision_detection/aabb_tree_node.h	(revision 8724)
@@ -0,0 +1,86 @@
+/*!
+ * @file aabb_tree_node.h
+ *  Definition of a bounding volume tree
+ */
+
+#ifndef _AABB_TREE_NODE_H
+#define _AABB_TREE_NODE_H
+
+
+#include "bv_tree_node.h"
+#include "plane.h"
+
+class BoundingVolume;
+class AABB;
+class OBBTree;
+class Plane;
+class PNode;
+
+
+//! A class that represents a bounding volume tree
+class AABBTreeNode : public BVTreeNode
+{
+
+
+  public:
+    AABBTreeNode(const OBBTree& tree, AABBTreeNode* prev, int depth);
+    AABBTreeNode(int depth = 0);
+    virtual ~AABBTreeNode();
+    void init();
+
+    /**  this function returns the bounding volume of this tree node @return: returns the BV */
+    virtual inline const BoundingVolume* getBV() const { return (BoundingVolume*)this->bvElement; }
+
+    void spawnBVTree(Model* model);
+    virtual void spawnBVTree(const modelInfo& modelInf, const int* triangleIndexes, int length);
+
+    virtual void collideWith(BVTreeNode* treeNode, WorldEntity* nodeA, WorldEntity* nodeB);
+    virtual void drawBV(int depth, int drawMode, const Vector& color = Vector(1,0,0), bool top = true) const;
+    void debug() const;
+
+    /**  gets the id of the current child @return id of the child */
+    inline const int getID() { return this->nextID++; }
+    inline AABB* getAABB() { return this->bvElement; }
+
+  private:
+    void calculateBoxAxis(AABB& box, const sVec3D* verticesList, unsigned int length);
+
+    void calculateBoxCovariance(AABB& box, const modelInfo& modelInf, const int* triangleIndexes, int length);
+    void calculateBoxEigenvectors(AABB& box, const modelInfo& modelInf, const int* triangleIndexes, int length);
+    void calculateBoxAxis(AABB& box, const modelInfo& modelInf, const int* triangleIndexes, int length);
+    void forkBox(AABB& box);
+
+    void collideWithOBB(AABBTreeNode* treeNode, WorldEntity* nodeA, WorldEntity* nodeB);
+    bool overlapTest(AABB* boxA, AABB* boxB, WorldEntity* nodeA, WorldEntity* nodeB);
+
+
+  protected:
+    AABB*                bvElement;                  //!< the obb element
+    AABBTreeNode*        nodePrev;                   //!< ref to the previous (parent) tree node = NULL if first
+    AABBTreeNode*        nodeLeft;                   //!< ref to the left tree node
+    AABBTreeNode*        nodeRight;                  //!< ref to the right tree node
+
+
+  private:
+    int                 treeIndex;                  //!< Index number of the BV in the tree
+    int                 nextID;                     //!< the id of the next child
+    int                 depth;                      //!< the depth of the node in the tree
+    const OBBTree*      obbTree;                    //!< reference to the obb tree
+
+    const modelInfo*    modelInf;                   //!< pointer to the models modelInfo object
+    const int*          triangleIndexes;            //!< indexes to the used model triangles
+
+    Plane               separationPlane;            //!< the separation plane of the obb
+    sVec3D              sepPlaneCenter;             //!< only needed to draw plane
+    int                 longestAxisIndex;           //!< only needed to draw plane
+
+    /* tmp saving place for obb variables */
+    int*                triangleIndexList1;         //!< pointer to the vert data of obbox1
+    int*                triangleIndexList2;         //!< pointer to the vert data of obbox1
+    int                 triangleIndexLength1;       //!< len vert data obbox1
+    int                 triangleIndexLength2;       //!< len vert data obbox2
+
+    WorldEntity*        owner;
+};
+
+#endif /* _AABB_TREE_NODE_H */
Index: trunk/src/lib/collision_reaction/collision_handle.cc
===================================================================
--- trunk/src/lib/collision_reaction/collision_handle.cc	(revision 8719)
+++ trunk/src/lib/collision_reaction/collision_handle.cc	(revision 8724)
@@ -101,6 +101,6 @@
       return;
 
-   // add element
-   //PRINTF(0)("addTarget: %i \n", target);
+  // add element
+   PRINTF(5)("addTarget: %i \n", target);
 
    this->targetList.push_back(target);
@@ -177,5 +177,5 @@
 
  c->registerCollisionEvent(collisionEvent);
- PRINTF(0)("Registering Collision Event: %s, %s\n", collisionEvent->getEntityA()->getClassName(), collisionEvent->getEntityB()->getClassName());
+ PRINTF(5)("Registering Collision Event: %s, %s\n", collisionEvent->getEntityA()->getClassName(), collisionEvent->getEntityB()->getClassName());
 }
 
@@ -231,5 +231,5 @@
     if( collisionEvent->getEntityA() == this->owner) {
       if( collisionEvent->getEntityB()->isA((ClassID)(*it))) {
-        PRINTF(0)("I am: %s colliding with: %s is a %i filter ok\n", owner->getClassName(),
+        PRINTF(5)("I am: %s colliding with: %s is a %i filter ok\n", owner->getClassName(),
                   collisionEvent->getEntityB()->getClassName(), *it);
         return true; }
@@ -237,5 +237,5 @@
     else {
       if( collisionEvent->getEntityA()->isA((ClassID)(*it))) {
-        PRINTF(0)("I am: %s colliding with: %s is a %i filter ok\n", owner->getClassName(),
+        PRINTF(5)("I am: %s colliding with: %s is a %i filter ok\n", owner->getClassName(),
                   collisionEvent->getEntityA()->getClassName(), *it);
       return true; }
Index: trunk/src/lib/collision_reaction/cr_object_damage.cc
===================================================================
--- trunk/src/lib/collision_reaction/cr_object_damage.cc	(revision 8719)
+++ trunk/src/lib/collision_reaction/cr_object_damage.cc	(revision 8724)
@@ -63,5 +63,5 @@
   if( collision->isEntityACollide()) {
     damage = collision->getEntityB()->getDamage();
-    collision->getEntityA()->decreaseHealth(damage);
+    collision->getEntityA()->hit(damage);
   }
   PRINTF(4)("Dealing damage - %f damage to %s \n", damage, collision->getEntityA()->getClassName());
@@ -69,5 +69,5 @@
   if( collision->isEntityBCollide()) {
     damage = collision->getEntityA()->getDamage();
-    collision->getEntityB()->decreaseHealth(damage);
+    collision->getEntityB()->hit(damage);
   }
   PRINTF(4)("Dealing damage - %f damage to %s \n", damage, collision->getEntityB()->getClassName());
Index: trunk/src/lib/collision_reaction/cr_physics_ground_walk.cc
===================================================================
--- trunk/src/lib/collision_reaction/cr_physics_ground_walk.cc	(revision 8719)
+++ trunk/src/lib/collision_reaction/cr_physics_ground_walk.cc	(revision 8724)
@@ -1,12 +1,12 @@
 /*
    orxonox - the future of 3D-vertical-scrollers
-
+ 
    Copyright (C) 2004 orx
-
+ 
    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, or (at your option)
    any later version.
-
+ 
    ### File Specific:
    main-programmer: Patrick Boenzli
@@ -24,6 +24,4 @@
 #include "cr_physics_ground_walk.h"
 
-#include "debug.h"
-
 #include <vector>
 
@@ -35,5 +33,5 @@
  */
 CRPhysicsGroundWalk::CRPhysicsGroundWalk ()
-  : CollisionReaction()
+    : CollisionReaction()
 {
   this->setClassID(CL_CR_PHYSICS_GROUND_WALK, "CRPhysicsGroundWalk");
@@ -45,6 +43,5 @@
  */
 CRPhysicsGroundWalk::~CRPhysicsGroundWalk ()
-{
-}
+{}
 
 
@@ -57,18 +54,64 @@
   CollisionEvent* ce = collision->getCollisionEvents().front();
   Vector normal = ce->getGroundNormal();
-  normal.normalize();
+  // normal.normalize();
 
   // put it back
-//   PRINTF(0)("putting it back to lastPos: \n");
-//   this->lastPositions[0].debug();
-//   PRINTF(0)("current pos:\n");
-//   collision->getEntityB()->getAbsCoor().debug();
+  //   PRINTF(0)("putting it back to lastPos: \n");
+  //   this->lastPositions[0].debug();
+  //   PRINTF(0)("current pos:\n");
+  //   collision->getEntityB()->getAbsCoor().debug();
 
+
+  Vector height = ce->getCollisionPosition() - collision->getEntityB()->getAbsCoor();
+
+  if(ce->getCollisionPosition().x <= 0.9 && ce->getGroundNormal().len() <= 1.4f) {
+    collision->getEntityB()->setAbsCoor(collision->getEntityB()->getLastAbsCoor());
+    return;
+  }
+  if(ce->getGroundNormal().len() <= 0.1f) {
+    collision->getEntityB()->setAbsCoor(collision->getEntityB()->getLastAbsCoor());
+    return;
+  }
+  if(ce->getGroundNormal().len() >= 1.4f) {
+    downspeed++;
+    collision->getEntityB()->setAbsCoor(collision->getEntityB()->getAbsCoor() + Vector(0.0,-0.08*downspeed,0.0));
+    return;
+  }
+
+
+  if(height.y < -3.510001 + 10.0) // Above ground
+  {
+    if(height.y > -15.6) // Snap in
+    {
+      downspeed = 0;
+      collision->getEntityB()->setAbsCoor(collision->getEntityB()->getAbsCoor() + Vector(0.0,height.y+3.500005 + 10.0,0.0));
+    } else
+    {
+      downspeed++;
+      collision->getEntityB()->setAbsCoor(collision->getEntityB()->getAbsCoor() + Vector(0.0,-0.08*downspeed,0.0));
+    }
+
+  }
+  else {
+    if(height.y > -3.50000 + 10.0  && height.y <    9.9+ 10.0) // below ground
+    {
+      //if(downspeed <= 0) downspeed =1;
+      collision->getEntityB()->setAbsCoor(collision->getEntityB()->getAbsCoor() + Vector(0.0, 0.00001 /*height.y+3.500005 + 10.0*/,0.0));
+      //collision->getEntityB()->setVelocity(Vector(0.0,0.0,0.0));
+      downspeed = 0;
+    }
+
+  }
+
+
+  /*
   PRINTF(0)("Collision with Ground: \n");
   collision->getEntityB()->getAbsCoor().debug();
+  collision->getEntityB()->setVelocity(Vector());
+  collision->getEntityB()->setAbsCoor(this->lastPositions[1]);
 
-  //collision->getEntityB()->setVelocity(Vector());
-  //collision->getEntityB()->setAbsCoor(this->lastPositions[5]);
+  */
 }
+
 
 
@@ -81,5 +124,5 @@
   for( int i = 9; i > 0; i--) {
     this->lastPositions[i] = this->lastPositions[i-1];
-//     PRINTF(0)("lastPosition[%i]: %f, %f, %f\n", i, lastPositions[i].x, lastPositions[i].y, lastPositions[i].z);
+    //     PRINTF(0)("lastPosition[%i]: %f, %f, %f\n", i, lastPositions[i].x, lastPositions[i].y, lastPositions[i].z);
   }
   this->lastPositions[0] = owner->getAbsCoor();
Index: trunk/src/lib/collision_reaction/cr_physics_ground_walk.h
===================================================================
--- trunk/src/lib/collision_reaction/cr_physics_ground_walk.h	(revision 8719)
+++ trunk/src/lib/collision_reaction/cr_physics_ground_walk.h	(revision 8724)
@@ -29,4 +29,5 @@
 
     Vector       lastPositions[10];           //!< last 10 positions
+    float        downspeed;
 };
 
Index: trunk/src/lib/event/key_mapper.cc
===================================================================
--- trunk/src/lib/event/key_mapper.cc	(revision 8719)
+++ trunk/src/lib/event/key_mapper.cc	(revision 8724)
@@ -45,4 +45,5 @@
 int KeyMapper::PEV_STRAFE_LEFT       = EV_UNKNOWN;
 int KeyMapper::PEV_STRAFE_RIGHT      = EV_UNKNOWN;
+int KeyMapper::PEV_JUMP              = EV_UNKNOWN;
 
 int KeyMapper::PEV_FIRE1             = EV_UNKNOWN;
@@ -83,4 +84,5 @@
   {&KeyMapper::PEV_STRAFE_LEFT,          "StrafeLeft",                       SDLK_q},
   {&KeyMapper::PEV_STRAFE_RIGHT,         "StrafeRight",                      SDLK_e},
+  {&KeyMapper::PEV_JUMP,                 "Jump",                             SDLK_SPACE},
 
   {&KeyMapper::PEV_FIRE1,                CONFIG_NAME_PLAYER_FIRE,            EV_MOUSE_BUTTON_LEFT},
Index: trunk/src/lib/event/key_mapper.h
===================================================================
--- trunk/src/lib/event/key_mapper.h	(revision 8719)
+++ trunk/src/lib/event/key_mapper.h	(revision 8724)
@@ -55,4 +55,6 @@
   static int PEV_STRAFE_RIGHT;      //!< strafe right button
 
+  static int PEV_JUMP;              //!< jump
+
   static int PEV_FIRE1;             //!< fire button 1
   static int PEV_FIRE2;             //!< fire button 2
Index: trunk/src/lib/graphics/importer/Makefile.am
===================================================================
--- trunk/src/lib/graphics/importer/Makefile.am	(revision 8719)
+++ trunk/src/lib/graphics/importer/Makefile.am	(revision 8724)
@@ -34,4 +34,5 @@
                            md3/md3_model.cc \
                            md3/md3_animation.cc \
+                           md3/md3_animation_cfg.cc \
                            md3/md3_bone_frame.cc \
                            md3/md3_mesh.cc \
@@ -76,4 +77,5 @@
                 md3/md3_model.h \
                 md3/md3_animation.h \
+                md3/md3_animation_cfg.h \
                 md3/md3_bone_frame.h \
                 md3/md3_mesh.h \
Index: trunk/src/lib/graphics/importer/bsp_manager.cc
===================================================================
--- trunk/src/lib/graphics/importer/bsp_manager.cc	(revision 8719)
+++ trunk/src/lib/graphics/importer/bsp_manager.cc	(revision 8724)
@@ -50,5 +50,5 @@
 BspManager::BspManager(WorldEntity* parent)
 {
- 
+
   this->parent = parent;
   /*// open a BSP file
@@ -840,5 +840,6 @@
         this->checkBrushRayN(&curBrush);
       if(curBrush.n_brushsides <=0) this->outputAllSolid = true;
-    }
+    } 
+    
     return;
   }
@@ -907,4 +908,15 @@
 
 }
+
+float BspManager::checkPatchAltitude(BspTreeNode* node)
+{
+  leaf& curLeaf = this->bspFile->leaves[node->leafIndex];
+  for(int i = 0; i < curLeaf.n_leaffaces ; i++)
+  {
+   
+  }
+  return 10.0f;
+}
+
 void BspManager::checkCollisionBox(void)
 {
@@ -937,14 +949,14 @@
 void BspManager::checkCollision(WorldEntity* worldEntity)
 {
-  
+
   this->outputStartsOut = true;
   this->outputAllSolid = false;
   this->outputFraction = 1.0f;
-  
-  Vector position = worldEntity->getAbsCoor();
+
+
 
 
   Vector forwardDir = worldEntity->getAbsDirX();
-  forwardDir = forwardDir * 8.0f;
+
 
   Vector upDir = worldEntity->getAbsDirY();
@@ -958,6 +970,6 @@
   dest.z  += forwardDir.z;
   */
-
-  dest = worldEntity->getAbsCoor() - upDir*40.0;
+  Vector position = worldEntity->getAbsCoor() + upDir*10.0f ;
+  dest = worldEntity->getAbsCoor() - upDir*40.0f; //
   Vector out = dest;
 
@@ -966,7 +978,7 @@
 
   bool collision = false;
-  Vector position1 = position + Vector(0.0,0.1,0.0);
-  Vector position2 = position + Vector(0.0,0.2,0.0);
-  Vector dest1 = position1 + forwardDir;
+  Vector position1 = position; // + Vector(0.0,0.6,0.0);
+  Vector position2 = position + Vector(0.0,1.0,0.0);
+  Vector dest1 = position + forwardDir*4.0f;
   Vector dest2 = position2 + forwardDir;
   dest = position - Vector(0.0, 40.0,0.0);
@@ -976,20 +988,37 @@
 
   float height = 40;
-  
+
   this->inputStart =  position;
   this->inputEnd =   dest;
   this->checkCollisionRayN(this->root,0.0f,1.0f, &position, &dest );
-
-  PRINTF(0)(" checking collision: %s, solid = %i, fraction = %f\n", worldEntity->getClassName(), this->outputAllSolid, this->outputFraction);
-  PRINTF(0)("checking collision!! Pos.Coords: %f , %f , %f\n", position.x , position.y, position.z);
-  PRINTF(0)("checking collision!! Dest.Coords: %f , %f , %f\n", dest.x , dest.y, dest.z);  
+  
+
+
+//   PRINTF(0)(" checking collision: %s, solid = %i, fraction = %f\n", worldEntity->getClassName(), this->outputAllSolid, this->outputFraction);
+//   PRINTF(0)("checking collision!! Pos.Coords: %f , %f , %f\n", position.x , position.y, position.z);
+//   PRINTF(0)("checking collision!! Dest.Coords: %f , %f , %f\n", dest.x , dest.y, dest.z);
+
 //   position1.debug();
+
+  if(!this->outputStartsOut )
+  {
+    this->collPlane = new plane;
+    this->collPlane->x = 0.0f;
+    this->collPlane->y = 0.0f;
+    this->collPlane->z = 0.0f;
+    collision = true;
+  }
+  else
+  {
+
+
+
 
   if( this->outputFraction == 1.0f)
   {
-    if(this->outputAllSolid)
+    if(this->outputAllSolid )
     {
       this->collPlane = new plane;
-      this->collPlane->x = 1.0f;
+      this->collPlane->x = 0.0f;
       this->collPlane->y = 0.0f;
       this->collPlane->z = 0.0f;
@@ -1013,9 +1042,31 @@
   }
 
+
+  }
+  
+  plane* testPlane = this->collPlane;
+  
+  this->outputStartsOut = true;
+  this->outputAllSolid = false;
+  this->outputFraction = 1.0f;
+  this->inputStart =  position;
+  this->inputEnd =   dest1;
+  this->checkCollisionRayN(this->root,0.0f,1.0f, &position, &dest1 );
+  out.x = this->outputFraction;
+  out.z = this->outputFraction;
+  
+  /*
+  out.x = position1.x + (dest.x -position1.x) * this->outputFraction;
+  
+  out.z = position1.z + (dest.z -position1.z) * this->outputFraction;
+  */
+  
+  
   // Return the normal here: Normal's stored in this->collPlane;
   if( collision) {
-    PRINTF(0)("We got a collision!! Are you sure: outputFraction = %f\n", this->outputFraction);
-    worldEntity->registerCollision(this->parent, worldEntity, Vector(this->collPlane->x, this->collPlane->y, this->collPlane->z), out);
-  }
+    PRINTF(5)("We got a collision!! Are you sure: outputFraction = %f\n", this->outputFraction);
+    worldEntity->registerCollision(this->parent, worldEntity, Vector(testPlane->x, testPlane->y, testPlane->z), out);
+  }
+  else  worldEntity->registerCollision(this->parent, worldEntity, Vector(0.0, 2.0, 0.0), dest);
 
 }
Index: trunk/src/lib/graphics/importer/bsp_manager.h
===================================================================
--- trunk/src/lib/graphics/importer/bsp_manager.h	(revision 8719)
+++ trunk/src/lib/graphics/importer/bsp_manager.h	(revision 8724)
@@ -73,9 +73,10 @@
   void  checkCollisionRay(BspTreeNode * node,float startFraction, float endFraction, Vector* start, Vector* end);
   void  checkCollisionRayN(BspTreeNode * node,float startFraction, float endFraction, Vector* start, Vector* end);
-  void TraceBox( Vector& inputStart, Vector& inputEnd,Vector& inputMins, Vector& inputMaxs );
+  void  TraceBox( Vector& inputStart, Vector& inputEnd,Vector& inputMins, Vector& inputMaxs );
   void  checkCollisionBox(void);
   void  checkBrushRay(brush* curBrush);
   void  checkBrushRayN(brush* curBrush);
-  void   checkBrushRayN(brush* curBrush, Vector& inputStart, Vector& inputEnd);
+  void  checkBrushRayN(brush* curBrush, Vector& inputStart, Vector& inputEnd);
+  float  checkPatchAltitude(BspTreeNode* node); //! To be implemented...
 
   void drawDebugCube(Vector* cam);
Index: trunk/src/lib/graphics/importer/interactive_model.h
===================================================================
--- trunk/src/lib/graphics/importer/interactive_model.h	(revision 8719)
+++ trunk/src/lib/graphics/importer/interactive_model.h	(revision 8724)
@@ -37,4 +37,5 @@
 
     virtual void setAnimation(int animNum, int playbackMode = 0) = 0;
+    virtual int getAnimation() = 0;
 };
 
Index: trunk/src/lib/graphics/importer/md2/md2Model.h
===================================================================
--- trunk/src/lib/graphics/importer/md2/md2Model.h	(revision 8719)
+++ trunk/src/lib/graphics/importer/md2/md2Model.h	(revision 8724)
@@ -159,5 +159,5 @@
   virtual void setAnimation(int type, int animPlayback = MD2_ANIM_LOOP);
   /**  returns the current animation @returns animation type */
-  inline int MD2Model::getAnim() { return this->animationState.type; }
+  inline int MD2Model::getAnimation() { return this->animationState.type; }
   /**  scales the current model @param scaleFactor: the factor [0..1] to use for scaling */
   void scaleModel(float scaleFactor) { this->scaleFactor = scaleFactor;}
Index: trunk/src/lib/graphics/importer/md3/md3_animation.cc
===================================================================
--- trunk/src/lib/graphics/importer/md3/md3_animation.cc	(revision 8719)
+++ trunk/src/lib/graphics/importer/md3/md3_animation.cc	(revision 8724)
@@ -22,4 +22,35 @@
 {
 
+
+
+  MD3AnimationMap MD3Animation::animationList[25] = {
+    { "Death 1",                 BOTH  },
+    { "Dead 1",                  BOTH  },
+    { "Death 2",                 BOTH  },
+    { "Dead 2",                  BOTH  },
+    { "Death 3",                 BOTH  },
+    { "Dead 3",                  BOTH  },
+    { "Gesture",                 BOTH  },
+    { "Shoot",                   TORSO },
+    { "Hit",                     TORSO },
+    { "Drop Weapon",             TORSO },
+    { "Raise Weapon",            TORSO },
+    { "Stand With Weapon",       TORSO },
+    { "Stand with Gauntlet",     TORSO },
+    { "Crouched Walk",           LEGS  },
+    { "Walk",                    LEGS  },
+    { "Run",                     LEGS  },
+    { "Backpedal",               LEGS  },
+    { "Swim",                    LEGS  },
+    { "Jump Forward",            LEGS  },
+    { "Land Forward",            LEGS  },
+    { "Jump Backward",           LEGS  },
+    { "Land Backward",           LEGS  },
+    { "Stand Idle",              LEGS  },
+    { "Crouched Idle",           LEGS  },
+    { "Turn In Place",           LEGS  }
+  };
+
+
   /**
    * create an empty MD3Animation object
@@ -28,15 +59,4 @@
   {
     this->init();
-  }
-
-
-  /**
-   * create a new MD3 Anumation object and initialize it with the data on the given line
-   * @param line: the line to read from
-   */
-  MD3Animation::MD3Animation(std::string line)
-  {
-    this->init();
-    // loadAnimation()
   }
 
Index: trunk/src/lib/graphics/importer/md3/md3_animation.h
===================================================================
--- trunk/src/lib/graphics/importer/md3/md3_animation.h	(revision 8719)
+++ trunk/src/lib/graphics/importer/md3/md3_animation.h	(revision 8724)
@@ -11,7 +11,23 @@
 #include <string>
 
+namespace md3
+{
 
-typedef struct AnimationType
-{};
+typedef enum MD3AnimationType {
+  LEGS      = 0,             //!< animation only applicatble to the legs. top level model loaded from lower.md3
+  TORSO,                     //!< animation only applicatboe to the torso. normaly loaded from upper.md3
+  BOTH,                      //!< animation is applicable on both
+  ALL,                       //!< animation is applicable to all submodels
+
+  NUM_ANIMATION_TYPE         //!< number of animations
+};
+
+
+typedef struct MD3AnimationMap {
+  std::string        animationName;
+  MD3AnimationType   animationType;
+};
+
+
 
 
@@ -24,5 +40,4 @@
   public:
     MD3Animation();
-    MD3Animation(std::string line);
     virtual ~MD3Animation();
 
@@ -33,16 +48,16 @@
 
   public:
-    AnimationType    type;                        //!< specifies for what parts of a model this animation is appilcable (e.g. LEGS, BOTH)
-    std::string      name;                        //!< name of the animation
+    MD3AnimationType      type;                      //!< specifies for what parts of a model this animation is appilcable (e.g. LEGS)
+    std::string           name;                      //!< name of the animation
 
-    int              offset;                      //!< for LEGS animation, this is the offset value to skip TORSO frames
-    int              first;                       //!< first frame
-    int              numFrames;                   //!< the number of frames in the anumation. < 0 means that all available frames used
-    int              numLoopFrames;               //!< number of looping frames
-    int              fps;                         //!< frames per second
+    int                   offset;                    //!< for LEGS animation, this is the offset value to skip TORSO frames
+    int                   first;                     //!< first frame
+    int                   numFrames;                 //!< the number of frames in the anumation. < 0 means that all available frames used
+    int                   numLoopFrames;             //!< number of looping frames
+    int                   fps;                       //!< frames per second
 
-
+    static MD3AnimationMap animationList[25];         //!< the animation list
 };
 
-
+}
 #endif /* _MD3_ANIMATION_H */
Index: trunk/src/lib/graphics/importer/md3/md3_animation_cfg.cc
===================================================================
--- trunk/src/lib/graphics/importer/md3/md3_animation_cfg.cc	(revision 8724)
+++ trunk/src/lib/graphics/importer/md3/md3_animation_cfg.cc	(revision 8724)
@@ -0,0 +1,229 @@
+/*
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 orx
+
+   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, or (at your option)
+   any later version.
+
+### File Specific:
+   main-programmer: Patrick Boenzli
+*/
+
+#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_IMPORTER
+
+#include "md3_animation_cfg.h"
+
+#include "md3_animation.h"
+
+#include "tokenizer.h"
+#include "helper_functions.h"
+
+#include "debug.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+using namespace std;
+
+namespace md3
+{
+
+  /**
+   * create an empty MD3AnimationCfg object
+   */
+  MD3AnimationCfg::MD3AnimationCfg()
+  {
+  }
+
+
+  /**
+   * create a new MD3 Anumation object and initialize it with the data on the given line
+   * @param line: the line to read from
+   */
+  MD3AnimationCfg::MD3AnimationCfg(std::string filename)
+  {
+
+
+    this->loadConfig(filename);
+  }
+
+
+  /**
+   * deconstructor
+   */
+  MD3AnimationCfg::~MD3AnimationCfg()
+  {}
+
+
+  /**
+   * loads the configuration file
+   */
+  void MD3AnimationCfg::loadConfig(std::string filename)
+  {
+//     BufferedReader bin=new BufferedReader(new InputStreamReader(in));
+
+    int      i = 0;                //!< last read animation, animation order is hard coded!
+    int      torsoOffset = -1;     //!< torso offset
+    int      firstTorsoFrame = -1; //!< first of the TORSO animation frames
+    bool     inHeader = true;      //!< are we still in the header of the .cfg file?
+
+
+    FILE* pFile;
+    char* cLine;
+    size_t len = 0;
+    ssize_t read = 0;
+
+    PRINTF(0)("opening file: %s\n", filename.c_str());
+    pFile = fopen(filename.c_str(), "r");
+    if( !pFile) {
+      PRINTF(1)("Error: file could not be opened: %s\n", filename.c_str());
+      return;
+    }
+
+
+    // parse file
+    while( (read = getline(&cLine, &len, pFile)) != -1) { /*( !this->dataStream.eof()) {*/
+      std::string line(cLine);
+
+//       PRINTF(0)("size = %i, line = |%s|\n", read, line.c_str());
+
+      //ignore empty lines and comments
+      if( line.length() > 2 && line.find("//") != 0) {
+
+        // find the gender section
+        if( inHeader && line.find("sex") == 0) {
+          //parse line: sex [m | f | ...]
+          std::vector<std::string> tokens;
+          Tokenizer::tokenize(line, tokens, " \t\n\r\f/");
+
+          std::string sexStr = tokens.back();
+          // probably error in the file format
+          if( sexStr.length() != 1) {
+            this->sex = '?';
+            PRINTF(2)("no section \"sex\" in the config file %s found\n", filename.c_str());
+          }
+          else {
+            this->sex = sexStr[0];
+          }
+
+          PRINTF(0)("sex of the md3 model: %c\n", this->sex);
+        }
+        else if( inHeader && line.find("headoffset") == 0) {
+          // parse line: headoffset X Y Z
+          std::vector<std::string> tokens;
+          Tokenizer::tokenize(line, tokens, " \t\n\r\f/");
+
+          float z = atof(tokens.back().c_str()); tokens.pop_back();
+          float y = atof(tokens.back().c_str()); tokens.pop_back();
+          float x = atof(tokens.back().c_str()); tokens.pop_back();
+
+          this->headOffset = Vector(x, y, z);
+
+          PRINTF(0)("got head offset: %f, %f, %f\n", x, y, z);
+        }
+        else if( inHeader && line.find("footsteps") == 0) {
+          //parse line: footsteps [normal | mech | ...]
+          std::vector<std::string> tokens;
+          Tokenizer::tokenize(line, tokens, " \t\n\r\f/");
+
+          this->footsteps = tokens.back();
+
+          //check if value is ok
+          if (!(nocaseCmp(this->footsteps, "default")   ||
+                nocaseCmp(this->footsteps, "normal")    ||
+                nocaseCmp(this->footsteps, "boot")      ||
+                nocaseCmp(this->footsteps, "flesh")     ||
+                nocaseCmp(this->footsteps, "mech")      ||
+                nocaseCmp(this->footsteps, "energy")) ) {
+            this->footsteps="illegal footsteps value (" + this->footsteps + ")";
+          }
+          PRINTF(0)("got footsteps: %s\n", this->footsteps.c_str());
+        }
+        else
+        {
+          // assume it's an animation line
+          inHeader = false;
+
+          MD3Animation* animation = new MD3Animation();
+          this->loadAnimation(animation, line);
+
+          if( i < 25)
+          {
+            animation->name = MD3Animation::animationList[i].animationName;
+            animation->type = MD3Animation::animationList[i++].animationType;
+          }
+
+          // workaround for strange numbering in animation.cfg: skip TORSO frames
+          // for LEGS animation lines...
+          if( animation->type == LEGS)
+          {
+            //when first LEGS animation is found, calc # of TORSO frames
+            if( torsoOffset == -1)
+              torsoOffset = animation->first - firstTorsoFrame;
+
+            animation->first -= torsoOffset;
+            animation->offset = torsoOffset;
+          }
+          else if( animation->type == TORSO)
+            if( firstTorsoFrame == -1)
+              firstTorsoFrame = animation->first;
+
+          this->putAnimation(animation);
+        }
+      }
+    }
+  }
+
+
+  /**
+   * loading the animation data itself
+   */
+  void MD3AnimationCfg::loadAnimation(MD3Animation* anim, std::string line)
+  {
+    // parse the line:
+    // first frame, num frames, looping frames, frames per second (fps)
+    std::vector<std::string> tokens;
+    Tokenizer::tokenize(line, tokens, " \t\n\r\f/");
+
+    anim->fps = atoi(tokens.back().c_str()); tokens.pop_back();
+    anim->numLoopFrames = atoi(tokens.back().c_str()); tokens.pop_back();
+    anim->numFrames = atoi(tokens.back().c_str()); tokens.pop_back();
+    anim->first = atoi(tokens.back().c_str()); tokens.pop_back();
+
+    //some adjustements:
+    if( anim->fps == 0)
+      anim->fps = 33;
+
+    PRINTF(0)("Animation: first frame: %i, num frames: %i, num loops: %i, fps: %i\n", anim->first, anim->numFrames, anim->numLoopFrames, anim->fps);
+  }
+
+
+  /**
+  * Look up the animation data for the animation with the specified name.
+  *
+  * @param name Name of the animation.
+  * @return The animation data associated with the name or null if no data was found.
+  */
+  MD3Animation* MD3AnimationCfg::getAnimation(std::string name)
+  {
+    return this->animations[name];
+  }
+
+
+  /**
+   * Add the specified animation to the list of known animations.
+   */
+   void MD3AnimationCfg::putAnimation(MD3Animation* anim)
+   {
+      this->animations[anim->name] = anim;
+   }
+
+
+}
+
+
+
Index: trunk/src/lib/graphics/importer/md3/md3_animation_cfg.h
===================================================================
--- trunk/src/lib/graphics/importer/md3/md3_animation_cfg.h	(revision 8724)
+++ trunk/src/lib/graphics/importer/md3/md3_animation_cfg.h	(revision 8724)
@@ -0,0 +1,61 @@
+/*!
+ * @file md3_animation.h
+ *
+ * Code heavely inspired by: JAVA MD3 Model Viewer - A Java based Quake 3 model viewer
+ * Copyright (C) 1999 Erwin 'KLR8' Vervaet
+ */
+
+#ifndef _MD3_ANIMATION_CFG_H
+#define _MD3_ANIMATION_CFG_H
+
+#include "vector.h"
+
+#include "base_object.h"
+
+#include <string>
+#include <map>
+
+#include <iostream>
+#include <fstream>
+
+
+
+namespace md3
+{
+  class MD3Animation;
+
+
+  /**
+   * a class with metadata describing an MD3 model animation
+   */
+  class MD3AnimationCfg : public BaseObject
+  {
+
+    public:
+      MD3AnimationCfg();
+      MD3AnimationCfg(std::string filename);
+      virtual ~MD3AnimationCfg();
+
+      void loadConfig(std::string filename);
+
+      MD3Animation* getAnimation(std::string name);
+      void putAnimation(MD3Animation* animation);
+
+    private:
+      void loadAnimation(MD3Animation* anim, std::string line);
+
+
+    public:
+      std::string             filename;            //!< filename of the config file
+
+      char                    sex;                 //!< sex of animated model: 'm' for male, 'f' for female
+      Vector                  headOffset;          //!< head offset. this is the offset of the head model in the HUD x,y,z
+      std::string             footsteps;           //!< type of the footstep sounds associated with anumations (e.g. "mech", "default")
+
+      std::ifstream           dataStream;          //!< the data stream
+
+      std::map<std::string, MD3Animation*>     animations;          //!< mapping of animation names to MD3Animation objects.
+  };
+}
+
+#endif /* _MD3_ANIMATION_CFG_H */
Index: trunk/src/lib/graphics/importer/md3/md3_bone_frame.h
===================================================================
--- trunk/src/lib/graphics/importer/md3/md3_bone_frame.h	(revision 8719)
+++ trunk/src/lib/graphics/importer/md3/md3_bone_frame.h	(revision 8724)
@@ -6,6 +6,6 @@
  */
 
-#ifndef _MD3_ANIMATION_H
-#define _MD3_ANIMATION_H
+#ifndef _MD3_BONE_FRAME_ANIMATION_H
+#define _MD3_BONE_FRAME_ANIMATION_H
 
 #include "vector.h"
@@ -51,3 +51,3 @@
 }
 
-#endif /* _MD3_ANIMATION_H */
+#endif /* _MD3_BONE_FRAME_ANIMATION_H */
Index: trunk/src/lib/graphics/importer/md3/md3_data.cc
===================================================================
--- trunk/src/lib/graphics/importer/md3/md3_data.cc	(revision 8719)
+++ trunk/src/lib/graphics/importer/md3/md3_data.cc	(revision 8724)
@@ -37,9 +37,20 @@
 MD3Data::MD3Data(const std::string& modelFileName, const std::string& skinFileName, float scale)
 {
-
-
+  this->filename = modelFileName;
+
+  this->parentTagIndex = -1;
+  this->parent = NULL;
+
+  this->animationState.currentFrame = 0;
+  this->animationState.nextFrame = 1;
+  this->animationState.interpolationFraction = 0.0f;
+
+  this->animation = NULL;
+  this->bInterpolate = false;
+  this->upperBound = 0;
 
   this->loadModel(modelFileName);
 //   this->loadSkin(skinFileName);
+  this->init();
 }
 
@@ -54,4 +65,63 @@
   delete this->header;
 }
+
+
+/**
+ * init data
+ */
+void MD3Data::init()
+{
+  // create the temporary data to work with (interpolation data)
+  this->tmpBoneFrame = new MD3BoneFrame();
+
+  this->tmpMesh = new sVec3D*[this->header->meshNum];
+  for( int i = 0; i < this->header->meshNum; i++)
+    this->tmpMesh[i] = new sVec3D[this->meshes[i]->header->vertexNum];
+
+  this->tmpNormal = new MD3Normal*[this->header->meshNum];
+  for( int i = 0; i < this->header->meshNum; i++)
+    this->tmpNormal[i] = new MD3Normal[this->meshes[i]->header->vertexNum];
+
+  // there are at most 4 different models and submodels
+  this->tmpMatrix = new float*[4];
+  for( int i = 0; i < 4; i++)
+    this->tmpMatrix[i] = new float[16];
+
+}
+
+
+/**
+ * link a model at the specified tag position to this model. if the position is already
+ * occupied, the old submodel will be replaced
+ *
+ *  @param tagIndex: tag to link the submodel to
+ *  @param child: the submodel that should be linked to this model
+ */
+void MD3Data::addLinkedModel(int tagIndex, MD3Data* child)
+{
+  this->sortedMap[tagIndex] = child;
+  child->parentTagIndex = tagIndex;
+}
+
+
+
+/**
+ * Return the index of the tag with the given name for this model.
+ *
+ * This will return -1 if their is no such tag.
+ */
+ int MD3Data::getTagIndexByName(std::string tagName)
+{
+   int res = -1;
+
+   if( this->header->boneFrameNum > 0) {
+     MD3Tag** tags = this->boneFrames[0]->tags;
+     for( int i = 0; i < this->header->tagNum; i++)
+       if( tags[i]->name.find(tagName) == std::string::npos)
+         return i;
+   }
+
+   return res;
+ }
 
 
@@ -67,5 +137,4 @@
 //  char* buffer;                           //buffer for frame data
   int fileOffset = 0;                     // file data offset
-
 
 
@@ -219,4 +288,14 @@
       fread(md, 1, sizeof(MD3TagData), pFile);
       this->boneFrames[i]->tags[j]->data = md;
+
+      this->boneFrames[i]->tags[j]->name = std::string(this->boneFrames[i]->tags[j]->data->name);
+      this->boneFrames[i]->tags[j]->position = Vector( this->boneFrames[i]->tags[j]->data->position[0],
+                                                       this->boneFrames[i]->tags[j]->data->position[1],
+                                                       this->boneFrames[i]->tags[j]->data->position[2]);
+      for( int k = 0; k < 3; k++)
+        for( int l = 0; l < 3; l++)
+          this->boneFrames[i]->tags[j]->matrix[k][l] = this->boneFrames[i]->tags[j]->data->matrix[k][l];
+
+      //PRINTF(0)("Tag name: %s\n", this->boneFrames[i]->tags[j]->name.c_str());
     }
   }
@@ -318,4 +397,9 @@
   fread(this->meshes[mesh]->triangles, 1, sizeof(MD3Triangle) * this->meshes[mesh]->header->triangleNum, pFile);
 
+//   for( int i = 0; i < this->meshes[mesh]->header->triangleNum; i++) {
+//     PRINTF(0)("Triangle read: %i, %i, %i\n", this->meshes[mesh]->triangles[i].vertexOffset[0], this->meshes[mesh]->triangles[i].vertexOffset[1]
+//         , this->meshes[mesh]->triangles[i].vertexOffset[2]);
+//   }
+
   return this->meshes[mesh]->header->triangleNum * sizeof(MD3Triangle);
 }
@@ -337,5 +421,9 @@
   for( int i = 0; i < this->meshes[mesh]->header->textureNum; i++) {
     PRINTF(0)(" texture file: %s\n", tex[i].fileName);
-    this->meshes[mesh]->material[i].setDiffuseMap(tex[i].fileName);
+#warning texture stuff hard coded. make this again
+    std::string path("/home/boenzlip/tmp/q3/Downloads/MOH/q3mdl-alien3/");
+    std::string path1(tex[i].fileName);
+    std::string fullPath( path + path1);
+    this->meshes[mesh]->material[i].setDiffuseMap(/*tex[i].fileName*/ /*fullPath.c_str()*/ "maps/creatures/gork/gorkup.tga");
     this->meshes[mesh]->material[i].setAmbient(1, 1, 1);
   }
@@ -355,4 +443,8 @@
   fread(this->meshes[mesh]->texVecs, 1, sizeof(MD3TexVecs) * this->meshes[mesh]->header->vertexNum, pFile);
 
+//   for( int i = 0; i < this->meshes[mesh]->header->vertexNum; i++)  {
+//     PRINTF(0)("TexVec read: %f, %f\n", this->meshes[mesh]->texVecs[i].textureCoord[0], this->meshes[mesh]->texVecs[i].textureCoord[0]);
+//   }
+
   return this->meshes[mesh]->header->vertexNum * sizeof(MD3TexVecs);
 }
@@ -367,35 +459,43 @@
 
   // reserver memory for the vertex informations
-  this->meshes[mesh]->meshFrames = new sVec3D[this->meshes[mesh]->header->meshFrameNum * this->meshes[mesh]->header->vertexNum];
-  this->meshes[mesh]->normals = new MD3Normal[this->meshes[mesh]->header->meshFrameNum * this->meshes[mesh]->header->vertexNum];
-
-  for( int i = 0; i < this->meshes[mesh]->header->meshFrameNum * this->meshes[mesh]->header->vertexNum; i++)
+  this->meshes[mesh]->meshFrames = new sVec3D*[this->meshes[mesh]->header->meshFrameNum]; // * this->meshes[mesh]->header->vertexNum
+  this->meshes[mesh]->normals = new MD3Normal*[this->meshes[mesh]->header->meshFrameNum];
+
+  for( int i = 0; i < this->meshes[mesh]->header->meshFrameNum; i++)
   {
-    // read out the compressed data
-    MD3VertexCompressed* vc = new MD3VertexCompressed;
-    fread(vc, 1, sizeof(MD3VertexCompressed), pFile);
-
-    this->meshes[mesh]->meshFrames[i][0] = (float)vc->vector[0] / 64.0f;
-    this->meshes[mesh]->meshFrames[i][1] = (float)vc->vector[1] / 64.0f;
-    this->meshes[mesh]->meshFrames[i][2] = (float)vc->vector[2] / 64.0f;
-
-    this->meshes[mesh]->normals[i].vertexNormal[0] = vc->vertexNormal[0];
-    this->meshes[mesh]->normals[i].vertexNormal[1] = vc->vertexNormal[1];
-
-    delete vc;
+    this->meshes[mesh]->meshFrames[i] = new sVec3D[this->meshes[mesh]->header->vertexNum];
+    this->meshes[mesh]->normals[i] = new MD3Normal[this->meshes[mesh]->header->vertexNum];
+
+    for( int j = 0; j < this->meshes[mesh]->header->vertexNum; j++)
+    {
+      // read out the compressed data
+      MD3VertexCompressed* vc = new MD3VertexCompressed;
+      fread(vc, 1, sizeof(MD3VertexCompressed), pFile);
+
+      this->meshes[mesh]->meshFrames[i][j][0] = (float)vc->vector[0] / 64.0f;
+      this->meshes[mesh]->meshFrames[i][j][1] = (float)vc->vector[1] / 64.0f;
+      this->meshes[mesh]->meshFrames[i][j][2] = (float)vc->vector[2] / 64.0f;
+
+      this->meshes[mesh]->normals[i][j].vertexNormal[0] = (int)vc->vertexNormal[0];
+      this->meshes[mesh]->normals[i][j].vertexNormal[1] = (int)vc->vertexNormal[1];
+
+//     PRINTF(0)("nr: %i, meshframes: %f, %f, %f, normal: %f, %f\n", i, this->meshes[mesh]->meshFrames[i][0], this->meshes[mesh]->meshFrames[i][1],
+//     this->meshes[mesh]->meshFrames[i][2], this->meshes[mesh]->normals[i].vertexNormal[0], this->meshes[mesh]->normals[i].vertexNormal[1]);
+
+      delete vc;
+    }
   }
 
-  // delete the temp memory again
-//   delete vc;
-
   return this->meshes[mesh]->header->meshFrameNum * this->meshes[mesh]->header->vertexNum * sizeof(MD3VertexCompressed);
 }
 
-}
-
-
-
-
-
-
-
+
+
+}
+
+
+
+
+
+
+
Index: trunk/src/lib/graphics/importer/md3/md3_data.h
===================================================================
--- trunk/src/lib/graphics/importer/md3/md3_data.h	(revision 8719)
+++ trunk/src/lib/graphics/importer/md3/md3_data.h	(revision 8724)
@@ -25,20 +25,11 @@
 #include "md_model_structure.h"
 
+#include <map>
+
 
 //! These are the needed defines for the max values when loading .MD2 files
 #define MD3_IDENT                       (('3'<<24) + ('P'<<16) + ('D'<<8) + 'I') //!< the md3 identifier tag in the bin file
 #define MD3_VERSION                     15                                       //!< the md2 version in the header
-#define MD2_MAX_TRIANGLES               4096                                     //!< maximal triangles count
-#define MD2_MAX_VERTICES                2048                                     //!< maximal vertices count
-#define MD2_MAX_TEXCOORDS               2048                                     //!< maximal tex coordinates
-#define MD2_MAX_FRAMES                  512                                      //!< maximal frames
-#define MD2_MAX_SKINS                   32                                       //!< maximal skins
-#define MD2_MAX_FRAMESIZE               (MD2_MAX_VERTICES * 4 + 128)             //!< maximal framesize
 
-#define NUM_VERTEX_NORMALS              162                                      //!< number of vertex normals
-#define SHADEDOT_QUANT                  16                                       //!< shade dot quantity - no idea what it is
-
-//! This stores the speed of the animation between each key frame - currently conflicting with the animation framework
-#define kAnimationSpeed                 12.0f                                    //!< animation speed
 
 
@@ -48,79 +39,91 @@
   class MD3BoneFrame;
   class MD3Mesh;
+  class MD3Normal;
+  class MD3Animation;
 
-//! This holds the header information that is read in at the beginning of the file: id software definition
-struct MD3Header
-{
-   int ident;                           //!< This is used to identify the file
-   int version;                         //!< The version number of the file (Must be 8)
+  //! This holds the header information that is read in at the beginning of the file: id software definition
+  typedef struct MD3Header
+  {
+    int ident;                           //!< This is used to identify the file
+    int version;                         //!< The version number of the file (Must be 8)
 
-   char filename[68];                   //!< The filename of the model
+    char filename[68];                   //!< The filename of the model
 
-   int boneFrameNum;                    //!< number of frames
-   int tagNum;                          //!< number of tags
-   int meshNum;                         //!< number of mesh
-   int maxTexNum;                       //!< number of texture
+    int boneFrameNum;                    //!< number of frames
+    int tagNum;                          //!< number of tags
+    int meshNum;                         //!< number of mesh
+    int maxTexNum;                       //!< number of texture
 
-   int boneFrameStart;                  //!< start of bone frames
-   int tagStart;                        //!< start of the tag
-   int meshStart;                       //!< mesh start
+    int boneFrameStart;                  //!< start of bone frames
+    int tagStart;                        //!< start of the tag
+    int meshStart;                       //!< mesh start
 
-   int fileSize;                        //!< file size
-};
+    int fileSize;                        //!< file size
+  };
+
+  //!< holding the informations about the current animation state
+  typedef struct MD3AnimationState
+  {
+    int     currentFrame;          //!< currently rendered animation key frame of this model. Every part has its own current frame!
+    int     nextFrame;             //!< next animation key frame of the model.
+    float   interpolationFraction; //!< interpolation position between currentFrame and nextFrame [0,1]
+  };
 
 
+  //! class to store the md2 data in
+  class MD3Data : public BaseObject
+  {
+    public:
+      MD3Data(const std::string& modelFileName, const std::string& skinFileName, float scale = 1.0f);
+      virtual ~MD3Data();
 
-//! class to store the md2 data in
-class MD3Data : public BaseObject
-{
- public:
-   MD3Data(const std::string& modelFileName, const std::string& skinFileName, float scale = 1.0f);
-  virtual ~MD3Data();
+      void addLinkedModel(int tagIndex, MD3Data* child);
+      int getTagIndexByName(std::string name);
+
+    private:
+      bool loadModel(const std::string& fileName);
+      bool loadSkin(const std::string& fileName = "");
+
+      void init();
+
+      int readHeader(FILE* pFile, int fileOffset);
+      int readBoneFrames(FILE* pFile, int fileOffset);
+      int readTags(FILE* pFile, int fileOffset);
+      int readMeshes(FILE* pFile, int fileOffset);
 
 
- private:
-   bool loadModel(const std::string& fileName);
-   bool loadSkin(const std::string& fileName = "");
-
-   int readHeader(FILE* pFile, int fileOffset);
-   int readBoneFrames(FILE* pFile, int fileOffset);
-   int readTags(FILE* pFile, int fileOffset);
-   int readMeshes(FILE* pFile, int fileOffset);
+      int readMeshTriangles(FILE* pFile, int fileOffset, int mesh);
+      int readMeshTextures(FILE* pFile, int fileOffset, int mesh);
+      int readMeshTexVecs(FILE* pFile, int fileOffset, int mesh);
+      int readMeshVertices(FILE* pFile, int fileOffset, int mesh);
 
 
-   int readMeshTriangles(FILE* pFile, int fileOffset, int mesh);
-   int readMeshTextures(FILE* pFile, int fileOffset, int mesh);
-   int readMeshTexVecs(FILE* pFile, int fileOffset, int mesh);
-   int readMeshVertices(FILE* pFile, int fileOffset, int mesh);
+    public:
 
- public:
+      MD3Header*                header;            //!< the header file
 
-  MD3Header*          header;            //!< the header file
+      std::map<int, MD3Data*>   sortedMap;         //!< map
+      int                       parentTagIndex;    //!< the tag index of the parent model
+      MD3Data*                  parent;            //!< the parent model
 
-  std::string         filename;          //!< the name of the file as recorded in the .md3 file
-  std::string         loadFilename;      //!< filename of the actual file from which data was loaded
+      std::string               filename;          //!< the name of the file as recorded in the .md3 file
 
-  int                 boneFrameNum;      //!< number of anumation key fames in the models
-  int                 tagNum;            //!< number of tags
-  int                 meshNum;           //!< number of meshes
+      MD3AnimationState         animationState;    //!< the animation state of this model
 
-  int                 maxTextureNum;     //!< maximum number of unique used in an md3 file
-  int                 boneFrameStart;    //!< starting position of bone frame data structures
-  int                 tagStart;          //!< starting position of tag-structures
+      MD3BoneFrame**            boneFrames;        //!< array of bone frames, contains the metadata (bounding box, tags,...) for each frame
+      MD3Mesh**                 meshes;            //!< array of meshes in the model. each containing the mesh for each of the animation
 
-  int                 meshStart;         //!< starting position of mesh structures
-
-  int                 fileSize;          //!< file size
+      MD3BoneFrame*             tmpBoneFrame;      //!< a temporary bone frame
+      sVec3D**                  tmpMesh;           //!< a temporary mesh frame
+      MD3Normal**               tmpNormal;         //!< a temporary normals frame
+      float**                   tmpMatrix;         //!< a temporary matrix
 
 
-  MD3BoneFrame**      boneFrames;        //!< array of bone frames, contains the metadata (bounding box, tags,...) for each frame
-  MD3Mesh**           meshes;            //!< array of meshes in the model. each containing the mesh for each of the animation
-
-  int                 parentTagIndex;    //!< tag index
-
-  //MD3Model*           parent;            //!< reference to the MD3Model
-
-
-};
+     /* the animation part */
+     MD3Animation*              animation;         //!< animation
+     int                        op;                //!< the current operation
+     int                        upperBound;        //!< the upper bound
+     bool                       bInterpolate;      //!< interpolate the frames
+  };
 
 
Index: trunk/src/lib/graphics/importer/md3/md3_mesh.h
===================================================================
--- trunk/src/lib/graphics/importer/md3/md3_mesh.h	(revision 8719)
+++ trunk/src/lib/graphics/importer/md3/md3_mesh.h	(revision 8724)
@@ -77,6 +77,6 @@
     MD3Triangle*       triangles;               //!< indices into mesh frames and texture coord arrays
     MD3TexVecs*        texVecs;                 //!< tex vecs coordinates
-    sVec3D*            meshFrames;              //!< mesh frames
-    MD3Normal*         normals;                 //!< 3d array of normals with spherical coordinates giving the dir of the vertex normal
+    sVec3D**           meshFrames;              //!< mesh frames
+    MD3Normal**        normals;                 //!< 3d array of normals with spherical coordinates giving the dir of the vertex normal
 
 };
Index: trunk/src/lib/graphics/importer/md3/md3_model.cc
===================================================================
--- trunk/src/lib/graphics/importer/md3/md3_model.cc	(revision 8719)
+++ trunk/src/lib/graphics/importer/md3/md3_model.cc	(revision 8724)
@@ -18,5 +18,17 @@
 
 #include "md3_data.h"
-
+#include "md3_mesh.h"
+#include "md3_tag.h"
+#include "md3_bone_frame.h"
+#include "md3_animation.h"
+
+#include "md3_animation_cfg.h"
+
+#include "material.h"
+#include "quaternion.h"
+
+#include "loading/resource_manager.h"
+
+#include "debug.h"
 
 namespace md3
@@ -28,5 +40,13 @@
   MD3Model::MD3Model(std::string filename, float scaling)
   {
-    this->md3Data = new MD3Data(filename, filename, scaling);
+    this->autoAssemblePlayerModel(filename, scaling);
+
+    this->bDrawBones = false;
+    this->bDrawNormals = false;
+
+    this->time = 0.0f;
+
+    // set the animation
+    this->interpolate(this->md3Data, this->config->getAnimation("Dead 1"), MD3_ANIM_NEXT, true);
   }
 
@@ -34,6 +54,664 @@
 
   MD3Model::~MD3Model()
+  {
+//     delete this->tmpBoneFrame;
+//     delete [] this->tmpMesh;
+
+    ///TODO deleting mesh
+    ///TODO deleting matrices
+  }
+
+
+  /**
+   * auto assemples a player model
+   * @param filename is the name to the directory of the modelzzzzzz
+   */
+  void MD3Model::autoAssemblePlayerModel(std::string filename, float scaling)
+  {
+    // loading the config file
+    std::string cfgName(filename + "/animation.cfg");
+    this->config = (MD3AnimationCfg*)ResourceManager::getInstance()->load(cfgName, MD3_CONFIG, RP_GAME);
+
+    //first load the torso or the upper part
+    std::string nameUpper(filename + "/upper.md3");
+    if( (this->md3Data = (MD3Data*)ResourceManager::getInstance()->load(nameUpper, MD3, RP_GAME, nameUpper, scaling)) == NULL)
+    {
+      std::string nameTorso(filename + "/torso.md3");
+      this->md3Data = (MD3Data*)ResourceManager::getInstance()->load(nameTorso, MD3, RP_GAME, nameTorso, scaling);
+    }
+
+    if( this->md3Data == NULL)
+    {
+      PRINTF(1)("Problems loading the MD3Model. Abording\n");
+      return;
+    }
+
+    // load lower
+    std::string nameLower(filename + "/lower.md3");
+    MD3Data* lower = (MD3Data*)ResourceManager::getInstance()->load(nameLower, MD3, RP_GAME, nameLower, scaling);
+    if( lower != NULL)
+    {
+      int tag = this->md3Data->getTagIndexByName("tag_lower");
+      PRINTF(0)("Loaded the %s model on index %i\n", nameLower.c_str(), tag);
+      if( tag >= 0)
+       this->md3Data->addLinkedModel(tag, lower);
+      else
+        PRINTF(0)("Could not add %s\n", nameLower.c_str());
+
+    }
+
+
+    // load head
+    std::string nameHead(filename + "/head.md3");
+    MD3Data* head = (MD3Data*)ResourceManager::getInstance()->load(nameHead, MD3, RP_GAME, nameLower, scaling);
+    if( head != NULL)
+    {
+      int tag = this->md3Data->getTagIndexByName("tag_head");
+      PRINTF(0)("Loaded the %s model on index %i\n", nameHead.c_str(), tag);
+      if( tag >= 0)
+        this->md3Data->addLinkedModel(tag, head);
+      else
+        PRINTF(0)("Could not add %s\n", nameHead.c_str());
+    }
+
+  }
+
+
+
+  /**
+   * tick float
+   * @param time: time elapsed
+   */
+  void MD3Model::tick(float time)
+  {
+    if(this->md3Data == NULL)
+      return;
+
+    this->visit(this->md3Data, time);
+
+    this->tick(time, this->md3Data);
+  }
+
+
+  /**
+   * tick each data
+   */
+  void MD3Model::tick(float time, MD3Data* data)
+  {
+    // draw the bones if needed#
+    if( this->bDrawBones)
+    {
+      // get bone frame, interpolate if necessary
+      if( data->animationState.interpolationFraction != 0.0 &&
+          data->animationState.currentFrame != data->animationState.nextFrame)
+      {
+        //interpolate bone frame
+        data->tmpBoneFrame = this->interpolateBoneFrame(data, data->boneFrames[data->animationState.currentFrame],
+                                                        data->boneFrames[data->animationState.nextFrame],
+                                                        data->animationState.interpolationFraction);
+      }
+      else
+      {
+        data->tmpBoneFrame = data->boneFrames[data->animationState.currentFrame];
+      }
+    }
+
+
+    //draw all meshes of current frame of this model
+    for( int i = 0;  i < data->header->meshNum; i++)
+    {
+      MD3Mesh* mesh = data->meshes[i];
+
+      //interpolate mesh frame between the 2 current mesh frames
+      if( data->header->boneFrameNum > 1)
+        this->interpolateMeshFrame( data,
+                                    mesh->meshFrames[data->animationState.currentFrame],
+                                    mesh->meshFrames[data->animationState.nextFrame],
+                                    data->animationState.interpolationFraction, mesh, i);
+      else
+        this->interpolateMeshFrame( data,
+                                    mesh->meshFrames[data->animationState.currentFrame],
+                                    mesh->meshFrames[data->animationState.currentFrame],
+                                    0.0f, mesh, i);
+
+      // draw vertex normals if needed
+      if( this->bDrawNormals)
+      {
+        // get vertex normals, interpolate if necessary
+        if( data->animationState.interpolationFraction != 0.0 &&
+            data->animationState.currentFrame != data->animationState.nextFrame)
+        {
+          //interpolate vertex normals
+          this->interpolateVertexNormals(data,
+                                         mesh->normals[data->animationState.currentFrame],
+                                         mesh->normals[data->animationState.nextFrame],
+                                         data->animationState.interpolationFraction, mesh, i);
+        }
+      }
+    }
+
+
+    // draw all models linked to this model
+    std::map<int, MD3Data*>::iterator it = data->sortedMap.begin();
+    int i = 0;
+    while( it != data->sortedMap.end())
+    {
+      MD3Data* child = it->second;
+
+      //build transformation array m from matrix, interpolate if necessary
+
+      MD3Tag* currFrameTag = data->boneFrames[data->animationState.currentFrame]->tags[child->parentTagIndex];
+
+      if( data->animationState.interpolationFraction != 0.0 &&
+          data->animationState.currentFrame != data->animationState.nextFrame)
+      {
+        //we need to interpolate
+        MD3Tag* nextFrameTag = data->boneFrames[data->animationState.nextFrame]->tags[child->parentTagIndex];
+        this->interpolateTransformation(child, currFrameTag, nextFrameTag, data->animationState.interpolationFraction, i);
+      }
+      else
+      {
+        //no interpolation needed, stay with last transformation
+        //OpenGL matrix is in column-major order
+        data->tmpMatrix[i][0] = currFrameTag->matrix[0][0];
+        data->tmpMatrix[i][1] = currFrameTag->matrix[1][0];
+        data->tmpMatrix[i][2] = currFrameTag->matrix[2][0];
+        data->tmpMatrix[i][3] = 0.0f;
+        data->tmpMatrix[i][4] = currFrameTag->matrix[0][1];
+        data->tmpMatrix[i][5] = currFrameTag->matrix[1][1];
+        data->tmpMatrix[i][6] = currFrameTag->matrix[2][1];
+        data->tmpMatrix[i][7] = 0.0f;
+        data->tmpMatrix[i][8] = currFrameTag->matrix[0][2];
+        data->tmpMatrix[i][9] = currFrameTag->matrix[1][2];
+        data->tmpMatrix[i][10]= currFrameTag->matrix[2][2];
+        data->tmpMatrix[i][11]= 0.0f;
+        data->tmpMatrix[i][12] = currFrameTag->position.x;
+        data->tmpMatrix[i][13] = currFrameTag->position.y;
+        data->tmpMatrix[i][14] = currFrameTag->position.z;
+        data->tmpMatrix[i][15] = 1.0f;
+      }
+
+      // switch to child coord system
+
+      // and tick child
+      this->tick(time, child);
+
+      i++;
+      it++;
+    }
+  }
+
+
+  /**
+   * this draws the md3 model
+   */
+  void MD3Model::draw() const
+  {
+    //draw current bone frame
+    this->draw(this->md3Data);
+  }
+
+
+  /**
+   * draw the md3model
+   * @param data: the data to be drawn
+   */
+  void MD3Model::draw(MD3Data* data) const
+  {
+
+    // draw the bones if needed
+    if( this->bDrawBones)
+    {
+      // get bone frame, interpolate if necessary
+      if( data->animationState.interpolationFraction != 0.0 &&
+          data->animationState.currentFrame != data->animationState.nextFrame) {
+        //interpolate bone frame
+        this->drawBoneFrame(data->tmpBoneFrame);
+      }
+      else {
+        //stick with current bone frame
+        this->drawBoneFrame(data->boneFrames[data->animationState.currentFrame]);
+      }
+    }
+
+
+    //draw all meshes of current frame of this model
+    for( int i = 0;  i < data->header->meshNum; i++)
+    {
+      MD3Mesh* mesh = data->meshes[i];
+      sVec3D* frame = data->tmpMesh[i];
+
+      if( mesh->header->textureNum > 0 && &mesh->material[0] != NULL)
+        mesh->material[0].select();
+
+      this->drawMesh(mesh, frame);
+
+      // draw vertex normals if needed
+      if( this->bDrawNormals)
+      {
+        // get vertex normals, interpolate if necessary
+        if( data->animationState.interpolationFraction != 0.0 &&
+            data->animationState.currentFrame != data->animationState.nextFrame)
+        {
+          //interpolate vertex normals
+          this->drawVertexNormals(frame, data->tmpNormal[i]);
+        }
+        else {
+          //stick with current vertex normals
+          this->drawVertexNormals(frame, mesh->normals[data->animationState.currentFrame]);
+        }
+      }
+    }
+
+
+    // draw all models linked to this model
+    int i = 0;
+    std::map<int, MD3Data*>::iterator it = data->sortedMap.begin();
+    while( it != data->sortedMap.end())
+    {
+      MD3Data* child = it->second;
+
+      //switch to child coord system
+      glPushMatrix();
+      glMultMatrixf(data->tmpMatrix[i]);
+
+      // and draw child
+      this->draw(child);
+
+      glPopMatrix();
+
+      i++;
+      it++;
+    }
+
+  }
+
+
+  /**
+   * draws the mesh
+   */
+  void MD3Model::drawMesh(MD3Mesh* mesh, sVec3D* frame) const
+  {
+    Vector tmpVec1, tmpVec2;
+
+    glColor3f(1.0f, 1.0f, 1.0f);
+    glBegin( GL_TRIANGLES);
+
+    // upload all triangles in the frame to OpenGL
+    for( int t = 0; t < mesh->header->triangleNum; t++)
+    {
+      // calc normal vector
+      tmpVec1.x = frame[mesh->triangles[t].vertexOffset[1]][0] - frame[mesh->triangles[t].vertexOffset[0]][0];
+      tmpVec1.y = frame[mesh->triangles[t].vertexOffset[1]][1] - frame[mesh->triangles[t].vertexOffset[0]][1];
+      tmpVec1.z = frame[mesh->triangles[t].vertexOffset[1]][2] - frame[mesh->triangles[t].vertexOffset[0]][2];
+
+      tmpVec2.x = frame[mesh->triangles[t].vertexOffset[2]][0] - frame[mesh->triangles[t].vertexOffset[0]][0];
+      tmpVec2.y = frame[mesh->triangles[t].vertexOffset[2]][1] - frame[mesh->triangles[t].vertexOffset[0]][1];
+      tmpVec2.z = frame[mesh->triangles[t].vertexOffset[2]][2] - frame[mesh->triangles[t].vertexOffset[0]][2];
+
+      Vector normal = tmpVec1.cross(tmpVec2);
+      normal.normalize();
+
+//       PRINTF(0)("normal: %f, %f, %f\n", normal.x, normal.y, normal.z);
+
+      glNormal3f(normal.x, normal.y, normal.z);
+      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[0]].textureCoord);
+      glVertex3f( frame[mesh->triangles[t].vertexOffset[0]][0],
+                  frame[mesh->triangles[t].vertexOffset[0]][2],
+                  frame[mesh->triangles[t].vertexOffset[0]][1]);
+
+      glNormal3f(normal.x, normal.y, normal.z);
+      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[1]].textureCoord);
+      glVertex3f( frame[mesh->triangles[t].vertexOffset[1]][0],
+                  frame[mesh->triangles[t].vertexOffset[1]][2],
+                  frame[mesh->triangles[t].vertexOffset[1]][1]);
+
+      glNormal3f(normal.x, normal.y, normal.z);
+      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[2]].textureCoord);
+      glVertex3f( frame[mesh->triangles[t].vertexOffset[2]][0],
+                  frame[mesh->triangles[t].vertexOffset[2]][2],
+                  frame[mesh->triangles[t].vertexOffset[2]][1]);
+    }
+    glEnd();
+  }
+
+
+  /**
+   *  drawo vertex normals
+   */
+  void MD3Model::drawVertexNormals(sVec3D* frame, MD3Normal* normals) const
   {}
 
 
+  /**
+   * draw bone frame
+   */
+  void MD3Model::drawBoneFrame(MD3BoneFrame* frame) const
+  {
+    float x1 = frame->mins.x;
+    float y1 = frame->mins.y;
+    float z1 = frame->mins.z;
+    float x2 = frame->maxs.x;
+    float y2 = frame->maxs.y;
+    float z2 = frame->maxs.z;
+
+    glPushAttrib(GL_TEXTURE_2D);
+    glPushAttrib(GL_LIGHTING);
+
+    glColor3f(1.0f,0.0f,0.0f);
+    glPointSize(6.0f);
+
+    glBegin(GL_POINTS);
+    glVertex3f(frame->position.x, frame->position.y, frame->position.z);
+    glEnd();
+    glPointSize(1.0f);
+
+    glColor3f(0.0f,1.0f,0.0f);
+    glBegin(GL_LINE_LOOP);
+    glVertex3f(x1,y1,z1);
+    glVertex3f(x1,y1,z2);
+    glVertex3f(x1,y2,z2);
+    glVertex3f(x1,y2,z1);
+    glEnd();
+
+    glBegin(GL_LINE_LOOP);
+    glVertex3f(x2,y2,z2);
+    glVertex3f(x2,y1,z2);
+    glVertex3f(x2,y1,z1);
+    glVertex3f(x2,y2,z1);
+    glEnd();
+
+    glBegin(GL_LINES);
+    glVertex3f(x1,y1,z1);
+    glVertex3f(x2,y1,z1);
+
+    glVertex3f(x1,y1,z2);
+    glVertex3f(x2,y1,z2);
+
+    glVertex3f(x1,y2,z2);
+    glVertex3f(x2,y2,z2);
+
+    glVertex3f(x1,y2,z1);
+    glVertex3f(x2,y2,z1);
+    glEnd();
+
+     glPopAttrib();
+     glPopAttrib();
+  }
+
+
+  /**
+   *  interpolate bone frame
+   * @param currBoneFrame Start bone frame.
+   * @param nextBoneFrame End bone frame.
+   * @param frac Interpolation fraction, in [0,1].
+   */
+  MD3BoneFrame* MD3Model::interpolateBoneFrame(MD3Data* data, MD3BoneFrame* currBoneFrame, MD3BoneFrame* nextBoneFrame, float frac)
+  {
+    data->tmpBoneFrame->mins.x      = (1.0f - frac) * currBoneFrame->mins.x       + frac * nextBoneFrame->mins.x;
+    data->tmpBoneFrame->maxs.x      = (1.0f - frac) * currBoneFrame->maxs.x       + frac * nextBoneFrame->maxs.x;
+    data->tmpBoneFrame->position.x  = (1.0f - frac) * currBoneFrame->position.x   + frac * nextBoneFrame->position.x;
+    data->tmpBoneFrame->mins.y      = (1.0f - frac) * currBoneFrame->mins.y       + frac * nextBoneFrame->mins.y;
+    data->tmpBoneFrame->maxs.y      = (1.0f - frac) * currBoneFrame->maxs.y       + frac * nextBoneFrame->maxs.y;
+    data->tmpBoneFrame->position.y  = (1.0f - frac) * currBoneFrame->position.y   + frac * nextBoneFrame->position.y;
+    data->tmpBoneFrame->mins.z      = (1.0f - frac) * currBoneFrame->mins.z       + frac * nextBoneFrame->mins.z;
+    data->tmpBoneFrame->maxs.z      = (1.0f - frac) * currBoneFrame->maxs.z       + frac * nextBoneFrame->maxs.z;
+    data->tmpBoneFrame->position.z  = (1.0f - frac) * currBoneFrame->position.z   + frac * nextBoneFrame->position.z;
+
+    return data->tmpBoneFrame;
+  }
+
+
+
+  /**
+   * interpolate mesh frame
+   */
+  sVec3D* MD3Model::interpolateMeshFrame(MD3Data* data, sVec3D* currMeshFrame, sVec3D* nextMeshFrame, float frac, MD3Mesh* mesh, int i)
+  {
+    int vertexNum = mesh->header->vertexNum;
+
+    if( /*frac == 0.0f*/ true)
+    {
+      // just copy the vertices
+      for( int t = 0; t < vertexNum; t++)
+      {
+        data->tmpMesh[i][t][0]  = currMeshFrame[t][0];
+        data->tmpMesh[i][t][1]  = currMeshFrame[t][1];
+        data->tmpMesh[i][t][2]  = currMeshFrame[t][2];
+      }
+    }
+    else
+    {
+      // calc interpolated vertices
+      for( int t = 0; t < vertexNum; t++)
+      {
+        data->tmpMesh[i][t][0]  = (1.0f - frac)   * currMeshFrame[t][0]  + frac * nextMeshFrame[t][0];
+        data->tmpMesh[i][t][1]  = (1.0f - frac)   * currMeshFrame[t][1]  + frac * nextMeshFrame[t][1];
+        data->tmpMesh[i][t][2]  = (1.0f - frac)   * currMeshFrame[t][2]  + frac * nextMeshFrame[t][2];
+      }
+    }
+
+    return data->tmpMesh[i];
+  }
+
+
+  /**
+   * interpolate vertex normal
+   */
+  MD3Normal* MD3Model::interpolateVertexNormals(MD3Data* data, MD3Normal* currNormals, MD3Normal* nextNormals, float frac, MD3Mesh* mesh, int i)
+  {
+    for( int j = 0; j < mesh->header->vertexNum; j++)
+    {
+      data->tmpNormal[i][j].vertexNormal[0] = (int)((1.0f - frac) * currNormals[j].vertexNormal[0] + frac * nextNormals[j].vertexNormal[0]);
+      data->tmpNormal[i][j].vertexNormal[1] = (int)((1.0f - frac) * currNormals[j].vertexNormal[1] + frac * nextNormals[j].vertexNormal[1]);
+    }
+
+    return data->tmpNormal[i];
+  }
+
+
+  /**
+   * interpolate transformation
+   */
+  float* MD3Model::interpolateTransformation(MD3Data* data, MD3Tag* currFrameTag, MD3Tag* nextFrameTag, float frac, int i)
+  {
+    // interpolate position
+    Vector interpolatedPosition = currFrameTag->position * (1.0f - frac) + nextFrameTag->position * frac;
+
+
+    // interpolate rotation matrix
+    float  currRot[4][4];
+    float  nextRot[4][4];
+    float  interpolatedMatrix[4][4];
+
+    Quaternion currQuat(currFrameTag->matrix); currQuat.matrix(currRot);
+    Quaternion nextQuat(nextFrameTag->matrix); nextQuat.matrix(nextRot);
+
+    Quaternion interpolatedQuat = Quaternion::quatSlerp(currQuat, nextQuat, frac); interpolatedQuat.matrix(interpolatedMatrix);
+
+    // quaternion code is column based, so use transposed matrix when spitting out to gl
+    data->tmpMatrix[i][0] = interpolatedMatrix[0][0];
+    data->tmpMatrix[i][4] = interpolatedMatrix[1][0];
+    data->tmpMatrix[i][8] = interpolatedMatrix[2][0];
+    data->tmpMatrix[i][12] = interpolatedPosition.x;
+    data->tmpMatrix[i][1] = interpolatedMatrix[0][1];
+    data->tmpMatrix[i][5] = interpolatedMatrix[1][1];
+    data->tmpMatrix[i][9] = interpolatedMatrix[2][1];
+    data->tmpMatrix[i][13] = interpolatedPosition.y;
+    data->tmpMatrix[i][2] = interpolatedMatrix[0][2];
+    data->tmpMatrix[i][6] = interpolatedMatrix[1][2];
+    data->tmpMatrix[i][10]= interpolatedMatrix[2][2];
+    data->tmpMatrix[i][14] = interpolatedPosition.z;
+    data->tmpMatrix[i][3] = 0.0f;
+    data->tmpMatrix[i][7] = 0.0f;
+    data->tmpMatrix[i][11]= 0.0f;
+    data->tmpMatrix[i][15] = 1.0f;
+
+    return data->tmpMatrix[i];
+
+  }
+
+
+
+  /**
+   * visit the model
+   */
+  void MD3Model::visit(MD3Data* data, float time)
+  {
+    if ( (data->filename.find("lower") == std::string::npos &&
+          (data->animation->type == LEGS || data->animation->type == BOTH)) // this is the LEGS model and the animation is applicable
+          ||
+          (data->filename.find("upper") == std::string::npos &&
+          (data->animation->type == TORSO || data->animation->type == BOTH)) // this is the TORSO model and the animation is applicable
+          ||
+          data->animation->type == ALL // the animation is allways applicable
+       )
+      this->doOp(data, time);
+
+    // visit children
+//     std::map<int, MD3Data*>::iterator it = data->sortedMap.begin();
+//     while( it != data->sortedMap.end())
+//     {
+//       this->visit(it->second);
+//       it++;
+//     }
+  }
+
+
+  /**
+   * Create a new visitor to apply an animation operation (NEXT, REWIND, ...)
+   * to a MD3 model. The operation is executed in the context of the specified
+   * animation.
+   *
+   * @param anim The animation that provides the context for the operation.
+   * @param op The operation to apply.
+   * @param interpolate Should interpolation be done?
+   */
+  void MD3Model::interpolate(MD3Data* data, MD3Animation* anim, int op, bool bInterpolate)
+  {
+     data->animation = anim;
+     if( op == MD3_ANIM_NEXT || op == MD3_ANIM_PREVIOUS || op == MD3_ANIM_REWIND)
+      data->op = op;
+
+     data->bInterpolate = bInterpolate;
+  }
+
+
+  /**
+   * calc next frame number
+   */
+  int MD3Model::next(MD3Data* data, int nr)
+  {
+    if( nr < (data->upperBound - 1))
+      return nr + 1;
+    else
+    { //rewind needed
+      if( data->animation->numFrames < 0)
+        return data->animation->first;
+      else {
+        nr = (data->animation->numLoopFrames != 0)?(data->animation->numFrames - data->animation->numLoopFrames):0;
+        return data->animation->first + nr;
+      }
+    }
+  }
+
+
+  /**
+   * calc prev frame number
+   */
+  int MD3Model::prev(MD3Data* data, int nr)
+  {
+    if( nr == data->animation->first)
+      return data->upperBound - 1;
+    else
+      return nr - 1;
+  }
+
+
+  /**
+   * apply the specified operation to the animation state data members of the model
+   * taking the specified animation into account
+   *
+   * @param data: the data of the model
+   */
+  void MD3Model::doOp(MD3Data* data, float time)
+  {
+    // animation to be applied could have illegal data with respect to this model,
+    // ignore anim in this case
+
+    if( data->animation->first >= data->animation->numFrames || data->animation->first < 0)
+    {
+      PRINTF(0)("MD3: this animation type seems to be invalid, no animation calculated\n");
+      return;
+    }
+
+
+    //calc upper bound for animation frames in this model
+    if( data->animation->numFrames < 0)
+      data->upperBound = data->header->boneFrameNum; //use all available frames
+    else
+    {
+      if( data->header->boneFrameNum < (data->animation->first + data->animation->numFrames))
+        data->upperBound = data->header->boneFrameNum;
+      else
+        data->upperBound = (data->animation->first + data->animation->numFrames);
+    }
+
+
+    switch( data->op) {
+
+      case MD3_ANIM_NEXT:
+        if( data->bInterpolate)
+        {
+          // keyframe interpolation animation
+          data->animationState.interpolationFraction += time * data->animation->fps;
+
+          if( data->animationState.interpolationFraction >= 1.0f)
+          {
+            data->animationState.currentFrame = data->animationState.nextFrame;
+            data->animationState.nextFrame = next(data, data->animationState.nextFrame);
+            data->animationState.interpolationFraction = 0.0f;
+          }
+        }
+        else
+        {
+          // only keyframe animation
+          this->time += time * data->animation->fps;
+          if( this->time > 1.0f)
+          {
+            data->animationState.currentFrame = data->animationState.nextFrame;
+            data->animationState.nextFrame = next(data, data->animationState.nextFrame);
+            this->time = 0.0f;
+          }
+        }
+        break;
+
+      case MD3_ANIM_PREVIOUS:
+        if( data->bInterpolate)
+        {
+          data->animationState.interpolationFraction -= time / data->animation->fps;
+          if( data->animationState.interpolationFraction < 0.0f)
+          {
+            data->animationState.nextFrame = data->animationState.currentFrame;
+            data->animationState.currentFrame = prev(data, data->animationState.currentFrame);
+            data->animationState.interpolationFraction = 0.8f;
+          }
+        }
+        else
+        {
+          data->animationState.nextFrame = data->animationState.currentFrame;
+          data->animationState.currentFrame = prev(data, data->animationState.currentFrame);
+        }
+        break;
+
+      case MD3_ANIM_REWIND:
+        data->animationState.currentFrame = data->animation->first;
+        data->animationState.nextFrame = next(data, data->animationState.currentFrame);
+        data->animationState.interpolationFraction = 0.0f;
+        break;
+    }
+
+  }
+
+
 }
Index: trunk/src/lib/graphics/importer/md3/md3_model.h
===================================================================
--- trunk/src/lib/graphics/importer/md3/md3_model.h	(revision 8719)
+++ trunk/src/lib/graphics/importer/md3/md3_model.h	(revision 8724)
@@ -13,4 +13,7 @@
 
 
+#define FRACTION 0.34f
+
+
 namespace md3
 {
@@ -18,4 +21,19 @@
 
 class MD3Data;
+class MD3BoneFrame;
+class MD3Mesh;
+class MD3Tag;
+class MD3AnimationCfg;
+class MD3Animation;
+
+struct MD3Normal;
+
+
+typedef enum MD3FrameHandling {
+  MD3_ANIM_NEXT = 0,          //!< swith to the next frame
+  MD3_ANIM_PREVIOUS,          //!< swith to the previous frame
+  MD3_ANIM_REWIND             //!< rewind the animation
+};
+
 
 class MD3Model : public InteractiveModel
@@ -26,10 +44,50 @@
     ~MD3Model();
 
-    virtual void tick(float dt) {}
     virtual void setAnimation(int animNum, int playbackMode = 0) {}
+    virtual int getAnimation() { return 0;}
+
+    virtual void tick(float dt);
+    virtual void draw() const;
+
+
+  private:
+
+    void autoAssemblePlayerModel(std::string filename, float scaling);
+
+    void draw(MD3Data* data) const;
+    void tick(float dt, MD3Data* data);
+
+
+    void drawMesh(MD3Mesh* mesh, sVec3D* frame) const;
+    void drawVertexNormals(sVec3D* frame, MD3Normal* normals) const;
+    void drawBoneFrame(MD3BoneFrame* frame) const;
+
+
+    MD3BoneFrame* interpolateBoneFrame(MD3Data* data, MD3BoneFrame* currBoneFrame, MD3BoneFrame* nextBoneFrame, float frac);
+    sVec3D* interpolateMeshFrame(MD3Data* data, sVec3D* currMeshFrame, sVec3D* nextMeshFrame, float frac, MD3Mesh* mesh, int i);
+    MD3Normal* interpolateVertexNormals(MD3Data* data, MD3Normal* curNormals, MD3Normal* nextNormals, float frac, MD3Mesh* mesh, int i);
+    float* interpolateTransformation(MD3Data* data, MD3Tag* currFrameTag, MD3Tag* nextFrameTag, float frac, int i);
+
+
+    void interpolate(MD3Data* data, MD3Animation* anim, int op, bool bInterpolate);
+
+    void visit(MD3Data* data, float time);
+    int next(MD3Data* data, int nr);
+    int prev(MD3Data* data, int nr);
+    void doOp(MD3Data* data, float time);
+
 
   private:
     MD3Data*            md3Data;           //!< reference to the md3 model data
+
+    bool                bDrawBones;        //!< draws the bone frames too
+    bool                bDrawNormals;      //!< draw the normals
+
+    MD3AnimationCfg*    config;            //!< the config file parsed
+
+    float               time;
+
 };
+
 
 }
Index: trunk/src/lib/math/quaternion.cc
===================================================================
--- trunk/src/lib/math/quaternion.cc	(revision 8719)
+++ trunk/src/lib/math/quaternion.cc	(revision 8724)
@@ -133,4 +133,5 @@
 
 
+
 /**
  * @brief Slerps this QUaternion performs a smooth move.
@@ -298,4 +299,53 @@
 }
 
+
+/**
+ * Creates a quaternion from a 3x3 rotation matrix.
+ * @param mat The 3x3 source rotation matrix.
+ * @return The equivalent 4 float quaternion.
+ */
+Quaternion::Quaternion(float mat[3][3])
+{
+  int   NXT[] = {1, 2, 0};
+  float q[4];
+
+  // check the diagonal
+  float tr = mat[0][0] + mat[1][1] + mat[2][2];
+  if( tr > 0.0f) {
+    float s = (float)sqrtf(tr + 1.0f);
+    this->w = s * 0.5f;
+    s = 0.5f / s;
+    this->v.x = (mat[1][2] - mat[2][1]) * s;
+    this->v.y = (mat[2][0] - mat[0][2]) * s;
+    this->v.z = (mat[0][1] - mat[1][0]) * s;
+  }
+  else
+  {
+    // diagonal is negative
+    // get biggest diagonal element
+    int i = 0;
+    if (mat[1][1] > mat[0][0]) i = 1;
+    if (mat[2][2] > mat[i][i]) i = 2;
+    //setup index sequence
+    int j = NXT[i];
+    int k = NXT[j];
+
+    float s = (float)sqrtf((mat[i][i] - (mat[j][j] + mat[k][k])) + 1.0f);
+
+    q[i] = s * 0.5f;
+
+    if (s != 0.0f) s = 0.5f / s;
+
+    q[j] = (mat[i][j] + mat[j][i]) * s;
+    q[k] = (mat[i][k] + mat[k][i]) * s;
+    q[3] = (mat[j][k] - mat[k][j]) * s;
+
+    this->v.x = q[0];
+    this->v.y = q[1];
+    this->v.z = q[2];
+    this->w   = q[3];
+  }
+}
+
 /**
  * @brief outputs some nice formated debug information about this quaternion
@@ -314,2 +364,8 @@
   PRINT(0)("angle = %f, axis: ax=%f, ay=%f, az=%f\n", this->getSpacialAxisAngle(), axis.x, axis.y, axis.z );
 }
+
+
+
+
+
+
Index: trunk/src/lib/math/quaternion.h
===================================================================
--- trunk/src/lib/math/quaternion.h	(revision 8719)
+++ trunk/src/lib/math/quaternion.h	(revision 8724)
@@ -42,4 +42,5 @@
   inline Quaternion (const Vector& v, float f) { this->w = f; this->v = v; }
   Quaternion (float m[4][4]);
+  Quaternion (float m[3][3]);
   /** turns a rotation along an axis into a Quaternion @param angle: the amount of radians to rotate @param axis: the axis to rotate around */
   inline Quaternion (float angle, const Vector& axis) { w = cos(angle/2.0); v = axis * sin(angle/2.0); }
@@ -118,4 +119,5 @@
 
 
+
 #endif /* __QUATERNION_H_ */
 
Index: trunk/src/lib/util/Makefile.am
===================================================================
--- trunk/src/lib/util/Makefile.am	(revision 8719)
+++ trunk/src/lib/util/Makefile.am	(revision 8724)
@@ -6,4 +6,5 @@
 libORXlibutil_a_SOURCES = \
 		substring.cc \
+		tokenizer.cc \
 		color.cc \
 		helper_functions.cc \
@@ -28,6 +29,8 @@
 		timer.cc
 
+
 noinst_HEADERS = \
 		substring.h \
+		tokenizer.h \
 		multi_type.h \
 		color.h \
Index: trunk/src/lib/util/loading/resource_manager.cc
===================================================================
--- trunk/src/lib/util/loading/resource_manager.cc	(revision 8719)
+++ trunk/src/lib/util/loading/resource_manager.cc	(revision 8724)
@@ -28,4 +28,6 @@
 #include "primitive_model.h"
 #include "md2/md2Model.h"
+#include "md3/md3_data.h"
+#include "md3/md3_animation_cfg.h"
 #endif /* NO_MODEL */
 #ifndef NO_TEXTURES
@@ -201,4 +203,8 @@
   else if (!strncmp(fileName.c_str()+(fileName.size()-4), ".md2", 4))
     tmpType = MD2;
+  else if (!strncmp(fileName.c_str()+(fileName.size()-4), ".md3", 4))
+    tmpType = MD3;
+  else if (!strncmp(fileName.c_str()+(fileName.size()-4), ".cfg", 4))
+    tmpType = MD3_CONFIG;
   else if (!strcasecmp(fileName.c_str(), "cube") ||
             !strcasecmp(fileName.c_str(), "sphere") ||
@@ -400,4 +406,20 @@
       }
       break;
+    case MD3:
+      if(File(fullName).isFile())
+      {
+        tmpResource->param[0] = param0;
+        tmpResource->param[1] = param1;
+        tmpResource->pointer = new md3::MD3Data(fullName, tmpResource->param[0].getCString(), tmpResource->param[1].getFloat());
+      }
+      break;
+    case MD3_CONFIG:
+      if(File(fullName).isFile())
+      {
+        tmpResource->param[0] = param0;
+        tmpResource->param[1] = param1;
+        tmpResource->pointer = new md3::MD3AnimationCfg(fullName);
+      }
+      break;
 #endif /* NO_MODEL */
 #ifndef NO_TEXT
@@ -624,4 +646,17 @@
             match = true;
           break;
+        case MD3:
+          if (param0 == MT_NULL && ((*resource)->param[0] == "") && param1 == MT_NULL && ((*resource)->param[0] == 1.0f))
+            match = true;
+          else if ((*resource)->param[0] == ((MultiType)param0).getString() && (*resource)->param[1] == ((MultiType)param1).getFloat())
+            match = true;
+          break;
+        case MD3_CONFIG:
+          if (param0 == MT_NULL && ((*resource)->param[0] == ""))
+            match = true;
+          else if ((*resource)->param[0] == ((MultiType)param0).getString())
+            match = true;
+          break;
+
 #endif /* NO_MODEL */
 #ifndef NO_TEXT
@@ -863,4 +898,6 @@
     "PrimitiveModel",
     "MD2-Data",
+    "MD3-Data",
+    "MD3-Config"
 #endif
 #ifndef NO_TEXT
Index: trunk/src/lib/util/loading/resource_manager.h
===================================================================
--- trunk/src/lib/util/loading/resource_manager.h	(revision 8719)
+++ trunk/src/lib/util/loading/resource_manager.h	(revision 8724)
@@ -33,4 +33,6 @@
   PRIM,                 //!< loading primitive model
   MD2,                  //!< loading md2-file
+  MD3,                  //!< loading md3-file
+  MD3_CONFIG,           //!< the md3 config file
 #endif /* NO_MODEL */
 #ifndef NO_TEXT
Index: trunk/src/lib/util/tokenizer.cc
===================================================================
--- trunk/src/lib/util/tokenizer.cc	(revision 8724)
+++ trunk/src/lib/util/tokenizer.cc	(revision 8724)
@@ -0,0 +1,29 @@
+/**
+ * @file tokenizer.cc
+ * @brief a tokenizer class
+ *
+ */
+
+#include "tokenizer.h"
+
+
+/**
+ * tokenize a string
+ */
+void Tokenizer::tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters)
+{
+    // Skip delimiters at beginning.
+  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
+    // Find first "non-delimiter".
+  std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
+
+  while (std::string::npos != pos || std::string::npos != lastPos)
+  {
+        // Found a token, add it to the vector.
+    tokens.push_back(str.substr(lastPos, pos - lastPos));
+        // Skip delimiters.  Note the "not_of"
+    lastPos = str.find_first_not_of(delimiters, pos);
+        // Find next "non-delimiter"
+    pos = str.find_first_of(delimiters, lastPos);
+  }
+}
Index: trunk/src/lib/util/tokenizer.h
===================================================================
--- trunk/src/lib/util/tokenizer.h	(revision 8724)
+++ trunk/src/lib/util/tokenizer.h	(revision 8724)
@@ -0,0 +1,26 @@
+
+/*!
+ * @file tokenzier.h
+ * @brief Definition of Tokenizer
+ *
+ */
+
+#ifndef _TOKENIZER_H
+#define _TOKENIZER_H
+
+
+#include <vector>
+#include <string>
+
+
+//! A class to handle time itself
+class Tokenizer
+{
+
+  public:
+    static void tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters = " ");
+
+
+};
+
+#endif /* _TOKENIZER_H */
Index: trunk/src/story_entities/game_world.cc
===================================================================
--- trunk/src/story_entities/game_world.cc	(revision 8719)
+++ trunk/src/story_entities/game_world.cc	(revision 8724)
@@ -305,4 +305,9 @@
     this->tick ();
 
+    
+    /* update the state */
+    this->update ();
+
+    
     /* collision detection */
     this->collisionDetection ();
@@ -310,9 +315,9 @@
     this->collisionReaction ();
 
+    /* check the game rules */
+    this->checkGameRules();
+    
     /* update the state */
     this->update ();
-
-    /* check the game rules */
-    this->checkGameRules();
     /* draw everything */
     this->display ();
Index: trunk/src/world_entities/WorldEntities.am
===================================================================
--- trunk/src/world_entities/WorldEntities.am	(revision 8719)
+++ trunk/src/world_entities/WorldEntities.am	(revision 8724)
@@ -4,4 +4,5 @@
                 world_entities/npcs/npc_test.cc \
                 world_entities/npcs/ground_turret.cc \
+                world_entities/npcs/generic_npc.cc \
                 \
                 world_entities/environment.cc \
@@ -41,4 +42,5 @@
                 world_entities/space_ships/collision_probe.cc \
                 world_entities/creatures/md2_creature.cc \
+                world_entities/creatures/fps_player.cc \
                 world_entities/spectator.cc \
                 \
@@ -97,4 +99,5 @@
                 space_ships/collision_probe.cc \
                 creatures/md2_creature.h \
+                creatures/fps_player.h \
                 spectator.h \
                 \
Index: trunk/src/world_entities/creatures/fps_player.cc
===================================================================
--- trunk/src/world_entities/creatures/fps_player.cc	(revision 8724)
+++ trunk/src/world_entities/creatures/fps_player.cc	(revision 8724)
@@ -0,0 +1,280 @@
+/*
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 orx
+
+   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, or (at your option)
+   any later version.
+
+### File Specific:
+   main-programmer: Patrick Boenzli
+   co-programmer: ...
+
+*/
+
+#include "fps_player.h"
+
+#include "interactive_model.h"
+#include "md2/md2Model.h"
+
+#include "src/lib/util/loading/factory.h"
+
+#include "key_mapper.h"
+
+#include "debug.h"
+
+
+
+CREATE_FACTORY(FPSPlayer, CL_FPS_PLAYER);
+
+
+using namespace std;
+
+
+/**
+ *  destructs the FPSPlayer, deletes alocated memory
+ */
+FPSPlayer::~FPSPlayer ()
+{
+  this->setPlayer(NULL);
+}
+
+
+/**
+ *  creates a new FPSPlayer from Xml Data
+ * @param root the xml element containing FPSPlayer data
+ *
+ */
+FPSPlayer::FPSPlayer(const TiXmlElement* root)
+{
+  this->init();
+
+  if (root != NULL)
+    this->loadParams(root);
+
+}
+
+
+/**
+ * initializes a FPSPlayer
+ */
+void FPSPlayer::init()
+{
+  this->setClassID(CL_FPS_PLAYER, "FPSPlayer");
+
+  this->getWeaponManager().changeWeaponConfig(1);
+
+  this->bLeft = false;
+  this->bRight = false;
+  this->bForward = false;
+  this->bBackward = false;
+  this->bJump = false;
+  this->xMouse = 0.0f;
+  this->yMouse = 0.0f;
+
+  this->setHealthMax(100);
+  this->setHealth(80);
+
+  this->mouseDir = this->getAbsDir();
+
+  //add events to the eventlist
+  registerEvent(KeyMapper::PEV_FORWARD);
+  registerEvent(KeyMapper::PEV_BACKWARD);
+  registerEvent(KeyMapper::PEV_LEFT);
+  registerEvent(KeyMapper::PEV_RIGHT);
+  registerEvent(KeyMapper::PEV_FIRE1);
+  registerEvent(KeyMapper::PEV_JUMP);
+  registerEvent(EV_MOUSE_MOTION);
+
+  this->getWeaponManager().setSlotCount(0);
+
+  this->getWeaponManager().getFixedTarget()->setParent(this);
+  this->getWeaponManager().getFixedTarget()->setRelCoor(100000,0,0);
+
+  dynamic_cast<Element2D*>(this->getWeaponManager().getFixedTarget())->setVisibility( false);
+
+  // network registration
+  registerVar( new SynchronizeableBool( &bLeft, &bLeft, "bLeft", PERMISSION_OWNER ) );
+  registerVar( new SynchronizeableBool( &bRight, &bRight, "bRight", PERMISSION_OWNER ) );
+  registerVar( new SynchronizeableBool( &bForward, &bForward, "bForward", PERMISSION_OWNER ) );
+  registerVar( new SynchronizeableBool( &bBackward, &bBackward, "bBackward", PERMISSION_OWNER ) );
+  registerVar( new SynchronizeableQuaternion( &mouseDir, &mouseDir, "mouseDir", PERMISSION_OWNER ) );
+
+  // collision reaction registration
+  this->subscribeReaction(CREngine::CR_PHYSICS_GROUND_WALK, CL_BSP_ENTITY);
+}
+
+
+/**
+ * loads the Settings of a FPSPlayer from an XML-element.
+ * @param root the XML-element to load the Spaceship's properties from
+ */
+void FPSPlayer::loadParams(const TiXmlElement* root)
+{
+  Playable::loadParams(root);
+}
+
+void FPSPlayer::setPlayDirection(const Quaternion& quat, float speed)
+{
+  this->mouseDir = quat;
+  this->angleY = quat.getHeading();
+  this->angleX = quat.getAttitude();
+}
+
+
+void FPSPlayer::reset()
+{
+  this->bLeft = false;
+  this->bRight = false;
+  this->bForward = false;
+  this->bBackward = false;
+  this->xMouse = 0.0f;
+  this->yMouse = 0.0f;
+
+  this->setHealth(80);
+}
+
+
+void FPSPlayer::enter()
+{
+  dynamic_cast<Element2D*>(this->getWeaponManager().getFixedTarget())->setVisibility( false );
+  this->attachCamera();
+}
+
+void FPSPlayer::leave()
+{
+  dynamic_cast<Element2D*>(this->getWeaponManager().getFixedTarget())->setVisibility( false);
+  this->detachCamera();
+}
+
+
+
+/**
+ *  the function called for each passing timeSnap
+ * @param time The timespan passed since last update
+ */
+void FPSPlayer::tick (float time)
+{
+  Playable::tick( time );
+
+  if( ( xMouse != 0 || yMouse != 0 ) /*&& this->getOwner() == this->getHostID() */)
+  {
+    xMouse *= time ;
+    yMouse *= time ;
+
+    angleX -= xMouse;
+    angleY -= yMouse;
+
+    if ( angleY > 2.05 )
+      angleY = 2.05;
+
+    if ( angleY < -1.15 )
+      angleY = -1.15;
+
+    this->mouseDir = Quaternion( angleX, Vector( 0, 1, 0 ) ) * Quaternion( angleY, Vector( 0, 0, 1 ) );
+
+    xMouse = yMouse = 0;
+  }
+
+  this->setAbsDir( this->mouseDir );
+
+  Vector velocity;
+
+  if ( this->bForward )
+  {
+    velocity += this->getAbsDirX();
+  }
+
+  if ( this->bBackward )
+  {
+    velocity -= this->getAbsDirX();
+  }
+
+  if ( this->bRight )
+  {
+    velocity += this->getAbsDirZ();
+  }
+
+  if ( this->bLeft )
+  {
+    velocity -= this->getAbsDirZ();
+  }
+
+  velocity *= 100;
+
+  this->shiftCoor( velocity*time );
+
+
+
+
+  if( likely(this->getModel(0) != NULL) && this->getModel(0)->isA(CL_INTERACTIVE_MODEL))
+  {
+    ((InteractiveModel*)this->getModel(0))->tick(time);
+//
+//     // handle animations differently
+//     if( this->bJump && likely(this->getModel(0) != NULL))
+//     {
+//       ((InteractiveModel*)this->getModel(0))->setAnimation(JUMP);
+//     }
+//     else if( this->bFire && likely(this->getModel(0) != NULL))
+//     {
+//       if( ((InteractiveModel*)this->getModel(0))->getAnim() != ATTACK)
+//         ((InteractiveModel*)this->getModel(0))->setAnimation(ATTACK);
+//     }
+//     else if( fabs(move.len()) > 0.0f && likely(this->getModel(0) != NULL))
+//     {
+//       if( ((InteractiveModel*)this->getModel(0))->getAnim() != RUN)
+//         ((InteractiveModel*)this->getModel(0))->setAnimation(RUN);
+//     }
+//     else if (likely(this->getModel(0) != NULL))
+//     {
+//       if( ((InteractiveModel*)this->getModel(0))->getAnimation() != STAND)
+//         ((InteractiveModel*)this->getModel(0))->setAnimation(STAND);
+//     }
+  }
+
+}
+
+
+
+/**
+ *  draws the MD2Creature after transforming it.
+ */
+void FPSPlayer::draw () const
+{
+  // only draw if this entity is not the player since the player nevers sees himself
+  if( this->getCurrentPlayer() == NULL)
+    WorldEntity::draw();
+}
+
+
+
+/**
+ * process
+ */
+void FPSPlayer::process(const Event &event)
+{
+  Playable::process(event);
+
+  if( event.type == KeyMapper::PEV_LEFT)
+    this->bLeft = event.bPressed;
+  else if( event.type == KeyMapper::PEV_RIGHT)
+    this->bRight = event.bPressed;
+  else if( event.type == KeyMapper::PEV_FORWARD)
+    this->bForward = event.bPressed; //this->shiftCoor(0,.1,0);
+  else if( event.type == KeyMapper::PEV_BACKWARD)
+    this->bBackward = event.bPressed; //this->shiftCoor(0,-.1,0);
+  else if( event.type == EV_MOUSE_MOTION)
+  {
+    this->xMouse += event.xRel;
+    this->yMouse += event.yRel;
+  }
+  else if( event.type == KeyMapper::PEV_JUMP)
+    this->getAbsCoor().debug();
+}
+
+
+
+
Index: trunk/src/world_entities/creatures/fps_player.h
===================================================================
--- trunk/src/world_entities/creatures/fps_player.h	(revision 8724)
+++ trunk/src/world_entities/creatures/fps_player.h	(revision 8724)
@@ -0,0 +1,54 @@
+/*!
+ * @file fps_player.h
+ * Implements a playable for fps games
+ */
+
+#ifndef _FPS_PLAYER_H
+#define _FPS_PLAYER_H
+
+
+#include "playable.h"
+
+
+class FPSPlayer : public Playable
+{
+
+  public:
+    FPSPlayer(const TiXmlElement* root = NULL);
+    virtual ~FPSPlayer();
+
+    virtual void loadParams(const TiXmlElement* root);
+
+    virtual void setPlayDirection(const Quaternion& rot, float speed = 0.0f);
+
+    virtual void enter();
+    virtual void leave();
+
+    virtual void reset();
+
+
+    virtual void tick(float time);
+    virtual void draw() const;
+
+
+    virtual void process(const Event &event);
+
+  private:
+    void init();
+
+    bool                  bLeft;
+    bool                  bRight;
+    bool                  bForward;
+    bool                  bBackward;
+    bool                  bJump;              //!< jumping
+
+    float                 xMouse;             //!< mouse moved in x-Direction
+    float                 yMouse;             //!< mouse moved in y-Direction
+    Quaternion            mouseDir;           //!< the direction where the player wants to fly
+
+    float                 angleX;
+    float                 angleY;
+
+};
+
+#endif
Index: trunk/src/world_entities/creatures/md2_creature.cc
===================================================================
--- trunk/src/world_entities/creatures/md2_creature.cc	(revision 8719)
+++ trunk/src/world_entities/creatures/md2_creature.cc	(revision 8724)
@@ -63,5 +63,4 @@
 
   this->loadParams(doc.RootElement());
-  this->toList(OM_GROUP_01);
 }
 
@@ -77,4 +76,17 @@
   if (root != NULL)
     this->loadParams(root);
+}
+
+
+/**
+ * initializes a MD2Creature
+ */
+void MD2Creature::init()
+{
+  PRINTF(4)("MD2CREATURE INIT\n");
+  //  this->setRelDir(Quaternion(M_PI, Vector(1,0,0)));
+  this->setClassID(CL_MD2_CREATURE, "MD2Creature");
+
+  this->toList(OM_GROUP_01);
 
   //weapons:
@@ -87,24 +99,21 @@
   cannon->setName("BFG");
 
-   this->getWeaponManager().addWeapon(wpLeft, 1, 0);
-   this->getWeaponManager().addWeapon(wpRight,1 ,1);
-//   this->getWeaponManager().addWeapon(cannon, 0, 6);
-
-  //this->getWeaponManager().addWeapon(turret, 3, 0);
-
+  this->addWeapon(wpLeft, 1, 0);
+  this->addWeapon(wpRight,1 ,1);
   this->getWeaponManager().changeWeaponConfig(0);
-}
-
-
-/**
- * initializes a MD2Creature
- */
-void MD2Creature::init()
-{
-//  this->setRelDir(Quaternion(M_PI, Vector(1,0,0)));
-  this->setClassID(CL_MD2_CREATURE, "MD2Creature");
-
-  PRINTF(4)("MD2CREATURE INIT\n");
-
+
+
+  // pnode camera issue
+  this->cameraConnNode.addNodeFlags(PNODE_PROHIBIT_DELETE_WITH_PARENT);
+  this->cameraConnNode.addNodeFlags(PNODE_PROHIBIT_CHILD_DELETE);
+  this->cameraConnNode.setName("CameraConnectorNode");
+  this->addChild(&this->cameraConnNode);
+  this->cameraConnNode.addChild(State::getCameraTargetNode());
+  this->cameraConnNode.addChild(State::getCameraNode());
+  State::getCameraTargetNode()->setRelCoor(10,0,0);
+ 
+
+
+  // control initialisation
   this->mouseDirX *= Quaternion( M_PI * 0.75f, Vector(0,1,0));
 
@@ -116,31 +125,21 @@
   cycle = 0.0;
 
-  this->cameraConnNode.addNodeFlags(PNODE_PROHIBIT_DELETE_WITH_PARENT);
-  this->cameraConnNode.setName("CameraConnectorNode");
-  this->addChild(&this->cameraConnNode);
-  this->cameraConnNode.addChild(State::getCameraTargetNode());
-  this->cameraConnNode.addChild(State::getCameraNode());
-  State::getCameraTargetNode()->setRelCoor(10,0,0);
-
-  travelSpeed = 15.0;
+  travelSpeed =300.0;
   this->velocity = Vector(0.0,0.0,0.0);
 
-//   GLGuiButton* button = new GLGuiPushButton();
-//   button->show();
-//   button->setLabel("orxonox");
-//   button->setBindNode(this);
 
   //add events to the eventlist
-  this->registerEvent(SDLK_w);
-  this->registerEvent(SDLK_s);
-  this->registerEvent(SDLK_a);
-  this->registerEvent(SDLK_d);
+  //add events to the eventlist
+  registerEvent(KeyMapper::PEV_FORWARD);
+  registerEvent(KeyMapper::PEV_BACKWARD);
+  registerEvent(KeyMapper::PEV_LEFT);
+  registerEvent(KeyMapper::PEV_RIGHT);
+  registerEvent(KeyMapper::PEV_UP);
+  registerEvent(KeyMapper::PEV_DOWN);
+  registerEvent(KeyMapper::PEV_FIRE1);
+  registerEvent(KeyMapper::PEV_NEXT_WEAPON);
+  registerEvent(KeyMapper::PEV_PREVIOUS_WEAPON);
+  registerEvent(EV_MOUSE_MOTION);
   this->registerEvent(SDLK_SPACE);
-  this->registerEvent(SDLK_q);
-  this->registerEvent(SDLK_e);
-  this->registerEvent(KeyMapper::PEV_FIRE1);
-  this->registerEvent(KeyMapper::PEV_NEXT_WEAPON);
-  this->registerEvent(KeyMapper::PEV_PREVIOUS_WEAPON);
-  this->registerEvent(EV_MOUSE_MOTION);
 
 
@@ -165,30 +164,16 @@
   this->getWeaponManager().setSlotPosition(5, Vector(-1.5, -.5, -.5));
   this->getWeaponManager().setSlotDirection(5, Quaternion(+M_PI_4*.5-M_PI, Vector(1,0,0)));
-//
-   this->getWeaponManager().setSlotPosition(6, Vector(-1, 0.0, 0));
-   this->getWeaponManager().setSlotCapability(6, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
-   //
-
-   this->cameraConnNode.addChild(this->getWeaponManager().getFixedTarget());
+  //
+  this->getWeaponManager().setSlotPosition(6, Vector(-1, 0.0, 0));
+  this->getWeaponManager().setSlotCapability(6, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
+  //
+
+  this->cameraConnNode.addChild(this->getWeaponManager().getFixedTarget());
   dynamic_cast<Element2D*>(this->getWeaponManager().getFixedTarget())->setVisibility( false);
 
-  this->getWeaponManager().getFixedTarget()->setRelCoor(10,0,0);
-
-}
-
-
-void MD2Creature::enter()
-{
-  dynamic_cast<Element2D*>(this->getWeaponManager().getFixedTarget())->setVisibility( true);
-  this->attachCamera();
-
-}
-
-void MD2Creature::leave()
-{
-  dynamic_cast<Element2D*>(this->getWeaponManager().getFixedTarget())->setVisibility( false);
-
-
-}
+  this->getWeaponManager().getFixedTarget()->setRelCoor(0,0,0);
+
+}
+
 
 /**
@@ -202,11 +187,26 @@
 
 
+void MD2Creature::enter()
+{
+  dynamic_cast<Element2D*>(this->getWeaponManager().getFixedTarget())->setVisibility( true);
+
+  State::getCameraNode()->setParent(&this->cameraConnNode);
+  State::getCameraNode()->setRelCoor(0, 0,0);
+  State::getCameraTargetNode()->setParentSoft(&this->cameraConnNode);
+
+}
+
+void MD2Creature::leave()
+{
+  dynamic_cast<Element2D*>(this->getWeaponManager().getFixedTarget())->setVisibility( false);
+  this->detachCamera();
+}
+
+
 /**
  *  effect that occurs after the MD2Creature is spawned
 */
 void MD2Creature::postSpawn ()
-{
-  //setCollision(new CollisionCluster(1.0, Vector(0,0,0)));
-}
+{}
 
 /**
@@ -234,5 +234,6 @@
   if (this->getCurrentPlayer() != NULL)
     WorldEntity::draw();
-//  this->cameraConnNode.debugDraw(0);
+
+  this->cameraConnNode.debugDraw(0);
 }
 
@@ -254,4 +255,6 @@
   this->shiftCoor (move);
 
+
+  // handle animations differently
   if( this->bJump && likely(this->getModel(0) != NULL))
   {
@@ -260,19 +263,25 @@
   else if( this->bFire && likely(this->getModel(0) != NULL))
   {
-    if( ((MD2Model*)this->getModel(0))->getAnim() != ATTACK) ((MD2Model*)this->getModel(0))->setAnimation(ATTACK);
+    if( ((MD2Model*)this->getModel(0))->getAnimation() != ATTACK)
+      ((MD2Model*)this->getModel(0))->setAnimation(ATTACK);
   }
   else if( fabs(move.len()) > 0.0f && likely(this->getModel(0) != NULL))
   {
-    if( ((MD2Model*)this->getModel(0))->getAnim() != RUN) ((MD2Model*)this->getModel(0))->setAnimation(RUN);
+    if( ((MD2Model*)this->getModel(0))->getAnimation() != RUN)
+      ((MD2Model*)this->getModel(0))->setAnimation(RUN);
   }
   else if (likely(this->getModel(0) != NULL))
   {
-    if( ((MD2Model*)this->getModel(0))->getAnim() != STAND) ((MD2Model*)this->getModel(0))->setAnimation(STAND);
+    if( ((MD2Model*)this->getModel(0))->getAnimation() != STAND)
+      ((MD2Model*)this->getModel(0))->setAnimation(STAND);
   }
 
 
   //orient the MD2Creature in direction of the mouse
-  this->setAbsDir(mouseDirX);
+//   this->setAbsDir(mouseDirX);
+//    this->cameraConnNode.setRelDir(mouseDirY);
+
   this->cameraConnNode.setRelDir(mouseDirY);
+  this->setAbsDir(this->mouseDirX);
 }
 
@@ -286,5 +295,5 @@
   Vector accel(0.0, 0.0, 0.0);
   /*
-  Vector rot(0.0, 0.0, 0.0); // wird benötigt für Helicopter
+  Vector rot(0.0, 0.0, 0.0); // wird ben�igt fr Helicopter
   */
   //float rotVal = 0.0;
@@ -292,13 +301,20 @@
   /* calculate the direction in which the craft is heading  */
 
+  if( bMouseMotion)
+  {
+    this->mouseDirX *= Quaternion(-M_PI / 4.0f * this->xMouse*mouseSensitivity, Vector(0,1,0));
+    this->mouseDirY *= Quaternion(-M_PI / 4.0f * this->yMouse*mouseSensitivity, Vector(0,0,1));
+    this->bMouseMotion = false;
+  }
+
   if( this->bUp )
-   {
-     accel += (this->getAbsDirX())*2;
-   }
+  {
+    accel += (this->getAbsDirX())*2;
+  }
 
   if( this->bDown )
-   {
-     accel -= (this->getAbsDirX())*2;
-   }
+  {
+    accel -= (this->getAbsDirX())*2;
+  }
 
   if( this->bLeft/* > -this->getRelCoor().z*2*/)
@@ -329,5 +345,5 @@
   }
 
-  velocity = accel * 20.0f;
+  velocity = accel * 40.0f;
   //rot.normalize();
   //this->setRelDirSoft(Quaternion(rotVal, rot), 5);
@@ -335,5 +351,4 @@
 
 
-
 /**
  * @todo switch statement ??
@@ -342,22 +357,19 @@
 {
   Playable::process(event);
-  if( event.type == SDLK_a)
-      this->bStrafeL = event.bPressed;
-  else if( event.type == SDLK_d)
-      this->bStrafeR = event.bPressed;
-  else if( event.type == SDLK_w)
-    this->bUp = event.bPressed; //this->shiftCoor(0,.1,0);
-  else if( event.type == SDLK_s)
-    this->bDown = event.bPressed; //this->shiftCoor(0,-.1,0);
+  if( event.type == KeyMapper::PEV_LEFT)
+    this->bStrafeL = event.bPressed;
+  else if( event.type == KeyMapper::PEV_RIGHT)
+    this->bStrafeR = event.bPressed;
+  else if( event.type == KeyMapper::PEV_FORWARD)
+    this->bUp = event.bPressed;
+  else if( event.type == KeyMapper::PEV_BACKWARD)
+    this->bDown = event.bPressed;
   else if( event.type == SDLK_SPACE)
     this->bJump = event.bPressed;
   else if( event.type == EV_MOUSE_MOTION)
   {
+    this->bMouseMotion = true;
     this->xMouse = event.xRel;
     this->yMouse = event.yRel;
-    this->mouseDirX *= Quaternion(-M_PI/4*this->xMouse*mouseSensitivity, Vector(0,1,0));
-    this->mouseDirY *= Quaternion(-M_PI/4*this->yMouse*mouseSensitivity, Vector(0,0,1));
-//     if( xMouse*xMouse < 0.9)
-//      this->setAbsDir(mouseDir);
-  }
-}
+  }
+}
Index: trunk/src/world_entities/creatures/md2_creature.h
===================================================================
--- trunk/src/world_entities/creatures/md2_creature.h	(revision 8719)
+++ trunk/src/world_entities/creatures/md2_creature.h	(revision 8724)
@@ -57,4 +57,5 @@
     bool                  bStrafeR;           //!< strafe to the rith side
     bool                  bJump;              //!< jump
+    bool                  bMouseMotion;       //!< mouse motion evet
 
     PNode                 cameraConnNode;     //!< The Node the camera is connected to.
Index: trunk/src/world_entities/npcs/generic_npc.cc
===================================================================
--- trunk/src/world_entities/npcs/generic_npc.cc	(revision 8724)
+++ trunk/src/world_entities/npcs/generic_npc.cc	(revision 8724)
@@ -0,0 +1,172 @@
+
+
+/*
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 orx
+
+   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, or (at your option)
+   any later version.
+
+   ### File Specific
+   main-programmer: Patrick Boenzli
+   co-programmer:
+*/
+#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
+
+
+#include "util/loading/factory.h"
+#include "util/loading/load_param.h"
+
+#include "interactive_model.h"
+#include "md2/md2Model.h"
+
+#include "sound_buffer.h"
+
+#include "loading/resource_manager.h"
+
+#include "generic_npc.h"
+
+using namespace std;
+
+
+
+CREATE_FACTORY(GenericNPC, CL_GENERIC_NPC);
+
+
+
+/**
+ * constructor
+ */
+GenericNPC::GenericNPC(const TiXmlElement* root)
+  : NPC(root)
+{
+  this->init();
+
+  if (root != NULL)
+    this->loadParams(root);
+}
+
+
+/**
+ * deconstructor
+ */
+GenericNPC::~GenericNPC ()
+{}
+
+
+/**
+ * initializing the npc enity
+ */
+void GenericNPC::init()
+{
+  this->setClassID(CL_GENERIC_NPC, "GenericNPC");
+  this->toList(OM_GROUP_00);
+
+  if (this->soundBuffer != NULL)
+    ResourceManager::getInstance()->unload(this->soundBuffer);
+  this->soundBuffer = (OrxSound::SoundBuffer*)ResourceManager::getInstance()->load("sound/rain.wav", WAV);
+
+  // collision reaction registration
+//   this->subscribeReaction(CREngine::CR_PHYSICS_GROUND_WALK, CL_BSP_ENTITY);
+}
+
+
+/**
+ * loads the Settings of a MD2Creature from an XML-element.
+ * @param root the XML-element to load the MD2Creature's properties from
+ */
+void GenericNPC::loadParams(const TiXmlElement* root)
+{
+  NPC::loadParams(root);
+
+}
+
+
+/**
+ * sets the animation of this npc
+ * @param anumationIndex: the animation index
+ * @param anumPlaybackMode: the playback mode
+ */
+void GenericNPC::setAnimation(int animationIndex, int animPlaybackMode)
+{
+  if( likely(this->getModel(0) != NULL))
+    ((InteractiveModel*)this->getModel(0))->setAnimation(animationIndex, animPlaybackMode);
+}
+
+
+/**
+ * sets the animation of this npc
+ * @param anumationIndex: the animation index
+ * @param anumPlaybackMode: the playback mode
+ */
+void GenericNPC::playAnimation(int animationIndex, int animPlaybackMode)
+{
+  if( likely(this->getModel(0) != NULL))
+    ((InteractiveModel*)this->getModel(0))->setAnimation(animationIndex, animPlaybackMode);
+
+}
+
+
+/**
+ * play a sound
+ * @param filename: name of the file
+ */
+void GenericNPC::playSound(std::string filename)
+{
+
+}
+
+
+/**
+ * walt to
+ * @param coordinate: coordinate to go to
+ */
+bool GenericNPC::walkTo(const Vector& coordinate, float time)
+{
+
+  return true;
+}
+
+
+/**
+ * walt to
+ * @param coordinate: coordinate to go to
+ */
+bool GenericNPC::walkTo(float x, float y, float z, float time)
+{
+
+  return true;
+}
+
+
+/**
+ * tick this world entity
+ * @param time: time in seconds expirded since the last tick
+ */
+void GenericNPC::tick (float time)
+{
+  if( likely(this->getModel(0) != NULL))
+    ((InteractiveModel*)this->getModel(0))->tick(time);
+}
+
+
+
+void GenericNPC::destroy()
+{
+  int randi = (int)(5.0f * (float)rand()/(float)RAND_MAX);
+
+  if( randi == 1)
+    this->setAnimation(DEATH_FALLBACK, MD2_ANIM_ONCE);
+  else if( randi == 2)
+    this->setAnimation(DEATH_FALLFORWARD, MD2_ANIM_ONCE);
+  else if( randi == 3)
+    this->setAnimation(DEATH_FALLBACKSLOW, MD2_ANIM_ONCE);
+  else if( randi == 4)
+    this->setAnimation(CROUCH_DEATH, MD2_ANIM_ONCE);
+  else
+    this->setAnimation(DEATH_FALLBACK, MD2_ANIM_ONCE);
+}
+
Index: trunk/src/world_entities/npcs/generic_npc.h
===================================================================
--- trunk/src/world_entities/npcs/generic_npc.h	(revision 8724)
+++ trunk/src/world_entities/npcs/generic_npc.h	(revision 8724)
@@ -0,0 +1,54 @@
+
+/*!
+ * @file generic_npc.h
+ * generic npc object
+ */
+
+#ifndef _GENERIC_ENTITY_H
+#define _GENERIC_ENTITY_H
+
+#include "npc.h"
+
+#include <string>
+//
+#include "sound_source.h"
+
+namespace OrxSound{ class SoundSource; }
+namespace OrxSound{ class SoundBuffer; }
+
+class TiXmlElement;
+
+
+class GenericNPC : public NPC
+{
+ public:
+  GenericNPC(const TiXmlElement* root);
+  virtual ~GenericNPC ();
+
+  void init();
+  virtual void loadParams(const TiXmlElement* root);
+
+  void setAnimation(int animationIndex, int animPlaybackMode);
+  /** sets the sound volume to @param vol: volume of the sound */
+  inline void setVolume(float vol) { this->soundVolume = vol; }
+
+  void playAnimation(int animationIndex, int animPlaybackMode);
+
+  void playSound(std::string filename);
+  void playSound(int i);
+
+  bool walkTo(const Vector& coordinate, float time);
+  bool walkTo(float x, float y, float z, float time);
+
+  void destroy();
+
+  virtual void tick (float time);
+
+
+ private:
+   OrxSound::SoundSource                   soundSource;
+   OrxSound::SoundBuffer*                  soundBuffer;
+   float                                   soundVolume;
+};
+
+#endif /* _GENERIC_ENTITY_H */
Index: trunk/src/world_entities/npcs/ground_turret.cc
===================================================================
--- trunk/src/world_entities/npcs/ground_turret.cc	(revision 8719)
+++ trunk/src/world_entities/npcs/ground_turret.cc	(revision 8724)
@@ -39,4 +39,5 @@
  */
 GroundTurret::GroundTurret(const TiXmlElement* root)
+  : NPC(root)
 {
   this->init();
Index: trunk/src/world_entities/npcs/npc.cc
===================================================================
--- trunk/src/world_entities/npcs/npc.cc	(revision 8719)
+++ trunk/src/world_entities/npcs/npc.cc	(revision 8724)
@@ -19,17 +19,13 @@
 
 #include "npc.h"
-#include "obb_tree.h"
 
-#include "state.h"
-#include "stdlibincl.h"
-#include "power_ups/turret_power_up.h"
-#include "power_ups/laser_power_up.h"
 
 using namespace std;
 
 
-NPC::NPC()
+NPC::NPC(const TiXmlElement* root)
 {
   this->setClassID(CL_NPC, "NPC");
+
   this->toList(OM_GROUP_00);
 }
@@ -39,48 +35,20 @@
 
 
-void NPC::collidesWith(WorldEntity* entity, const Vector& location)
-{
 
-  if (entity == collider)
-    return;
-  collider = entity;
-
-  if (entity->isA(CL_PROJECTILE))
-  {
-    this->decreaseHealth(entity->getHealth() *(float)rand()/(float)RAND_MAX);
-    // EXTREME HACK
-    if (this->getHealth() <= 0.0f)
-    {
-      this->destroy();
-    }
-  }
+/**
+ * adds an AI to this NPC
+ */
+void NPC::addAI(AI* ai)
+{}
 
 
-// //    PRINTF(3)("collision %s vs %s @ (%f,%f,%f)\n", this->getName(), entity->getName(), location.x, location.y, location.z);
-// //    this->applyForce(Vector(0,0,0)-location*1000);
-//     if ((float)rand()/RAND_MAX < .3)
-//     {
-//       WorldEntity* powerUp = new TurretPowerUp();
-//       powerUp->setAbsCoor(this->getAbsCoor());
-// //      powerUp->toList(OM_COMMON);
-//     }
-//     else if ((float)rand()/RAND_MAX < .3)
-//     {
-//       WorldEntity* powerUp = new LaserPowerUp();
-//       powerUp->setAbsCoor(this->getAbsCoor());
-//       powerUp->toList(OM_COMMON);
-//     }
-//     this->toList(OM_DEAD);
-//     this->removeNode();
-//
-//       this->collider = entity;
-//   }
-//   //  else if (entity->isA(CL_PLAYER))
-//   //    this->applyForce(Vector(0,0,0)-location*100);
-//   else if (entity->isA(CL_NPC))
-//   {
-//     this->setVisibiliy(false);
-//     this->toList(OM_DEAD);
-//     this->removeNode();
-//   }
+
+/**
+ * loads the xml tags
+ * @param root: root xml tag for this element
+ */
+void NPC::loadParams(const TiXmlElement* root)
+{
+  WorldEntity::loadParams(root);
 }
+
Index: trunk/src/world_entities/npcs/npc.h
===================================================================
--- trunk/src/world_entities/npcs/npc.h	(revision 8719)
+++ trunk/src/world_entities/npcs/npc.h	(revision 8724)
@@ -4,5 +4,4 @@
 
 #include "world_entity.h"
-#include "physics_interface.h"
 
 class AI;
@@ -11,17 +10,14 @@
 
  public:
-  NPC ();
+   NPC (const TiXmlElement* root);
   virtual ~NPC ();
 
+  virtual void loadParams(const TiXmlElement* root = NULL);
 
   void addAI(AI* ai);
-
-  virtual void collidesWith (WorldEntity* entity, const Vector& location);
 
 
  private:
 
-   WorldEntity* collider;
-
 };
 
Index: trunk/src/world_entities/npcs/npc_test.cc
===================================================================
--- trunk/src/world_entities/npcs/npc_test.cc	(revision 8719)
+++ trunk/src/world_entities/npcs/npc_test.cc	(revision 8724)
@@ -31,4 +31,5 @@
 
 NPC2::NPC2()
+  : NPC(NULL)
 {
   this->setClassID(CL_NPC_TEST2, "NPC2");
Index: trunk/src/world_entities/npcs/npc_test1.cc
===================================================================
--- trunk/src/world_entities/npcs/npc_test1.cc	(revision 8719)
+++ trunk/src/world_entities/npcs/npc_test1.cc	(revision 8724)
@@ -29,4 +29,5 @@
 
 NPCTest1::NPCTest1()
+  : NPC(NULL)
 {
   this->setClassID(CL_NPC_TEST1, "NPCTest1");
Index: trunk/src/world_entities/playable.cc
===================================================================
--- trunk/src/world_entities/playable.cc	(revision 8719)
+++ trunk/src/world_entities/playable.cc	(revision 8724)
@@ -65,5 +65,5 @@
 
   this->bDead = false;
-
+  
   this->subscribeReaction(CREngine::CR_PHYSICS_GROUND_WALK, CL_BSP_ENTITY);
 
@@ -376,5 +376,5 @@
     if (this->getHealth() <= 0.0f)
     {
-      this->die();
+//       this->destory();
 
       if( State::getGameRules() != NULL)
@@ -411,5 +411,6 @@
 
 
-void Playable::die()
+
+void Playable::destroy()
 {
   Explosion::explode(dynamic_cast<PNode*>(this), Vector(1.0f, 1.0f, 1.0f));
Index: trunk/src/world_entities/playable.h
===================================================================
--- trunk/src/world_entities/playable.h	(revision 8719)
+++ trunk/src/world_entities/playable.h	(revision 8724)
@@ -76,5 +76,5 @@
 
   // WorldEntity Extensions
-  virtual void die();
+  virtual void destroy();
   virtual void respawn();
   virtual void collidesWith(WorldEntity* entity, const Vector& location);
Index: trunk/src/world_entities/space_ships/collision_probe.cc
===================================================================
--- trunk/src/world_entities/space_ships/collision_probe.cc	(revision 8719)
+++ trunk/src/world_entities/space_ships/collision_probe.cc	(revision 8724)
@@ -67,5 +67,5 @@
   this->loadModel("models/dr_freak.md2");
 
-  this->localVelocity = Vector(0,-4,0);
+  this->localVelocity = Vector(0,0,0);
 }
 
Index: trunk/src/world_entities/test_entity.h
===================================================================
--- trunk/src/world_entities/test_entity.h	(revision 8719)
+++ trunk/src/world_entities/test_entity.h	(revision 8724)
@@ -15,6 +15,4 @@
 class TestEntity : public WorldEntity, public PhysicsInterface
 {
-  friend class World;
-
  public:
   TestEntity ();
Index: trunk/src/world_entities/world_entity.cc
===================================================================
--- trunk/src/world_entities/world_entity.cc	(revision 8719)
+++ trunk/src/world_entities/world_entity.cc	(revision 8724)
@@ -24,4 +24,6 @@
 #include "md3/md3_model.h"
 
+#include "aabb_tree_node.h"
+
 #include "util/loading/resource_manager.h"
 #include "util/loading/load_param.h"
@@ -60,4 +62,5 @@
 
   this->obbTree = NULL;
+  this->aabbNode = NULL;
   this->healthWidget = NULL;
   this->healthMax = 1.0f;
@@ -201,5 +204,5 @@
         this->buildObbTree(obbTreeDepth);
     }
-    else if(fileName.find(".md3") != std::string::npos)
+    else /*if(fileName.find(".md3") != std::string::npos)*/
     {
       PRINTF(4)("fetching MD3 file: %s\n", fileName.c_str());
@@ -240,8 +243,4 @@
 
   this->models[modelNumber] = model;
-
-
-  //   if (this->model != NULL)
-  //     this->buildObbTree(4);
 }
 
@@ -257,8 +256,5 @@
 
   if (this->models[0] != NULL)
-  {
     this->obbTree = new OBBTree(depth, models[0]->getModelInfo(), this);
-    return true;
-  }
   else
   {
@@ -267,4 +263,18 @@
     return false;
   }
+
+
+  // create the axis aligned bounding box
+  if( this->aabbNode != NULL)
+  {
+    delete this->aabbNode;
+    this->aabbNode = NULL;
+  }
+
+  if( this->models[0] != NULL) {
+    this->aabbNode = new AABBTreeNode();
+    this->aabbNode->spawnBVTree(this->models[0]);
+  }
+  return true;
 }
 
@@ -604,4 +614,8 @@
       this->models[0]->draw();
     }
+
+    if( this->aabbNode != NULL)
+      this->aabbNode->drawBV(0, DRAW_BV_POLYGON, Vector(1, 0.6, 0.2), true);
+
     glPopMatrix();
   }
@@ -712,4 +726,27 @@
     this->healthWidget->hide();
 }
+
+
+/**
+ * hit the world entity with
+ *  @param damage damage to be dealt
+ */
+void WorldEntity::hit(float damage)
+{
+  this->decreaseHealth(damage);
+
+  if( this->getHealth() > 0)
+  {
+    // any small explosion animaitions
+  }
+  else
+  {
+    this->destroy();
+
+//     if( State::getGameRules() != NULL)
+//       State::getGameRules()->registerKill(Kill(NULL, this));
+  }
+}
+
 
 /**
Index: trunk/src/world_entities/world_entity.h
===================================================================
--- trunk/src/world_entities/world_entity.h	(revision 8719)
+++ trunk/src/world_entities/world_entity.h	(revision 8724)
@@ -16,4 +16,6 @@
 #include <vector>
 
+#include "aabb_tree_node.h"
+
 #include "physics_interface.h"
 
@@ -26,4 +28,5 @@
 class BVTree;
 class BoundingVolume;
+class AABBTreeNode;
 class Model;
 class CollisionHandle;
@@ -58,5 +61,4 @@
   virtual void postSpawn ();
   virtual void leaveWorld ();
-  virtual void destroy() {};
 
   virtual void tick (float time);
@@ -73,4 +75,5 @@
   inline BVTree* getOBBTree() const { return this->obbTree; };
   void drawBVTree(int depth, int drawMode) const;
+  inline AABB* getModelAABB() { return (this->aabbNode)?this->aabbNode->getAABB():NULL;}
 
   /* --- Collision Reaction Block --- */
@@ -90,4 +93,7 @@
 
   CollisionHandle* getCollisionHandle(CREngine::CRType type) const { return this->collisionHandles[type]; }
+
+  virtual void hit(float damage);
+  virtual void destroy() {};
 
 
@@ -109,8 +115,4 @@
   /** @returns a Reference to the Iterator */
   ObjectManager::EntityList::iterator& getEntityIterator() { return this->objectListIterator; }
-
-  /* --- Network Block --- */
-  int       writeState(const byte* data, int length, int sender);
-  int       readState(byte* data, int maxLength );
 
   /* --- Character Attribute Block --- */
@@ -167,4 +169,5 @@
   std::string             modelLODName;       //!< the name of the model lod file
   BVTree*                 obbTree;            //!< this is the obb tree reference needed for collision detection
+  AABBTreeNode*           aabbNode;           //!< the tree node of the first level of a axis aligned bounding boxes tree: model dimension
 
   bool                    bCollide;           //!< If it should be considered for the collisiontest.
