2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 02:27:40 -04:00

CWE Directory Reorganization

Rearrange directory structure of CWE to be loosely equivalent to
the H'uru Plasma repository.

Part 1: Movement of directories and files.
This commit is contained in:
rarified
2021-05-15 12:49:46 -06:00
parent c3f4a640a3
commit 96903e8dca
4002 changed files with 159 additions and 644 deletions

View File

@ -0,0 +1,202 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
#include "hsTypes.h"
#include "plCullPoly.h"
#include "hsMatrix44.h"
#include "hsStream.h"
#include "hsFastMath.h"
plCullPoly& plCullPoly::InitFromVerts(UInt32 f)
{
fFlags = f;
hsAssert(fVerts.GetCount() > 2, "Initializing from degenerate poly");
hsVector3 a;
hsVector3 b;
a.Set(&fVerts[1], &fVerts[0]);
b.Set(&fVerts[2], &fVerts[0]);
fNorm = a % b;
hsFastMath::Normalize(fNorm);
fDist = -(fNorm.InnerProduct(fVerts[0]));
fCenter.Set(0,0,0);
int i;
for( i = 0; i < fVerts.GetCount(); i++ )
{
fCenter += fVerts[i];
}
fCenter *= 1.f / hsScalar(fVerts.GetCount());
fRadius = ICalcRadius();
return *this;
}
hsScalar plCullPoly::ICalcRadius() const
{
hsScalar radSq = 0;
int i;
for( i = 0; i < fVerts.GetCount(); i++ )
{
hsScalar tmpSq = hsVector3(&fVerts[i], &fCenter).MagnitudeSquared();
if( tmpSq > radSq )
radSq = tmpSq;
}
return radSq * hsFastMath::InvSqrt(radSq);
}
plCullPoly& plCullPoly::Flip(const plCullPoly& p)
{
fFlags = p.fFlags;
fNorm = -p.fNorm;
fDist = -p.fDist;
fCenter = p.fCenter;
fRadius = p.fRadius;
int n = p.fVerts.GetCount();
fVerts.SetCount(n);
int i;
for( i = 0; i < n; i++ )
fVerts[n-i-1] = p.fVerts[i];
return *this;
}
plCullPoly& plCullPoly::Transform(const hsMatrix44& l2w, const hsMatrix44& w2l, plCullPoly& dst) const
{
hsMatrix44 tpose;
w2l.GetTranspose(&tpose);
dst.fFlags = fFlags;
dst.fVerts.SetCount(fVerts.GetCount());
int i;
for( i = 0; i < fVerts.GetCount(); i++ )
{
dst.fVerts[i] = l2w * fVerts[i];
}
dst.fCenter = l2w * fCenter;
dst.fNorm = tpose * fNorm;
dst.fDist = -(dst.fNorm .InnerProduct(dst.fVerts[0]));
ICalcRadius();
return dst;
}
void plCullPoly::Read(hsStream* s, hsResMgr* mgr)
{
fFlags = s->ReadSwap32();
fNorm.Read(s);
fDist = s->ReadSwapScalar();
fCenter.Read(s);
fRadius = s->ReadSwapScalar();
int n = s->ReadSwap32();
fVerts.SetCount(n);
int i;
for( i = 0; i < n; i++ )
fVerts[i].Read(s);
}
void plCullPoly::Write(hsStream* s, hsResMgr* mgr)
{
s->WriteSwap32(fFlags);
fNorm.Write(s);
s->WriteSwapScalar(fDist);
fCenter.Write(s);
s->WriteSwapScalar(fRadius);
s->WriteSwap32(fVerts.GetCount());
int i;
for( i = 0; i < fVerts.GetCount(); i++ )
fVerts[i].Write(s);
}
#ifdef HS_DEBUGGING
#define MF_VALIDATE_POLYS
#endif // HS_DEBUGGING
#ifdef MF_VALIDATE_POLYS
hsBool plCullPoly::Validate() const
{
const hsScalar kMinMag = 1.e-8f;
hsScalar magSq = fNorm.MagnitudeSquared();
if( magSq < kMinMag )
return false;
if( fVerts.GetCount() < 3 )
return false;
hsVector3 norm = hsVector3(&fVerts[1], &fVerts[0]) % hsVector3(&fVerts[2], &fVerts[0]);
magSq = norm.MagnitudeSquared();
if( magSq < kMinMag )
return false;
norm *= hsFastMath::InvSqrtAppr(magSq);
int i;
for( i = 3; i < fVerts.GetCount(); i++ )
{
hsVector3 nextNorm = hsVector3(&fVerts[i-1], &fVerts[0]) % hsVector3(&fVerts[i], &fVerts[0]);
magSq = nextNorm.MagnitudeSquared();
if( magSq < kMinMag )
return false;
nextNorm *= hsFastMath::InvSqrtAppr(magSq);
if( nextNorm.InnerProduct(norm) < kMinMag )
return false;
}
return true;
}
#else // MF_VALIDATE_POLYS
hsBool plCullPoly::Validate() const
{
return true;
}
#endif // MF_VALIDATE_POLYS

View File

@ -0,0 +1,98 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plCullPoly_inc
#define plCullPoly_inc
#include "hsTemplates.h"
#include "hsGeometry3.h"
#include "hsBitVector.h"
class hsStream;
class hsResMgr;
struct hsMatrix44;
const hsScalar kCullPolyDegen = 1.e-4f;
class plCullPoly
{
public:
enum {
kNone = 0x0,
kHole = 0x1,
kTwoSided = 0x2
};
UInt32 fFlags;
mutable hsBitVector fClipped; // fClipped[i] => edge(fVerts[i], fVerts[(i+1)%n])
hsTArray<hsPoint3> fVerts;
hsVector3 fNorm;
hsScalar fDist;
hsPoint3 fCenter;
hsScalar fRadius;
const hsPoint3& GetCenter() const { return fCenter; }
hsScalar GetRadius() const { return fRadius; }
void SetHole(hsBool on) { if( on )fFlags |= kHole; else fFlags &= ~kHole; }
void SetTwoSided(hsBool on) { if( on )fFlags |= kTwoSided; else fFlags &= ~kTwoSided; }
hsBool IsHole() const { return fFlags & kHole; } // Assumes kHole is 0x1
hsBool IsTwoSided() const { return 0 != (fFlags & kTwoSided); }
plCullPoly& Init(const plCullPoly& p) { fClipped.Clear(); fVerts.SetCount(0); fFlags = p.fFlags; fNorm = p.fNorm; fDist = p.fDist; fCenter = p.fCenter; return *this; }
plCullPoly& Flip(const plCullPoly& p);
plCullPoly& InitFromVerts(UInt32 f=kNone);
hsScalar ICalcRadius() const;
plCullPoly& Transform(const hsMatrix44& l2w, const hsMatrix44& w2l, plCullPoly& dst) const;
void Read(hsStream* s, hsResMgr* mgr);
void Write(hsStream* s, hsResMgr* mgr);
hsBool DegenerateVert(const hsPoint3& p) const { return fVerts.GetCount() && (kCullPolyDegen > hsVector3(&p, &fVerts[fVerts.GetCount()-1]).MagnitudeSquared()); }
hsBool Validate() const; // no-op, except for special debugging circumstances.
};
#endif // plCullPoly_inc

View File

@ -0,0 +1,237 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
void plOccTree::AddPoly(plPolygon* poly)
{
fBasePolys.Append(*poly);
}
void plOccTree::MakeOccTree()
{
if( !fBasePolys.GetCount() )
return;
ISortBasePolys();
int i;
for( i = 0; i < fBasePolys.GetCount(); i++ )
fRoot = IAddPolyRecur(fRoot, fBasePolys[i], false);
fBasePolys.SetCount(0);
}
plOccNode* poOccTree::IMakeSubTree(plOccPoly* poly)
{
plOccNode* nextNode = nil;
plOccNode* lastNode = nil;
int i;
for( i = 0; i < poly->fVerts.GetCount(); i++ )
{
if( poly->fEdgeFlags[i] & plOccPoly::kEdgeClipped )
continue;
nextNode = fNodePool.Append();
nextNode->fFlags = 0;
nextNode->fOutChild = nil;
int j = i+1 < poly->fVerts.GetCount() ? i+1 : 0;
// Need to set the viewplane here. Calc once per base poly and use
// that for fragments?
nextNode->Init(poly->fVerts[i], poly->fVerts[j], fViewPos);
if( nextNode->fInChild = lastChild )
nextNode->fFlags = plOccNode::kHasInChild;
else
{
nextNode->fInChild = fNodePool.Append();
nextNode->fInChild->Init(poly, false);
}
lastNode = nextNode;
}
// If we have no nextNode, all our edges were clipped. In
// that case, we'll just return an "out" leaf.
if( !nextNode )
{
nextNode = fNodePool.Append();
nextNode->fFlags = 0;
nextNode->fInChild = nextNode->fOutChild = nil;
nextNode->Init(poly, true);
}
return nextNode;
}
void plOccNode::Init(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& pv)
{
hsVector3 v0, v1;
v0.Set(&p0, &pv);
v1.Set(&p1, &pv);
fPlane.fNormal = v0 % v1;
fPlane.fDist = fPlane.fNormal.InnerProduct(v0);
}
void plOccNode::Init(plOccPoly* poly)
{
fPlane = poly->fPlane;
// set the viewplane
fFlags = kIsLeaf;
}
// Adding a poly to a node
// if the node is nil
// IMakeSubTree(poly) replaces the node
// else
// if the node is a leaf
// pitch the poly
// return node (no replacement)
// else
// if poly is inside the node
// recur on node's inner child
// return node (no replacement)
// else
// if poly is ouside the node
// recur on node's outer child
// return node (no replacement)
// else (node splits poly)
// recur on node's inner child
// recur on node's outer child
// return node (no replacement)
// end
//
// Special case - Degenarate poly's can come
// from ITestPoly if an edge of the input poly
// is on the plane. In that case, the function
// will return kSplit, but either inPoly or outPoly
// will have no vertices. That degenerate poly,
// when added to a node, should just be pitched.
//
// Returns new root, in case it changed.
// This assumes polys are being added front to back.
// This function will break the poly into fragments that fit in the
// current planes within the tree. Planes are added when a final fragment
// is added (in IMakeSubTree).
// We count on ITestPoly to properly mark edges which were created by
// clipping, as those won't generate leaf nodes.
plOccNode* plOccTree::IAddPolyRecur(plOccNode* node, plOccPoly* poly)
{
if( !poly->fVerts.GetCount() )
return node;
if( !node )
{
return IMakeSubTree(poly);
}
plOccPoly* inPoly = nil;
plOccPoly* outPoly = nil;
UInt32 test = ITestPoly(node->fPlane, poly, inPoly, outPoly);
switch( test )
{
case kAllIn:
node->fInChild = IAddPolyRecur(node->fInChild, poly);
break;
case kAllOut:
node->fOutChild = IAddPolyRecur(node->fOutChild, poly);
break;
case kSplit:
node->fInChild = IAddPolyRecur(node->fInChild, inPoly);
node->fOutChild = IAddPolyRecur(node->fOutChild, outPoly);
break;
};
return node;
}
hsBool plOccTree::BoundsVisible(const hsBounds3Ext& bnd) const
{
if( !fRoot )
return true;
return fRoot->IBoundsVisible(bnd);
}
hsBool plOccNode::IInChildBoundsVisible(const hsBounds3Ext& bnd) const
{
return fInChild
? fInChild->IBoundsVisible(bnd)
: false;
}
hsBool plOccNode::IOutChildBoundsVisible(const hsBounds3Ext& bnd) const
{
return fOutChild
? fOutChild->IBoundsVisible(bnd)
: true;
}
hsBool plOccNode::IBoundsVisible(const hsBounds3Ext& bnd) const
{
hsPoint2 depth;
bnd.TestPlane(fPlane.fNormal, depth);
if( depth.fX > fPlane.fDist )
{
return IOutChildVisible(bnd);
}
else if( depth.fY < fPlane.fDist )
{
return IInChildVisible(bnd);
}
// here's where it gets wierd. we pass the bounds in
// both directions. if either says it's visible, it's visible.
// doesn't seem like it would work, but you never know.
return IOutChildVisible(bnd) || IInChildVisible(bnd);
}

View File

@ -0,0 +1,180 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plOccTree_inc
#define plOccTree_inc
#include "hsTemplates.h"
#include "hsGeometry3.h"
class plBoundsHierarchy;
class plOccPlane
{
public:
hsVector3 fNormal;
hsScalar fDist;
};
class plOccPoly
{
public:
enum {
kEdgeClipped = 0x1
};
plOccPlane fPlane;
hsTArray<hsPoint3> fVerts;
hsTArray<UInt8> fEdgeFlags; // flag[i] => edge(fVerts[i], fVerts[(i+1)%n])
};
class plOccNode
{
protected:
enum {
kNone = 0x0,
kIsLeaf = 0x1
};
enum {
kAllIn = 0x0,
kAllOut = 0x1,
kSplit = 0x2
};
UInt32 fFlags;
plOccPlane fPolyPlane; // Plane of the poly we came from
plOccPlane fViewPlane; // Plane perp to view dir.
// For an interior node, ViewPlane is for the nearest (to view) point
// on the poly. A bound closer than that will not be occluded by this
// node or any nodes deeper in the tree.
// For a leaf it's the farthest point on the poly. A bound inside this
// plane OR the PolyPlane is occluded.
plOccNode* fInChild;
plOccNode* fOutChild;
};
class plOccTree
{
protected:
enum {
kNone = 0x0,
kNeedsBuild = 0x1
};
UInt8 fFlags;
// Temp pools for building our trees each frame.
hsTArray<plOccPoly> fPolyPool;
hsTArray<plOccPoly> fBasePolys;
// The BSP used to add our polys front to back. This BSP is constant.
plOccNode* fBSP;
// This current frame's view pos and occluder tree.
plOccNode* fRoot;
hsPoint3 fViewPos;
plOccNode* IAddPolyRecur(plOccNode* n, plOccPoly* poly);
void ITrimPoly(plOccPlane& plane, plOccPoly* polyIn, plOccPoly*& polyIn, plOccPoly*& polyOut);
plOccNode* IBuildOccTree();
public:
plOccTree() : fFlags(kNone), fBSP(nil), fRoot(nil) {}
~plOccTree() {}
// We'll take in the view position (for sorting and building).
// The view direction isn't necessary, but may be useful for
// selecting a subset of occluders (like don't bother with ones parallel to the view dir).
// What we really want is to pass in the viewport walls, or all the clip planes to initialize
// the occtree, then occluders out of view are automatically pruned, and the single test
// does the full view/portal/occluder test.
void SetView(const hsPoint3& pos, const hsVector3& dir);
// The algorithm is:
// if bnd is totally inside this node's plane
// recur bnd on inside child/leaf
// else if bnd is totaly outside this node's plane
// recur bnd on outside child
// else
// recur bnd's children on this node
//
// There's two ways to output the visibility info
// 1) Set a visible/invisible bit for each of the bnd leaves
// 2) output a list of visible bnds.
// The second is preferable, since leaves determined invisible by interior
// node tests never get traversed. But if the rendering pipeline has needs
// to traverse the drawable data in some other order (for depth or material
// sorting for example), then the list of visible bnds needs to be translated
// into the first option anyway.
//
// Notes on the vague algorithm:
// When recurring on the inside child, hitting a leaf checks against the source
// occluder poly, with the usual inside=hidden, outside=visible, split recurs
// the bnd's children on this leaf.
// Hitting a nil outside child == visible
// It's a double recursion, recurring first on the bnd hierarchy, and second on the occluder tree.
// Recursion stops when:
// 1) A bnd is totally in or totally out of a leaf of the occluder tree
// 2) A bnd is a leaf of the bnd hierarchy.
//
void TestHeirarchy(plBoundsHierarchy* bnd);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
// Export only
void AddPoly(plOccPoly* poly);
void BuildBSP();
};
#endif // plOccTree_inc

