tge/engine/collision/abstractPolyList.h
2017-04-17 06:17:10 -06:00

242 lines
7.2 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _ABSTRACTPOLYLIST_H_
#define _ABSTRACTPOLYLIST_H_
#ifndef _MMATH_H_
#include "math/mMath.h"
#endif
#ifndef _MPLANETRANSFORMER_H_
#include "math/mPlaneTransformer.h"
#endif
#ifndef _TVECTOR_H_
#include "core/tVector.h"
#endif
class SceneObject;
//----------------------------------------------------------------------------
/// A polygon filtering interface.
///
/// The various AbstractPolyList subclasses are used in Torque as an interface to
/// handle spatial queries. SceneObject::buildPolyList() takes an implementor of
/// AbstractPolyList (such as ConcretePolyList, ClippedPolyList, etc.) and a
/// bounding volume. The function runs geometry data from all the objects in the
/// bounding volume through the passed PolyList.
///
/// This interface only provides a method to get data INTO your implementation. Different
/// subclasses provide different interfaces to get data back out, depending on their
/// specific quirks.
///
/// The physics engine now uses convex hulls for collision detection.
///
/// @see Convex
class AbstractPolyList
{
protected:
// User set state
SceneObject* mCurrObject;
MatrixF mBaseMatrix; // Base transform
MatrixF mTransformMatrix; // Current object transform
MatrixF mMatrix; // Base * current transform
Point3F mScale;
PlaneTransformer mPlaneTransformer;
bool mInterestNormalRegistered;
Point3F mInterestNormal;
public:
AbstractPolyList();
virtual ~AbstractPolyList();
/// @name Common Interface
/// @{
void setBaseTransform(const MatrixF& mat);
/// Sets the transform applying to the current stream of
/// vertices.
///
/// @param mat Transformation of the object. (in)
/// @param scale Scaling of the object. (in)
void setTransform(const MatrixF* mat, const Point3F& scale);
/// Gets the transform applying to the current stream of
/// vertices.
///
/// @param mat Transformation of the object. (out)
/// @param scale Scaling of the object. (out)
void getTransform(MatrixF* mat, Point3F * scale);
/// This is called by the object which is currently feeding us
/// vertices, to tell us who it is.
void setObject(SceneObject*);
/// Add a box via the query interface (below). This wraps some calls
/// to addPoint and addPlane.
void addBox(const Box3F &box);
void doConstruct();
/// @}
/// @name Query Interface
///
/// It is through this interface that geometry data is fed to the
/// PolyList. The order of calls are:
/// - begin()
/// - One or more calls to vertex() and one call to plane(), in any order.
/// - end()
///
/// @code
/// // Example code that adds data to a PolyList.
/// // See AbstractPolyList::addBox() for the function this was taken from.
///
/// // First, we add points... (note that we use base to track the start of adding.)
/// U32 base = addPoint(pos);
/// pos.y += dy; addPoint(pos);
/// pos.x += dx; addPoint(pos);
/// pos.y -= dy; addPoint(pos);
/// pos.z += dz; addPoint(pos);
/// pos.x -= dx; addPoint(pos);
/// pos.y += dy; addPoint(pos);
/// pos.x += dx; addPoint(pos);
///
/// // Now we add our surfaces. (there are six, as we are adding a cube here)
/// for (S32 i = 0; i < 6; i++) {
/// // Begin a surface
/// begin(0,i);
///
/// // Calculate the vertex ids; we have a lookup table to tell us offset from base.
/// // In your own code, you might use a different method.
/// S32 v1 = base + PolyFace[i][0];
/// S32 v2 = base + PolyFace[i][1];
/// S32 v3 = base + PolyFace[i][2];
/// S32 v4 = base + PolyFace[i][3];
///
/// // Reference the four vertices that make up this surface.
/// vertex(v1);
/// vertex(v2);
/// vertex(v3);
/// vertex(v4);
///
/// // Indicate the plane of this surface.
/// plane(v1,v2,v3);
///
/// // End the surface.
/// end();
/// }
/// @endcode
/// @{
/// Are we empty of data?
virtual bool isEmpty() const = 0;
/// Adds a point to the poly list, and returns
/// an ID number for that point.
virtual U32 addPoint(const Point3F& p) = 0;
/// Adds a plane to the poly list, and returns
/// an ID number for that point.
virtual U32 addPlane(const PlaneF& plane) = 0;
/// Start a surface.
///
/// @param material A material ID for this surface.
/// @param surfaceKey A key value to associate with this surface.
virtual void begin(U32 material,U32 surfaceKey) = 0;
/// Indicate the plane of the surface.
virtual void plane(U32 v1,U32 v2,U32 v3) = 0;
/// Indicate the plane of the surface.
virtual void plane(const PlaneF& p) = 0;
/// Indicate the plane of the surface.
virtual void plane(const U32 index) = 0;
/// Reference a vertex which is in this surface.
virtual void vertex(U32 vi) = 0;
/// Mark the end of a surface.
virtual void end() = 0;
/// Return list transform and bounds in list space.
///
/// @returns False if no data is available.
virtual bool getMapping(MatrixF *, Box3F *);
/// @}
/// @name Interest
///
/// This is a mechanism to let you specify interest in a specific normal.
/// If you set a normal you're interested in, then any planes facing "away"
/// from that normal are culled from the results.
///
/// This is handy if you're using this to do a physics check, as you're not
/// interested in polygons facing away from you (since you don't collide with
/// the backsides/insides of things).
/// @{
void setInterestNormal(const Point3F& normal);
void clearInterestNormal() { mInterestNormalRegistered = false; }
virtual bool isInterestedInPlane(const PlaneF& plane);
virtual bool isInterestedInPlane(const U32 index);
/// @}
protected:
/// A helper function to convert a plane index to a PlaneF structure.
virtual const PlaneF& getIndexedPlane(const U32 index) = 0;
};
inline AbstractPolyList::AbstractPolyList()
{
doConstruct();
}
inline void AbstractPolyList::doConstruct()
{
mCurrObject = NULL;
mBaseMatrix.identity();
mMatrix.identity();
mScale.set(1, 1, 1);
mPlaneTransformer.setIdentity();
mInterestNormalRegistered = false;
}
inline void AbstractPolyList::setBaseTransform(const MatrixF& mat)
{
mBaseMatrix = mat;
}
inline void AbstractPolyList::setTransform(const MatrixF* mat, const Point3F& scale)
{
mMatrix = mBaseMatrix;
mTransformMatrix = *mat;
mMatrix.mul(*mat);
mScale = scale;
mPlaneTransformer.set(mMatrix, mScale);
}
inline void AbstractPolyList::getTransform(MatrixF* mat, Point3F * scale)
{
*mat = mTransformMatrix;
*scale = mScale;
}
inline void AbstractPolyList::setObject(SceneObject* obj)
{
mCurrObject = obj;
}
#endif