You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
7.5 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
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 3 of the License, or
(at your option) any later version.
This program 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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plCullTree_inc
#define plCullTree_inc
#include "hsBounds.h"
#include "hsGeometry3.h"
#include "hsBitVector.h"
#include "plCuller.h"
#include "../plScene/plCullPoly.h"
#ifdef HS_DEBUGGING
#define DEBUG_POINTERS
#endif // HS_DEBUGGING
class plCullTree;
class plCullNode;
// for vis
struct hsPoint3;
struct hsVector3;
struct hsColorRGBA;
class plCullTree : public plCuller
{
protected:
// Visualization stuff, to be nuked from production version.
mutable hsBool fCapturePolys;
mutable hsTArray<hsPoint3> fVisVerts;
mutable hsTArray<hsVector3> fVisNorms;
mutable hsTArray<hsColorRGBA> fVisColors;
mutable hsTArray<UInt16> fVisTris;
mutable hsScalar fVisYon;
mutable hsTArray<plCullPoly> fScratchPolys;
mutable hsLargeArray<Int16> fScratchClear;
mutable hsLargeArray<Int16> fScratchSplit;
mutable hsLargeArray<Int16> fScratchCulled;
mutable hsBitVector fScratchBitVec;
mutable hsBitVector fScratchTotVec;
void IVisPolyShape(const plCullPoly& poly, hsBool dark) const;
void IVisPolyEdge(const hsPoint3& p0, const hsPoint3& p1, hsBool dark) const;
void IVisPoly(const plCullPoly& poly, hsBool dark) const;
hsPoint3 fViewPos;
Int16 fRoot;
mutable hsTArray<plCullNode> fNodeList; // Scratch list we make the tree from.
plCullNode* IGetRoot() const { return IGetNode(fRoot); }
plCullNode* IGetNode(Int16 i) const { return i >= 0 ? &fNodeList[i] : nil; }
void ITestNode(const plSpaceTree* space, Int16 who, hsTArray<Int16>& outList) const; // Appends to outlist
void ITestList(const plSpaceTree* space, const hsTArray<Int16>& inList, hsTArray<Int16>& outList) const;
Int16 IAddPolyRecur(const plCullPoly& poly, Int16 iNode);
Int16 IMakeHoleSubTree(const plCullPoly& poly) const;
Int16 IMakePolySubTree(const plCullPoly& poly) const;
Int16 IMakePolyNode(const plCullPoly& poly, int i0, int i1) const;
// Some scratch areas for the nodes use when building the tree etc.
hsTArray<plCullPoly>& ScratchPolys() const { return fScratchPolys; }
hsLargeArray<Int16>& ScratchClear() const { return fScratchClear; }
hsLargeArray<Int16>& ScratchSplit() const { return fScratchSplit; }
hsLargeArray<Int16>& ScratchCulled() const { return fScratchCulled; }
hsBitVector& ScratchBitVec() const { return fScratchBitVec; }
hsBitVector& ScratchTotVec() const { return fScratchTotVec; }
void ISetupScratch(UInt16 nNodes);
friend class plCullNode;
public:
plCullTree();
~plCullTree();
void Reset(); // Called before starting to add polys for this frame.
void InitFrustum(const hsMatrix44& world2NDC);
void SetViewPos(const hsPoint3& pos);
void AddPoly(const plCullPoly& poly);
UInt32 GetNumNodes() const { return fNodeList.GetCount(); }
virtual void Harvest(const plSpaceTree* space, hsTArray<Int16>& outList) const;
virtual hsBool BoundsVisible(const hsBounds3Ext& bnd) const;
virtual hsBool SphereVisible(const hsPoint3& center, hsScalar rad) const;
// Visualization stuff. Only to be called by the pipeline (or some other vis manager).
void SetVisualizationYon(hsScalar y) const { fVisYon = y; }
void BeginCapturePolys() const { fCapturePolys = true; }
void EndCapturePolys() const { fCapturePolys = false; }
hsTArray<hsPoint3>& GetCaptureVerts() const { return fVisVerts; }
hsTArray<hsVector3>& GetCaptureNorms() const { return fVisNorms; }
hsTArray<hsColorRGBA>& GetCaptureColors() const { return fVisColors; }
hsTArray<UInt16>& GetCaptureTris() const { return fVisTris; }
void ReleaseCapture() const;
};
class plCullNode
{
public:
enum plCullStatus
{
kClear,
kCulled,
kSplit,
kPureSplit
};
protected:
hsVector3 fNorm;
hsScalar fDist;
hsBool fIsFace;
Int16 fInnerChild;
Int16 fOuterChild;
const plCullTree* fTree;
plCullNode* IGetNode(Int16 i) const;
#ifdef DEBUG_POINTERS
mutable plCullNode* fInnerPtr;
mutable plCullNode* fOuterPtr;
void ISetPointersRecur() const;
#else // DEBUG_POINTERS
void ISetPointersRecur() const {}
#endif // DEBUG_POINTERS
// Bounds only version
plCullNode::plCullStatus ITestBoundsRecur(const hsBounds3Ext& bnd) const;
plCullNode::plCullStatus ITestSphereRecur(const hsPoint3& center, hsScalar rad) const;
// Using the nodes
plCullNode::plCullStatus ITestNode(const plSpaceTree* space, Int16 who, hsLargeArray<Int16>& clear, hsLargeArray<Int16>& split, hsLargeArray<Int16>& culled) const;
void ITestNode(const plSpaceTree* space, Int16 who, hsBitVector& totList, hsBitVector& outList) const;
void IHarvest(const plSpaceTree* space, hsTArray<Int16>& outList) const;
// Constructing the tree
hsScalar IInterpVert(const hsPoint3& p0, const hsPoint3& p1, hsPoint3& out) const;
plCullNode::plCullStatus ISplitPoly(const plCullPoly& poly, plCullPoly*& innerPoly, plCullPoly*& outerPoly) const;
void IMarkClipped(const plCullPoly& poly, const hsBitVector& onVerts) const;
void ITakeHalfPoly(const plCullPoly& scrPoly,
const hsTArray<int>& vtxIdx,
const hsBitVector& onVerts,
plCullPoly& outPoly) const;
void IBreakPoly(const plCullPoly& poly, const hsTArray<hsScalar>& depths,
hsBitVector& inVerts,
hsBitVector& outVerts,
hsBitVector& onVerts,
plCullPoly& srcPoly) const;
hsTArray<plCullPoly>& ScratchPolys() const { return fTree->ScratchPolys(); }
hsLargeArray<Int16>& ScratchClear() const { return fTree->ScratchClear(); }
hsLargeArray<Int16>& ScratchSplit() const { return fTree->ScratchSplit(); }
hsLargeArray<Int16>& ScratchCulled() const { return fTree->ScratchCulled(); }
hsBitVector& ScratchBitVec() const { return fTree->ScratchBitVec(); }
hsBitVector& ScratchTotVec() const { return fTree->ScratchTotVec(); }
friend class plCullTree;
public:
void Init(const plCullTree* t, const hsVector3& n, hsScalar d) { fIsFace = false; fTree = t; fInnerChild = fOuterChild = -1; SetPlane(n, d); }
void Init(const plCullTree* t, const plCullPoly& poly) { Init(t, poly.fNorm, poly.fDist); }
void SetPlane(const hsVector3& n, hsScalar d) { fNorm = n; fDist = d; }
const hsVector3& GetNormal() const { return fNorm; }
const hsScalar GetDist() const { return fDist; }
plCullStatus TestBounds(const hsBounds3Ext& bnd) const;
plCullStatus TestSphere(const hsPoint3& center, hsScalar rad) const;
};
inline plCullNode* plCullNode::IGetNode(Int16 i) const
{
return fTree->IGetNode(i);
}
#endif // plCullTree_inc