View File

@ -0,0 +1,403 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
#include "hsTypes.h"
#include "plOccluder.h"
#include "hsStream.h"
#include "plOccluderProxy.h"
#include "../plDrawable/plDrawableGenerator.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayerInterface.h"
#include "../plSurface/plLayer.h"
#include "../pnMessage/plNodeRefMsg.h"
#include "../pnKeyedObject/plKey.h"
#include "hsResMgr.h"
#include "plgDispatch.h"
#include "plVisRegion.h"
#include "plVisMgr.h"
plOccluder::plOccluder()
: fSceneNode(nil)
{
fProxyGen = TRACKED_NEW plOccluderProxy;
fProxyGen->Init(this);
fVisSet.SetBit(0);
}
plOccluder::~plOccluder()
{
delete fProxyGen;
}
hsBool plOccluder::MsgReceive(plMessage* msg)
{
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef(msg);
if( refMsg )
{
switch( refMsg->fType )
{
case kRefVisRegion:
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
{
IAddVisRegion(plVisRegion::ConvertNoRef(refMsg->GetRef()));
}
else
{
IRemoveVisRegion(plVisRegion::ConvertNoRef(refMsg->GetRef()));
}
return true;
default:
break;
}
}
return plObjInterface::MsgReceive(msg);
}
void plOccluder::IAddVisRegion(plVisRegion* reg)
{
if( reg )
{
int idx = fVisRegions.Find(reg);
if( fVisRegions.kMissingIndex == idx )
{
fVisRegions.Append(reg);
if( reg->GetProperty(plVisRegion::kIsNot) )
fVisNot.SetBit(reg->GetIndex());
else
{
fVisSet.SetBit(reg->GetIndex());
if( reg->ReplaceNormal() )
fVisSet.ClearBit(plVisMgr::kNormal);
}
}
}
}
void plOccluder::IRemoveVisRegion(plVisRegion* reg)
{
if( reg )
{
int idx = fVisRegions.Find(reg);
if( fVisRegions.kMissingIndex != idx )
{
fVisRegions.Remove(idx);
if( reg->GetProperty(plVisRegion::kIsNot) )
fVisNot.ClearBit(reg->GetIndex());
else
fVisSet.ClearBit(reg->GetIndex());
}
}
}
plDrawableSpans* plOccluder::CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo)
{
hsTArray<hsPoint3> pos;
hsTArray<hsVector3> norm;
hsTArray<hsColorRGBA> color;
hsTArray<UInt16> tris;
plLayer* lay = plLayer::ConvertNoRef(mat->GetLayer(0)->BottomOfStack());
if( lay )
lay->SetMiscFlags(lay->GetMiscFlags() & ~hsGMatState::kMiscTwoSided);
const hsTArray<plCullPoly>& polys = GetLocalPolyList();
int i;
for( i = 0; i < polys.GetCount(); i++ )
{
hsColorRGBA col;
if( polys[i].IsHole() )
col.Set(0,0,0,1.f);
else
col.Set(1.f, 1.f, 1.f, 1.f);
int triStart = tris.GetCount();
int idx0 = pos.GetCount();
pos.Append(polys[i].fVerts[0]);
norm.Append(polys[i].fNorm);
color.Append(col);
pos.Append(polys[i].fVerts[1]);
norm.Append(polys[i].fNorm);
color.Append(col);
int j;
for( j = 2; j < polys[i].fVerts.GetCount(); j++ )
{
int idxCurr = pos.GetCount();
pos.Append(polys[i].fVerts[j]);
norm.Append(polys[i].fNorm);
color.Append(col);
tris.Append(idx0);
tris.Append(idxCurr-1);
tris.Append(idxCurr);
}
#if 1
if( polys[i].IsTwoSided() )
{
int n = tris.GetCount();
while( --n >= triStart )
{
int idx = tris[n];
tris.Append(idx);
}
}
#endif
}
return plDrawableGenerator::GenerateDrawable(pos.GetCount(),
pos.AcquireArray(),
norm.AcquireArray(),
nil, 0,
color.AcquireArray(),
true,
nil,
tris.GetCount(),
tris.AcquireArray(),
mat,
GetLocalToWorld(),
true,
&idx,
addTo);
}
void plOccluder::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
{
// Commenting out the following asserts. Although they are fundamentally correct,
//essentially identity matrices which aren't so flagged (because of numerical
// precision) are triggering bogus asserts. mf
// hsAssert(l2w.fFlags & hsMatrix44::kIsIdent, "Non-identity transform to non-movable Occluder");
// hsAssert(w2l.fFlags & hsMatrix44::kIsIdent, "Non-identity transform to non-movable Occluder");
}
const hsMatrix44& plOccluder::GetLocalToWorld() const
{
return hsMatrix44::IdentityMatrix();
}
const hsMatrix44& plOccluder::GetWorldToLocal() const
{
return hsMatrix44::IdentityMatrix();
}
void plOccluder::ComputeFromPolys()
{
IComputeBounds();
IComputeSurfaceArea();
}
void plOccluder::IComputeBounds()
{
fWorldBounds.MakeEmpty();
const hsTArray<plCullPoly>& polys = GetLocalPolyList();
int i;
for( i =0 ; i < polys.GetCount(); i++ )
{
int j;
for( j = 0; j < polys[i].fVerts.GetCount(); j++ )
fWorldBounds.Union(&polys[i].fVerts[j]);
}
}
hsScalar plOccluder::IComputeSurfaceArea()
{
hsScalar area = 0;
const hsTArray<plCullPoly>& polys = GetLocalPolyList();
int i;
for( i =0 ; i < polys.GetCount(); i++ )
{
int j;
for( j = 2; j < polys[i].fVerts.GetCount(); j++ )
{
area += (hsVector3(&polys[i].fVerts[j], &polys[i].fVerts[j-2]) % hsVector3(&polys[i].fVerts[j-1], &polys[i].fVerts[j-2])).Magnitude();
}
}
area *= 0.5f;
return fPriority = area;
}
void plOccluder::SetPolyList(const hsTArray<plCullPoly>& list)
{
UInt16 n = list.GetCount();
fPolys.SetCount(n);
int i;
for( i = 0; i < n; i++ )
fPolys[i] = list[i];
}
void plOccluder::ISetSceneNode(plKey node)
{
if( fSceneNode != node )
{
if( node )
{
plNodeRefMsg* refMsg = TRACKED_NEW plNodeRefMsg(node, plRefMsg::kOnCreate, -1, plNodeRefMsg::kOccluder);
hsgResMgr::ResMgr()->AddViaNotify(GetKey(), refMsg, plRefFlags::kPassiveRef);
}
if( fSceneNode )
{
fSceneNode->Release(GetKey());
}
fSceneNode = node;
}
}
void plOccluder::Read(hsStream* s, hsResMgr* mgr)
{
plObjInterface::Read(s, mgr);
fWorldBounds.Read(s);
fPriority = s->ReadSwapScalar();
hsTArray<plCullPoly>& localPolys = IGetLocalPolyList();
UInt16 n = s->ReadSwap16();
localPolys.SetCount(n);
int i;
for( i = 0; i < n; i++ )
localPolys[i].Read(s, mgr);
plKey nodeKey = mgr->ReadKey(s);
ISetSceneNode(nodeKey);
n = s->ReadSwap16();
fVisRegions.SetCountAndZero(n);
for( i = 0; i < n; i++ )
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefVisRegion), plRefFlags::kActiveRef);
}
void plOccluder::Write(hsStream* s, hsResMgr* mgr)
{
plObjInterface::Write(s, mgr);
fWorldBounds.Write(s);
s->WriteSwapScalar(fPriority);
const hsTArray<plCullPoly>& localPolys = IGetLocalPolyList();
s->WriteSwap16(localPolys.GetCount());
int i;
for( i = 0; i < localPolys.GetCount(); i++ )
localPolys[i].Write(s, mgr);
mgr->WriteKey(s, fSceneNode);
s->WriteSwap16(fVisRegions.GetCount());
for( i = 0; i < fVisRegions.GetCount(); i++ )
mgr->WriteKey(s, fVisRegions[i]);
}
plMobileOccluder::plMobileOccluder()
{
fLocalToWorld.Reset();
fWorldToLocal.Reset();
}
plMobileOccluder::~plMobileOccluder()
{
}
void plMobileOccluder::IComputeBounds()
{
plOccluder::IComputeBounds();
fLocalBounds = fWorldBounds;
fWorldBounds.Transform(&fLocalToWorld);
}
void plMobileOccluder::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
{
fLocalToWorld = l2w;
fWorldToLocal = w2l;
if( fPolys.GetCount() != fOrigPolys.GetCount() )
fPolys.SetCount(fOrigPolys.GetCount());
int i;
for( i = 0; i < fPolys.GetCount(); i++ )
fOrigPolys[i].Transform(l2w, w2l, fPolys[i]);
if( fProxyGen )
fProxyGen->SetTransform(l2w, w2l);
}
void plMobileOccluder::SetPolyList(const hsTArray<plCullPoly>& list)
{
UInt16 n = list.GetCount();
fOrigPolys.SetCount(n);
fPolys.SetCount(n);
int i;
for( i = 0; i < n; i++ )
{
fPolys[i] = fOrigPolys[i] = list[i];
}
}
void plMobileOccluder::Read(hsStream* s, hsResMgr* mgr)
{
plOccluder::Read(s, mgr);
fLocalToWorld.Read(s);
fWorldToLocal.Read(s);
fLocalBounds.Read(s);
fPolys.SetCount(fOrigPolys.GetCount());
SetTransform(fLocalToWorld, fWorldToLocal);
}
void plMobileOccluder::Write(hsStream* s, hsResMgr* mgr)
{
plOccluder::Write(s, mgr);
fLocalToWorld.Write(s);
fWorldToLocal.Write(s);
fLocalBounds.Write(s);
}
void plMobileOccluder::ComputeFromPolys()
{
SetTransform(fLocalToWorld, fWorldToLocal);
plOccluder::ComputeFromPolys();
}

View File

@ -0,0 +1,169 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plOccluder_inc
#define plOccluder_inc
#include "../pnSceneObject/plObjInterface.h"
#include "hsTemplates.h"
#include "hsMatrix44.h"
#include "plCullPoly.h"
#include "hsBounds.h"
#include "hsBitVector.h"
class plOccluderProxy;
class plDrawableSpans;
class hsGMaterial;
class plVisRegion;
class plOccluder : public plObjInterface
{
public:
enum {
kDisable = 0x0,
kNumProps
};
enum {
kRefVisRegion
};
protected:
hsTArray<plCullPoly> fPolys;
plOccluderProxy* fProxyGen;
hsBitVector fVisSet;
hsTArray<plVisRegion*> fVisRegions;
hsBitVector fVisNot;
hsScalar fPriority;
hsBounds3Ext fWorldBounds;
plKey fSceneNode;
virtual hsScalar IComputeSurfaceArea();
virtual void IComputeBounds();
virtual hsTArray<plCullPoly>& IGetLocalPolyList() { return fPolys; }
virtual void ISetSceneNode(plKey node);
void IAddVisRegion(plVisRegion* reg);
void IRemoveVisRegion(plVisRegion* reg);
public:
plOccluder();
virtual ~plOccluder();
CLASSNAME_REGISTER( plOccluder );
GETINTERFACE_ANY( plOccluder, plObjInterface);
virtual hsBool MsgReceive(plMessage* msg);
virtual hsScalar GetPriority() const { return fPriority; }
hsBool InVisSet(const hsBitVector& visSet) const { return fVisSet.Overlap(visSet); }
hsBool InVisNot(const hsBitVector& visNot) const { return fVisNot.Overlap(visNot); }
virtual const hsBounds3Ext& GetWorldBounds() const { return fWorldBounds; }
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual const hsMatrix44& GetLocalToWorld() const;
virtual const hsMatrix44& GetWorldToLocal() const;
virtual void SetPolyList(const hsTArray<plCullPoly>& list);
virtual const hsTArray<plCullPoly>& GetWorldPolyList() const { return fPolys; }
virtual const hsTArray<plCullPoly>& GetLocalPolyList() const { return fPolys; }
virtual Int32 GetNumProperties() const { return kNumProps; }
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
// Visualization
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
// Export only function to initialize.
virtual void ComputeFromPolys();
// These two should only be called internally and on export/convert
virtual plKey GetSceneNode() const { return fSceneNode; }
};
class plMobileOccluder : public plOccluder
{
protected:
hsMatrix44 fLocalToWorld;
hsMatrix44 fWorldToLocal;
hsBounds3Ext fLocalBounds;
hsTArray<plCullPoly> fOrigPolys;
virtual void IComputeBounds();
virtual hsTArray<plCullPoly>& IGetLocalPolyList() { return fOrigPolys; }
public:
plMobileOccluder();
virtual ~plMobileOccluder();
CLASSNAME_REGISTER( plMobileOccluder );
GETINTERFACE_ANY( plMobileOccluder, plOccluder );
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual const hsMatrix44& GetLocalToWorld() const { return fLocalToWorld; }
virtual const hsMatrix44& GetWorldToLocal() const { return fWorldToLocal; }
virtual void SetPolyList(const hsTArray<plCullPoly>& list);
virtual const hsTArray<plCullPoly>& GetLocalPolyList() const { return fOrigPolys; }
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
// Export only function to initialize.
virtual void ComputeFromPolys();
};
#endif // plOccluder_inc

