246 lines
8.1 KiB
C
246 lines
8.1 KiB
C
|
/*************************************************************************
|
||
|
* *
|
||
|
* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
|
||
|
* All rights reserved. Email: russ@q12.org Web: www.q12.org *
|
||
|
* *
|
||
|
* This library is free software; you can redistribute it and/or *
|
||
|
* modify it under the terms of EITHER: *
|
||
|
* (1) The GNU Lesser General Public License as published by the Free *
|
||
|
* Software Foundation; either version 2.1 of the License, or (at *
|
||
|
* your option) any later version. The text of the GNU Lesser *
|
||
|
* General Public License is included with this library in the *
|
||
|
* file LICENSE.TXT. *
|
||
|
* (2) The BSD-style license that is included with this library in *
|
||
|
* the file LICENSE-BSD.TXT. *
|
||
|
* *
|
||
|
* This library is distributed in the hope that it will be useful, *
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
|
||
|
* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
|
||
|
* *
|
||
|
*************************************************************************/
|
||
|
|
||
|
// dHeightfield Collider
|
||
|
// Martijn Buijs 2006 http://home.planet.nl/~buijs512/
|
||
|
// Based on Terrain & Cone contrib by:
|
||
|
// Benoit CHAPEROT 2003-2004 http://www.jstarlab.com
|
||
|
|
||
|
#ifndef _DHEIGHTFIELD_H_
|
||
|
#define _DHEIGHTFIELD_H_
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
#include <ode/common.h>
|
||
|
#include "collision_kernel.h"
|
||
|
|
||
|
|
||
|
#define HEIGHTFIELDMAXCONTACTPERCELL 10
|
||
|
|
||
|
|
||
|
class HeightFieldVertex;
|
||
|
class HeightFieldEdge;
|
||
|
class HeightFieldTriangle;
|
||
|
|
||
|
//
|
||
|
// dxHeightfieldData
|
||
|
//
|
||
|
// Heightfield Data structure
|
||
|
//
|
||
|
struct dxHeightfieldData
|
||
|
{
|
||
|
dReal m_fWidth; // World space heightfield dimension on X axis
|
||
|
dReal m_fDepth; // World space heightfield dimension on Z axis
|
||
|
dReal m_fSampleWidth; // Vertex spacing on X axis edge (== m_vWidth / (m_nWidthSamples-1))
|
||
|
dReal m_fSampleDepth; // Vertex spacing on Z axis edge (== m_vDepth / (m_nDepthSamples-1))
|
||
|
dReal m_fSampleZXAspect; // Relation of Z axis spacing to X axis spacing (== m_fSampleDepth / m_fSampleWidth)
|
||
|
dReal m_fInvSampleWidth; // Cache of inverse Vertex count on X axis edge (== m_vWidth / (m_nWidthSamples-1))
|
||
|
dReal m_fInvSampleDepth; // Cache of inverse Vertex count on Z axis edge (== m_vDepth / (m_nDepthSamples-1))
|
||
|
|
||
|
dReal m_fHalfWidth; // Cache of half of m_fWidth
|
||
|
dReal m_fHalfDepth; // Cache of half of m_fDepth
|
||
|
|
||
|
dReal m_fMinHeight; // Min sample height value (scaled and offset)
|
||
|
dReal m_fMaxHeight; // Max sample height value (scaled and offset)
|
||
|
dReal m_fThickness; // Surface thickness (added to bottom AABB)
|
||
|
dReal m_fScale; // Sample value multiplier
|
||
|
dReal m_fOffset; // Vertical sample offset
|
||
|
|
||
|
int m_nWidthSamples; // Vertex count on X axis edge (number of samples)
|
||
|
int m_nDepthSamples; // Vertex count on Z axis edge (number of samples)
|
||
|
int m_bCopyHeightData; // Do we own the sample data?
|
||
|
int m_bWrapMode; // Heightfield wrapping mode (0=finite, 1=infinite)
|
||
|
int m_nGetHeightMode; // GetHeight mode ( 0=callback, 1=byte, 2=short, 3=float )
|
||
|
|
||
|
const void* m_pHeightData; // Sample data array
|
||
|
void* m_pUserData; // Callback user data
|
||
|
|
||
|
dContactGeom m_contacts[HEIGHTFIELDMAXCONTACTPERCELL];
|
||
|
|
||
|
dHeightfieldGetHeight* m_pGetHeightCallback; // Callback pointer.
|
||
|
|
||
|
dxHeightfieldData();
|
||
|
~dxHeightfieldData();
|
||
|
|
||
|
void SetData( int nWidthSamples, int nDepthSamples,
|
||
|
dReal fWidth, dReal fDepth,
|
||
|
dReal fScale, dReal fOffset,
|
||
|
dReal fThickness, int bWrapMode );
|
||
|
|
||
|
void ComputeHeightBounds();
|
||
|
|
||
|
bool IsOnHeightfield2 ( const HeightFieldVertex * const CellCorner,
|
||
|
const dReal * const pos, const bool isABC) const;
|
||
|
|
||
|
dReal GetHeight(int x, int z);
|
||
|
dReal GetHeight(dReal x, dReal z);
|
||
|
|
||
|
};
|
||
|
|
||
|
typedef int HeightFieldVertexCoords[2];
|
||
|
|
||
|
class HeightFieldVertex
|
||
|
{
|
||
|
public:
|
||
|
HeightFieldVertex(){};
|
||
|
|
||
|
dVector3 vertex;
|
||
|
HeightFieldVertexCoords coords;
|
||
|
bool state;
|
||
|
};
|
||
|
|
||
|
class HeightFieldEdge
|
||
|
{
|
||
|
public:
|
||
|
HeightFieldEdge(){};
|
||
|
|
||
|
HeightFieldVertex *vertices[2];
|
||
|
};
|
||
|
|
||
|
class HeightFieldTriangle
|
||
|
{
|
||
|
public:
|
||
|
HeightFieldTriangle(){};
|
||
|
|
||
|
inline void setMinMax()
|
||
|
{
|
||
|
maxAAAB = vertices[0]->vertex[1] > vertices[1]->vertex[1] ? vertices[0]->vertex[1] : vertices[1]->vertex[1];
|
||
|
maxAAAB = vertices[2]->vertex[1] > maxAAAB ? vertices[2]->vertex[1] : maxAAAB;
|
||
|
};
|
||
|
|
||
|
HeightFieldVertex *vertices[3];
|
||
|
dReal planeDef[4];
|
||
|
dReal maxAAAB;
|
||
|
|
||
|
bool isUp;
|
||
|
bool state;
|
||
|
};
|
||
|
|
||
|
class HeightFieldPlane
|
||
|
{
|
||
|
public:
|
||
|
HeightFieldPlane():
|
||
|
trianglelist(0),
|
||
|
trianglelistReservedSize(0),
|
||
|
trianglelistCurrentSize(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
~HeightFieldPlane()
|
||
|
{
|
||
|
delete [] trianglelist;
|
||
|
}
|
||
|
|
||
|
inline void setMinMax()
|
||
|
{
|
||
|
const sizeint asize = trianglelistCurrentSize;
|
||
|
if (asize > 0)
|
||
|
{
|
||
|
maxAAAB = trianglelist[0]->maxAAAB;
|
||
|
for (sizeint k = 1; asize > k; k++)
|
||
|
{
|
||
|
if (trianglelist[k]->maxAAAB > maxAAAB)
|
||
|
maxAAAB = trianglelist[k]->maxAAAB;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
void resetTriangleListSize(const sizeint newSize)
|
||
|
{
|
||
|
if (trianglelistReservedSize < newSize)
|
||
|
{
|
||
|
delete [] trianglelist;
|
||
|
trianglelistReservedSize = newSize;
|
||
|
trianglelist = new HeightFieldTriangle *[newSize];
|
||
|
}
|
||
|
trianglelistCurrentSize = 0;
|
||
|
}
|
||
|
|
||
|
void addTriangle(HeightFieldTriangle *tri)
|
||
|
{
|
||
|
dIASSERT(trianglelistCurrentSize < trianglelistReservedSize);
|
||
|
|
||
|
trianglelist[trianglelistCurrentSize++] = tri;
|
||
|
}
|
||
|
|
||
|
HeightFieldTriangle **trianglelist;
|
||
|
sizeint trianglelistReservedSize;
|
||
|
sizeint trianglelistCurrentSize;
|
||
|
|
||
|
dReal maxAAAB;
|
||
|
dReal planeDef[4];
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// dxHeightfield
|
||
|
//
|
||
|
// Heightfield geom structure
|
||
|
//
|
||
|
struct dxHeightfield : public dxGeom
|
||
|
{
|
||
|
dxHeightfieldData* m_p_data;
|
||
|
|
||
|
dxHeightfield( dSpaceID space, dHeightfieldDataID data, int bPlaceable );
|
||
|
~dxHeightfield();
|
||
|
|
||
|
void computeAABB();
|
||
|
|
||
|
int dCollideHeightfieldZone( const int minX, const int maxX, const int minZ, const int maxZ,
|
||
|
dxGeom *o2, const int numMaxContacts,
|
||
|
int flags, dContactGeom *contact, int skip );
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
TEMP_PLANE_BUFFER_ELEMENT_COUNT_ALIGNMENT = 4,
|
||
|
TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_X = 4,
|
||
|
TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_Z = 4,
|
||
|
TEMP_TRIANGLE_BUFFER_ELEMENT_COUNT_ALIGNMENT = 1 // Triangles are easy to reallocate and hard to predict
|
||
|
};
|
||
|
|
||
|
static inline sizeint AlignBufferSize(sizeint value, sizeint alignment) { dIASSERT((alignment & (alignment - 1)) == 0); return (value + (alignment - 1)) & ~(alignment - 1); }
|
||
|
|
||
|
void allocateTriangleBuffer(sizeint numTri);
|
||
|
void resetTriangleBuffer();
|
||
|
void allocatePlaneBuffer(sizeint numTri);
|
||
|
void resetPlaneBuffer();
|
||
|
void allocateHeightBuffer(sizeint numX, sizeint numZ);
|
||
|
void resetHeightBuffer();
|
||
|
|
||
|
void sortPlanes(const sizeint numPlanes);
|
||
|
|
||
|
HeightFieldPlane **tempPlaneBuffer;
|
||
|
HeightFieldPlane *tempPlaneInstances;
|
||
|
sizeint tempPlaneBufferSize;
|
||
|
|
||
|
HeightFieldTriangle *tempTriangleBuffer;
|
||
|
sizeint tempTriangleBufferSize;
|
||
|
|
||
|
HeightFieldVertex **tempHeightBuffer;
|
||
|
HeightFieldVertex *tempHeightInstances;
|
||
|
sizeint tempHeightBufferSizeX;
|
||
|
sizeint tempHeightBufferSizeZ;
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
#endif //_DHEIGHTFIELD_H_
|