//----------------------------------------------------------------------------- // 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