View File

@ -0,0 +1,82 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
#include "hsTypes.h"
#include "plOccluderProxy.h"
#include "plOccluder.h"
#include "../plDrawable/plDrawableSpans.h"
#include "../plDrawable/plDrawableGenerator.h"
#include "../pnMessage/plProxyDrawMsg.h"
plOccluderProxy::plOccluderProxy()
: plProxyGen(hsColorRGBA().Set(0.2f,0.2f,0.8f,1.f), hsColorRGBA().Set(1.f,0.5f,0.5f,1.f), 0.5f),
fOwner(nil)
{
}
plOccluderProxy::~plOccluderProxy()
{
}
hsBool plOccluderProxy::Init(plOccluder* occluder)
{
plProxyGen::Init(occluder);
fOwner = occluder;
fProxyMsgType = plProxyDrawMsg::kOccluder;
return fOwner != nil;
}
plKey plOccluderProxy::IGetNode() const
{
return fOwner ? fOwner->GetSceneNode() : nil;
}
plDrawableSpans* plOccluderProxy::ICreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo)
{
if( fOwner )
{
return fOwner->CreateProxy(mat, idx, addTo);
}
return nil;
}

View File

@ -0,0 +1,67 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plOccluderProxy_inc
#define plOccluderProxy_inc
#include "../plDrawable/plProxyGen.h"
class plOccluder;
class plDrawableSpans;
class hsGMaterial;
class plOccluderProxy : public plProxyGen
{
protected:
plOccluder* fOwner;
virtual plDrawableSpans* ICreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo=nil);
virtual plKey IGetNode() const;
public:
plOccluderProxy();
virtual ~plOccluderProxy();
hsBool Init(plOccluder* occluder);
};
#endif // plOccluderProxy_inc

View File

@ -0,0 +1,712 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
#include "hsTypes.h"
#include "plPageTreeMgr.h"
#include "../plDrawable/plSpaceTreeMaker.h"
#include "../plDrawable/plSpaceTree.h"
#include "plDrawable.h"
#include "../plScene/plSceneNode.h"
#include "plPipeline.h"
#include "../plMath/hsRadixSort.h"
#include "plCullPoly.h"
#include "plOccluder.h"
#include "hsFastMath.h"
#include "plProfile.h"
#include "plVisMgr.h"
#include "plTweak.h"
static hsTArray<hsRadixSortElem> scratchList;
hsBool plPageTreeMgr::fDisableVisMgr = 0;
plProfile_CreateTimer("Object Sort", "Draw", DrawObjSort);
plProfile_CreateCounter("Objects Sorted", "Draw", DrawObjSorted);
plProfile_CreateTimer("Occluder Sort", "Draw", DrawOccSort);
plProfile_CreateCounter("Occluders Used", "Draw", DrawOccUsed);
plProfile_CreateTimer("Occluder Build", "Draw", DrawOccBuild);
plProfile_CreateCounter("Occluder Polys Processed", "Draw", DrawOccPolyProc);
plProfile_CreateTimer("Occluder Poly Sort", "Draw", DrawOccPolySort);
plPageTreeMgr::plPageTreeMgr()
: fSpaceTree(nil)
{
fVisMgr = plGlobalVisMgr::Instance();
}
plPageTreeMgr::~plPageTreeMgr()
{
delete fSpaceTree;
}
void plPageTreeMgr::AddNode(plSceneNode* node)
{
ITrashSpaceTree();
node->Init();
fNodes.Append(node);
}
void plPageTreeMgr::RemoveNode(plSceneNode* node)
{
ITrashSpaceTree();
int idx = fNodes.Find(node);
if( idx != fNodes.kMissingIndex )
fNodes.Remove(idx);
}
void plPageTreeMgr::Reset()
{
fNodes.Reset();
ITrashSpaceTree();
}
void plPageTreeMgr::ITrashSpaceTree()
{
delete fSpaceTree;
fSpaceTree = nil;
}
hsBool plPageTreeMgr::Harvest(plVolumeIsect* isect, hsTArray<plDrawVisList>& levList)
{
levList.SetCount(0);
if( !(GetSpaceTree() || IBuildSpaceTree()) )
return false;
static hsTArray<Int16> list;
GetSpaceTree()->HarvestLeaves(isect, list);
int i;
for( i = 0; i < list.GetCount(); i++ )
{
fNodes[list[i]]->Harvest(isect, levList);
}
return levList.GetCount() > 0;
}
#include "plProfile.h"
plProfile_CreateTimer("DrawableTime", "Draw", DrawableTime);
plProfile_Extern(RenderScene);
int plPageTreeMgr::Render(plPipeline* pipe)
{
// If we don't have a space tree and can't make one, just bail
if( !(GetSpaceTree() || IBuildSpaceTree()) )
return 0;
static hsTArray<Int16> list;
list.SetCount(0);
plProfile_BeginTiming(RenderScene);
plVisMgr* visMgr = fDisableVisMgr ? nil : fVisMgr;
if( visMgr )
{
plProfile_Extern(VisEval);
plProfile_BeginTiming(VisEval);
visMgr->Eval(pipe->GetViewPositionWorld());
plProfile_EndTiming(VisEval);
}
pipe->BeginVisMgr(visMgr);
IRefreshTree(pipe);
IGetOcclusion(pipe, list);
pipe->HarvestVisible(GetSpaceTree(), list);
static hsTArray<plDrawVisList> levList;
levList.SetCount(0);
int i;
for( i = 0; i < list.GetCount(); i++ )
{
fNodes[list[i]]->CollectForRender(pipe, levList, visMgr);
}
int numDrawn = IRenderVisList(pipe, levList);
IResetOcclusion(pipe);
pipe->EndVisMgr(visMgr);
plProfile_EndTiming(RenderScene);
return numDrawn;
}
int plPageTreeMgr::IRenderVisList(plPipeline* pipe, hsTArray<plDrawVisList>& levList)
{
// Sort levList into sortedDrawList, which is just a list
// of drawable/visList pairs in ascending render priority order.
// visLists are just lists of span indices, but only of the
// spans which are visible (on screen and non-occluded and non-disabled).
static hsTArray<plDrawVisList> sortedDrawList;
if( !ISortByLevel(pipe, levList, sortedDrawList) )
{
return 0;
}
int numDrawn = 0;
plVisMgr* visMgr = fDisableVisMgr ? nil : fVisMgr;
// Going through the list in order, if we hit a drawable which doesn't need
// its spans sorted, we can just draw it.
// If we hit a drawable which does need its spans sorted, we could just draw
// it, but that precludes sorting spans between drawables (like the player avatar
// sorting with normal scene objects). So when we hit a drawable which needs
// span sorting, we sort its spans with the spans of the next N drawables in
// the sorted list which have the same render priority and which also want their
// spans sorted.
int i;
for( i = 0; i < sortedDrawList.GetCount(); i++ )
{
plDrawable* p = sortedDrawList[i].fDrawable;
plProfile_BeginLap(DrawableTime, p->GetKey()->GetUoid().GetObjectName());
if( sortedDrawList[i].fDrawable->GetNativeProperty(plDrawable::kPropSortSpans) )
{
// IPrepForRenderSortingSpans increments "i" to the next index to be drawn (-1 so the i++
// at the top of the loop is correct.
numDrawn += IPrepForRenderSortingSpans(pipe, sortedDrawList, i);
}
else
{
pipe->PrepForRender(sortedDrawList[i].fDrawable, sortedDrawList[i].fVisList, visMgr);
pipe->Render(sortedDrawList[i].fDrawable, sortedDrawList[i].fVisList);
numDrawn += sortedDrawList[i].fVisList.GetCount();
}
plProfile_EndLap(DrawableTime, p->GetKey()->GetUoid().GetObjectName());
}
return numDrawn;
}
hsBool plPageTreeMgr::ISortByLevel(plPipeline* pipe, hsTArray<plDrawVisList>& drawList, hsTArray<plDrawVisList>& sortedDrawList)
{
sortedDrawList.SetCount(0);
if( !drawList.GetCount() )
return false;
scratchList.SetCount(drawList.GetCount());
hsRadixSort::Elem* listTrav = nil;
int i;
for( i = 0; i < drawList.GetCount(); i++ )
{
listTrav = &scratchList[i];
listTrav->fBody = (void*)&drawList[i];
listTrav->fNext = listTrav+1;
listTrav->fKey.fULong = drawList[i].fDrawable->GetRenderLevel().Level();
}
listTrav->fNext = nil;
hsRadixSort rad;
hsRadixSort::Elem* sortedList = rad.Sort(scratchList.AcquireArray(), hsRadixSort::kUnsigned);
listTrav = sortedList;
while( listTrav )
{
plDrawVisList& drawVis = *(plDrawVisList*)listTrav->fBody;
sortedDrawList.Append(drawVis);
listTrav = listTrav->fNext;
}
return true;
}
// Render from iDrawStart in drawVis list all drawables with the sort by spans property, well, sorting
// by spans.
// Returns the index of the last one drawn.
int plPageTreeMgr::IPrepForRenderSortingSpans(plPipeline* pipe, hsTArray<plDrawVisList>& drawVis, int& iDrawStart)
{
UInt32 renderLevel = drawVis[iDrawStart].fDrawable->GetRenderLevel().Level();
int i;
static hsTArray<plDrawVisList*> drawables;
static hsTArray<plDrawSpanPair> pairs;
// Given the input drawVisList (list of drawable/visList pairs), we make two new
// lists. The list "drawables" is just the excerpted sub-list from drawVis starting
// from the input index and going through all compatible drawables (drawables which
// are appropriate to sort (and hence intermix) with the first drawable in the list.
// The second list is the drawableIndex/spanIndex pairs convenient for sorting (where
// drawIndex indexes into drawables and spanIndex indexes into drawVis[iDraw].fVisList.
// So pairs[i] resolves into
// drawables[pairs[i].fDrawable].fDrawable->GetSpan(pairs[i].fSpan)
drawables.Append(&drawVis[iDrawStart]);
for( i = 0; i < drawVis[iDrawStart].fVisList.GetCount(); i++ )
{
plDrawSpanPair* pair = pairs.Push();
pair->fDrawable = 0;
pair->fSpan = drawVis[iDrawStart].fVisList[i];
}
int iDraw;
for( iDraw = iDrawStart+1;
(iDraw < drawVis.GetCount())
&& (drawVis[iDraw].fDrawable->GetRenderLevel().Level() == renderLevel)
&& drawVis[iDraw].fDrawable->GetNativeProperty(plDrawable::kPropSortSpans);
iDraw++ )
{
plDrawable* drawable = drawVis[iDraw].fDrawable;
hsTArray<Int16>& visList = drawVis[iDraw].fVisList;
for( i = 0; i < visList.GetCount(); i++ )
{
plDrawSpanPair* pair = pairs.Push();
pair->fDrawable = drawables.GetCount();
pair->fSpan = visList[i];
}
drawables.Append(&drawVis[iDraw]);
}
// Now that we have them in a more convenient format, sort them and render.
IRenderSortingSpans(pipe, drawables, pairs);
int numDrawn = pairs.GetCount();
drawables.SetCount(0);
pairs.SetCount(0);
iDrawStart = iDraw - 1;
return numDrawn;
}
hsBool plPageTreeMgr::IRenderSortingSpans(plPipeline* pipe, hsTArray<plDrawVisList*>& drawList, hsTArray<plDrawSpanPair>& pairs)
{
if( !pairs.GetCount() )
return false;
hsPoint3 viewPos = pipe->GetViewPositionWorld();
plProfile_BeginTiming(DrawObjSort);
plProfile_IncCount(DrawObjSorted, pairs.GetCount());
hsRadixSort::Elem* listTrav;
scratchList.SetCount(pairs.GetCount());
// First, sort on distance to the camera (squared).
listTrav = nil;
int iSort = 0;
int i;
for( i = 0; i < pairs.GetCount(); i++ )
{
plDrawable* drawable = drawList[pairs[i].fDrawable]->fDrawable;
listTrav = &scratchList[iSort++];
listTrav->fBody = (void*)*(UInt32*)&pairs[i];
listTrav->fNext = listTrav + 1;
if( drawable->GetNativeProperty(plDrawable::kPropSortAsOne) )
{
const hsBounds3Ext& bnd = drawable->GetSpaceTree()->GetNode(drawable->GetSpaceTree()->GetRoot()).fWorldBounds;
plConst(hsScalar) kDistFudge(1.e-1f);
listTrav->fKey.fFloat = -(bnd.GetCenter() - viewPos).MagnitudeSquared() + hsScalar(pairs[i].fSpan) * kDistFudge;
}
else
{
const hsBounds3Ext& bnd = drawable->GetSpaceTree()->GetNode(pairs[i].fSpan).fWorldBounds;
listTrav->fKey.fFloat = -(bnd.GetCenter() - viewPos).MagnitudeSquared();
}
}
if( !listTrav )
{
plProfile_EndTiming(DrawObjSort);
return false;
}
listTrav->fNext = nil;
hsRadixSort rad;
hsRadixSort::Elem* sortedList = rad.Sort(scratchList.AcquireArray(), 0);
plProfile_EndTiming(DrawObjSort);
static hsTArray<Int16> visList;
visList.SetCount(0);
plVisMgr* visMgr = fDisableVisMgr ? nil : fVisMgr;
// Call PrepForRender on each of these bad boys. We only want to call
// PrepForRender once on each drawable, no matter how many times we're
// going to pass it off to be rendered (like if we render span 0 from
// drawable A, span 1 from drawable A, span 0 from drawable B, span 1 from Drawable A, we
// don't want to PrepForRender twice or three times on drawable A).
// So we're going to convert our sorted list back into a list of drawable/visList
// pairs. We could have done this with our original drawable/visList, but we've
// hopefully trimmed out some spans because of the fades. This drawable/visList
// isn't appropriate for rendering (because it doesn't let us switch back and forth
// from a drawable, but it's right for the PrepForRenderCall (which does things like
// face sorting).
for( i = 0; i < drawList.GetCount(); i++ )
drawList[i]->fVisList.SetCount(0);
listTrav = sortedList;
while( listTrav )
{
plDrawSpanPair& curPair = *(plDrawSpanPair*)&listTrav->fBody;
drawList[curPair.fDrawable]->fVisList.Append(curPair.fSpan);
listTrav = listTrav->fNext;
}
for( i = 0; i < drawList.GetCount(); i++ )
{
pipe->PrepForRender(drawList[i]->fDrawable, drawList[i]->fVisList, visMgr);
}
// We'd like to call Render once on a drawable for each contiguous
// set of spans (so we want to render span 0 and span 1 on a single Render
// of drawable A in the above, then render drawable B, then back to A).
// So we go through the sorted drawable/spanIndex pairs list, building
// a visList for as long as the drawable remains the same. When it
// changes, we render what we have so far, and start again with the
// next drawable. Repeat until done.
#if 0
listTrav = sortedList;
plDrawSpanPair& curPair = *(plDrawSpanPair*)&listTrav->fBody;
int curDraw = curPair.fDrawable;
visList.Append(curPair.fSpan);
listTrav = listTrav->fNext;
while( listTrav )
{
curPair = *(plDrawSpanPair*)&listTrav->fBody;
if( curPair.fDrawable != curDraw )
{
pipe->Render(drawList[curDraw]->fDrawable, visList);
curDraw = curPair.fDrawable;
visList.SetCount(0);
visList.Append(curPair.fSpan);
}
else
{
visList.Append(curPair.fSpan);
}
listTrav = listTrav->fNext;
}
pipe->Render(drawList[curDraw]->fDrawable, visList);
#else
listTrav = sortedList;
plDrawSpanPair& curPair = *(plDrawSpanPair*)&listTrav->fBody;
int curDraw = curPair.fDrawable;
listTrav = listTrav->fNext;
static hsTArray<UInt32> numDrawn;
numDrawn.SetCountAndZero(drawList.GetCount());
visList.Append(drawList[curDraw]->fVisList[numDrawn[curDraw]++]);
while( listTrav )
{
curPair = *(plDrawSpanPair*)&listTrav->fBody;
if( curPair.fDrawable != curDraw )
{
pipe->Render(drawList[curDraw]->fDrawable, visList);
curDraw = curPair.fDrawable;
visList.SetCount(0);
}
visList.Append(drawList[curDraw]->fVisList[numDrawn[curDraw]++]);
listTrav = listTrav->fNext;
}
pipe->Render(drawList[curDraw]->fDrawable, visList);
#endif
return true;
}
hsBool plPageTreeMgr::IBuildSpaceTree()
{
if( !fNodes.GetCount() )
return false;
plSpaceTreeMaker maker;
maker.Reset();
int i;
for( i = 0; i < fNodes.GetCount(); i++ )
{
maker.AddLeaf(fNodes[i]->GetSpaceTree()->GetWorldBounds(), fNodes[i]->GetSpaceTree()->IsEmpty());
}
fSpaceTree = maker.MakeTree();
return true;
}
hsBool plPageTreeMgr::IRefreshTree(plPipeline* pipe)
{
int i;
for( i = 0; i < fNodes.GetCount(); i++ )
{
if( fNodes[i]->GetSpaceTree()->IsDirty() )
{
fNodes[i]->GetSpaceTree()->Refresh();
GetSpaceTree()->MoveLeaf(i, fNodes[i]->GetSpaceTree()->GetWorldBounds());
if( !fNodes[i]->GetSpaceTree()->IsEmpty() && fSpaceTree->HasLeafFlag(i, plSpaceTreeNode::kDisabled) )
fSpaceTree->SetLeafFlag(i, plSpaceTreeNode::kDisabled, false);
}
}
GetSpaceTree()->SetViewPos(pipe->GetViewPositionWorld());
GetSpaceTree()->Refresh();
return true;
}
void plPageTreeMgr::AddOccluderList(const hsTArray<plOccluder*> occList)
{
int iStart = fOccluders.GetCount();
fOccluders.Expand(iStart + occList.GetCount());
fOccluders.SetCount(iStart + occList.GetCount());
plVisMgr* visMgr = fDisableVisMgr ? nil : fVisMgr;
if( visMgr )
{
const hsBitVector& visSet = visMgr->GetVisSet();
const hsBitVector& visNot = visMgr->GetVisNot();
int i;
for( i = 0; i < occList.GetCount(); i++ )
{
if( occList[i] && !occList[i]->InVisNot(visNot) && occList[i]->InVisSet(visSet) )
fOccluders[iStart++] = occList[i];
}
}
else
{
int i;
for( i = 0; i < occList.GetCount(); i++ )
{
if( occList[i] )
fOccluders[iStart++] = occList[i];
}
}
fOccluders.SetCount(iStart);
}
void plPageTreeMgr::IAddCullPolyList(const hsTArray<plCullPoly>& polyList)
{
int iStart = fCullPolys.GetCount();
fCullPolys.Expand(iStart + polyList.GetCount());
fCullPolys.SetCount(iStart + polyList.GetCount());
int i;
for( i = 0; i < polyList.GetCount(); i++ )
{
fCullPolys[i + iStart] = &polyList[i];
}
}
void plPageTreeMgr::ISortCullPolys(plPipeline* pipe)
{
fSortedCullPolys.SetCount(0);
if( !fCullPolys.GetCount() )
return;
const int kMaxCullPolys = 300;
int numSubmit = 0;
hsPoint3 viewPos = pipe->GetViewPositionWorld();
hsRadixSort::Elem* listTrav;
scratchList.SetCount(fCullPolys.GetCount());
int i;
for( i = 0; i < fCullPolys.GetCount(); i++ )
{
hsBool backFace = fCullPolys[i]->fNorm.InnerProduct(viewPos) + fCullPolys[i]->fDist <= 0;
if( backFace )
{
if( !fCullPolys[i]->IsHole() && !fCullPolys[i]->IsTwoSided() )
continue;
}
else
{
if( fCullPolys[i]->IsHole() )
continue;
}
listTrav = &scratchList[numSubmit];
listTrav->fBody = (void*)fCullPolys[i];
listTrav->fNext = listTrav + 1;
listTrav->fKey.fFloat = (fCullPolys[i]->GetCenter() - viewPos).MagnitudeSquared();
numSubmit++;
}
if( !numSubmit )
return;
listTrav->fNext = nil;
hsRadixSort rad;
hsRadixSort::Elem* sortedList = rad.Sort(scratchList.AcquireArray(), 0);
listTrav = sortedList;
if( numSubmit > kMaxCullPolys )
numSubmit = kMaxCullPolys;
fSortedCullPolys.SetCount(numSubmit);
for( i = 0; i < numSubmit; i++ )
{
fSortedCullPolys[i] = (const plCullPoly*)listTrav->fBody;
listTrav = listTrav->fNext;
}
}
hsBool plPageTreeMgr::IGetCullPolys(plPipeline* pipe)
{
if( !fOccluders.GetCount() )
return false;
plProfile_BeginTiming(DrawOccSort);
hsRadixSort::Elem* listTrav = nil;
scratchList.SetCount(fOccluders.GetCount());
hsPoint3 viewPos = pipe->GetViewPositionWorld();
// cull test the occluders submitted
int numSubmit = 0;
int i;
for( i = 0; i < fOccluders.GetCount(); i++ )
{
if( pipe->TestVisibleWorld(fOccluders[i]->GetWorldBounds()) )
{
hsScalar invDist = -hsFastMath::InvSqrtAppr((viewPos - fOccluders[i]->GetWorldBounds().GetCenter()).MagnitudeSquared());
listTrav = &scratchList[numSubmit++];
listTrav->fBody = (void*)fOccluders[i];
listTrav->fNext = listTrav+1;
listTrav->fKey.fFloat = fOccluders[i]->GetPriority() * invDist;
}
}
if( !listTrav )
{
plProfile_EndTiming(DrawOccSort);
return false;
}
listTrav->fNext = nil;
// Sort the occluders by priority
hsRadixSort rad;
hsRadixSort::Elem* sortedList = rad.Sort(scratchList.AcquireArray(), 0);
listTrav = sortedList;
const UInt32 kMaxOccluders = 1000;
if( numSubmit > kMaxOccluders )
numSubmit = kMaxOccluders;
plProfile_IncCount(DrawOccUsed, numSubmit);
// Take the polys from the first N of them
for( i = 0; i < numSubmit; i++ )
{
plOccluder* occ = (plOccluder*)listTrav->fBody;
IAddCullPolyList(occ->GetWorldPolyList());
listTrav = listTrav->fNext;
}
plProfile_EndTiming(DrawOccSort);
return fCullPolys.GetCount() > 0;
}
hsBool plPageTreeMgr::IGetOcclusion(plPipeline* pipe, hsTArray<Int16>& list)
{
plProfile_BeginTiming(DrawOccBuild);
fCullPolys.SetCount(0);
fOccluders.SetCount(0);
int i;
for( i = 0; i < fNodes.GetCount(); i++ )
{
fNodes[i]->SubmitOccluders(this);
}
if( !IGetCullPolys(pipe) )
{
plProfile_EndTiming(DrawOccBuild);
return false;
}
plProfile_IncCount(DrawOccPolyProc, fCullPolys.GetCount());
plProfile_BeginTiming(DrawOccPolySort);
ISortCullPolys(pipe);
plProfile_EndTiming(DrawOccPolySort);
if( fSortedCullPolys.GetCount() )
pipe->SubmitOccluders(fSortedCullPolys);
plProfile_EndTiming(DrawOccBuild);
return fSortedCullPolys.GetCount() > 0;
}
void plPageTreeMgr::IResetOcclusion(plPipeline* pipe)
{
fCullPolys.SetCount(0);
fSortedCullPolys.SetCount(0);
}

