Open Dynamics Engine

heightfield.h

00001 // dHeightfield Collider
00002 //  Martijn Buijs 2006 http://home.planet.nl/~buijs512/
00003 // Based on Terrain & Cone contrib by:
00004 //  Benoit CHAPEROT 2003-2004 http://www.jstarlab.com
00005 
00006 #ifndef _DHEIGHTFIELD_H_
00007 #define _DHEIGHTFIELD_H_
00008 //------------------------------------------------------------------------------
00009 
00010 #include <ode/common.h>
00011 #include "collision_kernel.h"
00012 
00013 
00014 #define HEIGHTFIELDMAXCONTACTPERCELL 10
00015 
00016 
00017 class HeightFieldVertex;
00018 class HeightFieldEdge;
00019 class HeightFieldTriangle;
00020 
00021 //
00022 // dxHeightfieldData
00023 //
00024 // Heightfield Data structure
00025 //
00026 struct dxHeightfieldData
00027 {
00028     dReal m_fWidth;           // World space heightfield dimension on X axis
00029     dReal m_fDepth;           // World space heightfield dimension on Z axis
00030     dReal m_fSampleWidth;     // Vertex spacing on X axis edge (== m_vWidth / (m_nWidthSamples-1))
00031     dReal m_fSampleDepth;     // Vertex spacing on Z axis edge (== m_vDepth / (m_nDepthSamples-1))
00032     dReal m_fSampleZXAspect;    // Relation of Z axis spacing to X axis spacing (== m_fSampleDepth / m_fSampleWidth)
00033     dReal m_fInvSampleWidth;     // Cache of inverse Vertex count on X axis edge (== m_vWidth / (m_nWidthSamples-1))
00034     dReal m_fInvSampleDepth;     // Cache of inverse Vertex count on Z axis edge (== m_vDepth / (m_nDepthSamples-1))
00035 
00036     dReal m_fHalfWidth;       // Cache of half of m_fWidth
00037     dReal m_fHalfDepth;       // Cache of half of m_fDepth
00038 
00039     dReal m_fMinHeight;        // Min sample height value (scaled and offset)
00040     dReal m_fMaxHeight;        // Max sample height value (scaled and offset)
00041     dReal m_fThickness;        // Surface thickness (added to bottom AABB)
00042     dReal m_fScale;            // Sample value multiplier
00043     dReal m_fOffset;           // Vertical sample offset
00044 
00045     int  m_nWidthSamples;       // Vertex count on X axis edge (number of samples)
00046     int  m_nDepthSamples;       // Vertex count on Z axis edge (number of samples)
00047     int m_bCopyHeightData;     // Do we own the sample data?
00048     int  m_bWrapMode;           // Heightfield wrapping mode (0=finite, 1=infinite)
00049     int m_nGetHeightMode;      // GetHeight mode ( 0=callback, 1=byte, 2=short, 3=float )
00050 
00051     const void* m_pHeightData; // Sample data array
00052     void* m_pUserData;         // Callback user data
00053 
00054     dContactGeom            m_contacts[HEIGHTFIELDMAXCONTACTPERCELL];
00055 
00056     dHeightfieldGetHeight* m_pGetHeightCallback;      // Callback pointer.
00057 
00058     dxHeightfieldData();
00059     ~dxHeightfieldData();
00060 
00061     void SetData( int nWidthSamples, int nDepthSamples,
00062         dReal fWidth, dReal fDepth,
00063         dReal fScale, dReal fOffset,
00064         dReal fThickness, int bWrapMode );
00065 
00066     void ComputeHeightBounds();
00067 
00068     bool IsOnHeightfield2  ( const HeightFieldVertex * const CellCorner, 
00069         const dReal * const pos,  const bool isABC) const;
00070 
00071     dReal GetHeight(int x, int z);
00072     dReal GetHeight(dReal x, dReal z);
00073 
00074 };
00075 
00076 typedef int HeightFieldVertexCoords[2];
00077 
00078 class HeightFieldVertex
00079 {
00080 public:
00081     HeightFieldVertex(){};
00082 
00083     dVector3 vertex;
00084     HeightFieldVertexCoords coords;
00085     bool state;
00086 };
00087 
00088 class HeightFieldEdge
00089 {
00090 public:
00091     HeightFieldEdge(){};
00092 
00093     HeightFieldVertex   *vertices[2];
00094 };
00095 
00096 class HeightFieldTriangle
00097 {
00098 public:
00099     HeightFieldTriangle(){};
00100 
00101     inline void setMinMax()
00102     {
00103         maxAAAB = vertices[0]->vertex[1] > vertices[1]->vertex[1] ? vertices[0]->vertex[1] : vertices[1]->vertex[1];
00104         maxAAAB = vertices[2]->vertex[1] > maxAAAB  ? vertices[2]->vertex[1] : maxAAAB;
00105     };
00106 
00107     HeightFieldVertex   *vertices[3];
00108     dReal               planeDef[4];
00109     dReal               maxAAAB;
00110 
00111     bool                isUp;
00112     bool                state;
00113 };
00114 
00115 class HeightFieldPlane
00116 {
00117 public:
00118     HeightFieldPlane():
00119       trianglelist(0),
00120       trianglelistReservedSize(0),
00121       trianglelistCurrentSize(0)
00122     {
00123 
00124     };
00125     ~HeightFieldPlane()
00126     {
00127         delete [] trianglelist;
00128     };
00129 
00130     inline void setMinMax()
00131     {
00132         const size_t asize = trianglelistCurrentSize;
00133         if (asize > 0)
00134         {  
00135             maxAAAB = trianglelist[0]->maxAAAB;
00136             for (size_t k = 1; asize > k; k++)
00137             {   
00138                 if (trianglelist[k]->maxAAAB >  maxAAAB)
00139                     maxAAAB = trianglelist[k]->maxAAAB;
00140             }
00141         }
00142     };
00143 
00144     void resetTriangleListSize(const size_t newSize)
00145     {
00146         if (trianglelistReservedSize < newSize)
00147         {
00148             delete [] trianglelist;
00149             trianglelistReservedSize = newSize;
00150             trianglelist = new HeightFieldTriangle *[newSize];
00151         }
00152         trianglelistCurrentSize = 0;
00153     }
00154 
00155     void addTriangle(HeightFieldTriangle *tri)
00156     {
00157       dIASSERT(trianglelistCurrentSize < trianglelistReservedSize);
00158 
00159         trianglelist[trianglelistCurrentSize++] = tri;
00160     }
00161 
00162     HeightFieldTriangle **trianglelist;
00163     size_t              trianglelistReservedSize;
00164     size_t              trianglelistCurrentSize;
00165 
00166     dReal   maxAAAB;
00167     dReal   planeDef[4];
00168 };
00169 
00170 //
00171 // dxHeightfield
00172 //
00173 // Heightfield geom structure
00174 //
00175 struct dxHeightfield : public dxGeom
00176 {
00177     dxHeightfieldData* m_p_data;
00178 
00179     dxHeightfield( dSpaceID space, dHeightfieldDataID data, int bPlaceable );
00180     ~dxHeightfield();
00181 
00182     void computeAABB();
00183 
00184     int dCollideHeightfieldZone( const int minX, const int maxX, const int minZ, const int maxZ,  
00185         dxGeom *o2, const int numMaxContacts,
00186         int flags, dContactGeom *contact, int skip );
00187 
00188    enum
00189    {
00190       TEMP_PLANE_BUFFER_ELEMENT_COUNT_ALIGNMENT = 4,
00191       TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_X = 4,
00192       TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_Z = 4,
00193       TEMP_TRIANGLE_BUFFER_ELEMENT_COUNT_ALIGNMENT = 1, // Triangles are easy to reallocate and hard to predict
00194    };
00195 
00196    static inline size_t AlignBufferSize(size_t value, size_t alignment) { dIASSERT((alignment & (alignment - 1)) == 0); return (value + (alignment - 1)) & ~(alignment - 1); }
00197 
00198    void  allocateTriangleBuffer(size_t numTri);
00199    void  resetTriangleBuffer();
00200    void  allocatePlaneBuffer(size_t numTri);
00201    void  resetPlaneBuffer();
00202    void  allocateHeightBuffer(size_t numX, size_t numZ);
00203     void  resetHeightBuffer();
00204 
00205     void  sortPlanes(const size_t numPlanes);
00206 
00207     HeightFieldPlane    **tempPlaneBuffer;
00208     HeightFieldPlane    *tempPlaneInstances;
00209     size_t              tempPlaneBufferSize;
00210 
00211     HeightFieldTriangle *tempTriangleBuffer;
00212     size_t              tempTriangleBufferSize;
00213 
00214     HeightFieldVertex   **tempHeightBuffer;
00215    HeightFieldVertex   *tempHeightInstances;
00216     size_t              tempHeightBufferSizeX;
00217     size_t              tempHeightBufferSizeZ;
00218 
00219 };
00220 
00221 
00222 //------------------------------------------------------------------------------
00223 #endif //_DHEIGHTFIELD_H_