View File

@ -0,0 +1,133 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plPageTreeMgr_inc
#define plPageTreeMgr_inc
#include "hsTemplates.h"
class plSceneNode;
class plSpaceTree;
class plPipeline;
class plCullPoly;
class plOccluder;
class plDrawable;
class plDrawVisList;
class plVolumeIsect;
class plVisMgr;
class plDrawSpanPair
{
public:
plDrawSpanPair() {}
plDrawSpanPair(UInt16 d, UInt16 s) : fDrawable(d), fSpan(s) {}
UInt16 fDrawable;
UInt16 fSpan;
};
class plDrawVisList
{
public:
plDrawVisList() : fDrawable(nil) {}
virtual ~plDrawVisList() {}
plDrawable* fDrawable;
hsTArray<Int16> fVisList;
plDrawVisList& operator=(const plDrawVisList& v) { fDrawable = v.fDrawable; fVisList = v.fVisList; return *this; }
};
class plPageTreeMgr
{
protected:
hsTArray<plSceneNode*> fNodes;
plSpaceTree* fSpaceTree;
plVisMgr* fVisMgr;
static hsBool fDisableVisMgr;
hsTArray<const plOccluder*> fOccluders;
hsTArray<const plCullPoly*> fCullPolys;
hsTArray<const plCullPoly*> fSortedCullPolys;
void ITrashSpaceTree();
hsBool IBuildSpaceTree();
hsBool IRefreshTree(plPipeline* pipe);
void ISortCullPolys(plPipeline* pipe);
hsBool IGetOcclusion(plPipeline* pipe, hsTArray<Int16>& list);
hsBool IGetCullPolys(plPipeline* pipe);
void IResetOcclusion(plPipeline* pipe);
void IAddCullPolyList(const hsTArray<plCullPoly>& polyList);
hsBool ISortByLevel(plPipeline* pipe, hsTArray<plDrawVisList>& drawList, hsTArray<plDrawVisList>& sortedDrawList);
int IPrepForRenderSortingSpans(plPipeline* pipe, hsTArray<plDrawVisList>& drawVis, int& iDrawStart);
hsBool IRenderSortingSpans(plPipeline* pipe, hsTArray<plDrawVisList*>& drawList, hsTArray<plDrawSpanPair>& pairs);
int IRenderVisList(plPipeline* pipe, hsTArray<plDrawVisList>& visList);
public:
plPageTreeMgr();
virtual ~plPageTreeMgr();
const hsTArray<plSceneNode*>& GetNodes() const { return fNodes; }
void AddNode(plSceneNode* node);
void RemoveNode(plSceneNode* node);
virtual void Reset(); // remove all nodes, nuke the space tree
virtual hsBool Empty() const { return !fNodes.GetCount(); }
virtual int Render(plPipeline* pipe);
hsBool Harvest(plVolumeIsect* isect, hsTArray<plDrawVisList>& levList);
void AddOccluderList(const hsTArray<plOccluder*> occList);
plSpaceTree* GetSpaceTree() { if( !fSpaceTree ) IBuildSpaceTree(); return fSpaceTree; }
void SetVisMgr(plVisMgr* visMgr) { fVisMgr = visMgr; }
plVisMgr* GetVisMgr() const { return fVisMgr; }
static void EnableVisMgr(hsBool on) { fDisableVisMgr = !on; }
static hsBool VisMgrEnabled() { return !fDisableVisMgr; }
};
#endif // plPageTreeMgr_inc

View File

@ -0,0 +1,337 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
#include "hsTypes.h"
#include "plPostEffectMod.h"
#include "plPageTreeMgr.h"
#include "plSceneNode.h"
#include "plRenderRequest.h"
#include "../plPipeline/plRenderTarget.h"
#include "../plMessage/plRenderRequestMsg.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "../plMessage/plRenderMsg.h"
#include "../pnMessage/plRefMsg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "plDrawable.h"
#include "plPipeline.h"
#include "plgDispatch.h"
#include "hsResMgr.h"
plPostEffectMod::plPostEffectMod()
: fHither(1.f),
fYon(100.f),
fFovX(hsScalarPI * 0.25f),
fFovY(hsScalarPI * 0.25f * 0.75f),
fPageMgr(nil),
fRenderTarget(nil),
fRenderRequest(nil)
{
fDefaultW2C = hsMatrix44::IdentityMatrix();
fDefaultC2W = hsMatrix44::IdentityMatrix();
ISetupRenderRequest();
}
plPostEffectMod::~plPostEffectMod()
{
IDestroyRenderRequest();
}
void plPostEffectMod::ISetupRenderRequest()
{
UInt32 rtFlags = 0;
// If we go to rendering to sub-window, we'll want to explicitly set width and height
UInt32 width = 0;
UInt32 height = 0;
UInt32 colorDepth = 0;
UInt32 zDepth = 0;
UInt32 stencilDepth = 0;
fRenderRequest = TRACKED_NEW plRenderRequest;
UInt32 renderState = plPipeline::kRenderNormal
| plPipeline::kRenderNoProjection
| plPipeline::kRenderNoLights
| plPipeline::kRenderClearDepth;
fRenderRequest->SetRenderState(renderState);
fRenderRequest->SetDrawableMask(plDrawable::kNormal);
fRenderRequest->SetSubDrawableMask(plDrawable::kSubAllTypes);
fRenderRequest->SetPerspective();
fRenderRequest->SetRenderTarget(fRenderTarget);
fPageMgr = TRACKED_NEW plPageTreeMgr;
fRenderRequest->SetPageTreeMgr(fPageMgr);
fRenderRequest->SetPriority(1.f);
IUpdateRenderRequest();
}
void plPostEffectMod::EnableLightsOnRenderRequest( void )
{
fRenderRequest->SetRenderState( fRenderRequest->GetRenderState() & ~plPipeline::kRenderNoLights );
}
void plPostEffectMod::IDestroyRenderRequest()
{
delete fRenderTarget;
fRenderTarget = nil;
delete fRenderRequest;
fRenderRequest = nil;
delete fPageMgr;
fPageMgr = nil;
}
void plPostEffectMod::IRegisterForRenderMsg(hsBool on)
{
if( on )
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
else
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
}
void plPostEffectMod::ISetEnable(hsBool on)
{
if( on )
{
IRegisterForRenderMsg(true);
fState.SetBit(kEnabled);
}
else
{
IRegisterForRenderMsg(false);
fState.ClearBit(kEnabled);
}
}
hsBool plPostEffectMod::IIsEnabled() const
{
return /*GetTarget() &&*/ !fPageMgr->Empty() && fState.IsBitSet(kEnabled);
}
hsBool plPostEffectMod::IEval(double secs, hsScalar del, UInt32 dirty)
{
return false;
}
void plPostEffectMod::IUpdateRenderRequest()
{
fRenderRequest->SetHither(fHither);
fRenderRequest->SetYon(fYon);
fRenderRequest->SetFovX(fFovX);
fRenderRequest->SetFovY(fFovY);
if( GetTarget() )
{
hsMatrix44 w2c = GetTarget()->GetWorldToLocal();
hsMatrix44 c2w = GetTarget()->GetLocalToWorld();
int i;
for( i = 0; i < 4; i++ )
{
w2c.fMap[2][i] *= -1.f;
c2w.fMap[i][2] *= -1.f;
}
w2c.NotIdentity();
c2w.NotIdentity();
fRenderRequest->SetCameraTransform(w2c, c2w);
}
else
fRenderRequest->SetCameraTransform( fDefaultW2C, fDefaultC2W );
// fRenderRequest->SetCameraTransform(hsMatrix44::IdentityMatrix(), hsMatrix44::IdentityMatrix());
}
// If translating from a scene object, send WorldToLocal() and LocalToWorld(), in that order
void plPostEffectMod::SetWorldToCamera( hsMatrix44 &w2c, hsMatrix44 &c2w )
{
int i;
fDefaultW2C = w2c;
fDefaultC2W = c2w;
for( i = 0; i < 4; i++ )
{
fDefaultW2C.fMap[2][i] *= -1.f;
fDefaultC2W.fMap[i][2] *= -1.f;
}
fDefaultW2C.NotIdentity();
fDefaultC2W.NotIdentity();
}
void plPostEffectMod::GetDefaultWorldToCamera( hsMatrix44 &w2c, hsMatrix44 &c2w )
{
w2c = fDefaultW2C;
c2w = fDefaultC2W;
}
void plPostEffectMod::ISubmitRequest()
{
hsAssert(fState.IsBitSet(kEnabled), "Submitting request when not active");
// No target is now valid...
// hsAssert(GetTarget(), "Submitting request without target loaded");
IUpdateRenderRequest();
plRenderRequestMsg* req = TRACKED_NEW plRenderRequestMsg(GetKey(), fRenderRequest);
plgDispatch::MsgSend(req);
}
void plPostEffectMod::IAddToPageMgr(plSceneNode* node)
{
fPageMgr->AddNode(node);
}
void plPostEffectMod::IRemoveFromPageMgr(plSceneNode* node)
{
fPageMgr->RemoveNode(node);
}
#include "plProfile.h"
plProfile_CreateTimer("PostEffect", "RenderSetup", PostEffect);
hsBool plPostEffectMod::MsgReceive(plMessage* msg)
{
plRenderMsg* rend = plRenderMsg::ConvertNoRef(msg);
if( rend && IIsEnabled() )
{
plProfile_BeginLap(PostEffect, this->GetKey()->GetUoid().GetObjectName());
ISubmitRequest();
plProfile_EndLap(PostEffect, this->GetKey()->GetUoid().GetObjectName());
return true;
}
plAnimCmdMsg* anim = plAnimCmdMsg::ConvertNoRef(msg);
if( anim )
{
if( anim->Cmd(plAnimCmdMsg::kContinue) )
ISetEnable(true);
else if( anim->Cmd(plAnimCmdMsg::kStop) )
ISetEnable(false);
else if( anim->Cmd(plAnimCmdMsg::kToggleState) )
ISetEnable(!fState.IsBitSet(kEnabled));
return true;
}
plGenRefMsg* ref = plGenRefMsg::ConvertNoRef(msg);
if( ref )
{
switch( ref->fType )
{
case kNodeRef:
if( ref->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest) )
{
IAddToPageMgr(plSceneNode::ConvertNoRef(ref->GetRef()));
}
else if( ref->GetContext() & plRefMsg::kOnReplace )
{
IRemoveFromPageMgr(plSceneNode::ConvertNoRef(ref->GetOldRef()));
IAddToPageMgr(plSceneNode::ConvertNoRef(ref->GetRef()));
}
else if( ref->GetContext() & (plRefMsg::kOnRemove | plRefMsg::kOnDestroy) )
{
IRemoveFromPageMgr(plSceneNode::ConvertNoRef(ref->GetRef()));
}
break;
}
return true;
}
return plSingleModifier::MsgReceive(msg);
}
void plPostEffectMod::Read(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Read(s, mgr);
fState.Read(s);
#if 0 // FORCE ENABLE ON LOAD - ONLY FOR DEBUGGING
ISetEnable(true);
#endif // FORCE ENABLE ON LOAD - ONLY FOR DEBUGGING
fHither = s->ReadSwapScalar();
fYon = s->ReadSwapScalar();
fFovX = s->ReadSwapScalar();
fFovY = s->ReadSwapScalar();
fNodeKey = mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kNodeRef), plRefFlags::kPassiveRef);
fDefaultW2C.Read( s );
fDefaultC2W.Read( s );
IUpdateRenderRequest();
}
void plPostEffectMod::Write(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Write(s, mgr);
fState.Write(s);
s->WriteSwapScalar(fHither);
s->WriteSwapScalar(fYon);
s->WriteSwapScalar(fFovX);
s->WriteSwapScalar(fFovY);
mgr->WriteKey(s, fNodeKey);
fDefaultW2C.Write( s );
fDefaultC2W.Write( s );
}
const plViewTransform& plPostEffectMod::GetViewTransform()
{
IUpdateRenderRequest();
return fRenderRequest->GetViewTransform();
}

View File

@ -0,0 +1,142 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plPostEffectMod_inc
#define plPostEffectMod_inc
#include "../pnModifier/plSingleModifier.h"
#include "hsMatrix44.h"
#include "hsBitVector.h"
class plSceneNode;
class plPageTreeMgr;
class plMessage;
class plRenderTarget;
class plRenderRequest;
class plViewTransform;
class plPostEffectMod : public plSingleModifier
{
public:
enum plPostEffectModStates {
kEnabled = 0
};
enum {
kNodeRef = 0x0
};
protected:
hsBitVector fState;
hsScalar fHither;
hsScalar fYon;
hsScalar fFovX;
hsScalar fFovY;
plKey fNodeKey;
plPageTreeMgr* fPageMgr;
plRenderTarget* fRenderTarget;
plRenderRequest* fRenderRequest;
hsMatrix44 fDefaultW2C, fDefaultC2W;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty); // called only by owner object's Eval()
void ISetupRenderRequest();
void IDestroyRenderRequest();
void IUpdateRenderRequest();
void IRegisterForRenderMsg(hsBool on);
void ISubmitRequest();
void IAddToPageMgr(plSceneNode* node);
void IRemoveFromPageMgr(plSceneNode* node);
void ISetEnable(hsBool on);
hsBool IIsEnabled() const;
public:
plPostEffectMod();
virtual ~plPostEffectMod();
CLASSNAME_REGISTER( plPostEffectMod );
GETINTERFACE_ANY( plPostEffectMod, plSingleModifier );
virtual hsBool MsgReceive(plMessage* pMsg);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
void GetDefaultWorldToCamera( hsMatrix44 &w2c, hsMatrix44 &c2w );
// Export only
void SetNodeKey(plKey key) { fNodeKey = key; }
plKey GetNodeKey() const { return fNodeKey; }
void SetHither(hsScalar h) { fHither = h; }
void SetYon(hsScalar y) { fYon = y; }
void SetFovX(hsScalar f) { fFovX = f; }
void SetFovY(hsScalar f) { fFovY = f; }
hsScalar GetHither() const { return fHither; }
hsScalar GetYon() const { return fYon; }
hsScalar GetFovX() const { return fFovX; }
hsScalar GetFovY() const { return fFovY; }
plPageTreeMgr* GetPageMgr() const { return fPageMgr; }
const plViewTransform& GetViewTransform();
// If translating from a scene object, send WorldToLocal() and LocalToWorld(), in that order
void SetWorldToCamera( hsMatrix44 &w2c, hsMatrix44 &c2w );
// Very bad
void EnableLightsOnRenderRequest( void );
};
#endif // plPostEffectMod_inc

View File

@ -0,0 +1,271 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
#include "plRelevanceMgr.h"
#include "plRelevanceRegion.h"
#include "../plIntersect/plRegionBase.h"
#include "hsStream.h"
#include "hsStringTokenizer.h"
plRelevanceMgr* plRelevanceMgr::fInstance = nil;
plRelevanceMgr::plRelevanceMgr() : fEnabled(true)
{
}
void plRelevanceMgr::Init()
{
fInstance = TRACKED_NEW plRelevanceMgr;
fInstance->RegisterAs(kRelevanceMgr_KEY);
}
void plRelevanceMgr::DeInit()
{
if (fInstance)
{
fInstance->UnRegisterAs(kRelevanceMgr_KEY);
fInstance = nil;
}
}
void plRelevanceMgr::IAddRegion(plRelevanceRegion *region)
{
int i;
int dstIdx = fRegions.GetCount();
for (i = 0; i < fRegions.GetCount(); i++)
{
if (fRegions[i] == nil)
{
dstIdx = i;
break;
}
}
if (dstIdx == fRegions.GetCount())
fRegions.Append(region);
else
fRegions[i] = region;
region->SetMgrIndex(dstIdx + 1);
}
void plRelevanceMgr::IRemoveRegion(plRelevanceRegion *region)
{
fRegions[region->fMgrIdx - 1] = nil;
}
void plRelevanceMgr::SetRegionVectors(const hsPoint3 &pos, hsBitVector &regionsImIn, hsBitVector &regionsICareAbout)
{
regionsImIn.Clear();
regionsICareAbout.Clear();
regionsICareAbout.SetBit(0, true); // Always care about region zero, the special "No region" node
hsBool inAnyRegion = false;
int i;
for (i = 0; i < fRegions.GetCount(); i++)
{
if (fRegions[i] && fRegions[i]->fRegion->IsInside(pos))
{
regionsImIn.SetBit(i + 1, true);
regionsICareAbout |= fRegions[i]->fRegionsICareAbout;
inAnyRegion = true;
}
}
// If I'm not in any region, that means I'm in the special zero region and care about everything.
if (!inAnyRegion)
{
regionsImIn.SetBit(0, true);
regionsICareAbout.Set(fRegions.GetCount());
}
}
UInt32 plRelevanceMgr::GetNumRegions() const
{
int i;
for (i = fRegions.GetCount(); i > 0 && fRegions[i - 1] == nil; i--);
return i + 1; // Add 1 for the special zero-region
}
hsBool plRelevanceMgr::MsgReceive(plMessage* msg)
{
plGenRefMsg *genMsg = plGenRefMsg::ConvertNoRef(msg);
if (genMsg)
{
plRelevanceRegion *region = plRelevanceRegion::ConvertNoRef(genMsg->GetRef());
if( genMsg->GetContext() & (plRefMsg::kOnCreate) )
{
IAddRegion(region);
}
else if( genMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
{
IRemoveRegion(region);
}
return true;
}
return hsKeyedObject::MsgReceive(msg);
}
UInt32 plRelevanceMgr::GetIndex(char *regionName)
{
int i;
for (i = 0; i < fRegions.GetCount(); i++)
{
if (fRegions[i] && !stricmp(regionName, fRegions[i]->GetKeyName()))
return i + 1;
}
return -1;
}
void plRelevanceMgr::MarkRegion(UInt32 localIdx, UInt32 remoteIdx, hsBool doICare)
{
if (localIdx == (UInt32)-1 || remoteIdx == (UInt32)-1)
return;
if (localIdx - 1 >= fRegions.GetCount() || remoteIdx - 1 >= fRegions.GetCount() || fRegions[localIdx - 1] == nil)
return;
fRegions[localIdx - 1]->fRegionsICareAbout.SetBit(remoteIdx, doICare);
}
// tiny class for the function below
class plRegionInfo
{
public:
char *fName;
int fIndex;
plRegionInfo() : fName(nil), fIndex(-1) {}
~plRegionInfo() { delete [] fName; }
};
/*
* This function expects a CSV file representing the matrix
*
* name1 name2 name3
* name1 value value value
* name2 value value value
* name3 value value value
*
* where the value determines how much the that row's region cares about the region in the current column.
* (Currently, the possible values are:
* 0: Doesn't care
* 1 or greater: row cares about column
*/
void plRelevanceMgr::ParseCsvInput(hsStream *s)
{
const int kBufSize = 512;
char buff[kBufSize];
hsTArray<plRegionInfo*> regions;
hsStringTokenizer toke;
hsBool firstLine = true;
while (!s->AtEnd())
{
if (!s->ReadLn(buff, kBufSize))
break;
if (firstLine)
{
firstLine = false;
toke.Reset(buff, ",");
while (toke.Next(buff, kBufSize))
{
if (strcmp(buff, "") == 0)
continue; // ignore the initial blank one
plRegionInfo *info = TRACKED_NEW plRegionInfo;
regions.Append(info);
info->fName = hsStrcpy(buff);
info->fIndex = GetIndex(buff);
}
}
else // parsing actual settings.
{
toke.Reset(buff, ",");
if (!toke.Next(buff, kBufSize))
continue;
int rowIndex = GetIndex(buff);
int column = 0;
while (toke.Next(buff, kBufSize) && column < regions.GetCount())
{
int value = atoi(buff);
MarkRegion(rowIndex, regions[column]->fIndex, value != 0);
column++;
}
}
}
int i;
for (i = regions.GetCount() - 1; i >= 0; i--)
delete regions[i];
}
std::string plRelevanceMgr::GetRegionNames(hsBitVector regions)
{
std::string retVal = "";
if (regions.IsBitSet(0))
retVal = "-Nowhere (0)-";
for (int i = 0; i < fRegions.GetCount(); ++i)
{
if (regions.IsBitSet(i + 1))
{
if (retVal.length() != 0)
retVal += ", ";
if (fRegions[i])
retVal += fRegions[i]->GetKeyName();
}
}
if (retVal.length() == 0)
retVal = "<NONE>";
return retVal;
}

View File

@ -0,0 +1,92 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plRelevanceMgr_inc
#define plRelevanceMgr_inc
#include "../pnKeyedObject/hsKeyedObject.h"
#include "hsGeometry3.h"
#include "hsTemplates.h"
#include "hsBitVector.h"
#include "hsStlUtils.h"
class plRelevanceRegion;
class hsStream;
class plRelevanceMgr : public hsKeyedObject
{
protected:
static plRelevanceMgr *fInstance;
public:
static plRelevanceMgr *Instance() { return fInstance; }
static void Init();
static void DeInit();
protected:
hsTArray<plRelevanceRegion*> fRegions;
hsBool fEnabled;
void IAddRegion(plRelevanceRegion *);
void IRemoveRegion(plRelevanceRegion *);
public:
plRelevanceMgr();
CLASSNAME_REGISTER( plRelevanceMgr );
GETINTERFACE_ANY( plRelevanceMgr, hsKeyedObject );
virtual hsBool MsgReceive(plMessage* msg);
hsBool GetEnabled() { return fEnabled; }
void SetEnabled(hsBool val) { fEnabled = val; }
UInt32 GetIndex(char *regionName);
void MarkRegion(UInt32 localIdx, UInt32 remoteIdx, hsBool doICare);
void SetRegionVectors(const hsPoint3 &pos, hsBitVector &regionsImIn, hsBitVector &regionsICareAbout);
UInt32 GetNumRegions() const; // includes the secret 0 region in its count
void ParseCsvInput(hsStream *s);
std::string GetRegionNames(hsBitVector regions);
};
#endif // plRelevanceMgr_inc

View File

@ -0,0 +1,98 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
#include "hsResMgr.h"
#include "plRelevanceRegion.h"
#include "plRelevanceMgr.h"
#include "../plIntersect/plRegionBase.h"
void plRelevanceRegion::Read(hsStream* s, hsResMgr* mgr)
{
plObjInterface::Read(s, mgr);
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, 0), plRefFlags::kActiveRef);
// Added to the manager when read in.
// Removed when paged out, due to passive ref.
if (plRelevanceMgr::Instance())
{
plGenRefMsg *msg = TRACKED_NEW plGenRefMsg(plRelevanceMgr::Instance()->GetKey(), plRefMsg::kOnCreate, -1, -1);
hsgResMgr::ResMgr()->AddViaNotify(GetKey(), msg, plRefFlags::kPassiveRef);
}
}
void plRelevanceRegion::Write(hsStream* s, hsResMgr* mgr)
{
plObjInterface::Write(s, mgr);
mgr->WriteKey(s, fRegion);
}
hsBool plRelevanceRegion::MsgReceive(plMessage* msg)
{
plGenRefMsg *genMsg = plGenRefMsg::ConvertNoRef(msg);
if (genMsg)
{
plRegionBase *base = plRegionBase::ConvertNoRef(genMsg->GetRef());
if( genMsg->GetContext() & (plRefMsg::kOnCreate) )
{
fRegion = base;
}
else if( genMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
{
fRegion = nil;
}
return true;
}
return plObjInterface::MsgReceive(msg);
}
void plRelevanceRegion::SetMgrIndex(UInt32 index)
{
if (fMgrIdx != (UInt32)-1)
fRegionsICareAbout.SetBit(fMgrIdx, false);
fMgrIdx = index;
fRegionsICareAbout.SetBit(index, true); // I care about myself. Awww...
}

View File

@ -0,0 +1,77 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plRelevanceRegion_inc
#define plRelevanceRegion_inc
#include "../pnSceneObject/plObjInterface.h"
class plRelevanceMgr;
class plRegionBase;
class plRelevanceRegion : public plObjInterface
{
friend class plRelevanceMgr;
protected:
plRegionBase *fRegion;
hsBitVector fRegionsICareAbout;
UInt32 fMgrIdx;
public:
plRelevanceRegion() : fRegion(nil), fMgrIdx((UInt32)-1) {}
virtual ~plRelevanceRegion() {}
CLASSNAME_REGISTER( plRelevanceRegion );
GETINTERFACE_ANY( plRelevanceRegion, plObjInterface );
virtual hsBool MsgReceive(plMessage* msg);
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l) {}
virtual Int32 GetNumProperties() const { return 1; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void SetMgrIndex(UInt32 idx);
};
#endif // plRelevanceRegion_inc

View File

@ -0,0 +1,170 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
#include "hsTypes.h"
#include "plRenderRequest.h"
#include "plPageTreeMgr.h"
#include "../plPipeline/plRenderTarget.h"
#include "hsFastMath.h"
#include "hsStream.h"
#include "plPipeline.h"
#include "../plMessage/plRenderRequestMsg.h"
#include "plgDispatch.h"
#include "plVisMgr.h"
plRenderRequest::plRenderRequest()
: fRenderTarget(nil),
fPageMgr(nil),
fAck(nil),
fOverrideMat(nil),
fEraseMat(nil),
fDrawableMask(UInt32(-1)),
fSubDrawableMask(UInt32(-1)),
fRenderState(0),
fClearDepth(1.f),
fFogStart(-1.f),
fClearDrawable(nil),
fPriority(-1.e6f),
fUserData(0),
fIgnoreOccluders(false)
{
fClearColor.Set(0,0,0,1.f);
fLocalToWorld.Reset();
fWorldToLocal.Reset();
}
plRenderRequest::~plRenderRequest()
{
}
void plRenderRequest::SetLocalTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
{
fLocalToWorld = l2w;
fWorldToLocal = w2l;
}
void plRenderRequest::Read(hsStream* s, hsResMgr* mgr)
{
fClearDrawable = nil;
fRenderTarget = nil;
fPageMgr = nil;
fDrawableMask = s->ReadSwap32();
fSubDrawableMask = s->ReadSwap32();
fRenderState = s->ReadSwap32();
fLocalToWorld.Read(s);
fWorldToLocal.Read(s);
fPriority = s->ReadSwapScalar();
}
void plRenderRequest::Write(hsStream* s, hsResMgr* mgr)
{
s->WriteSwap32(fDrawableMask);
s->WriteSwap32(fSubDrawableMask);
s->WriteSwap32(fRenderState);
fLocalToWorld.Write(s);
fWorldToLocal.Write(s);
s->WriteSwapScalar(fPriority);
}
void plRenderRequest::Render(plPipeline* pipe, plPageTreeMgr* pageMgr)
{
if( !fVisForce.Empty() )
{
plGlobalVisMgr::Instance()->DisableNormal();
plGlobalVisMgr::Instance()->ForceVisSets(fVisForce, false);
}
pipe->PushRenderRequest(this);
pipe->ClearRenderTarget(GetClearDrawable());
int numDrawn = 0;
if( GetPageTreeMgr() )
numDrawn = GetPageTreeMgr()->Render(pipe);
else
numDrawn = pageMgr->Render(pipe);
pipe->PopRenderRequest(this);
if( GetAck() )
{
plRenderRequestAck* ack = TRACKED_NEW plRenderRequestAck( GetAck(), GetUserData() );
ack->SetNumDrawn(numDrawn);
plgDispatch::MsgSend( ack );
}
}
void plRenderRequest::SetRenderTarget(plRenderTarget* t)
{
if( t != fRenderTarget )
{
fRenderTarget = t;
if( fRenderTarget )
{
fViewTransform.SetWidth(t->GetWidth());
fViewTransform.SetHeight(t->GetHeight());
}
}
}
void plRenderRequest::SetVisForce(const hsBitVector& b)
{
if( b.Empty() )
fVisForce.Reset();
else
fVisForce = b;
}
hsBool plRenderRequest::GetRenderCharacters() const
{
return fVisForce.IsBitSet(plVisMgr::kCharacter);
}

View File

@ -0,0 +1,207 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plRenderRequest_inc
#define plRenderRequest_inc
#include "hsMatrix44.h"
#include "hsColorRGBA.h"
#include "plViewTransform.h"
#include "hsRefCnt.h"
#include "hsBitVector.h"
#include "../pnKeyedObject/plKey.h"
#include "../plMessage/plRenderRequestMsg.h"
class plRenderTarget;
class plPageTreeMgr;
class hsStream;
class hsResMgr;
class plDrawable;
class hsGMaterial;
class plPipeline;
class plRenderRequest : public plRenderRequestBase
{
public:
protected:
UInt32 fRenderState; // Or'ed from plPipeline::RenderStateSettings::kRender*
plDrawable* fClearDrawable;
plRenderTarget* fRenderTarget;
plPageTreeMgr* fPageMgr;
hsGMaterial* fOverrideMat;
hsGMaterial* fEraseMat;
plKey fAck;
hsScalar fPriority;
UInt32 fDrawableMask;
UInt32 fSubDrawableMask;
hsColorRGBA fClearColor;
hsScalar fClearDepth;
hsScalar fFogStart;
hsMatrix44 fLocalToWorld;
hsMatrix44 fWorldToLocal;
plViewTransform fViewTransform;
hsBitVector fVisForce;
UInt32 fUserData;
hsBool fIgnoreOccluders;
public:
plRenderRequest();
~plRenderRequest();
hsBool GetRenderSelect() const { return !fVisForce.Empty(); }
hsBool GetRenderCharacters() const;
void SetRenderState(UInt32 st) { fRenderState = st; }
UInt32 GetRenderState() const { return fRenderState; }
void SetDrawableMask(UInt32 m) { fDrawableMask = m; }
UInt32 GetDrawableMask() const { return fDrawableMask; }
void SetSubDrawableMask(UInt32 m) { fSubDrawableMask = m; }
UInt32 GetSubDrawableMask() const { return fSubDrawableMask; }
void RequestAck(plKey key) { fAck = key; }
plKey GetAck() const { return fAck; }
plDrawable* GetClearDrawable() const { return fClearDrawable; }
void SetClearDrawable(plDrawable* d) { fClearDrawable = d; }
hsGMaterial* GetOverrideMat() const { return fOverrideMat; }
void SetOverrideMat(hsGMaterial* m) { fOverrideMat = m; }
hsGMaterial* GetEraseMat() const { return fEraseMat; }
void SetEraseMat(hsGMaterial* m) { fEraseMat = m; }
plRenderTarget* GetRenderTarget() const { return fRenderTarget; }
void SetRenderTarget(plRenderTarget* t);
plPageTreeMgr* GetPageTreeMgr() const { return fPageMgr; }
void SetPageTreeMgr(plPageTreeMgr* mgr) { fPageMgr = mgr; }
const hsBitVector& GetVisForce() const { return fVisForce; }
void SetVisForce(const hsBitVector& b);
const hsMatrix44& GetLocalToWorld() const { return fLocalToWorld; }
const hsMatrix44& GetWorldToLocal() const { return fWorldToLocal; }
const hsMatrix44& GetWorldToCamera() const { return fViewTransform.GetWorldToCamera(); }
const hsMatrix44& GetCameraToWorld() const { return fViewTransform.GetCameraToWorld(); }
const plViewTransform& GetViewTransform() const { return fViewTransform; }
hsScalar GetHither() const { return fViewTransform.GetHither(); }
hsScalar GetYon() const { return fViewTransform.GetYon(); }
hsScalar GetFovX() const { return fViewTransform.GetFovXDeg(); }
hsScalar GetFovY() const { return fViewTransform.GetFovYDeg(); }
hsScalar GetSizeX() const { return fViewTransform.GetOrthoWidth(); }
hsScalar GetSizeY() const { return fViewTransform.GetOrthoHeight(); }
UInt16 GetScreenWidth() const { return fViewTransform.GetScreenWidth(); }
UInt16 GetScreenHeight() const { return fViewTransform.GetScreenHeight(); }
const hsColorRGBA& GetClearColor() const { return fClearColor; }
hsScalar GetClearDepth() const { return fClearDepth; }
// FogStart
// negative => use current settings (default)
// 0 => no fog == fog starts at yon
// 1 => fog starts at camera.
// Fog start greater than 1 is legal. Fog always linear.
hsScalar GetFogStart() const { return fFogStart; }
hsScalar GetPriority() const { return fPriority; }
void SetLocalTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
void SetViewTransform(const plViewTransform& v) { fViewTransform = v; }
void SetCameraTransform(const hsMatrix44& w2c, const hsMatrix44& c2w) { fViewTransform.SetCameraTransform(w2c, c2w); }
void SetPerspective(hsBool on=true) { fViewTransform.SetPerspective(on); }
void SetOrthogonal(hsBool on=true) { fViewTransform.SetOrthogonal(on); }
void SetHither(hsScalar f) { fViewTransform.SetHither(f); }
void SetYon(hsScalar f) { fViewTransform.SetYon(f); }
void SetFovX(hsScalar f) { fViewTransform.SetFovXDeg(f); }
void SetFovY(hsScalar f) { fViewTransform.SetFovYDeg(f); }
void SetSizeX(hsScalar f) { fViewTransform.SetWidth(f); }
void SetSizeY(hsScalar f) { fViewTransform.SetHeight(f); }
void SetClearColor(const hsColorRGBA& c) { fClearColor = c; }
void SetClearDepth(hsScalar d) { fClearDepth = d; }
// FogStart
// negative => use current settings (default)
// 0 => no fog == fog starts at yon
// 1 => fog starts at camera.
// Fog start greater than 1 is legal. Fog always linear.
void SetFogStart(hsScalar d) { fFogStart = d; }
void SetPriority(hsScalar p) { fPriority = p; }
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
void SetUserData(UInt32 n) { fUserData = n; }
UInt32 GetUserData() const { return fUserData; }
void SetIgnoreOccluders(hsBool b) { fIgnoreOccluders = b; }
hsBool GetIgnoreOccluders() { return fIgnoreOccluders; }
// This function is called after the render request is processed by the client
virtual void Render(plPipeline* pipe, plPageTreeMgr* pageMgr);
};
#endif // plRenderRequest_inc

View File

@ -0,0 +1,77 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plSceneCreatable_inc
#define plSceneCreatable_inc
#include "../pnFactory/plCreatable.h"
#include "plSceneNode.h"
REGISTER_CREATABLE( plSceneNode );
#include "plOccluder.h"
REGISTER_CREATABLE( plOccluder );
REGISTER_CREATABLE( plMobileOccluder );
#include "plPostEffectMod.h"
REGISTER_CREATABLE( plPostEffectMod );
#include "plVisMgr.h"
REGISTER_CREATABLE( plVisMgr );
#include "plVisRegion.h"
REGISTER_CREATABLE( plVisRegion );
#include "plRelevanceMgr.h"
REGISTER_CREATABLE( plRelevanceMgr );
#include "plRelevanceRegion.h"
REGISTER_CREATABLE( plRelevanceRegion );
#endif // plSceneCreatable_inc

View File

@ -0,0 +1,523 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
#include "hsTypes.h"
#include "plSceneNode.h"
#include "../pnDispatch/plDispatch.h"
#include "../plMessage/plNodeCleanupMsg.h"
#include "../pnMessage/plNodeRefMsg.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "../pnSceneObject/plSceneObject.h"
#include "plDrawable.h"
#include "plPhysical.h"
#include "plAudible.h"
#include "../plGLight/plLightInfo.h"
#include "../pnMessage/plRefMsg.h"
#include "plPipeline.h"
#include "../pnKeyedObject/plKey.h"
#include "../plDrawable/plSpaceTreeMaker.h"
#include "../plDrawable/plSpaceTree.h"
#include "plPageTreeMgr.h"
#include "plOccluder.h"
//MFHORSE
//BLACK
// temp hack for debugging
#include "../plDrawable/plDrawableSpans.h"
#include "../pnKeyedObject/plKeyImp.h"
plSceneNode::plSceneNode()
: fDepth(0),
fSpaceTree(nil),
fFilterGenerics(false)
{
}
plSceneNode::~plSceneNode()
{
plgDispatch::Dispatch()->UnRegisterForExactType(plNodeCleanupMsg::Index(), GetKey());
delete fSpaceTree;
}
//// Init ////////////////////////////////////////////////////////////////////
// Because we can't register for messages on construction. Doh.
void plSceneNode::Init()
{
/// :P
plgDispatch::Dispatch()->RegisterForExactType(plNodeCleanupMsg::Index(), GetKey());
}
void plSceneNode::Read(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Read(s, mgr);
UInt32 n;
int i;
n = s->ReadSwap32();
fSceneObjects.Reset();
for( i = 0; i < n; i++ )
{
plNodeRefMsg* refMsg = TRACKED_NEW plNodeRefMsg(GetKey(), plRefMsg::kOnCreate, i, plNodeRefMsg::kObject);
plKey key = mgr->ReadKeyNotifyMe(s, refMsg, plRefFlags::kActiveRef);
}
n = s->ReadSwap32();
fGenericPool.Reset();
for( i = 0; i < n; i++ )
{
plNodeRefMsg* refMsg = TRACKED_NEW plNodeRefMsg(GetKey(), plRefMsg::kOnCreate, -1, plNodeRefMsg::kGeneric);
mgr->ReadKeyNotifyMe(s, refMsg, plRefFlags::kActiveRef);
}
}
void plSceneNode::Write(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Write(s, mgr);
int i;
s->WriteSwap32(fSceneObjects.GetCount());
for( i = 0; i < fSceneObjects.GetCount(); i++ )
mgr->WriteKey(s,fSceneObjects[i]);
s->WriteSwap32(fGenericPool.GetCount());
for( i = 0; i < fGenericPool.GetCount(); i++ )
mgr->WriteKey(s, fGenericPool[i]);
}
void plSceneNode::Harvest(plVolumeIsect* isect, hsTArray<plDrawVisList>& levList)
{
static hsTArray<Int16> visList;
visList.SetCount(0);
GetSpaceTree()->HarvestLeaves(isect, visList);
static hsTArray<Int16> visSpans;
visSpans.SetCount(0);
int i;
for( i = 0; i < visList.GetCount(); i++ )
{
int idx = visList[i];
fDrawPool[idx]->GetSpaceTree()->HarvestLeaves(isect, visSpans);
if( visSpans.GetCount() )
{
plDrawVisList* drawVis = levList.Push();
drawVis->fDrawable = fDrawPool[idx];
drawVis->fVisList.Swap(visSpans);
}
}
}
void plSceneNode::CollectForRender(plPipeline* pipe, hsTArray<plDrawVisList>& levList, plVisMgr* visMgr)
{
static hsTArray<Int16> visList;
visList.SetCount(0);
pipe->HarvestVisible(GetSpaceTree(), visList);
static hsTArray<Int16> visSpans;
visSpans.SetCount(0);
int i;
for( i = 0; i < visList.GetCount(); i++ )
{
int idx = visList[i];
if( pipe->PreRender(fDrawPool[idx], visSpans, visMgr) )
{
plDrawVisList* drawVis = levList.Push();
drawVis->fDrawable = fDrawPool[idx];
drawVis->fVisList.Swap(visSpans);
}
}
}
void plSceneNode::SubmitOccluders(plPageTreeMgr* pageMgr) const
{
pageMgr->AddOccluderList(fOccluders);
}
plSpaceTree* plSceneNode::IBuildSpaceTree()
{
plSpaceTreeMaker maker;
maker.Reset();
hsBounds3Ext bnd;
bnd.Reset(&hsPoint3(0,0,0));
int i;
for( i = 0; i < fDrawPool.GetCount(); i++ )
{
if( fDrawPool[i] )
maker.AddLeaf(fDrawPool[i]->GetSpaceTree()->GetWorldBounds());
else
maker.AddLeaf(bnd, true);
}
fSpaceTree = maker.MakeTree();
fSpaceTree->MakeDirty();
return fSpaceTree;
}
plSpaceTree* plSceneNode::ITrashSpaceTree()
{
delete fSpaceTree;
return fSpaceTree = nil;
}
void plSceneNode::IDirtySpaceTree()
{
int i;
for( i = 0; i < fDrawPool.GetCount(); i++ )
{
if( fDrawPool[i] && fDrawPool[i]->GetSpaceTree()->IsDirty() )
{
fDrawPool[i]->GetSpaceTree()->Refresh();
fSpaceTree->MoveLeaf(i, fDrawPool[i]->GetSpaceTree()->GetWorldBounds());
}
}
}
plSpaceTree* plSceneNode::GetSpaceTree()
{
if( !fSpaceTree )
{
IBuildSpaceTree();
}
IDirtySpaceTree();
return fSpaceTree;
}
void plSceneNode::ISetDrawable(plDrawable* d)
{
if( !d )
return;
if (fDrawPool.Find(d) == fDrawPool.kMissingIndex)
{
fDrawPool.Append(d);
}
ITrashSpaceTree();
}
void plSceneNode::ISetAudible(plAudible* a)
{
if( !a )
return;
if( fAudioPool.kMissingIndex == fAudioPool.Find(a) )
{
fAudioPool.Append(a);
}
}
void plSceneNode::ISetPhysical(plPhysical* p)
{
if( !p )
return;
if( fSimulationPool.kMissingIndex == fSimulationPool.Find(p) )
{
fSimulationPool.Append(p);
}
}
void plSceneNode::ISetObject(plSceneObject* o)
{
if( o && (fSceneObjects.kMissingIndex == fSceneObjects.Find(o)) )
{
fSceneObjects.Append(o);
// MF_NET_GROUPS_TEST
// This will have no effect on members of NetGroupConstants
o->SetNetGroup(o->SelectNetGroup(GetKey()));
o->SetSceneNode(GetKey());
}
}
void plSceneNode::ISetLight(plLightInfo* l)
{
if( fLightPool.kMissingIndex == fLightPool.Find(l) )
fLightPool.Append( l );
}
void plSceneNode::ISetOccluder(plOccluder* o)
{
if( fOccluders.kMissingIndex == fOccluders.Find(o) )
{
fOccluders.Append(o);
}
}
void plSceneNode::ISetGeneric(hsKeyedObject* k)
{
if( fGenericPool.kMissingIndex == fGenericPool.Find(k) )
fGenericPool.Append(k);
}
void plSceneNode::IRemoveDrawable(plDrawable* d)
{
int idx = fDrawPool.Find(d);
if( idx != fDrawPool.kMissingIndex )
fDrawPool.Remove(idx);
ITrashSpaceTree();
}
void plSceneNode::IRemoveAudible(plAudible* a)
{
int idx = fAudioPool.Find(a);
if( idx != fAudioPool.kMissingIndex )
fAudioPool.Remove(idx);
}
void plSceneNode::IRemovePhysical(plPhysical* p)
{
hsAssert(p, "Removing nil physical");
#ifdef HS_DEBUGGING
if (p)
{
plKey oldNodeKey = p->GetSceneNode();
if (oldNodeKey && oldNodeKey != GetKey())
{
char buf[256];
sprintf(buf, "Trying to remove physical %s from scenenode %s,\nbut it's actually in %s",
p->GetKeyName(), GetKeyName(), oldNodeKey->GetName());
hsAssert(0, buf);
}
}
#endif
int idx = fSimulationPool.Find(p);
if( idx != fSimulationPool.kMissingIndex )
fSimulationPool.Remove(idx);
}
void plSceneNode::IRemoveObject(plSceneObject* o)
{
int idx = fSceneObjects.Find(o);
if( idx != fSceneObjects.kMissingIndex )
fSceneObjects.Remove(idx);
}
void plSceneNode::IRemoveLight(plLightInfo* l)
{
hsAssert(l, "Removing nil light");
int idx = fLightPool.Find(l);
if( idx != fLightPool.kMissingIndex )
{
fLightPool.Remove(idx);
}
}
void plSceneNode::IRemoveOccluder(plOccluder* o)
{
int idx = fOccluders.Find(o);
if( idx != fOccluders.kMissingIndex )
fOccluders.Remove(idx);
}
void plSceneNode::IRemoveGeneric(hsKeyedObject* k)
{
int idx = fGenericPool.Find(k);
if( idx != fGenericPool.kMissingIndex )
fGenericPool.Remove(idx);
}
hsBool plSceneNode::IOnRemove(plNodeRefMsg* refMsg)
{
switch( refMsg->fType )
{
case plNodeRefMsg::kDrawable:
IRemoveDrawable(plDrawable::ConvertNoRef(refMsg->GetRef()));
break;
case plNodeRefMsg::kPhysical:
IRemovePhysical(plPhysical::ConvertNoRef(refMsg->GetRef()));
break;
case plNodeRefMsg::kAudible:
IRemoveAudible(plAudible::ConvertNoRef(refMsg->GetRef()));
break;
case plNodeRefMsg::kObject:
IRemoveObject(plSceneObject::ConvertNoRef(refMsg->GetRef()));
break;
case plNodeRefMsg::kLight:
IRemoveLight(plLightInfo::ConvertNoRef(refMsg->GetRef()));
break;
case plNodeRefMsg::kOccluder:
IRemoveOccluder(plOccluder::ConvertNoRef(refMsg->GetRef()));
break;
case plNodeRefMsg::kGeneric:
IRemoveGeneric(refMsg->GetRef());
break;
}
if( refMsg->GetRef() && (refMsg->GetContext() & plRefMsg::kOnRemove) )
GetKey()->Release(refMsg->GetRef()->GetKey());
return true;
}
hsBool plSceneNode::IOnAdd(plNodeRefMsg* refMsg)
{
int which = refMsg->fWhich;
switch( refMsg->fType )
{
case plNodeRefMsg::kDrawable:
ISetDrawable(plDrawable::ConvertNoRef(refMsg->GetRef()));
return true;
case plNodeRefMsg::kPhysical:
ISetPhysical(plPhysical::ConvertNoRef(refMsg->GetRef()));
return true;
case plNodeRefMsg::kAudible:
ISetAudible(plAudible::ConvertNoRef(refMsg->GetRef()));
return true;
case plNodeRefMsg::kObject:
ISetObject(plSceneObject::ConvertNoRef(refMsg->GetRef()));
return true;
case plNodeRefMsg::kLight:
ISetLight(plLightInfo::ConvertNoRef(refMsg->GetRef()));
return true;
case plNodeRefMsg::kOccluder:
ISetOccluder(plOccluder::ConvertNoRef(refMsg->GetRef()));
return true;
case plNodeRefMsg::kGeneric:
ISetGeneric(refMsg->GetRef());
}
return true;
}
hsBool plSceneNode::MsgReceive(plMessage* msg)
{
plNodeCleanupMsg *cleanMsg = plNodeCleanupMsg::ConvertNoRef( msg );
if( cleanMsg )
{
ICleanUp();
return true;
}
plNodeRefMsg* refMsg = plNodeRefMsg::ConvertNoRef(msg);
if( refMsg )
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
return IOnAdd(refMsg);
else if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
return IOnRemove(refMsg);
}
return hsKeyedObject::MsgReceive(msg);
}
//// ICleanUp ////////////////////////////////////////////////////////////////
// Export only: Clean up the scene node (i.e. make sure drawables optimize)
void plSceneNode::ICleanUp( void )
{
int i;
/// Go find drawables to delete
for( i = 0; i < fDrawPool.GetCount(); i++ )
fDrawPool[ i ]->Optimize();
if (fFilterGenerics)
{
for( i = fSceneObjects.GetCount() - 1; i >= 0; i--)
GetKey()->Release(fSceneObjects[i]->GetKey());
for( i = fDrawPool.GetCount() - 1; i >= 0; i--)
GetKey()->Release(fDrawPool[i]->GetKey());
for( i = fSimulationPool.GetCount() - 1; i >= 0; i--)
GetKey()->Release(fSimulationPool[i]->GetKey());
for( i = fAudioPool.GetCount() - 1; i >= 0; i--)
GetKey()->Release(fAudioPool[i]->GetKey());
for( i = fOccluders.GetCount() - 1; i >= 0; i--)
GetKey()->Release(fOccluders[i]->GetKey());
for( i = fLightPool.GetCount() - 1; i >= 0; i--)
GetKey()->Release(fLightPool[i]->GetKey());
}
ITrashSpaceTree();
}
//// GetMatchingDrawable /////////////////////////////////////////////////////
// Export only: Query for a given drawable.
plDrawable *plSceneNode::GetMatchingDrawable( const plDrawableCriteria& crit )
{
int i;
for( i = 0; i < fDrawPool.GetCount(); i++ )
{
if( fDrawPool[ i ]->DoIMatch( crit ) )
return fDrawPool[ i ];
}
return nil;
}
//// OptimizeDrawables ///////////////////////////////////////////////////////
// Loops through all the drawables and calls Optimize on each one. For the
// export side, to be called right before writing the drawables to disk.
void plSceneNode::OptimizeDrawables( void )
{
int i;
for( i = 0; i < fDrawPool.GetCount(); i++ )
fDrawPool[ i ]->Optimize();
}

View File

@ -0,0 +1,155 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plSceneNode_inc
#define plSceneNode_inc
#include "../pnKeyedObject/hsKeyedObject.h"
#include "hsTemplates.h"
class plSceneObject;
class plDrawable;
class plPhysical;
class plAudible;
class plLightInfo;
class plPipeline;
class plNodeRefMsg;
class plDispatchBase;
class plSpaceTree;
class plDrawSpanPair;
class plDrawVisList;
class plOccluder;
class plPageTreeMgr;
class plDrawableCriteria;
class plVolumeIsect;
class plVisMgr;
class plSceneNode : public hsKeyedObject
{
public:
enum {
kMaxSceneDepth = 4
};
protected:
hsBool fFilterGenerics; // Export only
Int16 fDepth;
hsTArray<plSceneObject*> fSceneObjects;
hsTArray<plDrawable*> fDrawPool;
hsTArray<plPhysical*> fSimulationPool;
hsTArray<plAudible*> fAudioPool;
hsTArray<plOccluder*> fOccluders;
hsTArray<plLightInfo*> fLightPool;
hsTArray<hsKeyedObject*> fGenericPool;
plSpaceTree* fSpaceTree;
void IDirtySpaceTree();
plSpaceTree* ITrashSpaceTree();
plSpaceTree* IBuildSpaceTree();
void IRemoveDrawable(plDrawable* d);
void IRemoveAudible(plAudible* a);
void IRemovePhysical(plPhysical* p);
void IRemoveObject(plSceneObject* o);
void IRemoveLight(plLightInfo* l);
void IRemoveOccluder(plOccluder* o);
void IRemoveGeneric(hsKeyedObject* k);
void ISetObject(plSceneObject* o);
void ISetPhysical(plPhysical* p);
void ISetAudible(plAudible* a);
void ISetDrawable(plDrawable* d);
void ISetLight(plLightInfo* l);
void ISetOccluder(plOccluder* o);
void ISetGeneric(hsKeyedObject* k);
hsBool IOnRemove(plNodeRefMsg* refMsg);
hsBool IOnAdd(plNodeRefMsg* refMsg);
// Export only: Clean up empty drawables
void ICleanUp( void );
public:
plSceneNode();
virtual ~plSceneNode();
CLASSNAME_REGISTER( plSceneNode );
GETINTERFACE_ANY( plSceneNode, hsKeyedObject );
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual void Harvest(plVolumeIsect* isect, hsTArray<plDrawVisList>& levList);
virtual void CollectForRender(plPipeline* pipe, hsTArray<plDrawVisList>& levList, plVisMgr* visMgr);
virtual void SubmitOccluders(plPageTreeMgr* pageMgr) const;
virtual hsBool MsgReceive(plMessage* msg);
Int16 GetDepth() { return fDepth; }
Int16 IncDepth() { return ++fDepth; }
Int16 DecDepth() { return --fDepth; }
void Init( void );
plSpaceTree* GetSpaceTree();
// Export only: Query for a given drawable
virtual plDrawable *GetMatchingDrawable( const plDrawableCriteria& crit );
// Export only: Optimize all my stinkin' drawables
virtual void OptimizeDrawables( void );
void SetFilterGenericsOnly(hsBool b) { fFilterGenerics = b; }
const hsTArray<plDrawable*>& GetDrawPool() const { return fDrawPool; }
};
#endif // plSceneNode_inc

View File

@ -0,0 +1,223 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
#include "hsTypes.h"
#include "plVisMgr.h"
#include "plVisRegion.h"
hsBitVector plVisMgr::fIdxSet;
hsBitVector plVisMgr::fIdxNot;
plVisMgr::plVisMgr()
: fMaxSet(kCharacter),
fMaxNot(-1)
{
ResetNormal();
}
plVisMgr::~plVisMgr()
{
}
hsBool plVisMgr::MsgReceive(plMessage* msg)
{
return hsKeyedObject::MsgReceive(msg);
}
void plVisMgr::Read(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Read(s, mgr);
}
void plVisMgr::Write(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Write(s, mgr);
}
void plVisMgr::Register(plVisRegion* reg, hsBool not)
{
// This should happen pretty infrequently, or
// I wouldn't be doing it so cloth-headed-ly.
hsTArray<plVisRegion*>& regions = not ? fNotRegions : fRegions;
hsBitVector& indices = not ? fIdxNot : fIdxSet;
int& maxIdx = not ? fMaxNot : fMaxSet;
int i;
for( i = kNumReserved; ; i++ )
{
if( !indices.IsBitSet(i) )
{
if( i > maxIdx )
maxIdx = i;
indices.SetBit(i);
reg->SetIndex(i);
regions.Append(reg);
return;
}
}
hsAssert(false, "Infinite bitvector has all bits set?");
}
void plVisMgr::UnRegister(plVisRegion* reg, hsBool not)
{
// Mark our index for recycling
hsBitVector& indices= not ? fIdxNot : fIdxSet;
indices.ClearBit(reg->GetIndex());
// Nuke the region from our list.
hsTArray<plVisRegion*>& regions = not ? fNotRegions : fRegions;
int idx = regions.Find(reg);
if( regions.kMissingIndex != idx )
regions.Remove(idx);
}
void plVisMgr::Eval(const hsPoint3& pos)
{
fVisSet = fOnBitSet;
int i;
for( i = 0; i < fRegions.GetCount(); i++ )
{
hsAssert(fRegions[i], "Nil region in list");
if( !fOffBitSet.IsBitSet(fRegions[i]->GetIndex()) )
{
if( fRegions[i]->Eval(pos) )
{
fVisSet.SetBit(fRegions[i]->GetIndex());
if( fRegions[i]->DisableNormal() )
{
fVisSet.ClearBit(kNormal);
fVisSet.SetBit(kCharacter);
}
}
}
}
fVisNot = fOnBitNot;
for( i = 0; i < fNotRegions.GetCount(); i++ )
{
hsAssert(fNotRegions[i], "Nil region in list");
if( !fOffBitNot.IsBitSet(fNotRegions[i]->GetIndex()) )
{
if( fNotRegions[i]->Eval(pos) )
{
fVisNot.SetBit(fNotRegions[i]->GetIndex());
}
}
}
ResetNormal();
}
void plVisMgr::ResetNormal()
{
fOnBitSet.Clear();
fOnBitSet.SetBit(kNormal);
fOffBitSet.Clear();
fOnBitNot.Clear();
fOffBitNot.Clear();
}
void plVisMgr::DisableNormal()
{
fOnBitSet.Clear();
if( fMaxSet > 0 )
fOffBitSet.Set(fMaxSet);
fOnBitNot.Clear();
if( fMaxNot > 0 )
fOffBitNot.Set(fMaxNot);
}
void plVisMgr::EnableVisSet(int idx, hsBool isNot)
{
hsBitVector& offs = isNot ? fOffBitNot : fOffBitSet;
offs.ClearBit(idx);
}
void plVisMgr::EnableVisSets(const hsBitVector& enabled, hsBool isNot)
{
hsBitVector& offs = isNot ? fOffBitNot : fOffBitSet;
offs -= enabled;
}
void plVisMgr::ForceVisSet(int idx, hsBool isNot)
{
EnableVisSet(idx, isNot);
hsBitVector& ons = isNot ? fOnBitNot : fOnBitSet;
ons.SetBit(idx);
}
void plVisMgr::ForceVisSets(const hsBitVector& enabled, hsBool isNot)
{
EnableVisSets(enabled, isNot);
hsBitVector& ons = isNot ? fOnBitNot : fOnBitSet;
ons |= enabled;
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
plVisMgr* plGlobalVisMgr::fInstance = nil;
void plGlobalVisMgr::Init()
{
fInstance = TRACKED_NEW plVisMgr;
fInstance->RegisterAs(kGlobalVisMgr_KEY);
}
void plGlobalVisMgr::DeInit()
{
if (fInstance)
{
fInstance->UnRegisterAs(kGlobalVisMgr_KEY);
fInstance = nil;
}
}

View File

@ -0,0 +1,138 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plVisMgr_inc
#define plVisMgr_inc
#include "../pnKeyedObject/hsKeyedObject.h"
#include "hsTemplates.h"
#include "hsBitVector.h"
class hsStream;
class hsResMgr;
class plVisRegion;
class plMessage;
struct hsPoint3;
class plVisMgr : public hsKeyedObject
{
public:
enum RsvBits
{
kNormal,
kCharacter,
kNumReserved
};
protected:
hsTArray<plVisRegion*> fRegions;
hsTArray<plVisRegion*> fNotRegions;
hsBitVector fVisSet;
hsBitVector fVisNot;
int fMaxSet;
int fMaxNot;
hsBitVector fOnBitSet; // Forces a true response from that enabling region
hsBitVector fOffBitSet; // Forces a false response from that enabling region
hsBitVector fOnBitNot; // Forces a true response from that disabling region
hsBitVector fOffBitNot; // Forces a falseresponse from that disabling region
static hsBitVector fIdxSet;
static hsBitVector fIdxNot;
// There's currently no reason why you would call ResetNormal
// because it's called after every Eval.
void ResetNormal();
public:
plVisMgr();
virtual ~plVisMgr();
CLASSNAME_REGISTER( plVisMgr );
GETINTERFACE_ANY( plVisMgr, hsKeyedObject );
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void Register(plVisRegion* reg, hsBool not);
void UnRegister(plVisRegion* reg, hsBool not);
void Eval(const hsPoint3& pos);
const hsBitVector& GetVisSet() const { return fVisSet; }
const hsBitVector& GetVisNot() const { return fVisNot; }
// All the following persist only through the next Eval. So a normal
// use would be to call DisableNormal() in your RenderRequest's Render method,
// then Enable a few vissets of personal interest, then call the base RenderRequest::Render().
//
// Turns all regions off, so NOTHING gets drawn. That includes Normal and Character.
void DisableNormal();
// Enable drawing of selected sets. Either one index at a time or pass in a bitvector.
// The regions are just enabled, they can still say no.
void EnableVisSet(int idx, hsBool isNot = false);
void EnableVisSets(const hsBitVector& enabled, hsBool isNot = false);
// Make specified regions say yes, no matter where the camera is.
// This will implicitly call EnableVisSet for you.
void ForceVisSet(int idx, hsBool isNot = false);
void ForceVisSets(const hsBitVector& enabled, hsBool isNot = false);
};
class plGlobalVisMgr
{
protected:
static plVisMgr* fInstance;
public:
static plVisMgr* Instance() { return fInstance; }
static void Init();
static void DeInit();
};
#endif // plVisMgr_inc

View File

@ -0,0 +1,145 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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==*/
#include "hsTypes.h"
#include "plVisRegion.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "plVisMgr.h"
#include "../pnMessage/plEnableMsg.h"
#include "../plIntersect/plRegionBase.h"
plVisRegion::plVisRegion()
: fIndex(0),
fRegion(nil),
fMgr(nil)
{
fMgr = plGlobalVisMgr::Instance();
SetProperty(kReplaceNormal, true);
}
plVisRegion::~plVisRegion()
{
if( fMgr )
fMgr->UnRegister(this, GetProperty(kIsNot));
}
hsBool plVisRegion::Eval(const hsPoint3& pos) const
{
if( GetProperty(kDisable) )
return false;
if( !fRegion )
return true;
return fRegion->IsInside(pos);
}
hsBool plVisRegion::MsgReceive(plMessage* msg)
{
plEnableMsg* enaMsg = plEnableMsg::ConvertNoRef(msg);
if( enaMsg )
{
SetProperty(kDisable, enaMsg->Cmd(plEnableMsg::kDisable));
return true;
}
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef(msg);
if( refMsg )
{
switch( refMsg->fType )
{
case kRefRegion:
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
{
fRegion = plRegionBase::ConvertNoRef(refMsg->GetRef());
}
else
{
fRegion = nil;
}
return true;
case kRefVisMgr:
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
{
if( fMgr )
fMgr->UnRegister(this, GetProperty(kIsNot));
fMgr = plVisMgr::ConvertNoRef(refMsg->GetRef());
hsAssert(fMgr, "Just set my manager to nil.");
fMgr->Register(this, GetProperty(kIsNot));
}
else
{
fMgr = nil;
}
return true;
default:
break;
}
}
return plObjInterface::MsgReceive(msg);
}
void plVisRegion::Read(hsStream* s, hsResMgr* mgr)
{
plObjInterface::Read(s, mgr);
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefRegion), plRefFlags::kActiveRef);
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefVisMgr), plRefFlags::kActiveRef);
if( fMgr )
fMgr->Register(this, GetProperty(kIsNot));
}
void plVisRegion::Write(hsStream* s, hsResMgr* mgr)
{
plObjInterface::Write(s, mgr);
mgr->WriteKey(s, fRegion);
mgr->WriteKey(s, fMgr);
}

View File

@ -0,0 +1,109 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 plVisRegion_inc
#define plVisRegion_inc
#include "../pnSceneObject/plObjInterface.h"
class hsStream;
class hsResMgr;
class plMessage;
class plVisMgr;
class plRegionBase;
struct hsPoint3;
class plVisRegion : public plObjInterface
{
public:
enum
{
kRefRegion,
kRefVisMgr
};
enum
{
kDisable = 0, // Always disable is zero
kIsNot,
kReplaceNormal, // Defaults to true
kDisableNormal
};
protected:
plRegionBase* fRegion;
plVisMgr* fMgr;
Int32 fIndex;
void SetIndex(Int32 i) { fIndex = i; }
friend class plVisMgr;
public:
plVisRegion();
virtual ~plVisRegion();
CLASSNAME_REGISTER( plVisRegion );
GETINTERFACE_ANY( plVisRegion, plObjInterface );
virtual Int32 GetNumProperties() const { return 3; } // This is stupid.
virtual hsBool MsgReceive(plMessage* msg);
// Set transform doesn't do anything, because the regions themselves are
// object interfaces, so they'll move when their sceneobjects move.
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l) {}
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
hsBool Eval(const hsPoint3& pos) const;
Int32 GetIndex() const { return fIndex; }
hsBool Registered() const { return GetIndex() > 0; }
hsBool IsNot() const { return GetProperty(kIsNot); }
hsBool ReplaceNormal() const { return GetProperty(kReplaceNormal); }
hsBool DisableNormal() const { return GetProperty(kDisableNormal); }
};
#endif // plVisRegion_inc