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,357 @@
/*==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 "plAccMeshSmooth.h"
#include "plGeometrySpan.h"
#include "plAccessGeometry.h"
#include "plAccessTriSpan.h"
#include "hsFastMath.h"
class EdgeBin
{
public:
UInt16 fVtx;
UInt16 fCount;
EdgeBin() : fVtx(0), fCount(0) {}
};
void plAccMeshSmooth::FindEdges(UInt32 maxVtxIdx, UInt32 nTris, UInt16* idxList, hsTArray<UInt16>& edgeVerts)
{
hsTArray<EdgeBin>* bins = TRACKED_NEW hsTArray<EdgeBin>[maxVtxIdx+1];
hsBitVector edgeVertBits;
// For each vert pair (edge) in idxList
int i;
for( i = 0; i < nTris; i++ )
{
int j;
for( j = 0; j < 3; j++ )
{
int jPlus = j < 2 ? j+1 : 0;
int idx0 = idxList[i*3 + j];
int idx1 = idxList[i*3 + jPlus];
int lo, hi;
// Look in the LUT for the lower index.
if( idx0 < idx1 )
{
lo = idx0;
hi = idx1;
}
else
{
lo = idx1;
hi = idx0;
}
hsTArray<EdgeBin>& loBin = bins[lo];
// In that bucket, look for the higher index.
int k;
for( k = 0; k < loBin.GetCount(); k++ )
{
if( loBin[k].fVtx == hi )
break;
}
// If we find it, increment it's count,
// else add it.
if( k < loBin.GetCount() )
{
loBin[k].fCount++;
}
else
{
EdgeBin* b = loBin.Push();
b->fVtx = hi;
b->fCount = 1;
}
}
}
// For each bucket in the LUT,
for( i = 0; i < maxVtxIdx+1; i++ )
{
hsTArray<EdgeBin>& loBin = bins[i];
// For each higher index
int j;
for( j = 0; j < loBin.GetCount(); j++ )
{
// If the count is one, it's an edge, so set the edge bit for both indices (hi and lo)
if( 1 == loBin[j].fCount )
{
edgeVertBits.SetBit(i);
edgeVertBits.SetBit(loBin[j].fVtx);
}
}
}
// Now translate the bitvector to a list of indices.
for( i = 0; i < maxVtxIdx+1; i++ )
{
if( edgeVertBits.IsBitSet(i) )
edgeVerts.Append(i);
}
delete [] bins;
}
void plAccMeshSmooth::FindEdges(hsTArray<plGeometrySpan*>& spans, hsTArray<UInt16>* edgeVerts)
{
fSpans.SetCount(spans.GetCount());
int i;
for( i = 0; i < spans.GetCount(); i++ )
{
fAccGeom.AccessSpanFromGeometrySpan(fSpans[i], spans[i]);
if( !fSpans[i].HasAccessTri() )
continue;
plAccessTriSpan& triSpan = fSpans[i].AccessTri();
UInt32 nTris = triSpan.TriCount();
UInt16* idxList = triSpan.fTris;
UInt32 maxVertIdx = triSpan.VertCount()-1;
FindEdges(maxVertIdx, nTris, idxList, edgeVerts[i]);
}
}
void plAccMeshSmooth::Smooth(hsTArray<plGeometrySpan*>& spans)
{
hsTArray<UInt16>* shareVtx = TRACKED_NEW hsTArray<UInt16>[spans.GetCount()];
hsTArray<UInt16>* edgeVerts = TRACKED_NEW hsTArray<UInt16>[spans.GetCount()];
FindEdges(spans, edgeVerts);
int i;
for( i = 0; i < spans.GetCount(); i++ )
{
while( edgeVerts[i].GetCount() )
{
int j = edgeVerts[i].GetCount()-1;
plAccessTriSpan& triSpan = fSpans[i].AccessTri();
VtxAccum accum;
accum.fPos = IPositionToWorld(fSpans[i], edgeVerts[i][j]);
accum.fNorm = INormalToWorld(fSpans[i], edgeVerts[i][j]);
if( triSpan.HasDiffuse() )
accum.fDiffuse = triSpan.DiffuseRGBA(edgeVerts[i][j]);
else
accum.fDiffuse.Set(1.f, 1.f, 1.f, 1.f);
shareVtx[i].Append(edgeVerts[i][j]);
// Find shared verts on this same span
FindSharedVerts(fSpans[i], j, edgeVerts[i], shareVtx[i], accum);
// Now look through the rest of the spans
int k;
for( k = i+1; k < spans.GetCount(); k++ )
{
FindSharedVerts(fSpans[k], edgeVerts[k].GetCount(), edgeVerts[k], shareVtx[k], accum);
}
accum.fNorm.Normalize();
if( fFlags & kSmoothNorm )
{
for( k = i; k < spans.GetCount(); k++ )
{
SetNormals(fSpans[k], shareVtx[k], accum.fNorm);
}
}
if( fFlags & kSmoothPos )
{
for( k = i; k < spans.GetCount(); k++ )
{
SetPositions(fSpans[k], shareVtx[k], accum.fPos);
}
}
if( fFlags & kSmoothDiffuse )
{
for( k = i; k < spans.GetCount(); k++ )
{
SetDiffuse(fSpans[k], shareVtx[k], accum.fDiffuse);
}
}
// Now remove all the shared verts (which we just processed)
// from edgeVerts so we don't process them again.
for( k = i; k < spans.GetCount(); k++ )
{
int m;
for( m = 0; m < shareVtx[k].GetCount(); m++ )
{
int idx = edgeVerts[k].Find(shareVtx[k][m]);
hsAssert(idx != edgeVerts[k].kMissingIndex, "Lost vertex between find and remove");
edgeVerts[k].Remove(idx);
}
shareVtx[k].SetCount(0);
}
}
}
delete [] shareVtx;
delete [] edgeVerts;
}
hsPoint3 plAccMeshSmooth::IPositionToWorld(plAccessSpan& span, int i) const
{
return span.GetLocalToWorld() * span.AccessTri().Position(i);
}
hsVector3 plAccMeshSmooth::INormalToWorld(plAccessSpan& span, int i) const
{
if( span.GetWorldToLocal().fFlags & hsMatrix44::kIsIdent )
{
return span.AccessTri().Normal(i);
}
hsMatrix44 l2wInvTransp;
span.GetWorldToLocal().GetTranspose(&l2wInvTransp);
hsVector3 ret = l2wInvTransp * span.AccessTri().Normal(i);
hsFastMath::NormalizeAppr(ret);
return ret;
}
hsPoint3 plAccMeshSmooth::IPositionToLocal(plAccessSpan& span, const hsPoint3& wPos) const
{
return span.GetWorldToLocal() * wPos;
}
hsVector3 plAccMeshSmooth::INormalToLocal(plAccessSpan& span, const hsVector3& wNorm) const
{
if( span.GetLocalToWorld().fFlags & hsMatrix44::kIsIdent )
{
return wNorm;
}
hsMatrix44 w2lInvTransp;
span.GetLocalToWorld().GetTranspose(&w2lInvTransp);
hsVector3 ret = w2lInvTransp * wNorm;
hsFastMath::NormalizeAppr(ret);
return ret;
}
void plAccMeshSmooth::FindSharedVerts(plAccessSpan& span, int numEdgeVerts, hsTArray<UInt16>& edgeVerts, hsTArray<UInt16>& shareVtx, VtxAccum& accum)
{
plAccessTriSpan& triSpan = span.AccessTri();
int i;
for( i = 0; i < numEdgeVerts; i++ )
{
hsPoint3 pos = IPositionToWorld(span, edgeVerts[i]);
hsVector3 diff(&accum.fPos, &pos);
if( diff.MagnitudeSquared() < fDistTolSq )
{
hsVector3 norm = INormalToWorld(span, edgeVerts[i]);
if( norm.InnerProduct(accum.fNorm) > fMinNormDot )
{
shareVtx.Append(edgeVerts[i]);
accum.fPos += pos;
accum.fPos *= 0.5f;
accum.fNorm += norm;
hsFastMath::NormalizeAppr(accum.fNorm);
hsColorRGBA diff;
if( triSpan.HasDiffuse() )
diff = triSpan.DiffuseRGBA(edgeVerts[i]);
else
diff.Set(1.f, 1.f, 1.f, 1.f);
accum.fDiffuse += diff;
accum.fDiffuse *= 0.5f;
}
}
}
}
void plAccMeshSmooth::SetPositions(plAccessSpan& span, hsTArray<UInt16>& shareVtx, const hsPoint3& pos) const
{
plAccessTriSpan& triSpan = span.AccessTri();
int i;
for( i = 0; i < shareVtx.GetCount(); i++ )
triSpan.Position(shareVtx[i]) = IPositionToLocal(span, pos);
}
void plAccMeshSmooth::SetNormals(plAccessSpan& span, hsTArray<UInt16>& shareVtx, const hsVector3& norm) const
{
plAccessTriSpan& triSpan = span.AccessTri();
int i;
for( i = 0; i < shareVtx.GetCount(); i++ )
triSpan.Normal(shareVtx[i]) = INormalToLocal(span, norm);
}
void plAccMeshSmooth::SetDiffuse(plAccessSpan& span, hsTArray<UInt16>& shareVtx, const hsColorRGBA& diff) const
{
plAccessTriSpan& triSpan = span.AccessTri();
hsAssert(triSpan.HasDiffuse(), "Calling SetColors on data with no color");
int i;
for( i = 0; i < shareVtx.GetCount(); i++ )
triSpan.Diffuse32(shareVtx[i]) = diff.ToARGB32();
}
void plAccMeshSmooth::SetAngle(hsScalar degs)
{
fMinNormDot = hsCosine(hsScalarDegToRad(degs));
}
hsScalar plAccMeshSmooth::GetAngle() const
{
return hsScalarRadToDeg(hsACosine(fMinNormDot));
}
void plAccMeshSmooth::SetDistTol(hsScalar dist)
{
fDistTolSq = dist * dist;
}
hsScalar plAccMeshSmooth::GetDistTol() const
{
return hsSquareRoot(fDistTolSq);
}

View File

@ -0,0 +1,107 @@
/*==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 plAccMeshSmooth_inc
#define plAccMeshSmooth_inc
#include "hsTemplates.h"
#include "plAccessGeometry.h"
#include "plAccessSpan.h"
struct hsPoint3;
struct hsVector3;
class plGeometrySpan;
class plAccMeshSmooth
{
public:
enum {
kNone = 0x0,
kSmoothNorm = 0x1,
kSmoothPos = 0x2,
kSmoothDiffuse = 0x4
};
protected:
struct VtxAccum
{
hsPoint3 fPos;
hsVector3 fNorm;
hsColorRGBA fDiffuse;
};
UInt32 fFlags;
hsScalar fMinNormDot;
hsScalar fDistTolSq;
plAccessGeometry fAccGeom;
hsTArray<plAccessSpan> fSpans;
hsPoint3 IPositionToWorld(plAccessSpan& span, int i) const;
hsVector3 INormalToWorld(plAccessSpan& span, int i) const;
hsPoint3 IPositionToLocal(plAccessSpan& span, const hsPoint3& wPos) const;
hsVector3 INormalToLocal(plAccessSpan& span, const hsVector3& wNorm) const;
void FindEdges(UInt32 maxVtxIdx, UInt32 nTris, UInt16* idxList, hsTArray<UInt16>& edgeVerts);
void FindEdges(hsTArray<plGeometrySpan*>& sets, hsTArray<UInt16>* edgeVerts);
void FindSharedVerts(plAccessSpan& span, int numEdgeVerts, hsTArray<UInt16>& edgeVerts, hsTArray<UInt16>& shareVtx, VtxAccum& accum);
void SetNormals(plAccessSpan& span, hsTArray<UInt16>& shareVtx, const hsVector3& norm) const;
void SetPositions(plAccessSpan& span, hsTArray<UInt16>& shareVtx, const hsPoint3& pos) const;
void SetDiffuse(plAccessSpan& span, hsTArray<UInt16>& shareVtx, const hsColorRGBA& diff) const;
public:
plAccMeshSmooth() : fFlags(kSmoothNorm), fMinNormDot(0.25f), fDistTolSq(1.e-4f), fAccGeom() {}
void SetAngle(hsScalar degs);
hsScalar GetAngle() const; // returns degrees
void SetDistTol(hsScalar dist);
hsScalar GetDistTol() const;
void Smooth(hsTArray<plGeometrySpan*>& sets);
void SetFlags(UInt32 f) { fFlags = f; }
UInt32 GetFlags() const { return fFlags; }
};
#endif // plAccMeshSmooth_inc

View File

@ -0,0 +1,599 @@
/*==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 "plAccessGeometry.h"
#include "../pnSceneObject/plDrawInterface.h"
#include "plDrawableSpans.h"
#include "plGeometrySpan.h"
#include "plAccessSpan.h"
#include "plAccessPartySpan.h"
#include "plAccessTriSpan.h"
#include "plAccessVtxSpan.h"
#include "plAccessSnapShot.h"
// For dipping directly into device buffers.
#include "../plPipeline/plGBufferGroup.h"
#include "../plPipeline/hsGDeviceRef.h"
#include "plPipeline.h"
#include "plTweak.h"
//////////////////////////////////////////////////////////////////////////////////
// Dropping these here, because they have no place else to go except a header.
void plAccessSpan::SetSource(plSpan* s)
{
fLocalToWorld = &s->fLocalToWorld;
fWorldToLocal = &s->fWorldToLocal;
fLocalBounds = &s->fLocalBounds;
fWorldBounds = &s->fWorldBounds;
fWaterHeight = s->fProps & plSpan::kWaterHeight ? &s->fWaterHeight : nil;
}
void plAccessSpan::SetSource(plGeometrySpan* s)
{
fLocalToWorld = &s->fLocalToWorld;
fWorldToLocal = &s->fWorldToLocal;
fLocalBounds = &s->fLocalBounds;
fWorldBounds = &s->fWorldBounds;
fWaterHeight = s->fProps & plGeometrySpan::kWaterHeight ? &s->fWaterHeight : nil;
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// Simple constructor
plAccessGeometry::plAccessGeometry(plPipeline* pipe)
: fPipe(pipe)
{
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// Global access stuff.
plAccessGeometry* plAccessGeometry::fInstance = nil;
void plAccessGeometry::Init(plPipeline* pipe)
{
plAccessGeometry* oldAcc = fInstance;
fInstance = NEW(plAccessGeometry)(pipe);
hsRefCnt_SafeUnRef(oldAcc);
}
void plAccessGeometry::DeInit()
{
if( fInstance )
fInstance->Nilify();
hsRefCnt_SafeUnRef(fInstance);
}
void plAccessGeometry::SetTheIntance(plAccessGeometry* i)
{
hsRefCnt_SafeAssign(fInstance, i);
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// The first couple of these just interpret between the SceneObjects we like to
// think about and the clumps of geometry that comprise each one.
void plAccessGeometry::OpenRO(const plDrawInterface* di, hsTArray<plAccessSpan>& accs, hsBool useSnap) const
{
int numGot = 0;
accs.SetCount(di->GetNumDrawables());
accs.SetCount(0);
int j;
for( j = 0; j < di->GetNumDrawables(); j++ )
{
plDrawableSpans* dr = plDrawableSpans::ConvertNoRef(di->GetDrawable(j));
// Nil dr - it hasn't loaded yet or something.
if( dr )
{
plDISpanIndex& diIndex = dr->GetDISpans(di->GetDrawableMeshIndex(j));
if( !diIndex.IsMatrixOnly() )
{
int k;
for( k = 0; k < diIndex.GetCount(); k++ )
{
accs.Expand(numGot+1);
accs.SetCount(numGot+1);
OpenRO(dr, diIndex[k], accs[numGot++]);
}
}
}
}
}
void plAccessGeometry::OpenRW(const plDrawInterface* di, hsTArray<plAccessSpan>& accs, hsBool idxToo) const
{
int numGot = 0;
accs.Expand(di->GetNumDrawables());
accs.SetCount(0);
int j;
for( j = 0; j < di->GetNumDrawables(); j++ )
{
plDrawableSpans* dr = plDrawableSpans::ConvertNoRef(di->GetDrawable(j));
// Nil dr - it hasn't loaded yet or something.
if( dr )
{
plDISpanIndex& diIndex = dr->GetDISpans(di->GetDrawableMeshIndex(j));
if( !diIndex.IsMatrixOnly() )
{
int k;
for( k = 0; k < diIndex.GetCount(); k++ )
{
accs.Expand(numGot+1);
accs.SetCount(numGot+1);
OpenRW(dr, diIndex[k], accs[numGot++], idxToo);
}
}
}
}
}
void plAccessGeometry::Close(hsTArray<plAccessSpan>& accs) const
{
int i;
for( i = 0; i < accs.GetCount(); i++ )
Close(accs[i]);
}
void plAccessGeometry::TakeSnapShot(const plDrawInterface* di, UInt32 channels) const
{
int j;
for( j = 0; j < di->GetNumDrawables(); j++ )
{
plDrawableSpans* dr = plDrawableSpans::ConvertNoRef(di->GetDrawable(j));
// Nil dr - it hasn't loaded yet or something.
if( dr )
{
plDISpanIndex& diIndex = dr->GetDISpans(di->GetDrawableMeshIndex(j));
if( !diIndex.IsMatrixOnly() )
{
int k;
for( k = 0; k < diIndex.GetCount(); k++ )
{
TakeSnapShot(dr, diIndex[k], channels);
}
}
}
}
}
void plAccessGeometry::RestoreSnapShot(const plDrawInterface* di, UInt32 channels) const
{
int j;
for( j = 0; j < di->GetNumDrawables(); j++ )
{
plDrawableSpans* dr = plDrawableSpans::ConvertNoRef(di->GetDrawable(j));
// Nil dr - it hasn't loaded yet or something.
if( dr )
{
plDISpanIndex& diIndex = dr->GetDISpans(di->GetDrawableMeshIndex(j));
if( !diIndex.IsMatrixOnly() )
{
int k;
for( k = 0; k < diIndex.GetCount(); k++ )
{
RestoreSnapShot(dr, diIndex[k], channels);
}
}
}
}
}
void plAccessGeometry::ReleaseSnapShot(const plDrawInterface* di) const
{
int j;
for( j = 0; j < di->GetNumDrawables(); j++ )
{
plDrawableSpans* dr = plDrawableSpans::ConvertNoRef(di->GetDrawable(j));
// Nil dr - it hasn't loaded yet or something.
if( dr )
{
plDISpanIndex& diIndex = dr->GetDISpans(di->GetDrawableMeshIndex(j));
if( !diIndex.IsMatrixOnly() )
{
int k;
for( k = 0; k < diIndex.GetCount(); k++ )
{
ReleaseSnapShot(dr, diIndex[k]);
}
}
}
}
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
void plAccessGeometry::Close(plAccessSpan& acc) const
{
if( !fPipe )
return;
fPipe->CloseAccess(acc);
}
void plAccessGeometry::IOpen(plDrawable* d, UInt32 spanIdx, plAccessSpan& acc, hsBool useSnap, hsBool readOnly, hsBool idxToo) const
{
acc.SetType(plAccessSpan::kUndefined);
plDrawableSpans* drawable = plDrawableSpans::ConvertNoRef(d);
if( !drawable )
return;
if( drawable->GetSourceSpans().GetCount() && !drawable->GetNumSpans() )
IAccessSpanFromSourceSpan(acc, drawable->GetSourceSpans()[spanIdx]);
else
IAccessSpanFromSpan(acc, drawable, drawable->GetSpan(spanIdx), useSnap, readOnly);
if( !readOnly )
{
// Need to mark the drawable's data as dirty.
plDrawableSpans* ds = plDrawableSpans::ConvertNoRef(drawable);
if( !ds )
return;
if( acc.HasAccessVtx() )
{
plVertexSpan* vtx = (plVertexSpan*)ds->GetSpan(spanIdx);
ds->DirtyVertexBuffer(vtx->fGroupIdx, vtx->fVBufferIdx);
}
if( idxToo && acc.HasAccessTri() )
{
plIcicle* ice = (plIcicle*)ds->GetSpan(spanIdx);
ds->DirtyIndexBuffer(ice->fGroupIdx, ice->fIBufferIdx);
}
}
}
void plAccessGeometry::OpenRO(plDrawable* d, UInt32 spanIdx, plAccessSpan& acc, hsBool useSnap) const
{
IOpen(d, spanIdx, acc, useSnap, true);
}
void plAccessGeometry::OpenRW(plDrawable* drawable, UInt32 spanIdx, plAccessSpan& acc, hsBool idxToo) const
{
IOpen(drawable, spanIdx, acc, false, false, idxToo);
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
void plAccessGeometry::TakeSnapShot(plDrawable* drawable, UInt32 spanIdx, UInt32 channels) const
{
plDrawableSpans* ds = plDrawableSpans::ConvertNoRef(drawable);
if( !ds )
return;
const plSpan* span = ds->GetSpan(spanIdx);
if( !span->fSnapShot )
span->fSnapShot = NEW(plAccessSnapShot);
plAccessSpan tmp;
OpenRO(drawable, spanIdx, tmp, false);
if( tmp.HasAccessVtx() )
{
span->fSnapShot->IncRef();
span->fSnapShot->CopyFrom(tmp.AccessVtx(), channels);
}
}
void plAccessGeometry::RestoreSnapShot(plDrawable* drawable, UInt32 spanIdx, UInt32 channels) const
{
plDrawableSpans* ds = plDrawableSpans::ConvertNoRef(drawable);
if( !ds )
return;
const plSpan* span = ds->GetSpan(spanIdx);
if( !span->fSnapShot )
return;
plAccessSpan tmp;
OpenRW(drawable, spanIdx, tmp);
if( tmp.HasAccessVtx() )
span->fSnapShot->CopyTo(tmp.AccessVtx(), channels);
}
void plAccessGeometry::ReleaseSnapShot(plDrawable* drawable, UInt32 spanIdx) const
{
plDrawableSpans* ds = plDrawableSpans::ConvertNoRef(drawable);
if( !ds )
return;
const plSpan* span = ds->GetSpan(spanIdx);
if( !span->fSnapShot )
return;
span->fSnapShot->Release();
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
void plAccessGeometry::IAccessSpanFromSourceSpan(plAccessSpan& dst, const plGeometrySpan* src) const
{
// Get the connectivity info
dst.SetType(plAccessSpan::kTri);
plAccessTriSpan& tri = dst.AccessTri();
tri.fNumTris = src->fNumIndices / 3;
tri.fTris = src->fIndexData;
tri.fIdxDeviceRef = nil;
dst.SetSource(const_cast<plGeometrySpan*>(src));
dst.SetMaterial(src->fMaterial);
plAccessVtxSpan& acc = dst.AccessVtx();
acc.fNumVerts = (UInt16)(src->fNumVerts);
UInt32 sz = src->GetVertexSize(src->fFormat);
UInt8* ptr = src->fVertexData;
acc.PositionStream(ptr, (UInt16)sz, 0);
ptr += sizeof(hsPoint3);
acc.NormalStream(ptr, (UInt16)sz, 0);
ptr += sizeof(hsVector3);
acc.DiffuseStream(src->fDiffuseRGBA, sizeof(UInt32), 0);
acc.SpecularStream(src->fSpecularRGBA, sizeof(UInt32), 0);
acc.UVWStream(ptr, (UInt16)sz, 0);
acc.SetNumUVWs(src->CalcNumUVs(src->fFormat));
acc.fVtxDeviceRef = nil;
}
void plAccessGeometry::IAccessSpanFromSpan(plAccessSpan& dst, plDrawableSpans* drawable, const plSpan* span, hsBool useSnap, hsBool readOnly) const
{
dst.SetType(plAccessSpan::kUndefined);
dst.SetSource(const_cast<plSpan*> (span));
if( span->fTypeMask & plSpan::kIcicleSpan )
{
IAccessSpanFromIcicle(dst, drawable, (const plIcicle*)span, readOnly);
}
else if( span->fTypeMask & plSpan::kParticleSpan )
{
IAccessSpanFromParticle(dst, drawable, (const plParticleSpan*)span, readOnly);
}
if( useSnap )
{
IAccessSpanFromSnap(dst, drawable, span);
}
}
void plAccessGeometry::IAccessSpanFromSnap(plAccessSpan& dst, plDrawableSpans* drawable, const plSpan* span) const
{
plAccessVtxSpan& acc = dst.AccessVtx();
if( span->fSnapShot )
{
span->fSnapShot->SetupChannels(acc);
}
}
void plAccessGeometry::IAccessSpanFromVertexSpan(plAccessSpan& dst, plDrawableSpans* drawable, const plVertexSpan* span, hsBool readOnly) const
{
dst.SetMaterial(drawable->GetMaterial(span->fMaterialIdx));
plAccessVtxSpan& acc = dst.AccessVtx();
plGBufferGroup* grp = drawable->GetBufferGroup(span->fGroupIdx);
//#define MF_TOSSER
#ifndef MF_TOSSER
plConst(hsBool) useDev(false);
#else // MF_TOSSER
plConst(hsBool) useDev(true);
#endif // MF_TOSSER
if( useDev && !drawable->GetNativeProperty(plDrawable::kPropVolatile) && grp->GetVertexBufferRef(span->fVBufferIdx) )
{
fPipe->OpenAccess(dst, drawable, span, readOnly);
return;
}
acc.fNumVerts = (UInt16)(span->fVLength);
plGBufferCell* cell = grp->GetCell(span->fVBufferIdx, span->fCellIdx);
UInt8* ptr = grp->GetVertBufferData(span->fVBufferIdx);
// Interleaved
if( cell->fColorStart == UInt32(-1) )
{
UInt32 stride = grp->GetVertexSize();
ptr += cell->fVtxStart + span->fCellOffset * stride;
Int32 offset = (-(Int32)(span->fVStartIdx)) * (Int32)stride;
acc.PositionStream(ptr, (UInt16)stride, offset);
ptr += sizeof(hsPoint3);
int numWgts = grp->GetNumWeights();
if( numWgts )
{
acc.SetNumWeights(numWgts);
acc.WeightStream(ptr, (UInt16)stride, offset);
ptr += numWgts * sizeof(hsScalar);
if( grp->GetVertexFormat() & plGBufferGroup::kSkinIndices )
{
acc.WgtIndexStream(ptr, (UInt16)stride, offset);
ptr += sizeof(UInt32);
}
else
{
acc.WgtIndexStream(nil, 0, offset);
}
}
else
{
acc.SetNumWeights(0);
}
acc.NormalStream(ptr, (UInt16)stride, offset);
ptr += sizeof(hsVector3);
acc.DiffuseStream(ptr, (UInt16)stride, offset);
ptr += sizeof(UInt32);
acc.SpecularStream(ptr, (UInt16)stride, offset);
ptr += sizeof(UInt32);
acc.UVWStream(ptr, (UInt16)stride, offset);
acc.SetNumUVWs(grp->GetNumUVs());
}
else
{
UInt32 stride = grp->GetVertexLiteStride();
ptr += cell->fVtxStart + span->fCellOffset * stride;
Int32 posOffset = (-(Int32)(span->fVStartIdx)) * (Int32)stride;
acc.PositionStream(ptr, (UInt16)stride, posOffset);
ptr += sizeof(hsPoint3);
int numWgts = grp->GetNumWeights();
if( numWgts )
{
acc.SetNumWeights(numWgts);
acc.WeightStream(ptr, (UInt16)stride, posOffset);
ptr += numWgts * sizeof(hsScalar);
if( grp->GetVertexFormat() & plGBufferGroup::kSkinIndices )
{
acc.WgtIndexStream(ptr, (UInt16)stride, posOffset);
ptr += sizeof(UInt32);
}
else
{
acc.WgtIndexStream(nil, 0, 0);
}
}
else
{
acc.SetNumWeights(0);
}
acc.NormalStream(ptr, (UInt16)stride, posOffset);
ptr += sizeof(hsVector3);
plGBufferColor* col = grp->GetColorBufferData(span->fVBufferIdx) + cell->fColorStart;
Int16 colOffset = (Int16)((-(Int32)(span->fVStartIdx)) * (Int32)stride);
colOffset = (Int16)((-(Int32)(span->fVStartIdx)) * sizeof(*col));
acc.DiffuseStream(&col->fDiffuse, sizeof(*col), colOffset);
acc.SpecularStream(&col->fSpecular, sizeof(*col), colOffset);
acc.UVWStream(ptr, (UInt16)stride, posOffset);
acc.SetNumUVWs(grp->GetNumUVs());
}
acc.fVtxDeviceRef = nil;
}
void plAccessGeometry::IAccessConnectivity(plAccessSpan& dst, plDrawableSpans* drawable, const plSpan* src) const
{
if( src->fTypeMask & plSpan::kIcicleSpan )
{
const plIcicle* span = (const plIcicle*)src;
dst.SetType(plAccessSpan::kTri);
plAccessTriSpan& acc = dst.AccessTri();
acc.fNumTris = span->fILength / 3;
plGBufferGroup* grp = drawable->GetBufferGroup(span->fGroupIdx);
acc.fTris = grp->GetIndexBufferData(span->fIBufferIdx) + span->fIStartIdx;
acc.fIdxDeviceRef = nil;
}
// Hmm, particle should probably go here...
else
{
dst.SetType(plAccessSpan::kVtx);
}
}
void plAccessGeometry::IAccessSpanFromIcicle(plAccessSpan& dst, plDrawableSpans* drawable, const plIcicle* span, hsBool readOnly) const
{
dst.SetType(plAccessSpan::kTri);
plAccessTriSpan& acc = dst.AccessTri();
IAccessSpanFromVertexSpan(dst, drawable, span, readOnly);
acc.fNumTris = span->fILength / 3;
plGBufferGroup* grp = drawable->GetBufferGroup(span->fGroupIdx);
acc.fTris = grp->GetIndexBufferData(span->fIBufferIdx) + span->fIStartIdx;
acc.fIdxDeviceRef = nil;
}
void plAccessGeometry::IAccessSpanFromParticle(plAccessSpan& dst, plDrawableSpans* drawable, const plParticleSpan* span, hsBool readOnly) const
{
hsAssert(false, "Aint got to it yet");
// dst.SetType(plAccessSpan::kParty);
}

View File

@ -0,0 +1,177 @@
/*==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 plAccessGeometry_inc
#define plAccessGeometry_inc
#include "hsTemplates.h"
class plDrawable;
class plDrawableSpans;
class plGeometrySpan;
class plDrawInterface;
class plAccessSpan;
class plSpan;
class plParticleSpan;
class plIcicle;
class plVertexSpan;
class plPipeline;
class plAccessGeometry : public hsRefCnt
{
protected:
void Nilify() { fPipe = nil; }
friend class plAccessGeometry;
plPipeline* fPipe;
static plAccessGeometry* fInstance;
public:
// You're welcome to make your own,
// but this is normally just called by the global plAccessGeometry's Init() function.
// You should normally just use the instance supplied by Instance();
plAccessGeometry(plPipeline* pipe=nil);
static plAccessGeometry* Instance() { return fInstance; }
// App will initialize, which will create the global instance.
// DeInit will nil the global instance.
static void Init(plPipeline* pipe);
static void DeInit();
// External DLL's will share the same plAccessGeometry. After the main App has
// DeInited the AccessGeometry,
// all calls to Instance()->Function() will return nil in one form or another (e.g.
// empty triangle lists). The external DLL needs to either not try to use these
// accessor functions after PythonInterface::WeAreInShutdown() (it won't do any good
// anyway as any work done will be thrown away), or else be prepared for receiving
// empty data where there was data before.
static void SetTheIntance(plAccessGeometry* i);
// You have 2 options in opening the data.
// RO - Read Only.
// If you specify useSnapShot=true, then for channels which have had a snapshot
// taken, you will get pointers to this constant original snapshot form. For
// channels which have no snapshot data, or if useSnapShot=false, you will get
// pointers to the current (possibly modified since load) data. See SnapShot functions
// below.
// RW - Read/Write access to the source data. After closing, this modified source data
// will be used to update the buffer data used for rendering.
// In the normal case of reading the original (disk image) data, performing some operation
// on it and updating the renderable data, you need to open the same data twice, once
// RO(useSnapShot=true) (to get the constant source data) and once RW (for destination data). Note that
// the memory returned by RO will may be the same as returned by RW if there has been no snapshot
// taken.
// The RW permutation by itself is useful when performing a one-time operation on the data (e.g.
// loadtime), so the modified source data is, to everyone else, what was read from disk.
// The only way to retrieve the original source data is to read it from disk again,
// unless you've made a snapshot. Normally you would do a RW modify the original data,
// then take the snapshot if you are going to be performing more modifications.
// In ALL MODIFICATION CASES, if the modified data is paged out, and the original paged back in, you will
// need to perform your operation again - your modifications aren't saved anywhere.
void OpenRO(plDrawable* drawable, UInt32 spanIdx, plAccessSpan& acc, hsBool useSnapShot=true) const;
void OpenRW(plDrawable* drawable, UInt32 spanIdx, plAccessSpan& acc, hsBool idxToo=false) const;
// What do we need to close up here?
void Close(plAccessSpan& acc) const;
// Second set. You have a SceneObject's DrawInterface. This can reference into
// multiple drawables, and multiple spans within each drawable. You would rather
// not deal with it. So you can open by passing in a DrawInterface, and get back
// a list of geometry corresponding to that SceneObject/DrawInterface.
// NOTE: the list is in no way suggested to be homogenous. In fact, it's guaranteed
// not to be, because the reason the single object resolved into multiple geometry spans
// (possibly across multiple drawables) is that the conceptual single object is composed
// of multiple types of data that can't be batched into a single drawprimitive call.
// At the least, the different AccessSpans will have different materials. But it's just
// as likely that they will have different underlying formats (number of UVs, etc.).
// Again, if you are using the iterators supplied, you probably don't care, but sometimes
// you will (like if you are messing with the UVs).
void OpenRO(const plDrawInterface* di, hsTArray<plAccessSpan>& accs, hsBool useSnapShot=true) const;
void OpenRW(const plDrawInterface* di, hsTArray<plAccessSpan>& accs, hsBool idxToo=false) const;
void Close(hsTArray<plAccessSpan>& accs) const;
// SnapShot functions.
// If you need to generate channel values based on the original values (e.g. normal perterbation)
// you need to reserve a copy of the original data. Only the channels specified will be copied.
// Only one snapshot is ever taken, and it is the union of all channels requested. For example,
// taking a snapshot of positions AFTER taking a snapshot of positions/normals is a no-op,
// but taking a snapshot of positions/normals AFTER a snapshot of just positions will result in
// a copy of positions from the old snapshot, then a copy of normals from the buffergroup
// into the new snapshot, then freeing of the old snapshot.
// Still, you should only snapshot the minimum set of channels you will need to be reading in their
// original form later.
// The snapshot data is refcounted. You need to match your TakeSnapShots with FreeSnapShots.
// SnapShot data is stored interleaved for efficiency, but don't count on it. Use an iterator.
// RestoreSnapShot will copy the stored channels back into the buffer group, resetting those channels to
// the state when the snapshot was taken. Note that channels not SnapShotted might have been modified
// via OpenRW.
//
void TakeSnapShot(plDrawable* drawable, UInt32 spanIdx, UInt32 channels) const;
void RestoreSnapShot(plDrawable* drawable, UInt32 spanIdx, UInt32 channels) const;
void ReleaseSnapShot(plDrawable* drawable, UInt32 spanIdx) const;
void TakeSnapShot(const plDrawInterface* di, UInt32 channels) const;
void RestoreSnapShot(const plDrawInterface* di, UInt32 channels) const;
void ReleaseSnapShot(const plDrawInterface* di) const;
// We often have geometry spans just sitting around devoid of any DI's, drawables or sceneobjects.
// They aren't too bad to access directly (not like diving through the drawable into buffergroups),
// but this let's them be accessed in a manner consistent with other geometry manipulations.
void AccessSpanFromGeometrySpan(plAccessSpan& dst, const plGeometrySpan* src) const { IAccessSpanFromSourceSpan(dst, src); }
protected:
void IAccessSpanFromSourceSpan(plAccessSpan& dst, const plGeometrySpan* src) const;
void IAccessSpanFromSpan(plAccessSpan& dst, plDrawableSpans* drawable, const plSpan* span, hsBool useSnap, hsBool readOnly) const;
void IAccessSpanFromVertexSpan(plAccessSpan& dst, plDrawableSpans* drawable, const plVertexSpan* span, hsBool readOnly) const;
void IAccessConnectivity(plAccessSpan& dst, plDrawableSpans* drawable, const plSpan* src) const;
void IAccessSpanFromIcicle(plAccessSpan& dst, plDrawableSpans* drawable, const plIcicle* span, hsBool readOnly) const;
void IAccessSpanFromParticle(plAccessSpan& dst, plDrawableSpans* drawable, const plParticleSpan* span, hsBool readOnly) const;
void IAccessSpanFromSnap(plAccessSpan& dst, plDrawableSpans* drawable, const plSpan* src) const;
void IOpen(plDrawable* d, UInt32 spanIdx, plAccessSpan& acc, hsBool useSnap, hsBool readOnly, hsBool idxToo=true) const;
};
#endif // plAccessGeometry_inc

View File

@ -0,0 +1,55 @@
/*==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 plAccessPartySpan_inc
#define plAccessPartySpan_inc
#include "plAccessVtxSpan.h"
class plAccessPartySpan : public plAccessVtxSpan
{
public:
};
#endif // plAccessPartySpan_inc

View File

@ -0,0 +1,286 @@
/*==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 "plAccessSnapShot.h"
#include "hsGeometry3.h"
#include <memory.h>
void plAccessSnapShot::Clear()
{
ClearVerts();
int i;
for( i = 0; i < kNumValidChans; i++ )
fChanSize[i] = 0;
}
void plAccessSnapShot::Destroy()
{
Clear();
delete [] fData;
fRefCnt = 0;
}
void plAccessSnapShot::Release()
{
hsAssert(fRefCnt, "Releasing a snapshot with no refs. Check matching TakeSnapShot/ReleaseSnapShot calls.");
if( !--fRefCnt )
{
Destroy();
}
}
UInt32 plAccessSnapShot::ICheckAlloc(const plAccessVtxSpan& src, UInt32 chanMask, UInt32 chan, UInt16 chanSize)
{
if( ((1 << chan) & chanMask) && src.fStrides[chan] )
{
if( fChanSize[chan] )
{
// We already have this one
chanMask &= ~(1 << chan);
}
else
{
// We'll get this one
fChanSize[chan] = chanSize;
}
}
else
{
// either we haven't been asked for this or src doesn't have it.
// either way, we're never going to get it.
chanMask &= ~(1 << chan);
}
return chanMask;
}
void plAccessSnapShot::IRecordSizes(UInt16 sizes[]) const
{
int chan;
for( chan = 0; chan < kNumValidChans; chan++ )
sizes[chan] = fChanSize[chan];
}
UInt16 plAccessSnapShot::IComputeStride() const
{
UInt16 stride = 0;
int chan;
for( chan = 0; chan < kNumValidChans; chan++ )
stride += fChanSize[chan];
return stride;
}
void plAccessSnapShot::ICopyOldData(UInt8* data, const UInt16* const oldSizes, UInt16 oldStride, UInt16 newStride)
{
UInt32 oldOffset = 0;
UInt32 newOffset = 0;
UInt8* srcChannels[kNumValidChans];
UInt8* dstChannels[kNumValidChans];
int chan;
for( chan = 0; chan < kNumValidChans; chan++ )
{
if( oldSizes[chan] )
{
hsAssert(fChanSize[chan], "Copying a channel we don't have");
srcChannels[chan] = data + oldOffset;
oldOffset += oldSizes[chan];
}
if( fChanSize[chan] )
{
dstChannels[chan] = fData + newOffset;
newOffset += fChanSize[chan];
}
}
int i;
for( i = 0; i < fNumVerts; i++ )
{
for( chan = 0; chan < kNumValidChans; chan++ )
{
if( oldSizes[chan] )
{
memcpy(dstChannels[chan], srcChannels[chan], oldSizes[chan]);
dstChannels[chan] += newStride;
srcChannels[chan] += oldStride;
}
}
}
}
void plAccessSnapShot::ISetupPointers(UInt16 newStride)
{
fData = TRACKED_NEW UInt8[fNumVerts * newStride];
int size = 0;
int chan;
for( chan = 0; chan < kNumValidChans; chan++ )
{
if( fChanSize[chan] )
{
fStrides[chan] = newStride;
fChannels[chan] = fData + size;
size += fChanSize[chan];
}
}
}
UInt32 plAccessSnapShot::CopyFrom(const plAccessVtxSpan& src, UInt32 chanMask)
{
hsAssert(!fNumVerts || (fNumVerts == src.fNumVerts), "Copying from a different sized span");
fNumVerts = src.fNumVerts;
UInt16 oldSize[kNumValidChans];
UInt8* oldData = fData;
IRecordSizes(oldSize);
UInt16 oldStride = IComputeStride();
// First, allocate any storage we need. Kill any requested channels out of the
// mask that we already have.
chanMask = ICheckAlloc(src, chanMask, kPosition, sizeof(hsPoint3));
chanMask = ICheckAlloc(src, chanMask, kWeight, sizeof(hsScalar) * src.fNumWeights);
if( fChanSize[kWeight] )
fNumWeights = src.fNumWeights;
chanMask = ICheckAlloc(src, chanMask, kWgtIndex, sizeof(UInt32));
chanMask = ICheckAlloc(src, chanMask, kNormal, sizeof(hsVector3));
chanMask = ICheckAlloc(src, chanMask, kDiffuse, sizeof(UInt32));
chanMask = ICheckAlloc(src, chanMask, kSpecular, sizeof(UInt32));
chanMask = ICheckAlloc(src, chanMask, kUVW, sizeof(hsPoint3) * src.fNumUVWsPerVert);
if( fChanSize[kUVW] )
fNumUVWsPerVert = src.fNumUVWsPerVert;
// If our chanMask has gone to zero, we've only been asked to record
// channels we already have, so there's nothing to do.
if( !chanMask )
return 0;
UInt16 newStride = IComputeStride();
ISetupPointers(newStride);
ICopyOldData(oldData, oldSize, oldStride, newStride);
UInt8* srcChannels[kNumValidChans];
UInt8* dstChannels[kNumValidChans];
int chan;
for( chan = 0; chan < kNumValidChans; chan++ )
{
srcChannels[chan] = src.fChannels[chan];
dstChannels[chan] = fChannels[chan];
}
int i;
for( i = 0; i < src.VertCount(); i++ )
{
for( chan = 0; chan < kNumValidChans; chan++ )
{
if( (1<< chan) & chanMask )
{
memcpy(dstChannels[chan], srcChannels[chan], fChanSize[chan]);
dstChannels[chan] += fStrides[chan];
srcChannels[chan] += src.fStrides[chan];
}
}
}
return chanMask;
}
UInt32 plAccessSnapShot::CopyTo(const plAccessVtxSpan& dst, UInt32 chanMask)
{
hsAssert(fNumVerts == dst.fNumVerts, "Vertex count mismatch, is this our real source?");
int chan;
for( chan = 0; chan < kNumValidChans; chan++ )
{
if( !(fChanSize[chan] && dst.fStrides[chan]) )
chanMask &= ~(1 << chan);
}
// If chanMask has gone to zero, either we don't have any of the requested channels
// recorded, or dst doesn't have them. Both being true is valid, but
// us having a channel recorded that's not in dst is probably an error.
if( !chanMask )
return 0;
int i;
for( i = 0; i < fNumVerts; i++ )
{
for( chan = 0; chan < kNumValidChans; chan++ )
{
if( (1 << chan) & chanMask )
{
memcpy(
dst.fChannels[chan] + dst.fStrides[chan] * i,
fChannels[chan] + fStrides[chan] * i,
fChanSize[chan]);
}
}
}
return chanMask;
}
void plAccessSnapShot::SetupChannels(plAccessVtxSpan& dst) const
{
int chan;
for( chan = 0; chan < kNumValidChans; chan++ )
{
if( fChanSize[chan] )
{
dst.fChannels[chan] = fChannels[chan];
dst.fStrides[chan] = fStrides[chan];
dst.fOffsets[chan] = 0;
}
}
}

View File

@ -0,0 +1,87 @@
/*==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 plAccessSnapShot_inc
#define plAccessSnapShot_inc
#include "plAccessVtxSpan.h"
// All functions and fields here (including constructor) are private,
// because the only valid user of this is the friend class plAccessGeometry.
// Use this only via plAccessGeometry.
class plAccessSnapShot : public plAccessVtxSpan
{
public:
void Destroy(); // Free up and reset to zero.
protected:
UInt16 fRefCnt;
UInt8* fData;
UInt16 fChanSize[kNumValidChans];
void ICopyOldData(UInt8* data, const UInt16* const oldSizes, UInt16 oldStride, UInt16 newStride);
UInt16 IComputeStride() const;
void IRecordSizes(UInt16 sizes[]) const;
UInt32 ICheckAlloc(const plAccessVtxSpan& src, UInt32 chanMask, UInt32 chan, UInt16 chanSize);
void ISetupPointers(UInt16 newStride);
void SetupChannels(plAccessVtxSpan& dst) const;
UInt32 CopyTo(const plAccessVtxSpan& dst, UInt32 chanMask);
UInt32 CopyFrom(const plAccessVtxSpan& src, UInt32 chanMask);
void Release(); // Decrements refcnt, calls Destroy on zero
void Clear(); // Initialize to zeros
void IncRef() { fRefCnt++; }
void DecRef() { Release(); }
plAccessSnapShot() : fRefCnt(0), fData(nil) { Clear(); }
friend class plAccessGeometry;
};
#endif // plAccessSnapShot_inc

View File

@ -0,0 +1,146 @@
/*==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 plAccessSpan_inc
#define plAccessSpan_inc
#include "plAccessVtxSpan.h"
#include "plAccessTriSpan.h"
#include "plAccessPartySpan.h"
#include "plSpanTypes.h"
#include "plGeometrySpan.h"
class plGeometrySpan;
class plSpan;
class hsGMaterial;
class plAccessSpan
{
public:
enum AccessType
{
kTri = 0,
kParty,
kVtx,
kUndefined
};
private:
union
{
plAccessTriSpan fAccessTri;
plAccessPartySpan fAccessParty;
plAccessVtxSpan fAccessVtx;
} fAccess;
AccessType fType;
const hsMatrix44* fLocalToWorld;
const hsMatrix44* fWorldToLocal;
hsBounds3Ext* fLocalBounds;
hsBounds3Ext* fWorldBounds;
hsScalar* fWaterHeight;
hsGMaterial* fMaterial;
void SetSource(plSpan* s);
void SetSource(plGeometrySpan* s);
void SetMaterial(hsGMaterial* m) { fMaterial = m; }
friend class plAccessGeometry;
public:
plAccessSpan() : fType(kUndefined), fLocalToWorld(nil), fWorldToLocal(nil), fLocalBounds(nil), fWorldBounds(nil), fWaterHeight(nil), fMaterial(nil) {}
plAccessSpan(AccessType t) : fType(t), fLocalToWorld(nil), fWorldToLocal(nil), fLocalBounds(nil), fWorldBounds(nil), fWaterHeight(nil), fMaterial(nil) {}
void SetType(AccessType t) { fType = t; }
AccessType GetType() const { return fType; }
hsBool HasAccessTri() const { return fType == kTri; }
hsBool HasAccessParty() const { return fType == kParty; }
hsBool HasAccessVtx() const { return fType != kUndefined; }
plAccessTriSpan& AccessTri() { hsAssert(fType == kTri, "Cross type access"); return fAccess.fAccessTri; }
plAccessPartySpan& AccessParty() { hsAssert(fType == kParty, "Cross type access"); return fAccess.fAccessParty; }
inline plAccessVtxSpan& AccessVtx();
const hsMatrix44& GetLocalToWorld() const { return *fLocalToWorld; }
const hsMatrix44& GetWorldToLocal() const { return *fWorldToLocal; }
hsGMaterial* GetMaterial() const { return fMaterial; }
const hsBounds3Ext& GetLocalBounds() const { return *fLocalBounds; }
const hsBounds3Ext& GetWorldBounds() const { return *fWorldBounds; }
void SetLocalBounds(const hsBounds3Ext& bnd) { *fWorldBounds = *fLocalBounds = bnd; fWorldBounds->Transform(fLocalToWorld); }
void SetWorldBounds(const hsBounds3Ext& wBnd) { *fWorldBounds = wBnd; }
hsBool HasWaterHeight() const { return nil != fWaterHeight; }
hsScalar GetWaterHeight() const { hsAssert(HasWaterHeight(), "Check before asking"); return *fWaterHeight; }
};
inline plAccessVtxSpan& plAccessSpan::AccessVtx()
{
switch( fType )
{
case kTri:
return fAccess.fAccessTri;
case kParty:
return fAccess.fAccessParty;
case kVtx:
return fAccess.fAccessVtx;
case kUndefined:
default:
break;
}
hsAssert(false, "Undefined type");
return fAccess.fAccessVtx;
}
#endif // plAccessSpan_inc

View File

@ -0,0 +1,174 @@
/*==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 plAccessTriSpan_inc
#define plAccessTriSpan_inc
#include "plAccessVtxSpan.h"
class plAccessTriSpan : public plAccessVtxSpan
{
public:
hsGDeviceRef* fIdxDeviceRef;
UInt16* fTris; // array length fNumTris*3
UInt32 fNumTris;
void ClearTris() { fTris = nil; fNumTris = 0; }
UInt32 TriCount() const { return fNumTris; }
void SetIdxDeviceRef(hsGDeviceRef* ref) { fIdxDeviceRef = ref; }
hsGDeviceRef* GetIdxDeviceRef() const { return fIdxDeviceRef; }
};
class plAccTriIterator
{
protected:
UInt16* fCurrIdx;
UInt16* fEndIdx;
plAccessTriSpan* fAccess;
public:
plAccTriIterator() { Set(nil); }
plAccTriIterator(plAccessTriSpan* acc) { Set(acc); }
void Set(plAccessTriSpan* acc) { fAccess = acc; fCurrIdx = nil; }
void Begin();
void Advance();
void SetTri(int i);
hsBool More() const;
UInt32 NumTris() const { return fAccess->fNumTris; }
UInt16& RawIndex(int iVtx) const { return fCurrIdx[iVtx]; }
hsPoint3& Position(int iVtx) const { return fAccess->PositionOff(fCurrIdx[iVtx]); }
hsVector3& Normal(int iVtx) const { return fAccess->NormalOff(fCurrIdx[iVtx]); }
UInt32 Diffuse32(int iVtx) const { return fAccess->Diffuse32Off(fCurrIdx[iVtx]); }
UInt32 Specular32(int iVtx) const { return fAccess->Specular32Off(fCurrIdx[iVtx]); }
hsColorRGBA DiffuseRGBA(int iVtx) const { return fAccess->DiffuseRGBAOff(fCurrIdx[iVtx]); }
hsColorRGBA SpecularRGBA(int iVtx) const { return fAccess->SpecularRGBAOff(fCurrIdx[iVtx]); }
hsPoint3* UVWs(int iVtx) const { return fAccess->UVWsOff(fCurrIdx[iVtx]); }
hsPoint3& UVW(int iVtx, int iUVW) const { return fAccess->UVWOff(fCurrIdx[iVtx], iUVW); }
hsPoint3 InterpPosition(const hsPoint3& bary) const;
hsVector3 InterpNormal(const hsPoint3& bary) const;
UInt32 InterpDiffuse32(const hsPoint3& bary) const;
UInt32 InterpSpecular32(const hsPoint3& bary) const;
hsColorRGBA InterpDiffuseRGBA(const hsPoint3& bary) const;
hsColorRGBA InterpSpecularRGBA(const hsPoint3& bary) const;
hsPoint3 InterpUVW(const hsPoint3& bary, int i) const;
};
inline void plAccTriIterator::Begin()
{
fCurrIdx = fAccess->fTris;
fEndIdx = fCurrIdx + fAccess->fNumTris*3;
}
inline void plAccTriIterator::Advance()
{
fCurrIdx += 3;
}
inline void plAccTriIterator::SetTri(int i)
{
fCurrIdx = fAccess->fTris + i * 3;
}
inline hsBool plAccTriIterator::More() const
{
return fCurrIdx < fEndIdx;
}
inline hsPoint3 plAccTriIterator::InterpPosition(const hsPoint3& bary) const
{
return Position(0) * bary[0]
+ Position(1) * bary[1]
+ Position(2) * bary[2];
}
inline hsVector3 plAccTriIterator::InterpNormal(const hsPoint3& bary) const
{
return Normal(0) * bary[0]
+ Normal(1) * bary[1]
+ Normal(2) * bary[2];
}
inline hsColorRGBA plAccTriIterator::InterpDiffuseRGBA(const hsPoint3& bary) const
{
return DiffuseRGBA(0) * bary[0]
+ DiffuseRGBA(1) * bary[1]
+ DiffuseRGBA(2) * bary[2];
}
inline hsColorRGBA plAccTriIterator::InterpSpecularRGBA(const hsPoint3& bary) const
{
return SpecularRGBA(0) * bary[0]
+ SpecularRGBA(1) * bary[1]
+ SpecularRGBA(2) * bary[2];
}
inline UInt32 plAccTriIterator::InterpDiffuse32(const hsPoint3& bary) const
{
return InterpDiffuseRGBA(bary).ToARGB32();
}
inline UInt32 plAccTriIterator::InterpSpecular32(const hsPoint3& bary) const
{
return InterpSpecularRGBA(bary).ToARGB32();
}
inline hsPoint3 plAccTriIterator::InterpUVW(const hsPoint3& bary, int i) const
{
return UVW(0, i) * bary[0]
+ UVW(1, i) * bary[1]
+ UVW(2, i) * bary[2];
}
#endif // plAccessTriSpan_inc

View File

@ -0,0 +1,463 @@
/*==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 plAccessVtxSpan_inc
#define plAccessVtxSpan_inc
#include "hsGeometry3.h"
#include "hsColorRGBA.h"
class hsGMaterial;
struct hsMatrix44;
class hsGDeviceRef;
// AccessSpan - a generic "vertex array". It'll at least act like one,
// whatever the underlying storage mechanism. For random access, just
// use the accessor functions. For faster sequential iteration, use
// the iterator classes defined further down. I'm leaving the actual
// data (fChannels & fStrides) public, but I'll probably regret it.
// I have to dig pretty deep to come up with a reason not to use
// either the indexed accessors or the iterator classes.
//
// You may be wondering why have separate strides for each of the data channels,
// especially since this means doing nChan pointer adds to advance rather than
// one. The answer is two part. First, the different channels may be in different
// buffers, either because we're on the export side and haven't glommed them together
// into a single stream yet, or because we finally got around to using multiple
// streams on the runtime side (say to support instancing). The point is for you
// to be able to write your code without knowing or caring. The second part is that
// those nChan adds aren't really costing you anything. Say the data is stored contiguously,
// and we keep a base pointer and an advance just adds the (single) stride to the base
// pointer. That's probably your position, and we've just saved a bunch of adds in advancing
// it. Now you want to access your normal, well, you still have to do an add on the base pointer
// to get to your normal, and another to get to your color, etc. So if you really want to
// eliminate those extra adds, go ahead and use the iterator, just make sure you use
// the most focused iterator available. Like if you're just looking at position and
// normal, use the plAccPosNormIterator.
class plAccessVtxSpan
{
public:
enum Channel
{
kPosition = 0,
kWeight,
kWgtIndex,
kNormal,
kDiffuse,
kSpecular,
kUVW,
kNumValidChans,
kInvalid = 0xffff
};
// Mask versions, to be or'ed together and passed in when using plAccessGeometry::SnapShotStuff.
enum
{
kPositionMask = (1 << kPosition),
kWeightMask = (1 << kWeight),
kWgtIndexMask = (1 << kWgtIndex),
kNormalMask = (1 << kNormal),
kDiffuseMask = (1 << kDiffuse),
kSpecularMask = (1 << kSpecular),
kUVWMask = (1 << kUVW)
};
hsGDeviceRef* fVtxDeviceRef;
UInt8* fChannels[kNumValidChans];
UInt16 fStrides[kNumValidChans];
Int32 fOffsets[kNumValidChans];
UInt16 fNumWeights;
UInt16 fNumUVWsPerVert;
UInt16 fNumVerts;
//////////////////////////////////
// QUERY SECTION
// Queries on how much of what we got.
UInt32 VertCount() const { return fNumVerts; }
hsBool HasChannel(Channel chan) const { return fStrides[chan] > 0; }
hsBool HasPositions() const { return HasChannel(kPosition); }
hsBool HasWeights() const { return HasChannel(kWeight); }
int NumWeights() const { return fNumWeights; }
hsBool HasWgtIndex() const { return HasChannel(kWgtIndex); }
hsBool HasNormals() const { return HasChannel(kNormal); }
hsBool HasDiffuse() const { return HasChannel(kDiffuse); }
hsBool HasSpecular() const { return HasChannel(kSpecular); }
hsBool HasUVWs() const { return HasChannel(kUVW); }
hsBool HasUVWs(int n) { return HasChannel(kUVW) && (n <= fNumUVWsPerVert); }
int NumUVWs() const { return fNumUVWsPerVert; }
//////////////////////////////////
// ACCESSOR SECTION
hsPoint3& Position(int i) const { return *(hsPoint3*)(fChannels[kPosition] + i*fStrides[kPosition]); }
hsVector3& Normal(int i) const { return *(hsVector3*)(fChannels[kNormal] + i*fStrides[kNormal]); }
hsScalar& Weight(int iVtx, int iWgt) const { return *(hsScalar*)(fChannels[kWeight] + iVtx*fStrides[kWeight] + iWgt*sizeof(hsScalar)); }
hsScalar* Weights(int i) const { return (hsScalar*)(fChannels[kWeight] + i*fStrides[kWeight]); }
UInt32& WgtIndices(int i) const { return *(UInt32*)(fChannels[kWgtIndex] + i * fStrides[kWgtIndex]); }
UInt8& WgtIndex(int iVtx, int iWgt) const { return *(fChannels[kWgtIndex] + iVtx*fStrides[kWgtIndex] + iWgt); }
UInt32& Diffuse32(int i) const { return *(UInt32*)(fChannels[kDiffuse] + i*fStrides[kDiffuse]); }
UInt32& Specular32(int i) const { return *(UInt32*)(fChannels[kSpecular] + i*fStrides[kSpecular]); }
hsColorRGBA DiffuseRGBA(int i) const { return hsColorRGBA().FromARGB32(Diffuse32(i)); }
hsColorRGBA SpecularRGBA(int i) const { return hsColorRGBA().FromARGB32(Specular32(i)); }
// Two versions of UVW, first to get the iVtx'th vertex's iUVW'th uvw.
// Second just gets the vertex's uvw array, which is hopefully stored contiguously or we're screwed.
hsPoint3& UVW(int iVtx, int iUVW) const { return *(hsPoint3*)(fChannels[kUVW] + iVtx*fStrides[kUVW] + iUVW*sizeof(hsPoint3)); }
hsPoint3* UVWs(int i) const { return (hsPoint3*)(fChannels[kUVW] + i*fStrides[kUVW]); }
// OFFSET VERSIONS
// Tri and particle accessors call the offset versions because they have indices into the original
// buffers, but our pointers are based at the beginning of our data.
hsPoint3& PositionOff(int i) const { return *(hsPoint3*)(fChannels[kPosition] + i*fStrides[kPosition] + fOffsets[kPosition]); }
hsVector3& NormalOff(int i) const { return *(hsVector3*)(fChannels[kNormal] + i*fStrides[kNormal] + fOffsets[kNormal]); }
hsScalar& WeightOff(int iVtx, int iWgt) const { return *(hsScalar*)(fChannels[kWeight] + iVtx*fStrides[kWeight] + fOffsets[kWeight] + iWgt*sizeof(hsScalar)); }
hsScalar* WeightsOff(int i) const { return (hsScalar*)(fChannels[kWeight] + i*fStrides[kWeight] + fOffsets[kWeight]); }
UInt32& WgtIndicesOff(int i) const { return *(UInt32*)(fChannels[kWgtIndex] + i * fStrides[kWgtIndex] + fOffsets[kWgtIndex]); }
UInt8& WgtIndexOff(int iVtx, int iWgt) const { return *(fChannels[kWgtIndex] + iVtx*fStrides[kWgtIndex] + fOffsets[kWgtIndex] + iWgt); }
UInt32& Diffuse32Off(int i) const { return *(UInt32*)(fChannels[kDiffuse] + i*fStrides[kDiffuse] + fOffsets[kDiffuse]); }
UInt32& Specular32Off(int i) const { return *(UInt32*)(fChannels[kSpecular] + i*fStrides[kSpecular] + fOffsets[kSpecular]); }
hsColorRGBA DiffuseRGBAOff(int i) const { return hsColorRGBA().FromARGB32(Diffuse32Off(i)); }
hsColorRGBA SpecularRGBAOff(int i) const { return hsColorRGBA().FromARGB32(Specular32Off(i)); }
// Two versions of UVW, first to get the iVtx'th vertex's iUVW'th uvw.
// Second just gets the vertex's uvw array, which is hopefully stored contiguously or we're screwed.
hsPoint3& UVWOff(int iVtx, int iUVW) const { return *(hsPoint3*)(fChannels[kUVW] + iVtx*fStrides[kUVW] + fOffsets[kUVW] + iUVW*sizeof(hsPoint3)); }
hsPoint3* UVWsOff(int i) const { return (hsPoint3*)(fChannels[kUVW] + i*fStrides[kUVW] + fOffsets[kUVW]); }
//////////////////////////////////
// SETUP SECTION.
//////////////////////////////////
//////////////////////////////////
// Call Clear to initialize.
void ClearVerts();
// Must at least set a count and the valid channels. Note below on setting up for UVW access.
plAccessVtxSpan& SetVertCount(UInt16 c) { fNumVerts = c; return *this; }
plAccessVtxSpan& SetStream(void* p, UInt16 stride, Int32 offset, Channel chan) { fChannels[chan] = (UInt8*)p; fStrides[chan] = stride; fOffsets[chan] = offset; return *this; }
//////////////////////////////////
// Convenience versions. You get the idea.
plAccessVtxSpan& PositionStream(void* p, UInt16 stride, Int32 offset) { return SetStream(p, stride, offset, kPosition); }
plAccessVtxSpan& NormalStream(void* p, UInt16 stride, Int32 offset) { return SetStream(p, stride, offset, kNormal); }
plAccessVtxSpan& DiffuseStream(void* p, UInt16 stride, Int32 offset) { return SetStream(p, stride, offset, kDiffuse); }
plAccessVtxSpan& SpecularStream(void* p, UInt16 stride, Int32 offset) { return SetStream(p, stride, offset, kSpecular); }
plAccessVtxSpan& WeightStream(void* p, UInt16 stride, Int32 offset) { return SetStream(p, stride, offset, kWeight); }
plAccessVtxSpan& WgtIndexStream(void* p, UInt16 stride, Int32 offset) { return SetStream(p, stride, offset, kWgtIndex); }
plAccessVtxSpan& SetNumWeights(int n) { if( !(fNumWeights = n) ) SetStream(nil, 0, 0, kWeight).SetStream(nil, 0, 0, kWgtIndex); return *this; }
// Note on UVW access setup, you don't actually "have" to set the number of uvws per vertex,
// but one way or another you'll need to know to access the uvws. If you're going to be setting
// up the AccessSpan and passing it off for processing, you definitely better set it. But the
// accessor and iterators don't ever use it.
// Note that this means the UVWStream stride is from uvw[0][0] to uvw[1][0] in bytes.
plAccessVtxSpan& UVWStream(void* p, UInt16 stride, Int32 offset) { return SetStream(p, stride, offset, kUVW); }
plAccessVtxSpan& SetNumUVWs(int n) { if( !(fNumUVWsPerVert = n) )SetStream(nil, 0, 0, kUVW); return *this; }
//////////////////////////////////
// Cache away any device stuff that needed to be opened (locked) to get this data, so
// we can close (unlock) it later.
void SetVtxDeviceRef(hsGDeviceRef* ref) { fVtxDeviceRef = ref; }
hsGDeviceRef* GetVtxDeviceRef() const { return fVtxDeviceRef; }
};
inline void plAccessVtxSpan::ClearVerts()
{
int i;
for( i = 0; i < kNumValidChans; i++ )
{
fChannels[i] = nil;
fStrides[i] = 0;
}
fNumVerts = 0;
fNumUVWsPerVert = 0;
fNumWeights = 0;
}
template <class T> class plAccIterator
{
private:
union
{
T* fValue;
UInt8* fValueByte;
};
UInt8* fValueEnd;
plAccessVtxSpan* fAccess;
plAccessVtxSpan::Channel fChan;
void ISetEnd() { fValueEnd = fAccess->fChannels[fChan] + fAccess->fNumVerts * fAccess->fStrides[fChan]; }
public:
plAccIterator(plAccessVtxSpan* acc, plAccessVtxSpan::Channel chan) { Set(acc, chan); }
plAccIterator(const plAccIterator& accIt) { *this = accIt; }
plAccIterator() : fValueByte(nil), fValueEnd(nil), fAccess(nil), fChan(plAccessVtxSpan::kInvalid) {}
void Set(plAccessVtxSpan* acc, plAccessVtxSpan::Channel chan) { fAccess = acc; fChan = chan; ISetEnd(); }
T* Value() const { return fValue; }
int Count() const { return fAccess->VertCount(); }
int GetCount() const { return Count(); }
void Begin() { fValueByte = fAccess->fChannels[fChan]; }
void Advance() { fValueByte += fAccess->fStrides[fChan]; }
hsBool More() const { return fValueByte < fValueEnd; }
};
class plAccPositionIterator
{
protected:
plAccIterator<hsPoint3> fPosition;
public:
plAccPositionIterator(plAccessVtxSpan* acc)
: fPosition(acc, plAccessVtxSpan::kPosition) {}
plAccPositionIterator() {}
plAccPositionIterator& Set(plAccessVtxSpan* acc)
{
fPosition.Set(acc, plAccessVtxSpan::kPosition);
return *this;
}
hsPoint3* Position() const { return fPosition.Value(); }
void Begin() { fPosition.Begin(); }
void Advance() { fPosition.Advance(); }
hsBool More() const { return fPosition.More(); }
};
class plAccPosNormIterator
{
protected:
plAccIterator<hsPoint3> fPosition;
plAccIterator<hsVector3> fNormal;
public:
plAccPosNormIterator(plAccessVtxSpan* acc)
: fPosition(acc, plAccessVtxSpan::kPosition),
fNormal(acc, plAccessVtxSpan::kNormal) {}
plAccPosNormIterator() {}
plAccPosNormIterator& Set(plAccessVtxSpan* acc)
{
fPosition.Set(acc, plAccessVtxSpan::kPosition);
fNormal.Set(acc, plAccessVtxSpan::kNormal);
return *this;
}
hsPoint3* Position() const { return fPosition.Value(); }
hsVector3* Normal() const { return fNormal.Value(); }
void Begin() { fPosition.Begin(); fNormal.Begin(); }
void Advance() { fPosition.Advance(); fNormal.Advance(); }
hsBool More() const { return fPosition.More(); }
};
class plAccPosNormUVWIterator
{
protected:
plAccIterator<hsPoint3> fPosition;
plAccIterator<hsVector3> fNormal;
plAccIterator<hsPoint3> fUVW;
public:
plAccPosNormUVWIterator(plAccessVtxSpan* acc)
: fPosition(acc, plAccessVtxSpan::kPosition),
fNormal(acc, plAccessVtxSpan::kNormal),
fUVW(acc, plAccessVtxSpan::kUVW) {}
plAccPosNormUVWIterator() {}
plAccPosNormUVWIterator& Set(plAccessVtxSpan* acc)
{
fPosition.Set(acc, plAccessVtxSpan::kPosition);
fNormal.Set(acc, plAccessVtxSpan::kNormal);
fUVW.Set(acc, plAccessVtxSpan::kUVW);
return *this;
}
hsPoint3* Position() const { return fPosition.Value(); }
hsVector3* Normal() const { return fNormal.Value(); }
hsPoint3* UVWs() const { return fUVW.Value(); }
hsPoint3* UVW(int i) const { return fUVW.Value() + i; }
void Begin() { fPosition.Begin(); fNormal.Begin(); fUVW.Begin(); }
void Advance() { fPosition.Advance(); fNormal.Advance(); fUVW.Advance(); }
hsBool More() const { return fPosition.More(); }
};
class plAccUVWIterator
{
plAccIterator<hsPoint3> fUVW;
public:
plAccUVWIterator(plAccessVtxSpan* acc)
: fUVW(acc, plAccessVtxSpan::kUVW) {}
plAccUVWIterator() {}
plAccUVWIterator& Set(plAccessVtxSpan* acc)
{
fUVW.Set(acc, plAccessVtxSpan::kUVW);
return *this;
}
hsPoint3* UVWs() const { return fUVW.Value(); }
hsPoint3* UVW(int i) const { return fUVW.Value() + i; }
void Begin() { fUVW.Begin(); }
void Advance() { fUVW.Advance(); }
hsBool More() const { return fUVW.More(); }
};
class plAccDiffuseIterator
{
plAccIterator<UInt32> fDiffuse;
public:
plAccDiffuseIterator(plAccessVtxSpan* acc)
: fDiffuse(acc, plAccessVtxSpan::kDiffuse) {}
plAccDiffuseIterator() {}
plAccDiffuseIterator& Set(plAccessVtxSpan* acc)
{
fDiffuse.Set(acc, plAccessVtxSpan::kDiffuse);
return *this;
}
UInt32* Diffuse32() const { return fDiffuse.Value(); }
hsColorRGBA DiffuseRGBA() const { return hsColorRGBA().FromARGB32(*Diffuse32()); }
void Begin() { fDiffuse.Begin(); }
void Advance() { fDiffuse.Advance(); }
hsBool More() const { return fDiffuse.More(); }
};
class plAccDiffSpecIterator
{
protected:
plAccIterator<UInt32> fDiffuse;
plAccIterator<UInt32> fSpecular;
public:
plAccDiffSpecIterator(plAccessVtxSpan* acc)
: fDiffuse(acc, plAccessVtxSpan::kDiffuse),
fSpecular(acc, plAccessVtxSpan::kSpecular) {}
plAccDiffSpecIterator() {}
plAccDiffSpecIterator& Set(plAccessVtxSpan* acc)
{
fDiffuse.Set(acc, plAccessVtxSpan::kDiffuse);
fSpecular.Set(acc, plAccessVtxSpan::kSpecular);
return *this;
}
UInt32* Diffuse32() const { return fDiffuse.Value(); }
UInt32* Specular32() const { return fSpecular.Value(); }
hsColorRGBA DiffuseRGBA() const { return hsColorRGBA().FromARGB32(*Diffuse32()); }
hsColorRGBA SpecularRGBA() const { return hsColorRGBA().FromARGB32(*Specular32()); }
void Begin() { fDiffuse.Begin(); fSpecular.Begin(); }
void Advance() { fDiffuse.Advance(); fSpecular.Advance(); }
hsBool More() const { return fDiffuse.More(); }
};
class plAccVertexIterator
{
protected:
plAccIterator<hsPoint3> fPosition;
plAccIterator<hsScalar> fWeight;
plAccIterator<UInt8> fWgtIndex;
plAccIterator<hsVector3> fNormal;
plAccIterator<UInt32> fDiffuse;
plAccIterator<UInt32> fSpecular;
plAccIterator<hsPoint3> fUVW;
public:
plAccVertexIterator(plAccessVtxSpan* acc)
: fPosition(acc, plAccessVtxSpan::kPosition),
fWeight(acc, plAccessVtxSpan::kWeight),
fWgtIndex(acc, plAccessVtxSpan::kWgtIndex),
fNormal(acc, plAccessVtxSpan::kNormal),
fDiffuse(acc, plAccessVtxSpan::kDiffuse),
fSpecular(acc, plAccessVtxSpan::kSpecular),
fUVW(acc, plAccessVtxSpan::kUVW) {}
plAccVertexIterator() {}
plAccVertexIterator& Set(plAccessVtxSpan* acc)
{
fPosition.Set(acc, plAccessVtxSpan::kPosition);
fWeight.Set(acc, plAccessVtxSpan::kWeight);
fWgtIndex.Set(acc, plAccessVtxSpan::kWgtIndex);
fNormal.Set(acc, plAccessVtxSpan::kNormal);
fDiffuse.Set(acc, plAccessVtxSpan::kDiffuse);
fSpecular.Set(acc, plAccessVtxSpan::kSpecular);
fUVW.Set(acc, plAccessVtxSpan::kUVW);
return *this;
}
hsPoint3* Position() const { return fPosition.Value(); }
hsScalar* Weights() const { return fWeight.Value(); }
hsScalar* Weight(int i) const { return fWeight.Value() + i; }
UInt32* WgtIndices() const { return (UInt32*)(fWgtIndex.Value()); }
UInt8* WgtIndex(int i) const { return fWgtIndex.Value() + i; }
hsVector3* Normal() const { return fNormal.Value(); }
hsPoint3* UVWs() const { return fUVW.Value(); }
hsPoint3* UVW(int i) const { return fUVW.Value() + i; }
UInt32* Diffuse32() const { return fDiffuse.Value(); }
UInt32* Specular32() const { return fSpecular.Value(); }
hsColorRGBA DiffuseRGBA() const { return hsColorRGBA().FromARGB32(*Diffuse32()); }
hsColorRGBA SpecularRGBA() const { return hsColorRGBA().FromARGB32(*Specular32()); }
void Begin() { fPosition.Begin(); fWeight.Begin(); fNormal.Begin(); fDiffuse.Begin(); fSpecular.Begin(); fUVW.Begin(); }
void Advance() { fPosition.Advance(); fWeight.Advance(); fNormal.Advance(); fDiffuse.Begin(); fSpecular.Begin(); fUVW.Advance(); }
hsBool More() const { return fPosition.More(); }
};
#endif // plAccessVtxSpan_inc

View File

@ -0,0 +1,130 @@
/*==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 "plActivePrintShape.h"
#include "../plMessage/plRippleShapeMsg.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "plgDispatch.h"
#include "../pnMessage/plTimeMsg.h"
plActivePrintShape::plActivePrintShape()
: fShapeMsg(nil)
{
}
plActivePrintShape::~plActivePrintShape()
{
delete fShapeMsg;
}
void plActivePrintShape::Read(hsStream* stream, hsResMgr* mgr)
{
plPrintShape::Read(stream, mgr);
UInt32 n = stream->ReadSwap32();
fDecalMgrs.SetCount(n);
int i;
for( i = 0; i < n; i++ )
fDecalMgrs[i] = mgr->ReadKey(stream);
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
void plActivePrintShape::Write(hsStream* stream, hsResMgr* mgr)
{
plPrintShape::Write(stream, mgr);
stream->WriteSwap32(fDecalMgrs.GetCount());
int i;
for( i = 0; i < fDecalMgrs.GetCount(); i++ )
mgr->WriteKey(stream, fDecalMgrs[i]);
}
// Export construction
void plActivePrintShape::AddDecalKey(const plKey& k)
{
fDecalMgrs.Append(k);
}
hsBool plActivePrintShape::MsgReceive(plMessage* msg)
{
plEvalMsg* eval = plEvalMsg::ConvertNoRef(msg);
if( eval )
{
return INotify();
}
return plPrintShape::MsgReceive(msg);
}
hsBool plActivePrintShape::INotify()
{
if( !fShapeMsg )
ISetupShapeMsg();
if( fDecalMgrs.GetCount() )
{
fShapeMsg->SetBCastFlag(plMessage::kBCastByExactType, false);
int i;
for( i = 0; i < fDecalMgrs.GetCount(); i++ )
{
fShapeMsg->ClearReceivers().SendAndKeep(fDecalMgrs[i]);
}
}
else
{
fShapeMsg->SetBCastFlag(plMessage::kBCastByExactType, true);
fShapeMsg->SendAndKeep();
}
return true;
}
plRippleShapeMsg* plActivePrintShape::ISetupShapeMsg()
{
fShapeMsg = TRACKED_NEW plRippleShapeMsg(nil, this);
return fShapeMsg;
}

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 plActivePrintShape_inc
#define plActivePrintShape_inc
#include "plPrintShape.h"
class plRippleShapeMsg;
class plActivePrintShape : public plPrintShape
{
protected:
hsTArray<plKey> fDecalMgrs;
plRippleShapeMsg* fShapeMsg;
plRippleShapeMsg* ISetupShapeMsg();
hsBool INotify();
public:
plActivePrintShape();
virtual ~plActivePrintShape();
CLASSNAME_REGISTER( plActivePrintShape );
GETINTERFACE_ANY( plActivePrintShape, plPrintShape );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
// Export construction
void AddDecalKey(const plKey& k);
};
#endif // plActivePrintShape_inc

View File

@ -0,0 +1,116 @@
/*==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 plAuxSpan_inc
#define plAuxSpan_inc
#include "hsTemplates.h"
#include "plSpanTypes.h"
#include "../plPipeline/plGBufferGroup.h"
class plDrawableSpans;
class hsGMaterial;
class plGBufferGroup;
class plDecalVtxFormat;
class plAuxSpan
{
public:
enum
{
kRTLit = 0x1,
kOverrideLiteModel = 0x2,
kAttenColor = 0x4,
kWorldSpace = 0x8,
kVertexShader = 0x10
};
void* fOwner;
plDrawableSpans* fDrawable;
UInt32 fBaseSpanIdx;
hsGMaterial* fMaterial;
UInt32 fFlags;
hsTArray<hsPoint3> fOrigPos;
hsTArray<hsPoint3> fOrigUVW;
plGBufferGroup* fGroup; // Which buffer group, i.e. which vertex format
UInt32 fVBufferIdx; // Which vertex buffer in group
UInt32 fCellIdx; // Cell index inside the vertex buffer
UInt32 fCellOffset; // Offset inside the cell
UInt32 fVStartIdx; // Start vertex # in the actual interlaced buffer
UInt32 fVLength; // Length of this span in the buffer
UInt32 fVBufferInit;
UInt32 fVBufferLimit;
UInt32 fIBufferIdx; // Which index buffer in group
UInt32 fIStartIdx; // Redundant, since all spans are contiguous. Here for debugging
UInt32 fILength; // Length of this span in the buffer
UInt32 fIBufferInit;
UInt32 fIBufferLimit;
plDecalVtxFormat* GetBaseVtxPtr() const
{
plGBufferGroup* grp = fGroup;
plGBufferCell* cell = grp->GetCell(fVBufferIdx, fCellIdx);
UInt8* ptr = grp->GetVertBufferData(fVBufferIdx);
ptr += cell->fVtxStart + fCellOffset;
return (plDecalVtxFormat*)ptr;
}
UInt16* GetBaseIdxPtr() const
{
plGBufferGroup* grp = fGroup;
return grp->GetIndexBufferData(fIBufferIdx) + fIBufferInit;
}
};
#endif // plAuxSpan_inc

View File

@ -0,0 +1,286 @@
/*==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 "plAvMeshSmooth.h"
#include "plGeometrySpan.h"
#include "plAccessGeometry.h"
#include "plAccessTriSpan.h"
#include "hsFastMath.h"
class EdgeBin
{
public:
UInt16 fVtx;
UInt16 fCount;
EdgeBin() : fVtx(0), fCount(0) {}
};
void plAvMeshSmooth::FindEdges(UInt32 maxVtxIdx, UInt32 nTris, UInt16* idxList, hsTArray<UInt16>& edgeVerts)
{
hsTArray<EdgeBin>* bins = TRACKED_NEW hsTArray<EdgeBin>[maxVtxIdx+1];
hsBitVector edgeVertBits;
// For each vert pair (edge) in idxList
int i;
for( i = 0; i < nTris; i++ )
{
int j;
for( j = 0; j < 3; j++ )
{
int jPlus = j < 2 ? j+1 : 0;
int idx0 = idxList[i*3 + j];
int idx1 = idxList[i*3 + jPlus];
int lo, hi;
// Look in the LUT for the lower index.
if( idx0 < idx1 )
{
lo = idx0;
hi = idx1;
}
else
{
lo = idx1;
hi = idx0;
}
hsTArray<EdgeBin>& loBin = bins[lo];
// In that bucket, look for the higher index.
int k;
for( k = 0; k < loBin.GetCount(); k++ )
{
if( loBin[k].fVtx == hi )
break;
}
// If we find it, increment it's count,
// else add it.
if( k < loBin.GetCount() )
{
loBin[k].fCount++;
}
else
{
EdgeBin* b = loBin.Push();
b->fVtx = hi;
b->fCount = 1;
}
}
}
// For each bucket in the LUT,
for( i = 0; i < maxVtxIdx+1; i++ )
{
hsTArray<EdgeBin>& loBin = bins[i];
// For each higher index
int j;
for( j = 0; j < loBin.GetCount(); j++ )
{
// If the count is one, it's an edge, so set the edge bit for both indices (hi and lo)
if( 1 == loBin[j].fCount )
{
edgeVertBits.SetBit(i);
edgeVertBits.SetBit(loBin[j].fVtx);
}
}
}
// Now translate the bitvector to a list of indices.
for( i = 0; i < maxVtxIdx+1; i++ )
{
if( edgeVertBits.IsBitSet(i) )
edgeVerts.Append(i);
}
delete [] bins;
}
void plAvMeshSmooth::FindEdges(hsTArray<XfmSpan>& spans, hsTArray<UInt16>* edgeVerts)
{
int i;
for( i = 0; i < spans.GetCount(); i++ )
{
fAccGeom.AccessSpanFromGeometrySpan(spans[i].fAccSpan, spans[i].fSpan);
if( !spans[i].fAccSpan.HasAccessTri() )
continue;
plAccessTriSpan& triSpan = spans[i].fAccSpan.AccessTri();
UInt32 nTris = triSpan.TriCount();
UInt16* idxList = triSpan.fTris;
UInt32 maxVertIdx = triSpan.VertCount()-1;
FindEdges(maxVertIdx, nTris, idxList, edgeVerts[i]);
}
}
// A little note about why we need to pass in so much to do this.
// If the input geometryspans were in local space (ForceLocal), then
// all we would need to do is ignore any transforms they might have,
// and life is grand.
// But for reasons I don't pretend to understand, we can't do that, so
// here, to smooth the delta meshes, we transform both them and the base "snap-to"
// meshes into their respective local spaces, and then look for matches. This works
// because the base and delta meshes are constrained, not to be coincident in world space,
// but to be coincident in the local space relative to Max pivot.
// The funny painful thing is that later, when we go to use these smoothed delta meshes,
// again we need to coerce them into a neutral space. At that time, we'll use the
// morph target mesh's local space. Whatever.
void plAvMeshSmooth::Smooth(hsTArray<XfmSpan>& srcSpans, hsTArray<XfmSpan>& dstSpans)
{
hsTArray<UInt16>* dstEdgeVerts = TRACKED_NEW hsTArray<UInt16>[dstSpans.GetCount()];
FindEdges(dstSpans, dstEdgeVerts);
hsTArray<UInt16>* srcEdgeVerts = TRACKED_NEW hsTArray<UInt16>[srcSpans.GetCount()];
FindEdges(srcSpans, srcEdgeVerts);
int i;
for( i = 0; i < dstSpans.GetCount(); i++ )
{
plAccessTriSpan& dstTriSpan = dstSpans[i].fAccSpan.AccessTri();
int j;
for( j = 0; j < dstEdgeVerts[i].GetCount(); j++ )
{
hsPoint3 dstPos = IPositionToNeutral(dstSpans[i], dstEdgeVerts[i][j]);
hsVector3 dstNorm = INormalToNeutral(dstSpans[i], dstEdgeVerts[i][j]);
hsColorRGBA dstDiff;
if( dstTriSpan.HasDiffuse() )
dstDiff = dstTriSpan.DiffuseRGBA(dstEdgeVerts[i][j]);
else
dstDiff.Set(1.f, 1.f, 1.f, 1.f);
hsScalar maxDot = fMinNormDot;
hsPoint3 smoothPos = dstPos;
hsVector3 smoothNorm = dstNorm;
hsColorRGBA smoothDiff = dstDiff;
int k;
for( k = 0; k < srcSpans.GetCount(); k++ )
{
int m;
for( m = 0; m < srcEdgeVerts[k].GetCount(); m++ )
{
hsPoint3 srcPos = IPositionToNeutral(srcSpans[k], srcEdgeVerts[k][m]);
hsVector3 srcNorm = INormalToNeutral(srcSpans[k], srcEdgeVerts[k][m]);
hsScalar dist = hsVector3(&dstPos, &srcPos).MagnitudeSquared();
if( dist <= fDistTolSq )
{
smoothPos = srcPos;
hsScalar currDot = srcNorm.InnerProduct(dstNorm);
if( currDot > maxDot )
{
maxDot = currDot;
smoothNorm = srcNorm;
if( srcSpans[k].fAccSpan.AccessTri().HasDiffuse() )
smoothDiff = srcSpans[k].fAccSpan.AccessTri().DiffuseRGBA(srcEdgeVerts[k][m]);
else
smoothDiff = dstDiff;
}
}
}
}
if( fFlags & kSmoothPos )
dstTriSpan.Position(dstEdgeVerts[i][j]) = IPositionToSpan(dstSpans[i], smoothPos);
if( fFlags & kSmoothNorm )
dstTriSpan.Normal(dstEdgeVerts[i][j]) = INormalToSpan(dstSpans[i], smoothNorm);
if( (fFlags & kSmoothDiffuse) && dstTriSpan.HasDiffuse() )
dstTriSpan.Diffuse32(dstEdgeVerts[i][j]) = smoothDiff.ToARGB32();
}
}
delete [] srcEdgeVerts;
delete [] dstEdgeVerts;
}
hsPoint3 plAvMeshSmooth::IPositionToNeutral(XfmSpan& span, int i) const
{
return span.fSpanToNeutral * span.fAccSpan.AccessTri().Position(i);
}
hsVector3 plAvMeshSmooth::INormalToNeutral(XfmSpan& span, int i) const
{
hsVector3 ret = span.fNormSpanToNeutral * span.fAccSpan.AccessTri().Normal(i);
hsFastMath::Normalize(ret);
return ret;
}
hsPoint3 plAvMeshSmooth::IPositionToSpan(XfmSpan& span, const hsPoint3& wPos) const
{
return span.fNeutralToSpan * wPos;
}
hsVector3 plAvMeshSmooth::INormalToSpan(XfmSpan& span, const hsVector3& wNorm) const
{
hsVector3 ret = span.fNormNeutralToSpan * wNorm;
hsFastMath::Normalize(ret);
return ret;
}
void plAvMeshSmooth::SetAngle(hsScalar degs)
{
fMinNormDot = hsCosine(hsScalarDegToRad(degs));
}
hsScalar plAvMeshSmooth::GetAngle() const
{
return hsScalarRadToDeg(hsACosine(fMinNormDot));
}
void plAvMeshSmooth::SetDistTol(hsScalar dist)
{
fDistTolSq = dist * dist;
}
hsScalar plAvMeshSmooth::GetDistTol() const
{
return hsSquareRoot(fDistTolSq);
}

View File

@ -0,0 +1,108 @@
/*==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 plAvMeshSmooth_inc
#define plAvMeshSmooth_inc
#include "hsTemplates.h"
#include "plAccessGeometry.h"
#include "plAccessSpan.h"
struct hsPoint3;
struct hsVector3;
class plGeometrySpan;
class plAvMeshSmooth
{
public:
enum {
kNone = 0x0,
kSmoothNorm = 0x1,
kSmoothPos = 0x2,
kSmoothDiffuse = 0x4
};
class XfmSpan
{
public:
plGeometrySpan* fSpan;
hsMatrix44 fSpanToNeutral;
hsMatrix44 fNormSpanToNeutral; // == Transpose(Inverse(fSpanToNeutral)) == Transpose(fNeutralToSpan)
hsMatrix44 fNeutralToSpan;
hsMatrix44 fNormNeutralToSpan; // == Transpose(Inverse(fNeutralToSpan)) == Transpose(fSpanToNeutral)
plAccessSpan fAccSpan;
};
protected:
UInt32 fFlags;
hsScalar fMinNormDot;
hsScalar fDistTolSq;
plAccessGeometry fAccGeom;
hsPoint3 IPositionToNeutral(XfmSpan& span, int i) const;
hsVector3 INormalToNeutral(XfmSpan& span, int i) const;
hsPoint3 IPositionToSpan(XfmSpan& span, const hsPoint3& wPos) const;
hsVector3 INormalToSpan(XfmSpan& span, const hsVector3& wNorm) const;
void FindEdges(UInt32 maxVtxIdx, UInt32 nTris, UInt16* idxList, hsTArray<UInt16>& edgeVerts);
void FindEdges(hsTArray<XfmSpan>& spans, hsTArray<UInt16>* edgeVerts);
public:
plAvMeshSmooth() : fFlags(kSmoothNorm), fMinNormDot(0.25f), fDistTolSq(1.e-4f), fAccGeom() {}
void SetAngle(hsScalar degs);
hsScalar GetAngle() const; // returns degrees
void SetDistTol(hsScalar dist);
hsScalar GetDistTol() const;
void Smooth(hsTArray<XfmSpan>& srcSpans, hsTArray<XfmSpan>& dstSpans);
void SetFlags(UInt32 f) { fFlags = f; }
UInt32 GetFlags() const { return fFlags; }
};
#endif // plAvMeshSmooth_inc

View File

@ -0,0 +1,212 @@
/*==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 "hsStream.h"
#include "plCluster.h"
#include "plSpanTemplate.h"
#include "plSpanInstance.h"
#include "hsFastMath.h"
plCluster::plCluster()
: fGroup(nil)
{
}
plCluster::~plCluster()
{
int i;
for( i = 0; i < fInsts.GetCount(); i++ )
delete fInsts[i];
}
void plCluster::Read(hsStream* s, plClusterGroup* grp)
{
fGroup = grp;
fEncoding.Read(s);
hsAssert(fGroup->GetTemplate(), "Template should have been loaded by now");
const int numVerts = fGroup->GetTemplate()->NumVerts();
const int numInst = s->ReadSwap32();
fInsts.SetCount(numInst);
int i;
for( i = 0; i < numInst; i++ )
{
fInsts[i] = TRACKED_NEW plSpanInstance;
fInsts[i]->Read(s, fEncoding, numVerts);
}
}
void plCluster::Write(hsStream* s) const
{
fEncoding.Write(s);
const int numVerts = fGroup->GetTemplate()->NumVerts();
s->WriteSwap32(fInsts.GetCount());
int i;
for( i = 0; i < fInsts.GetCount(); i++ )
{
fInsts[i]->Write(s, fEncoding, numVerts);
}
}
inline void inlTESTPOINT(const hsPoint3& destP,
hsScalar& minX, hsScalar& minY, hsScalar& minZ,
hsScalar& maxX, hsScalar& maxY, hsScalar& maxZ)
{
if( destP.fX < minX )
minX = destP.fX;
else if( destP.fX > maxX )
maxX = destP.fX;
if( destP.fY < minY )
minY = destP.fY;
else if( destP.fY > maxY )
maxY = destP.fY;
if( destP.fZ < minZ )
minZ = destP.fZ;
else if( destP.fZ > maxZ )
maxZ = destP.fZ;
}
void plCluster::UnPack(UInt8* vDst, UInt16* iDst, int idxOffset, hsBounds3Ext& wBnd) const
{
hsScalar minX = 1.e33f;
hsScalar minY = 1.e33f;
hsScalar minZ = 1.e33f;
hsScalar maxX = -1.e33f;
hsScalar maxY = -1.e33f;
hsScalar maxZ = -1.e33f;
hsAssert(fGroup->GetTemplate(), "Can't unpack without a template");
const plSpanTemplate& templ = *fGroup->GetTemplate();
int i;
for( i = 0; i < fInsts.GetCount(); i++ )
{
// First, just copy our template, offsetting by prescribed amount.
const UInt16* iSrc = templ.IndexData();
int n = templ.NumIndices();
while( n-- )
{
*iDst = *iSrc + idxOffset;
iDst++;
iSrc++;
}
idxOffset += templ.NumVerts();
memcpy(vDst, templ.VertData(), templ.VertSize());
// Now we need to fix it up. That means,
// a) Possibly adding a delta to the position.
// b) Transforming the position and normal.
// c) Possibly overwriting some (or all) of the color.
// If we have individual position and/or color info, apply
// it, along with the transform.
if( GetInst(i).HasPosDelta() || GetInst(i).HasColor() )
{
const int posOff = templ.PositionOffset();
const int normOff = templ.NormalOffset();
const int colOff = templ.ColorOffset();
const int stride = templ.Stride();
const hsMatrix44 l2w = GetInst(i).LocalToWorld();
hsMatrix44 w2l;
GetInst(i).WorldToLocal().GetTranspose(&w2l);
plSpanInstanceIter iter(fInsts[i], fEncoding, templ.NumVerts());
const int numVerts = templ.NumVerts();
int iVert;
for( iVert = 0, iter.Begin(); iVert < numVerts; iVert++, iter.Advance() )
{
hsPoint3* pos = (hsPoint3*)(vDst + posOff);
*pos = iter.Position(*pos);
*pos = l2w * *pos;
inlTESTPOINT(*pos, minX, minY, minZ, maxX, maxY, maxZ);
hsVector3* norm = (hsVector3*)(vDst + normOff);
*norm = w2l * *norm;
hsFastMath::NormalizeAppr(*norm);
UInt32* color = (UInt32*)(vDst + colOff);
*color = iter.Color(*color);
vDst += stride;
}
}
else
{
// Just transform the position and normal.
const int posOff = templ.PositionOffset();
const int normOff = templ.NormalOffset();
const int stride = templ.Stride();
const hsMatrix44 l2w = GetInst(i).LocalToWorld();
hsMatrix44 w2l;
GetInst(i).WorldToLocal().GetTranspose(&w2l);
const int numVerts = templ.NumVerts();
int iVert;
for( iVert = 0; iVert < numVerts; iVert++ )
{
hsPoint3* pos = (hsPoint3*)(vDst + posOff);
*pos = l2w * *pos;
inlTESTPOINT(*pos, minX, minY, minZ, maxX, maxY, maxZ);
hsVector3* norm = (hsVector3*)(vDst + normOff);
*norm = w2l * *norm;
vDst += stride;
}
}
}
wBnd.Reset(&hsPoint3(minX, minY, minZ));
wBnd.Union(&hsPoint3(maxX, maxY, maxZ));
}

View File

@ -0,0 +1,110 @@
/*==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 plCluster_inc
#define plCluster_inc
#include "hsTemplates.h"
#include "plClusterGroup.h"
#include "plSpanInstance.h"
class hsGMaterial;
class hsStream;
class plSpanInstance;
class hsKeyedObject;
class plLightInfo;
class plSpanTemplate;
class plVisRegion;
class hsBounds3Ext;
class plCluster
{
public:
enum
{
kNoIdx = UInt8(-1)
};
protected:
plClusterGroup* fGroup;
hsTArray<plSpanInstance*> fInsts;
plSpanEncoding fEncoding;
friend class plClusterUtil;
plSpanInstance* IGetInst(int i) const { return fInsts[i]; }
void IAddInst(plSpanInstance* inst) { fInsts.Append(inst); }
public:
plCluster();
~plCluster();
void Read(hsStream* s, plClusterGroup* grp);
void Write(hsStream* s) const;
UInt32 NumInsts() const { return fInsts.GetCount(); }
const plSpanInstance& GetInst(int i) const { return *fInsts[i]; }
void UnPack(UInt8* vDst, UInt16* iDst, int idxOffset, hsBounds3Ext& wBnd) const;
// Getters and setters, mostly for export construction.
const plSpanTemplate* GetTemplate() const { return fGroup->GetTemplate(); }
void SetEncoding(const plSpanEncoding& c) { fEncoding = c; }
plSpanEncoding GetEncoding() const { return fEncoding; }
plClusterGroup* GetGroup() const { return fGroup; }
void SetGroup(plClusterGroup* g) { fGroup = g; }
hsGMaterial* GetMaterial() const { return fGroup->GetMaterial(); }
const hsBitVector& GetVisSet() const { return fGroup->GetVisSet(); }
const hsBitVector& GetVisNot() const { return fGroup->GetVisNot(); }
const hsTArray<plLightInfo*>& GetLights() const { fGroup->GetLights(); }
const plLODDist& GetLOD() const { return fGroup->GetLOD(); }
};
#endif // plCluster_inc

View File

@ -0,0 +1,343 @@
/*==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 "plClusterGroup.h"
#include "plSpanTemplate.h"
#include "plCluster.h"
#include "../pnMessage/plTimeMsg.h"
#include "../plScene/plVisMgr.h"
#include "../plScene/plVisRegion.h"
#include "../plSurface/hsGMaterial.h"
#include "../plGLight/plLightInfo.h"
#include "plDrawableSpans.h"
#include "hsBitVector.h"
#include "hsStream.h"
#include "hsResMgr.h"
//STUB
#include "plgDispatch.h"
#include "../plMessage/plAgeLoadedMsg.h"
plClusterGroup::plClusterGroup()
: fSceneNode(nil),
fDrawable(nil),
fTemplate(nil),
fMaterial(nil),
fUnPacked(0)
{
fVisSet.SetBit(plVisMgr::kNormal);
}
plClusterGroup::~plClusterGroup()
{
int i;
for( i = 0; i < fClusters.GetCount(); i++ )
delete fClusters[i];
delete fTemplate;
}
plCluster* plClusterGroup::IAddCluster()
{
plCluster* cluster = TRACKED_NEW plCluster;
// Set the cluster's group.
cluster->SetGroup(this);
fClusters.Append(cluster);
return cluster;
}
plCluster* plClusterGroup::IGetCluster(int i) const
{
return fClusters[i];
}
const plCluster* plClusterGroup::GetCluster(int i) const
{
return fClusters[i];
}
void plClusterGroup::Read(hsStream* stream, hsResMgr* mgr)
{
hsKeyedObject::Read(stream, mgr);
int i;
fTemplate = TRACKED_NEW plSpanTemplate;
fTemplate->Read(stream);
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefMaterial), plRefFlags::kActiveRef);
const int numClust = stream->ReadSwap32();
fClusters.SetCount(numClust);
for( i = 0; i < numClust; i++ )
{
fClusters[i] = TRACKED_NEW plCluster;
fClusters[i]->Read(stream, this);
}
const int numRegions = stream->ReadSwap32();
for( i = 0; i < numRegions; i++ )
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefRegion), plRefFlags::kActiveRef);
const int numLights = stream->ReadSwap32();
for( i = 0; i < numLights; i++ )
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefLight), plRefFlags::kActiveRef);
fLOD.Read(stream);
fRenderLevel.Set(stream->ReadSwap32());
fSceneNode = mgr->ReadKey(stream);
//STUB
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
void plClusterGroup::Write(hsStream* stream, hsResMgr* mgr)
{
hsKeyedObject::Write(stream, mgr);
int i;
fTemplate->Write(stream);
mgr->WriteKey(stream, fMaterial);
stream->WriteSwap32(fClusters.GetCount());
for( i = 0; i < fClusters.GetCount(); i++ )
fClusters[i]->Write(stream);
stream->WriteSwap32(fRegions.GetCount());
for( i = 0; i < fRegions.GetCount(); i++ )
mgr->WriteKey(stream, fRegions[i]);
stream->WriteSwap32(fLights.GetCount());
for( i = 0; i < fLights.GetCount(); i++ )
mgr->WriteKey(stream, fLights[i]);
fLOD.Write(stream);
stream->WriteSwap32(fRenderLevel.Level());
mgr->WriteKey(stream, fSceneNode);
}
void plClusterGroup::ISendToSelf(RefType t, hsKeyedObject* ref)
{
hsAssert(ref, "Sending self a nil object");
plGenRefMsg* refMsg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, t);
hsgResMgr::ResMgr()->SendRef(ref->GetKey(), refMsg, plRefFlags::kActiveRef);
}
hsBool plClusterGroup::IAddVisRegion(plVisRegion* reg)
{
if( reg )
{
int idx = fRegions.Find(reg);
if( idx == fRegions.kMissingIndex )
{
fRegions.Append(reg);
if( reg->GetProperty(plVisRegion::kIsNot) )
fVisNot.SetBit(reg->GetIndex());
else
{
fVisSet.SetBit(reg->GetIndex());
if( reg->ReplaceNormal() )
fVisSet.ClearBit(plVisMgr::kNormal);
}
}
}
return true;
}
hsBool plClusterGroup::IRemoveVisRegion(plVisRegion* reg)
{
if( reg )
{
int idx = fRegions.Find(reg);
if( fRegions.kMissingIndex != idx )
{
fRegions.Remove(idx);
if( reg->GetProperty(plVisRegion::kIsNot) )
fVisNot.ClearBit(reg->GetIndex());
else
fVisSet.ClearBit(reg->GetIndex());
}
}
return true;
}
hsBool plClusterGroup::IAddLight(plLightInfo* li)
{
int idx = fLights.Find(li);
if( fLights.kMissingIndex == idx )
{
fLights.Append(li);
}
return true;
}
hsBool plClusterGroup::IRemoveLight(plLightInfo* li)
{
int idx = fLights.Find(li);
if( fLights.kMissingIndex != idx )
{
fLights.Remove(idx);
}
return true;
}
hsBool plClusterGroup::IOnReceive(plGenRefMsg* ref)
{
switch( ref->fType )
{
case kRefMaterial:
fMaterial = hsGMaterial::ConvertNoRef(ref->GetRef());
return true;
case kRefRegion:
return IAddVisRegion(plVisRegion::ConvertNoRef(ref->GetRef()));
case kRefLight:
return IAddLight(plLightInfo::ConvertNoRef(ref->GetRef()));
}
return false;
}
hsBool plClusterGroup::IOnRemove(plGenRefMsg* ref)
{
int idx = -1;
switch( ref->fType )
{
case kRefMaterial:
fMaterial = nil;
return true;
case kRefRegion:
return IRemoveVisRegion(plVisRegion::ConvertNoRef(ref->GetRef()));
case kRefLight:
return IRemoveLight(plLightInfo::ConvertNoRef(ref->GetRef()));
}
return false;
}
hsBool plClusterGroup::IOnRef(plGenRefMsg* ref)
{
if( ref->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
{
return IOnReceive(ref);
}
return IOnRemove(ref);
}
hsBool plClusterGroup::MsgReceive(plMessage* msg)
{
plGenRefMsg* ref = plGenRefMsg::ConvertNoRef(msg);
if( ref )
{
if( IOnRef(ref) )
return true;
}
// STUB
plEvalMsg* evalMsg = plEvalMsg::ConvertNoRef(msg);
if (evalMsg)
{
UnPack();
fUnPacked = true;
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
return true;
}
return hsKeyedObject::MsgReceive(msg);
}
void plClusterGroup::UnPack()
{
plDrawableSpans* drawable = TRACKED_NEW plDrawableSpans;
fDrawable = hsgResMgr::ResMgr()->NewKey(GetKey()->GetName(), drawable, GetKey()->GetUoid().GetLocation());
drawable->UnPackCluster(this);
drawable->SetSceneNode(fSceneNode);
}
void plClusterGroup::SetVisible(bool visible)
{
if (fDrawable)
{
plDrawableSpans *drawable = plDrawableSpans::ConvertNoRef(fDrawable->ObjectIsLoaded());
if (drawable)
drawable->SetProperty(0,!visible); // property 0 is the disable drawing property
}
}
UInt32 plClusterGroup::NumInst() const
{
UInt32 numInst = 0;
int i;
for( i = 0; i < fClusters.GetCount(); i++ )
numInst += fClusters[i]->NumInsts();
return numInst;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
void plLODDist::Read(hsStream* s)
{
fMinDist = s->ReadSwapScalar();
fMaxDist = s->ReadSwapScalar();
}
void plLODDist::Write(hsStream* s) const
{
s->WriteSwapScalar(fMinDist);
s->WriteSwapScalar(fMaxDist);
}

View File

@ -0,0 +1,163 @@
/*==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 plClusterGroup_inc
#define plClusterGroup_inc
#include "hsTemplates.h"
#include "hsBitVector.h"
#include "plRenderLevel.h"
#include "../pnKeyedObject/hsKeyedObject.h"
class hsStream;
class hsResMgr;
class plSpanTemplate;
class plCluster;
class hsGMaterial;
class plVisRegion;
class plLightInfo;
class plMessage;
class plGenRefMsg;
class plDrawableSpans;
class plLODDist
{
public:
hsScalar fMinDist;
hsScalar fMaxDist;
plLODDist(hsScalar minDist, hsScalar maxDist) : fMinDist(minDist), fMaxDist(maxDist) {}
plLODDist() : fMinDist(0), fMaxDist(0) {}
plLODDist& Set(float minDist, float maxDist) { fMinDist = minDist; fMaxDist = maxDist; return *this; }
plLODDist& operator=(int d) { fMinDist = hsScalar(d); fMaxDist = hsScalar(d); return *this; }
int operator==(const plLODDist& d) const { return (fMinDist == d.fMinDist)&&(fMaxDist == d.fMaxDist); }
void Read(hsStream* s);
void Write(hsStream* s) const;
};
class plClusterGroup : public hsKeyedObject
{
public:
enum RefType {
kRefMaterial,
kRefRegion,
kRefLight
};
protected:
plSpanTemplate* fTemplate;
hsGMaterial* fMaterial;
hsTArray<plVisRegion*> fRegions;
hsBitVector fVisSet;
hsBitVector fVisNot;
hsTArray<plLightInfo*> fLights;
plLODDist fLOD;
hsTArray<plCluster*> fClusters;
UInt32 fUnPacked;
plKey fSceneNode;
plKey fDrawable;
plRenderLevel fRenderLevel;
hsBool IAddVisRegion(plVisRegion* reg);
hsBool IRemoveVisRegion(plVisRegion* reg);
hsBool IAddLight(plLightInfo* li);
hsBool IRemoveLight(plLightInfo* li);
hsBool IOnRef(plGenRefMsg* ref);
hsBool IOnRemove(plGenRefMsg* ref);
hsBool IOnReceive(plGenRefMsg* ref);
void ISetVisBits();
void ISendToSelf(RefType t, hsKeyedObject* ref);
plCluster* IAddCluster();
plCluster* IGetCluster(int i) const;
friend class plClusterUtil;
public:
plClusterGroup();
~plClusterGroup();
CLASSNAME_REGISTER( plClusterGroup );
GETINTERFACE_ANY( plClusterGroup, hsKeyedObject );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
hsGMaterial* GetMaterial() const { return fMaterial; }
const hsBitVector& GetVisSet() const { return fVisSet; }
const hsBitVector& GetVisNot() const { return fVisNot; }
const hsTArray<plLightInfo*>& GetLights() const { return fLights; }
const plLODDist& GetLOD() const { return fLOD; }
const plSpanTemplate* GetTemplate() const { return fTemplate; }
const plCluster* GetCluster(int i) const;
int GetNumClusters() const { return fClusters.GetCount(); }
UInt32 NumInst() const;
// The drawable needs us to be able to convert our data
// into, well, drawable stuff.
void UnPack();
void SetVisible(bool visible=true);
void SetSceneNode(const plKey& key) { fSceneNode = key; }
plKey GetSceneNode() const { return fSceneNode; }
plKey GetDrawable() const { return fDrawable; }
plRenderLevel GetRenderLevel() const { return fRenderLevel; }
};
#endif // plClusterGroup_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,178 @@
/*==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 plCutter_inc
#define plCutter_inc
#include "../pnFactory/plCreatable.h"
#include "hsGeometry3.h"
#include "hsTemplates.h"
#include "hsBounds.h"
#include "../plIntersect/plVolumeIsect.h"
#include "hsColorRGBA.h"
struct hsPoint3;
struct hsVector3;
class plPrintCollect;
class plAccTriIterator;
class plAccessSpan;
class plCutoutHit
{
public:
hsPoint3 fPos;
hsVector3 fNorm;
};
class plCutoutVtx
{
public:
plCutoutVtx& Init(const hsPoint3& p, const hsVector3& n, const hsColorRGBA& c) { fPos = p; fNorm = n; fColor = c; return *this; }
hsPoint3 fPos;
hsVector3 fNorm;
hsColorRGBA fColor;
hsPoint3 fUVW;
};
class plCutoutPoly
{
public:
hsTArray<plCutoutVtx> fVerts;
hsBool fBaseHasAlpha;
};
class plCutoutMiniVtx
{
public:
hsPoint3 fPos;
hsPoint3 fUVW;
};
class plFlatGridMesh
{
public:
hsTArray<plCutoutMiniVtx> fVerts;
hsTArray<UInt16> fIdx;
void Reset() { fVerts.SetCount(0); fIdx.SetCount(0); }
};
class plCutter : public plCreatable
{
protected:
// Permanent attributes
hsScalar fLengthU;
hsScalar fLengthV;
hsScalar fLengthW;
// Internal cached stuff
hsScalar fDistU;
hsScalar fDistV;
hsScalar fDistW;
hsVector3 fDirU;
hsVector3 fDirV;
hsVector3 fDirW;
hsVector3 fBackDir;
hsBounds3Ext fWorldBounds;
plBoundsIsect fIsect;
void IConstruct(hsTArray<plCutoutPoly>& dst, hsTArray<plCutoutVtx>& poly, hsBool baseHasAlpha) const;
hsBool IPolyClip(hsTArray<plCutoutVtx>& poly, const hsPoint3 vPos[]) const;
inline void ICutoutVtxHiU(const plCutoutVtx& inVtx, const plCutoutVtx& outVtx, plCutoutVtx& dst) const;
inline void ICutoutVtxHiV(const plCutoutVtx& inVtx, const plCutoutVtx& outVtx, plCutoutVtx& dst) const;
inline void ICutoutVtxHiW(const plCutoutVtx& inVtx, const plCutoutVtx& outVtx, plCutoutVtx& dst) const;
inline void ICutoutVtxLoU(const plCutoutVtx& inVtx, const plCutoutVtx& outVtx, plCutoutVtx& dst) const;
inline void ICutoutVtxLoV(const plCutoutVtx& inVtx, const plCutoutVtx& outVtx, plCutoutVtx& dst) const;
inline void ICutoutVtxLoW(const plCutoutVtx& inVtx, const plCutoutVtx& outVtx, plCutoutVtx& dst) const;
inline void ICutoutVtxMidV(const plCutoutVtx& inVtx, const plCutoutVtx& outVtx, plCutoutVtx& dst) const;
inline void ICutoutVtxMidU(const plCutoutVtx& inVtx, const plCutoutVtx& outVtx, plCutoutVtx& dst) const;
inline void ICutoutVtxMidW(const plCutoutVtx& inVtx, const plCutoutVtx& outVtx, plCutoutVtx& dst) const;
hsBool IFindHitPoint(const hsTArray<plCutoutVtx>& inPoly, plCutoutHit& hit) const;
inline void ISetPosNorm(hsScalar parm, const plCutoutVtx& inVtx, const plCutoutVtx& outVtx, plCutoutVtx& dst) const;
void ICutoutTransformed(plAccessSpan& src, hsTArray<plCutoutPoly>& dst) const;
void ICutoutConstHeight(plAccessSpan& src, hsTArray<plCutoutPoly>& dst) const;
void ICutoutTransformedConstHeight(plAccessSpan& src, hsTArray<plCutoutPoly>& dst) const;
public:
plCutter() {}
virtual ~plCutter() {}
CLASSNAME_REGISTER( plCutter );
GETINTERFACE_ANY( plCutter, plCreatable );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
hsBool FindHitPoints(const hsTArray<plCutoutPoly>& src, hsTArray<plCutoutHit>& hits) const;
hsBool FindHitPointsConstHeight(const hsTArray<plCutoutPoly>& src, hsTArray<plCutoutHit>& hits, hsScalar height) const;
void Set(const hsPoint3& pos, const hsVector3& dir, const hsVector3& out, hsBool flip=false);
void Cutout(plAccessSpan& src, hsTArray<plCutoutPoly>& dst) const;
hsBool CutoutGrid(int nWid, int nLen, plFlatGridMesh& dst) const;
void SetLength(const hsVector3& s) { fLengthU = s.fX; fLengthV = s.fY; fLengthW = s.fZ; }
hsScalar GetLengthU() const { return fLengthU; }
hsScalar GetLengthV() const { return fLengthV; }
hsScalar GetLengthW() const { return fLengthW; }
const hsBounds3Ext& GetWorldBounds() const { return fWorldBounds; }
plBoundsIsect& GetIsect() { return fIsect; }
hsVector3 GetBackDir() const { return fBackDir; }
static hsBool MakeGrid(int nWid, int nLen, const hsPoint3& center, const hsVector3& halfU, const hsVector3& halfV, plFlatGridMesh& grid);
};
#endif // plCutter_inc

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 plDrawableCreatable_inc
#define plDrawableCreatable_inc
#include "../pnFactory/plCreator.h"
#include "plDrawableSpans.h"
REGISTER_CREATABLE( plDrawableSpans );
#include "plSpaceTree.h"
REGISTER_CREATABLE( plSpaceTree );
#include "plSharedMesh.h"
REGISTER_CREATABLE( plSharedMesh );
REGISTER_CREATABLE( plSharedMeshBCMsg );
#include "plInstanceDrawInterface.h"
REGISTER_CREATABLE( plInstanceDrawInterface );
#include "plDynaDecalMgr.h"
REGISTER_NONCREATABLE( plDynaDecalMgr );
#include "plDynaFootMgr.h"
REGISTER_CREATABLE( plDynaFootMgr );
#include "plDynaRippleMgr.h"
REGISTER_CREATABLE( plDynaRippleMgr );
#include "plDynaBulletMgr.h"
REGISTER_CREATABLE( plDynaBulletMgr );
#include "plDynaPuddleMgr.h"
REGISTER_CREATABLE( plDynaPuddleMgr );
#include "plDynaTorpedoMgr.h"
REGISTER_CREATABLE( plDynaTorpedoMgr );
#include "plDynaTorpedoVSMgr.h"
REGISTER_CREATABLE( plDynaTorpedoVSMgr );
#include "plDynaWakeMgr.h"
REGISTER_CREATABLE( plDynaWakeMgr );
#include "plCutter.h"
REGISTER_CREATABLE( plCutter );
#include "plPrintShape.h"
REGISTER_CREATABLE( plPrintShape );
#include "plActivePrintShape.h"
REGISTER_CREATABLE( plActivePrintShape );
#include "plWaveSetBase.h"
REGISTER_NONCREATABLE( plWaveSetBase );
#include "plWaveSet7.h"
REGISTER_CREATABLE( plWaveSet7 );
#include "plMorphSequence.h"
REGISTER_CREATABLE( plMorphSequence );
REGISTER_CREATABLE( plMorphDataSet );
#include "plMorphSequenceSDLMod.h"
REGISTER_CREATABLE( plMorphSequenceSDLMod );
#include "plMorphDelta.h"
REGISTER_CREATABLE( plMorphDelta );
#include "plDynaRippleVSMgr.h"
REGISTER_CREATABLE( plDynaRippleVSMgr );
#include "plClusterGroup.h"
REGISTER_CREATABLE( plClusterGroup );
#endif // plDrawableCreatable_inc

View File

@ -0,0 +1,765 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plDrawableGenerator Class Functions //
// //
//// Version History /////////////////////////////////////////////////////////
// //
// 5.15.2001 mcn - Created. //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plDrawableGenerator.h"
#include "plDrawableSpans.h"
#include "plGeometrySpan.h"
#include "hsFastMath.h"
#include "plRenderLevel.h"
#include "hsResMgr.h"
#include "../pnKeyedObject/plUoid.h"
// Making light white and dark black by default, because this is really
// redundant. The handling of what color unlit and fully lit map to is
// encapsulated in the material used to draw the mesh. The caller
// wants illumination values, and can handle on screen contrast
// through the material. mf
hsColorRGBA plDrawableGenerator::fLiteColor = { 1, 1, 1, 1 };
hsColorRGBA plDrawableGenerator::fDarkColor = { 0.0, 0.0, 0.0, 1 };
//// SetFauxLightColors //////////////////////////////////////////////////////
// Set the colors for the foux lighting on generated drawables
void plDrawableGenerator::SetFauxLightColors( hsColorRGBA &lite, hsColorRGBA &dark )
{
fLiteColor = lite;
fDarkColor = dark;
}
//// IQuickShadeVerts ////////////////////////////////////////////////////////
// Quickly shades vertices based on a fake directional light. Good for doing
// faux shadings on proxy objects.
void plDrawableGenerator::IQuickShadeVerts( UInt32 count, hsVector3 *normals, hsColorRGBA *colors, hsColorRGBA* origColors, const hsColorRGBA* multColor )
{
hsVector3 lightDir;
float scale;
lightDir.Set( 1, 1, 1 );
lightDir.Normalize();
while( count-- )
{
scale = ( normals[ count ] * lightDir );
// pretend there are two opposing directional lights, but the
// one pointing downish is a little stronger.
const hsScalar kReverseLight = -0.8f;
if( scale < 0 )
scale = kReverseLight * scale;
colors[ count ] = fLiteColor * scale + fDarkColor * ( 1.f - scale );
if( origColors )
colors[ count ] *= origColors[ count ];
if( multColor )
colors[ count ] *= *multColor;
}
}
void plDrawableGenerator::IFillSpan( UInt32 vertCount, hsPoint3 *positions, hsVector3 *normals,
hsPoint3 *uvws, UInt32 uvwsPerVtx,
hsColorRGBA *origColors, hsBool fauxShade, const hsColorRGBA* multColor,
UInt32 numIndices, UInt16 *indices,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended,
plGeometrySpan* span )
{
hsTArray<hsVector3> myNormals;
/// Calculate normals if we don't have them
if( normals == nil )
{
int i;
hsVector3 normal, v1, v2;
myNormals.SetCount( vertCount );
for( i = 0; i < vertCount; i++ )
myNormals[ i ].Set( 0, 0, 0 );
for( i = 0; i < numIndices; i += 3 )
{
v1.Set( &positions[ indices[ i + 1 ] ], &positions[ indices[ i ] ] );
v2.Set( &positions[ indices[ i + 2 ] ], &positions[ indices[ i ] ] );
normal = v1 % v2;
myNormals[ indices[ i ] ] += normal;
myNormals[ indices[ i + 1 ] ] += normal;
myNormals[ indices[ i + 2 ] ] += normal;
}
for( i = 0; i < vertCount; i++ )
myNormals[ i ].Normalize();
normals = myNormals.AcquireArray();
}
if( uvws == nil )
uvwsPerVtx = 0;
span->BeginCreate( material, localToWorld, plGeometrySpan::UVCountToFormat( (UInt8)uvwsPerVtx ) );
if( !origColors && !fauxShade )
span->AddVertexArray( vertCount, positions, normals, nil, uvws, uvwsPerVtx );
else
{
hsTArray<hsColorRGBA> colArray;
hsColorRGBA* colors;
if( fauxShade )
{
colArray.SetCount(vertCount);
IQuickShadeVerts( vertCount, normals, colArray.AcquireArray(), origColors, multColor );
colors = colArray.AcquireArray();
}
else // just use the origColors
{
colors = origColors;
}
hsTArray<UInt32> tempColors;
int i;
UInt8 a, r, g, b;
tempColors.SetCount( vertCount );
for( i = 0; i < vertCount; i++ )
{
hsColorRGBA *color = &colors[ i ];
a = (UInt8)( color->a >= 1 ? 255 : color->a <= 0 ? 0 : color->a * 255.0 );
r = (UInt8)( color->r >= 1 ? 255 : color->r <= 0 ? 0 : color->r * 255.0 );
g = (UInt8)( color->g >= 1 ? 255 : color->g <= 0 ? 0 : color->g * 255.0 );
b = (UInt8)( color->b >= 1 ? 255 : color->b <= 0 ? 0 : color->b * 255.0 );
tempColors[ i ] = ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | ( b );
}
span->AddVertexArray( vertCount, positions, normals, tempColors.AcquireArray(), uvws, uvwsPerVtx );
}
span->AddIndexArray( numIndices, indices );
span->EndCreate();
}
//// RegenerateDrawable ////////////////////////////////////////////////////////
// Static function that refills an existing drawable based on the vertex/index
// data given. That data had better match the data the drawable was first filled
// with (i.e. vertex/index count
hsBool plDrawableGenerator::RegenerateDrawable( UInt32 vertCount, hsPoint3 *positions, hsVector3 *normals,
hsPoint3 *uvws, UInt32 uvwsPerVtx,
hsColorRGBA *origColors, hsBool fauxShade, const hsColorRGBA* multColor,
UInt32 numIndices, UInt16 *indices,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended,
UInt32 diIndex, plDrawableSpans *destDraw )
{
plDISpanIndex spanList = destDraw->GetDISpans( diIndex );
if( spanList.GetCount() != 1 )
{
hsAssert(false, "Don't know how to distribute this geometry over multiple spans");
return false;
}
plGeometrySpan* span = destDraw->GetGeometrySpan(spanList[0]);
if( (span->fNumVerts != vertCount)
||(span->fNumIndices != numIndices) )
{
hsAssert(false, "Mismatched data coming in for a refill");
return false;
}
IFillSpan( vertCount, positions, normals,
uvws, uvwsPerVtx,
origColors, fauxShade, multColor,
numIndices, indices,
material, localToWorld, blended,
span );
destDraw->RefreshDISpans( diIndex );
return true;
}
//// GenerateDrawable ////////////////////////////////////////////////////////
// Static function that creates a new drawable based on the vertex/index
// data given.
plDrawableSpans *plDrawableGenerator::GenerateDrawable( UInt32 vertCount, hsPoint3 *positions, hsVector3 *normals,
hsPoint3 *uvws, UInt32 uvwsPerVtx,
hsColorRGBA *origColors, hsBool fauxShade, const hsColorRGBA* multColor,
UInt32 numIndices, UInt16 *indices,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended,
hsTArray<UInt32> *retIndex, plDrawableSpans *toAddTo )
{
plDrawableSpans *newDraw;
hsTArray<plGeometrySpan *> spanArray;
plGeometrySpan *span;
// Set up props on the new drawable
if( toAddTo != nil )
newDraw = toAddTo;
else
{
newDraw = TRACKED_NEW plDrawableSpans;
// newDraw->SetNativeProperty( plDrawable::kPropVolatile, true );
if( blended )
{
newDraw->SetRenderLevel(plRenderLevel(plRenderLevel::kBlendRendMajorLevel, plRenderLevel::kDefRendMinorLevel));
newDraw->SetNativeProperty( plDrawable::kPropSortSpans | plDrawable::kPropSortFaces, true );
}
static int nameIdx = 0;
char buff[256];
sprintf(buff, "%s_%d", "GenDrawable", nameIdx++);
hsgResMgr::ResMgr()->NewKey( buff, newDraw, plLocation::kGlobalFixedLoc );
}
// Create a temp plGeometrySpan
spanArray.SetCount( 1 );
span = spanArray[ 0 ] = TRACKED_NEW plGeometrySpan;
IFillSpan( vertCount, positions, normals,
uvws, uvwsPerVtx,
origColors, fauxShade, multColor,
numIndices, indices,
material, localToWorld, blended,
span );
/// Now add the span to the new drawable, clear up the span's buffers and return!
UInt32 trash = UInt32(-1);
UInt32 idx = newDraw->AppendDISpans( spanArray, trash, false );
if( retIndex != nil )
retIndex->Append(idx);
return newDraw;
}
//// GenerateSphericalDrawable ///////////////////////////////////////////////
plDrawableSpans *plDrawableGenerator::GenerateSphericalDrawable( const hsPoint3& pos, hsScalar radius, hsGMaterial *material,
const hsMatrix44 &localToWorld, hsBool blended,
const hsColorRGBA* multColor,
hsTArray<UInt32> *retIndex, plDrawableSpans *toAddTo,
hsScalar qualityScalar )
{
hsTArray<hsPoint3> points;
hsTArray<hsVector3> normals;
hsTArray<UInt16> indices;
hsTArray<hsColorRGBA> colors;
hsPoint3 point;
hsVector3 normal;
int i, j, numDivisions, start;
float angle, z, x, y, internRad;
plDrawableSpans *drawable;
numDivisions = (int)( radius * qualityScalar / 10.f );
if( numDivisions < 5 )
numDivisions = 5;
else if( numDivisions > 30 )
numDivisions = 30;
/// Generate points
for( i = 0; i <= numDivisions; i++ )
{
angle = (float)i * ( hsScalarPI ) / (float)numDivisions;
hsFastMath::SinCosInRange( angle, internRad, z );
internRad *= radius;
for( j = 0; j < numDivisions; j++ )
{
angle = (float)j * ( 2 * hsScalarPI ) / (float)numDivisions;
hsFastMath::SinCosInRange( angle, x, y );
point.Set( pos.fX + x * internRad, pos.fY + y * internRad, pos.fZ + z * radius );
normal.Set( x * internRad, y * internRad, z * radius );
normal.Normalize();
points.Append( point );
normals.Append( normal );
}
}
/// Generate indices
for( i = 0, start = 0; i < numDivisions; i++, start += numDivisions )
{
for( j = 0; j < numDivisions - 1; j++ )
{
indices.Append( start + j );
indices.Append( start + j + 1 );
indices.Append( start + j + numDivisions + 1 );
indices.Append( start + j );
indices.Append( start + j + numDivisions + 1 );
indices.Append( start + j + numDivisions );
}
indices.Append( start + j );
indices.Append( start );
indices.Append( start + numDivisions );
indices.Append( start + j );
indices.Append( start + numDivisions );
indices.Append( start + j + numDivisions );
}
/// Create a drawable for it
drawable = plDrawableGenerator::GenerateDrawable( points.GetCount(), points.AcquireArray(), normals.AcquireArray(),
nil, 0,
nil, true, multColor,
indices.GetCount(), indices.AcquireArray(),
material, localToWorld, blended, retIndex, toAddTo );
return drawable;
}
//// GenerateBoxDrawable /////////////////////////////////////////////////////
plDrawableSpans *plDrawableGenerator::GenerateBoxDrawable( hsScalar width, hsScalar height, hsScalar depth,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended,
const hsColorRGBA* multColor,
hsTArray<UInt32> *retIndex, plDrawableSpans *toAddTo )
{
hsVector3 xVec, yVec, zVec;
hsPoint3 pt;
xVec.Set( width, 0, 0 );
yVec.Set( 0, height, 0 );
zVec.Set( 0, 0, depth );
pt.Set( -width / 2.f, -height / 2.f, -depth / 2.f );
return GenerateBoxDrawable( pt, xVec, yVec, zVec, material, localToWorld, blended, multColor, retIndex, toAddTo );
}
//// GenerateBoxDrawable /////////////////////////////////////////////////////
// Version that takes a corner and three vectors, for x, y and z edges.
#define CALC_NORMAL( nA, xVec, yVec, zVec ) { hsVector3 n = (xVec) + (yVec) + (zVec); n = -n; n.Normalize(); nA.Append( n ); }
plDrawableSpans *plDrawableGenerator::GenerateBoxDrawable( const hsPoint3 &corner, const hsVector3 &xVec, const hsVector3 &yVec, const hsVector3 &zVec,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended,
const hsColorRGBA* multColor,
hsTArray<UInt32> *retIndex, plDrawableSpans *toAddTo )
{
hsTArray<hsPoint3> points;
hsTArray<hsVector3> normals;
hsTArray<UInt16> indices;
hsTArray<hsColorRGBA> colors;
hsTArray<hsPoint3> uvws;
hsPoint3 point;
plDrawableSpans *drawable;
float mults[ 8 ][ 3 ] = { { -1, -1, -1 }, { 1, -1, -1 }, { 1, 1, -1 }, { -1, 1, -1 },
{ -1, -1, 1 }, { 1, -1, 1 }, { 1, 1, 1 }, { -1, 1, 1 } };
/// Generate points and normals
points.Expand( 8 );
normals.Expand( 8 );
point = corner; points.Append( point );
point += xVec; points.Append( point );
point += yVec; points.Append( point );
point = corner + yVec; points.Append( point );
point = corner + zVec; points.Append( point );
point += xVec; points.Append( point );
point += yVec; points.Append( point );
point = corner + zVec + yVec; points.Append( point );
CALC_NORMAL( normals, xVec, yVec, zVec );
CALC_NORMAL( normals, -xVec, yVec, zVec );
CALC_NORMAL( normals, -xVec, -yVec, zVec );
CALC_NORMAL( normals, xVec, -yVec, zVec );
CALC_NORMAL( normals, xVec, yVec, -zVec );
CALC_NORMAL( normals, -xVec, yVec, -zVec );
CALC_NORMAL( normals, -xVec, -yVec, -zVec );
CALC_NORMAL( normals, xVec, -yVec, -zVec );
uvws.Expand( 8 );
uvws.Append( hsPoint3( 0.f, 1.f, 0.f ) );
uvws.Append( hsPoint3( 1.f, 1.f, 0.f ) );
uvws.Append( hsPoint3( 1.f, 0.f, 0.f ) );
uvws.Append( hsPoint3( 0.f, 0.f, 0.f ) );
uvws.Append( hsPoint3( 1.f, 1.f, 0.f ) );
uvws.Append( hsPoint3( 1.f, 0.f, 0.f ) );
uvws.Append( hsPoint3( 0.f, 0.f, 0.f ) );
uvws.Append( hsPoint3( 0.f, 1.f, 0.f ) );
/// Generate indices
indices.Expand( 36 );
indices.Append( 0 ); indices.Append( 1 ); indices.Append( 2 );
indices.Append( 0 ); indices.Append( 2 ); indices.Append( 3 );
indices.Append( 1 ); indices.Append( 0 ); indices.Append( 4 );
indices.Append( 1 ); indices.Append( 4 ); indices.Append( 5 );
indices.Append( 2 ); indices.Append( 1 ); indices.Append( 5 );
indices.Append( 2 ); indices.Append( 5 ); indices.Append( 6 );
indices.Append( 3 ); indices.Append( 2 ); indices.Append( 6 );
indices.Append( 3 ); indices.Append( 6 ); indices.Append( 7 );
indices.Append( 0 ); indices.Append( 3 ); indices.Append( 7 );
indices.Append( 0 ); indices.Append( 7 ); indices.Append( 4 );
indices.Append( 7 ); indices.Append( 6 ); indices.Append( 5 );
indices.Append( 7 ); indices.Append( 5 ); indices.Append( 4 );
/// Create a drawable for it
drawable = plDrawableGenerator::GenerateDrawable( points.GetCount(), points.AcquireArray(), normals.AcquireArray(),
uvws.AcquireArray(), 1,
nil, true, multColor,
indices.GetCount(), indices.AcquireArray(),
material, localToWorld, blended, retIndex, toAddTo );
return drawable;
}
//// GenerateBoundsDrawable //////////////////////////////////////////////////
plDrawableSpans *plDrawableGenerator::GenerateBoundsDrawable( hsBounds3Ext *bounds,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended,
const hsColorRGBA* multColor,
hsTArray<UInt32> *retIndex, plDrawableSpans *toAddTo )
{
hsTArray<hsPoint3> points;
hsTArray<hsVector3> normals;
hsTArray<UInt16> indices;
hsTArray<hsColorRGBA> colors;
hsPoint3 point;
hsVector3 normal;
int i;
plDrawableSpans *drawable;
float mults[ 8 ][ 3 ] = { { -1, -1, -1 }, { 1, -1, -1 }, { 1, 1, -1 }, { -1, 1, -1 },
{ -1, -1, 1 }, { 1, -1, 1 }, { 1, 1, 1 }, { -1, 1, 1 } };
/// Generate points and normals
points.Expand( 8 );
normals.Expand( 8 );
hsPoint3 min = bounds->GetMins();
hsPoint3 max = bounds->GetMaxs();
for( i = 0; i < 8; i++ )
{
points.Append( hsPoint3( mults[ i ][ 0 ] > 0 ? max.fX : min.fX,
mults[ i ][ 1 ] > 0 ? max.fY : min.fY,
mults[ i ][ 2 ] > 0 ? max.fZ : min.fZ ) );
normals.Append( hsVector3( mults[ i ][ 0 ], mults[ i ][ 1 ], mults[ i ][ 2 ] ) );
}
/// Generate indices
indices.Expand( 36 );
indices.Append( 0 ); indices.Append( 1 ); indices.Append( 2 );
indices.Append( 0 ); indices.Append( 2 ); indices.Append( 3 );
indices.Append( 1 ); indices.Append( 0 ); indices.Append( 4 );
indices.Append( 1 ); indices.Append( 4 ); indices.Append( 5 );
indices.Append( 2 ); indices.Append( 1 ); indices.Append( 5 );
indices.Append( 2 ); indices.Append( 5 ); indices.Append( 6 );
indices.Append( 3 ); indices.Append( 2 ); indices.Append( 6 );
indices.Append( 3 ); indices.Append( 6 ); indices.Append( 7 );
indices.Append( 0 ); indices.Append( 3 ); indices.Append( 7 );
indices.Append( 0 ); indices.Append( 7 ); indices.Append( 4 );
indices.Append( 7 ); indices.Append( 6 ); indices.Append( 5 );
indices.Append( 7 ); indices.Append( 5 ); indices.Append( 4 );
/// Create a drawable for it
drawable = plDrawableGenerator::GenerateDrawable( points.GetCount(), points.AcquireArray(), normals.AcquireArray(),
nil, 0,
nil, true, multColor,
indices.GetCount(), indices.AcquireArray(),
material, localToWorld, blended, retIndex, toAddTo );
return drawable;
}
//// GenerateConicalDrawable /////////////////////////////////////////////////
plDrawableSpans *plDrawableGenerator::GenerateConicalDrawable( hsScalar radius, hsScalar height, hsGMaterial *material,
const hsMatrix44 &localToWorld, hsBool blended,
const hsColorRGBA* multColor,
hsTArray<UInt32> *retIndex, plDrawableSpans *toAddTo )
{
hsVector3 direction;
direction.Set( 0, 0, height );
return GenerateConicalDrawable( hsPoint3( 0, 0, 0 ), direction, radius, material, localToWorld, blended,
multColor, retIndex, toAddTo );
}
//// GenerateConicalDrawable /////////////////////////////////////////////////
plDrawableSpans *plDrawableGenerator::GenerateConicalDrawable( hsPoint3 &apex, hsVector3 &direction, hsScalar radius, hsGMaterial *material,
const hsMatrix44 &localToWorld, hsBool blended,
const hsColorRGBA* multColor,
hsTArray<UInt32> *retIndex, plDrawableSpans *toAddTo )
{
hsTArray<hsPoint3> points;
hsTArray<hsVector3> normals;
hsTArray<UInt16> indices;
hsTArray<hsColorRGBA> colors;
hsPoint3 point;
hsVector3 normal;
int i, numDivisions;
float angle, x, y;
plDrawableSpans *drawable;
numDivisions = (int)( radius / 4.f );
if( numDivisions < 6 )
numDivisions = 6;
else if( numDivisions > 20 )
numDivisions = 20;
/// First, we need a few more vectors--specifically, the x and y vectors for the cone's base
hsPoint3 baseCenter = apex + direction;
hsVector3 xVec, yVec;
xVec.Set( 1, 0, 0 );
yVec = xVec % direction;
if( yVec.MagnitudeSquared() == 0 )
{
xVec.Set( 0, 1, 0 );
yVec = xVec % direction;
hsAssert( yVec.MagnitudeSquared() != 0, "Weird funkiness when doing this!!!" );
}
xVec = yVec % direction;
xVec.Normalize();
yVec.Normalize();
/// Now generate points based on those
points.Expand( numDivisions + 2 );
normals.Expand( numDivisions + 2 );
points.Append( apex );
normals.Append( -direction );
for( i = 0; i < numDivisions; i++ )
{
angle = (float)i * ( hsScalarPI * 2.f ) / (float)numDivisions;
hsFastMath::SinCosInRange( angle, x, y );
points.Append( baseCenter + ( xVec * x * radius ) + ( yVec * y * radius ) );
normals.Append( ( xVec * x ) + ( yVec * y ) );
}
/// Generate indices
indices.Expand( ( numDivisions + 1 + numDivisions - 2 ) * 3 );
for( i = 0; i < numDivisions - 1; i++ )
{
indices.Append( 0 );
indices.Append( i + 2 );
indices.Append( i + 1 );
}
indices.Append( 0 );
indices.Append( 1 );
indices.Append( numDivisions );
// Bottom cap
for( i = 3; i < numDivisions + 1; i++ )
{
indices.Append( i - 1 );
indices.Append( i );
indices.Append( 1 );
}
/// Create a drawable for it
drawable = plDrawableGenerator::GenerateDrawable( points.GetCount(), points.AcquireArray(), normals.AcquireArray(),
nil, 0,
nil, true, multColor,
indices.GetCount(), indices.AcquireArray(),
material, localToWorld, blended, retIndex, toAddTo );
return drawable;
}
//// GenerateAxesDrawable ////////////////////////////////////////////////////
plDrawableSpans *plDrawableGenerator::GenerateAxesDrawable( hsGMaterial *material,
const hsMatrix44 &localToWorld, hsBool blended,
const hsColorRGBA* multColor,
hsTArray<UInt32> *retIndex, plDrawableSpans *toAddTo )
{
hsTArray<hsPoint3> points;
hsTArray<hsVector3> normals;
hsTArray<hsColorRGBA> colors;
hsTArray<UInt16> indices;
int i;
float size = 15;
plDrawableSpans *drawable;
/// Generate points
points.SetCount( 6 * 3 );
normals.SetCount( 6 * 3 );
colors.SetCount( 6 * 3 );
points[ 0 ].Set( 0, 0, 0 );
points[ 1 ].Set( size, -size * 0.1f, 0 );
points[ 2 ].Set( size, -size * 0.3f, 0 );
points[ 3 ].Set( size * 1.3f, 0, 0 );
points[ 4 ].Set( size, size * 0.3f, 0 );
points[ 5 ].Set( size, size * 0.1f, 0 );
for( i = 0; i < 6; i++ )
{
points[ i + 6 ].fX = - points[ i ].fY;
points[ i + 6 ].fY = points[ i ].fX;
points[ i + 6 ].fZ = 0;
points[ i + 12 ].fX = points[ i ].fY;
points[ i + 12 ].fZ = points[ i ].fX;
points[ i + 12 ].fY = 0;
colors[ i ].Set( 1, 0, 0, 1 );
colors[ i + 6 ].Set( 0, 1, 0, 1 );
colors[ i + 12 ].Set( 0, 0, 1, 1 );
if( multColor )
colors[ i ] *= *multColor;
}
/// Generate indices
indices.SetCount( 6 * 3 );
for( i = 0; i < 18; i += 6 )
{
indices[ i ] = i + 0;
indices[ i + 1 ] = i + 1;
indices[ i + 2 ] = i + 5;
indices[ i + 3 ] = i + 2;
indices[ i + 4 ] = i + 3;
indices[ i + 5 ] = i + 4;
}
/// Create a drawable for it
drawable = plDrawableGenerator::GenerateDrawable( points.GetCount(), points.AcquireArray(), normals.AcquireArray(),
nil, 0,
nil, true, multColor,
indices.GetCount(), indices.AcquireArray(),
material, localToWorld, blended, retIndex, toAddTo );
return drawable;
}
//// GeneratePlanarDrawable //////////////////////////////////////////////////
// Version that takes a corner and two vectors, for x and y edges.
#define CALC_PNORMAL( nA, xVec, yVec ) { hsVector3 n = (xVec) % (yVec); n.Normalize(); nA.Append( n ); }
plDrawableSpans *plDrawableGenerator::GeneratePlanarDrawable( const hsPoint3 &corner, const hsVector3 &xVec, const hsVector3 &yVec,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended,
const hsColorRGBA* multColor,
hsTArray<UInt32> *retIndex, plDrawableSpans *toAddTo )
{
hsTArray<hsPoint3> points;
hsTArray<hsVector3> normals;
hsTArray<UInt16> indices;
hsTArray<hsColorRGBA> colors;
hsTArray<hsPoint3> uvws;
hsPoint3 point;
plDrawableSpans *drawable;
/// Generate points and normals
points.Expand( 4 );
normals.Expand( 4 );
point = corner; points.Append( point );
point += xVec; points.Append( point );
point += yVec; points.Append( point );
point = corner + yVec; points.Append( point );
CALC_PNORMAL( normals, xVec, yVec );
CALC_PNORMAL( normals, xVec, yVec );
CALC_PNORMAL( normals, xVec, yVec );
CALC_PNORMAL( normals, xVec, yVec );
uvws.Expand( 4 );
uvws.Append( hsPoint3( 0.f, 1.f, 0.f ) );
uvws.Append( hsPoint3( 1.f, 1.f, 0.f ) );
uvws.Append( hsPoint3( 1.f, 0.f, 0.f ) );
uvws.Append( hsPoint3( 0.f, 0.f, 0.f ) );
/// Generate indices
indices.Expand( 6 );
indices.Append( 0 ); indices.Append( 1 ); indices.Append( 2 );
indices.Append( 0 ); indices.Append( 2 ); indices.Append( 3 );
/// Create a drawable for it
drawable = plDrawableGenerator::GenerateDrawable( points.GetCount(), points.AcquireArray(), normals.AcquireArray(),
uvws.AcquireArray(), 1,
nil, true, multColor,
indices.GetCount(), indices.AcquireArray(),
material, localToWorld, blended, retIndex, toAddTo );
return drawable;
}

View File

@ -0,0 +1,168 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plDrawableGenerator Header //
// //
// Static helper class for creating various kind of drawable primitives. //
// Can be very useful for visualization stuff ;) //
// //
//// Version History /////////////////////////////////////////////////////////
// //
// 5.15.2001 mcn - Created. //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plDrawableGenerator_h
#define _plDrawableGenerator_h
#include "hsTemplates.h"
#include "hsBounds.h"
#include "hsMatrix44.h"
class hsGMaterial;
class plDrawableSpans;
class plGeometrySpan;
struct hsColorRGBA;
//// Class Definition ////////////////////////////////////////////////////////
class plDrawableGenerator
{
public:
// Set the colors for the faux lighting on generated drawables
static void SetFauxLightColors( hsColorRGBA &lite, hsColorRGBA &dark );
// Refills a drawable previously created with GenerateDrawable with the new data. New data
// must match previous data in counts.
hsBool RegenerateDrawable( UInt32 vertCount, hsPoint3 *positions, hsVector3 *normals,
hsPoint3 *uvws, UInt32 uvwsPerVtx,
hsColorRGBA *origColors, hsBool fauxShade, const hsColorRGBA* multColor,
UInt32 numIndices, UInt16 *indices,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended,
UInt32 diIndex, plDrawableSpans *destDraw );
// Generates a drawable based on the vertex/index data given
// uvws is an array vertCount*uvwsPerVtx long in order [uvw(s) for vtx0, uvw(s) for vtx1, ...], or is nil
static plDrawableSpans *GenerateDrawable( UInt32 vertCount, hsPoint3 *positions, hsVector3 *normals,
hsPoint3 *uvws, UInt32 uvwsPerVtx,
hsColorRGBA *origColors, hsBool fauxShade, const hsColorRGBA* multColor,
UInt32 numIndices, UInt16 *indices,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended = false,
hsTArray<UInt32> *retIndex = nil, plDrawableSpans *toAddTo = nil );
// Generates a spherical drawable
static plDrawableSpans *GenerateSphericalDrawable( const hsPoint3& localPos, hsScalar radius, hsGMaterial *material,
const hsMatrix44 &localToWorld, hsBool blended = false,
const hsColorRGBA* multColor = nil,
hsTArray<UInt32> *retIndex = nil, plDrawableSpans *toAddTo = nil,
hsScalar qualityScalar = 1.f );
// Generates a rectangular drawable
static plDrawableSpans *GenerateBoxDrawable( hsScalar width, hsScalar height, hsScalar depth,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended = false,
const hsColorRGBA* multColor = nil,
hsTArray<UInt32> *retIndex = nil, plDrawableSpans *toAddTo = nil );
// Generate a rectangular drawable based on a corner and three vectors
static plDrawableSpans *GenerateBoxDrawable( const hsPoint3 &corner, const hsVector3 &xVec, const hsVector3 &yVec, const hsVector3 &zVec,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended = false,
const hsColorRGBA* multColor = nil,
hsTArray<UInt32> *retIndex = nil, plDrawableSpans *toAddTo = nil );
// Generates a bounds-based drawable
static plDrawableSpans *GenerateBoundsDrawable( hsBounds3Ext *bounds,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended = false,
const hsColorRGBA* multColor = nil,
hsTArray<UInt32> *retIndex = nil, plDrawableSpans *toAddTo = nil );
// Generates a conical drawable
static plDrawableSpans *GenerateConicalDrawable( hsScalar radius, hsScalar height, hsGMaterial *material,
const hsMatrix44 &localToWorld, hsBool blended = false,
const hsColorRGBA* multColor = nil,
hsTArray<UInt32> *retIndex = nil, plDrawableSpans *toAddTo = nil );
// Generates a general conical drawable based on a center and direction
static plDrawableSpans *GenerateConicalDrawable( hsPoint3 &apex, hsVector3 &direction, hsScalar radius, hsGMaterial *material,
const hsMatrix44 &localToWorld, hsBool blended = false,
const hsColorRGBA* multColor = nil,
hsTArray<UInt32> *retIndex = nil, plDrawableSpans *toAddTo = nil );
// Generates a drawable representing 3 axes
static plDrawableSpans *GenerateAxesDrawable( hsGMaterial *material,
const hsMatrix44 &localToWorld, hsBool blended = false,
const hsColorRGBA* multColor = nil,
hsTArray<UInt32> *retIndex = nil, plDrawableSpans *toAddTo = nil );
// Generate a planar drawable based on a corner and two vectors
static plDrawableSpans *GeneratePlanarDrawable( const hsPoint3 &corner, const hsVector3 &xVec, const hsVector3 &yVec,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended = false,
const hsColorRGBA* multColor = nil,
hsTArray<UInt32> *retIndex = nil, plDrawableSpans *toAddTo = nil );
protected:
// Shade the vertices given based on a quick fake directional light.
// If origColors is non-nil, it must be an array of length count. Each outColor[i] *= origColor[i].
// If multColor is non-nil, modulate the output by multColor.
static void IQuickShadeVerts( UInt32 count, hsVector3 *normals,
hsColorRGBA *colors,
hsColorRGBA* origColors = nil,
const hsColorRGBA* multColor = nil );
// Take the vertex and connectivity info supplied and fill out a geometry span with it.
// Output span is ready to be added to a Drawable, or refreshed in a Drawable if it's
// already in the SourceSpans.
static void IFillSpan( UInt32 vertCount, hsPoint3 *positions, hsVector3 *normals,
hsPoint3 *uvws, UInt32 uvwsPerVtx,
hsColorRGBA *origColors, hsBool fauxShade, const hsColorRGBA* multColor,
UInt32 numIndices, UInt16 *indices,
hsGMaterial *material, const hsMatrix44 &localToWorld, hsBool blended,
plGeometrySpan* span );
static hsColorRGBA fLiteColor;
static hsColorRGBA fDarkColor;
};
#endif // _plDrawableGenerator_h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,390 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plDrawableSpans Header //
// //
// The base plDrawable derivative for ice (triangle list) //
// drawables. Contains the basic structure for spans and the functions //
// to deal with them. //
// //
//// Version History /////////////////////////////////////////////////////////
// //
// 4.3.2001 mcn - Created. //
// 5.3.2001 mcn - Completely revamped. Now plDrawableSpans *IS* the group //
// of spans, and each span is either an icicle or patch. //
// This eliminates the need entirely for separate drawables,//
// at the cost of having to do a bit of extra work to //
// maintain different types of spans in the same drawable. //
// 4.20.2006 bob - Patches are long gone. Only icicle (or particle) spans //
// now.
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plDrawableSpans_h
#define _plDrawableSpans_h
#include "hsBitVector.h"
#include "hsTemplates.h"
#include "plDrawable.h"
#include "hsBounds.h"
#include "hsMatrix44.h"
#include "plSpanTypes.h"
class plPipeline;
class plMessage;
class hsGMaterial;
class plGeometrySpan;
class plSpaceTree;
class plFogEnvironment;
class plLightInfo;
class plGBufferGroup;
class plParticleCore;
class plAccessSpan;
class plAccessVtxSpan;
class plAccessTriSpan;
class plVisMgr;
class plVisRegion;
class plClusterGroup;
//// Class Definition ////////////////////////////////////////////////////////
class plDISpanIndex
{
public:
enum {
kNone = 0x0,
kMatrixOnly = 0x1,
kDontTransformSpans = 0x2 // Only used for particle systems right now
};
UInt8 fFlags;
hsTArray<UInt32> fIndices;
hsBool IsMatrixOnly() const { return 0 != (fFlags & kMatrixOnly); }
hsBool DontTransform() const { return 0 != ( fFlags & kDontTransformSpans ); }
void Append(UInt32 i) { fIndices.Append(i); }
void Reset() { fFlags = kNone; fIndices.Reset(); }
void SetCountAndZero(int c) { fIndices.SetCountAndZero(c); }
UInt32 GetCount() const { return fIndices.GetCount(); }
UInt32& operator[](int i) const { return fIndices[i]; }
};
struct hsColorRGBA;
class plDrawableSpans : public plDrawable
{
protected:
static const UInt32 kSpanTypeMask;
static const UInt32 kSpanIDMask;
static const UInt32 kSpanTypeIcicle;
static const UInt32 kSpanTypeParticleSpan;
UInt32 fType;
hsBool fReadyToRender;
hsBounds3Ext fLocalBounds;
hsBounds3Ext fWorldBounds;
hsBounds3Ext fMaxWorldBounds;
hsMatrix44 fLocalToWorld;
hsMatrix44 fWorldToLocal;
hsTArray<hsMatrix44> fLocalToWorlds;
hsTArray<hsMatrix44> fWorldToLocals;
hsTArray<hsMatrix44> fLocalToBones;
hsTArray<hsMatrix44> fBoneToLocals;
hsTArray<hsGMaterial *> fMaterials;
mutable plSpaceTree* fSpaceTree;
hsBitVector fVisSet; // the or of all our spans visset's. Doesn't have to be exact, just conservative.
hsBitVector fVisNot; // same, but for visregions that exclude us.
mutable hsBitVector fLastVisSet; // Last vis set we were evaluated against.
mutable hsBitVector fLastVisNot; // Last exclusion set we were evaluated agains.
hsBitVector fVisCache; // the enabled section of the space tree
hsTArray<plIcicle> fIcicles;
hsTArray<plParticleSpan> fParticleSpans;
hsTArray<plSpan *> fSpans; // Pointers into the above two arrays
hsTArray<UInt32> fSpanSourceIndices; // For volatile drawables only
hsTArray<plGBufferGroup *> fGroups;
hsTArray<plDISpanIndex*> fDIIndices;
UInt32 fProps;
UInt32 fCriteria;
plRenderLevel fRenderLevel;
plLoadMask fLoadMask;
hsBool fRegisteredForRecreate, fNeedCleanup;
hsBool fRegisteredForRender;
hsBitVector fParticleSpanVector;
hsBitVector fBlendingSpanVector;
hsBitVector fFakeBlendingSpanVector;
plKey fSceneNode;
hsBool fSettingMatIdxLock;
UInt32 fSkinTime;
/// Export-only members
hsTArray<plGeometrySpan *> fSourceSpans;
hsBool fOptimized;
virtual void IQuickSpaceTree( void ) const;
// Temp placeholder function. See code for comments.
void IUpdateMatrixPaletteBoundsHack( );
void ICleanupMatrices();
void IRemoveGarbage( void );
void IAdjustSortData( plGBufferTriangle *triList, UInt32 count, UInt32 threshhold, Int32 delta );
// The following two functions return true if they create a new span, false if it's just an instance
hsBool IConvertGeoSpanToVertexSpan( plGeometrySpan *geoSpan, plVertexSpan *span, int lod, plVertexSpan *instancedParent );
hsBool IConvertGeoSpanToIcicle( plGeometrySpan *geoSpan, plIcicle *icicle, int lod, plIcicle *instancedParent = nil );
void IUpdateIcicleFromGeoSpan( plGeometrySpan *geoSpan, plIcicle *icicle );
void IUpdateVertexSpanFromGeoSpan( plGeometrySpan *geoSpan, plVertexSpan *span );
UInt32 IXlateSpanProps( UInt32 props, hsBool xlateToSpan );
UInt32 IAddAMaterial( hsGMaterial *material );
UInt32 IRefMaterial( UInt32 index );
void ICheckToRemoveMaterial( UInt32 materialIdx );
// Annoying to need this, but necessary until materials can test for properties on any of their layers (might add in the future)
hsBool ITestMatForSpecularity( hsGMaterial *mat );
void IAssignMatIdxToSpan( plSpan *span, hsGMaterial *mtl );
// Create the sorting data for a given span and flag it as sortable
void ICheckSpanForSortable( UInt32 idx ) { if( !(fSpans[idx]->fProps & plSpan::kPropFacesSortable) )IMakeSpanSortable(idx); }
void IMakeSpanSortable( UInt32 index );
/// Bit vector build thingies
virtual void IBuildVectors( void );
hsBool IBoundsInvalid(const hsBounds3Ext& bnd) const;
/// EXPORT-ONLY FUNCTIONS
// Packs the span indices
void IPackSourceSpans( void );
// Sort the spans
void ISortSourceSpans( void );
// Compare two spans for sorting
short ICompareSpans( plGeometrySpan *span1, plGeometrySpan *span2 );
// Find a buffer group of the given format (returns its index into fGroups)
UInt8 IFindBufferGroup( UInt8 vtxFormat, UInt32 numVertsNeeded, int lod, hsBool vertVolatile, hsBool idxVolatile);
// Write a span to a stream
void IWriteSpan( hsStream *s, plSpan *span );
/// EXPORT-ONLY FUNCTIONS
/// DYNAMIC FUNCTIONS
plDISpanIndex *IFindDIIndices( UInt32 &index );
void IRebuildSpanArray( void );
plParticleSpan *ICreateParticleIcicle( hsGMaterial *material, plParticleSet *set );
virtual void SetKey(plKey k);
public:
plDrawableSpans();
virtual ~plDrawableSpans();
CLASSNAME_REGISTER( plDrawableSpans );
GETINTERFACE_ANY( plDrawableSpans, plDrawable );
virtual void SetNativeTransform(UInt32 idx, const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual plDrawable& SetTransform( UInt32 index, const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual const hsMatrix44& GetLocalToWorld( UInt32 index = (UInt32)-1 ) const;
virtual const hsMatrix44& GetWorldToLocal( UInt32 index = (UInt32)-1 ) const;
virtual plDrawable& SetProperty( UInt32 index, int prop, hsBool on );
virtual hsBool GetProperty( UInt32 index, int prop ) const;
virtual plDrawable& SetProperty( int prop, hsBool on );
virtual hsBool GetProperty( int prop ) const;
virtual plDrawable& SetNativeProperty( int prop, hsBool on ) { if( on ) fProps |= prop; else fProps &= ~prop; return *this; }
virtual hsBool GetNativeProperty( int prop ) const { return ( fProps & prop ) ? true : false; }
virtual plDrawable& SetNativeProperty( UInt32 index, int prop, hsBool on );
virtual hsBool GetNativeProperty( UInt32 index, int prop ) const;
virtual plDrawable& SetSubType( UInt32 index, plSubDrawableType t, hsBool on );
virtual UInt32 GetSubType( UInt32 index ) const; // returns or of all spans with this index (index==-1 is all spans).
virtual UInt32 GetType( void ) const { return fType; }
virtual void SetType( UInt32 type ) { fType = type; }
virtual void SetRenderLevel(const plRenderLevel& l);
virtual const plRenderLevel& GetRenderLevel() const;
const hsBounds3Ext& GetLocalBounds( UInt32 index = (UInt32)-1 ) const;
const hsBounds3Ext& GetWorldBounds( UInt32 index = (UInt32)-1 ) const;
const hsBounds3Ext& GetMaxWorldBounds( UInt32 index = (UInt32)-1 ) const;
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual plSpaceTree* GetSpaceTree() const { if(!fSpaceTree)IQuickSpaceTree(); return fSpaceTree; }
virtual void SetSpaceTree(plSpaceTree* st) const;
virtual void SetVisSet(plVisMgr* visMgr);
virtual void SetDISpanVisSet(UInt32 diIndex, hsKeyedObject* reg, hsBool on);
virtual const plSpan *GetSpan( UInt32 index ) const { return fSpans[ index ]; }
virtual const plSpan *GetSpan( UInt32 diIndex, UInt32 index ) const { return fSpans[ (*fDIIndices[ diIndex ])[ index ] ]; }
virtual const UInt32 GetNumSpans( void ) const { return fSpans.GetCount(); }
virtual const hsTArray<plSpan *> &GetSpanArray( void ) const { return fSpans; }
hsMatrix44* GetMatrixPalette(int baseMatrix) const { return &fLocalToWorlds[baseMatrix]; }
const hsMatrix44& GetPaletteMatrix(int i) const { return fLocalToWorlds[i]; }
void SetInitialBone(int i, const hsMatrix44& l2b, const hsMatrix44& b2l);
// Get the vertex buffer ref of a given group
hsGDeviceRef *GetVertexRef( UInt32 group, UInt32 idx );
// Get the index buffer ref of a given group
hsGDeviceRef *GetIndexRef( UInt32 group, UInt32 idx );
// BufferGroups accessed only by Pipeline and it's close personal acquaintances.
plGBufferGroup* GetBufferGroup(UInt32 i) const { return fGroups[i]; }
UInt32 GetNumBufferGroups() const { return fGroups.GetCount(); }
const hsTArray<plGeometrySpan*>& GetSourceSpans() const { return fSourceSpans; }
void DirtyVertexBuffer(UInt32 group, UInt32 idx);
void DirtyIndexBuffer(UInt32 group, UInt32 idx);
// Prepare all internal data structures for rendering
virtual void PrepForRender( plPipeline *p );
void SetNotReadyToRender() { fReadyToRender = false; }
virtual hsBool MsgReceive( plMessage* msg );
// These two should only be called by the SceneNode
virtual plKey GetSceneNode() const { return fSceneNode; }
virtual void SetSceneNode(plKey newNode);
// Lookup a material in the material array
hsGMaterial *GetMaterial( UInt32 index ) const { return ( ( index == (UInt32)-1 ) ? nil : fMaterials[ index ] ); }
UInt32 GetNumMaterials( void ) const { return fMaterials.GetCount(); }
// Convert intermediate data into export/run-time-ready data
virtual void Optimize( void );
// Called by the sceneNode to determine if we match the criteria
virtual hsBool DoIMatch( const plDrawableCriteria& crit );
// To set the criteria that this ice fits
void SetCriteria( const plDrawableCriteria& crit );
// Get a bitVector of the spans that are particle spans
virtual hsBitVector const &GetParticleSpanVector( void ) const;
// Get a bitVector of the spans that are blending (i.e. numMatrices > 0)
virtual hsBitVector const &GetBlendingSpanVector( void ) const;
// Set a single bit in the bitVector of spans that are blending
virtual void SetBlendingSpanVectorBit( UInt32 bitNumber, hsBool on );
// Taking span index. DI Index doesn't make sense here, because one object's DI can dereference into many materials etc.
virtual hsGMaterial* GetSubMaterial(int index) const;
virtual hsBool GetSubVisDists(int index, hsScalar& minDist, hsScalar& maxDist) const; // return true if span invisible before minDist and/or after maxDist
// Used by the pipeline to keep from reskinning on multiple renders per frame.
UInt32 GetSkinTime() const { return fSkinTime; }
void SetSkinTime(UInt32 t) { fSkinTime = t; }
void UnPackCluster(plClusterGroup* cluster);
/// EXPORT-ONLY FUNCTIONS
virtual UInt32 AddDISpans( hsTArray<plGeometrySpan *> &spans, UInt32 index = (UInt32)-1);
virtual plDISpanIndex& GetDISpans( UInt32 index ) const;
// Data Access functions
// Runtime
hsPoint3& GetPosition(int spanIdx, int vtxIdx);
hsVector3& GetNormal(int spanIdx, int vtxIdx);
UInt32 GetNumTris(int spanIdx);
UInt16* GetIndexList(int spanIdx);
// Conversion (before geometryspans get tossed (at write)).
UInt32 CvtGetNumVerts(int spanIdx) const;
hsPoint3& CvtGetPosition(int spanIdx, int vtxIdx);
hsVector3& CvtGetNormal(int spanIdx, int vtxIdx);
UInt32 CvtGetNumTris(int spanIdx);
UInt16* CvtGetIndexList(int spanIdx);
plGeometrySpan* GetGeometrySpan(int spanIdx);
/// DYNAMIC FUNCTIONS
virtual void RemoveDISpans( UInt32 index );
virtual UInt32 AppendDISpans( hsTArray<plGeometrySpan *> &spans, UInt32 index = (UInt32)-1, hsBool clearSpansAfterAdd = true, hsBool doNotAddToSource = false, hsBool addToFront = false, int lod = 0 );
virtual UInt32 RefreshDISpans( UInt32 diIndex );
virtual UInt32 RefreshSpan( UInt32 srcSpanIndex );
virtual void RemoveDIMatrixSpans(UInt32 index);
virtual UInt32 AppendDIMatrixSpans(int n);
virtual UInt32 FindBoneBaseMatrix(const hsTArray<hsMatrix44>& initL2B, hsBool searchAll) const;
virtual UInt32 NewDIMatrixIndex();
void SortSpan( UInt32 index, plPipeline *pipe );
void SortVisibleSpans(const hsTArray<Int16>& visList, plPipeline* pipe);
void SortVisibleSpansPartial(const hsTArray<Int16>& visList, plPipeline* pipe);
void CleanUpGarbage( void ) { IRemoveGarbage(); }
/// Funky particle system functions
virtual UInt32 CreateParticleSystem( UInt32 maxNumEmitters, UInt32 maxNumParticles, hsGMaterial *material );
virtual void ResetParticleSystem( UInt32 index );
virtual void AssignEmitterToParticleSystem( UInt32 index, plParticleEmitter *emitter );
/// SceneViewer only!
void GetOrigGeometrySpans( UInt32 diIndex, hsTArray<plGeometrySpan *> &arrayToFill );
void ClearAndSetMaterialCount(UInt32 count);
};
#endif // _plDrawableSpans_h

View File

@ -0,0 +1,784 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plDrawableSpans Class Export-only Functions //
// //
//// Version History /////////////////////////////////////////////////////////
// //
// Created 4.3.2001 mcn //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plDrawableSpans.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "plPipeline.h"
#include "plGeometrySpan.h"
#include "plSpaceTree.h"
#include "plSpaceTreeMaker.h" // This is fun and amusing and wonderful to have here.
// Keep it here forever.
#include "../plSurface/hsGMaterial.h"
#include "../plPipeline/plFogEnvironment.h"
#include "../pnMessage/plRefMsg.h"
#include "../pnMessage/plNodeRefMsg.h" // for NodeRefMsg
#include "../plMessage/plDeviceRecreateMsg.h"
#include "../plPipeline/plGBufferGroup.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayerInterface.h"
#include "../plGImage/plBitmap.h"
#include "../plGLight/plLightInfo.h"
#include "plgDispatch.h"
#include "../plStatusLog/plStatusLog.h"
//#define VERT_LOG
//// Write ///////////////////////////////////////////////////////////////////
void plDrawableSpans::Write( hsStream* s, hsResMgr* mgr )
{
UInt32 i, j, count;
// Make sure we're optimized before we write (should be tho)
// Optimize();
// Make sure all the garbage is cleaned up
if( fNeedCleanup )
IRemoveGarbage();
// Parent write
plDrawable::Write(s, mgr);
s->WriteSwap32( fProps );
s->WriteSwap32( fCriteria );
s->WriteSwap32( fRenderLevel.fLevel );
/// Write out the material keys
s->WriteSwap32( fMaterials.GetCount() );
for( i = 0; i < fMaterials.GetCount(); i++ )
mgr->WriteKey( s, fMaterials[ i ] );
/// Write out the icicles
s->WriteSwap32( fIcicles.GetCount() );
for( i = 0; i < fIcicles.GetCount(); i++ )
fIcicles[ i ].Write( s );
/// Write out the patches
// FIXME MAJOR VERSION
// no more patches, remove this line
s->WriteSwap32(0);
/// Write out the index table based on the pointer array
count = fSpans.GetCount();
s->WriteSwap32( count );
for( i = 0; i < count; i++ )
{
UInt8 *icicle = (UInt8 *)fSpans[ i ], *base = (UInt8 *)fIcicles.AcquireArray();
j = (UInt32)( icicle - base ) / sizeof( plIcicle );
s->WriteSwap32( j );
}
/// Write out the common keys
for( i = 0; i < count; i++ )
{
// The fog environ key
mgr->WriteKey( s, fSpans[ i ]->fFogEnvironment );
}
/// Write out the bounds and stuff
if( count > 0 )
{
fLocalBounds.Write(s);
fWorldBounds.Write(s);
fMaxWorldBounds.Write(s);
}
for( i = 0; i < count; i++ )
{
if( fSpans[i]->fProps & plSpan::kPropHasPermaLights )
{
UInt32 lcnt = fSpans[i]->fPermaLights.GetCount();
s->WriteSwap32(lcnt);
int j;
for( j = 0; j < lcnt; j++ )
mgr->WriteKey( s, fSpans[i]->fPermaLights[j]);
}
if( fSpans[i]->fProps & plSpan::kPropHasPermaProjs )
{
UInt32 lcnt = fSpans[i]->fPermaProjs.GetCount();
s->WriteSwap32(lcnt);
int j;
for( j = 0; j < lcnt; j++ )
mgr->WriteKey( s, fSpans[i]->fPermaProjs[j]);
}
}
/// Write out the source spans if necessary
s->WriteSwap32( fSourceSpans.GetCount() );
if( fSourceSpans.GetCount() > 0 )
{
for( i = 0; i < fSourceSpans.GetCount(); i++ )
fSourceSpans[ i ]->Write( s );
}
count = fLocalToWorlds.GetCount();
s->WriteSwap32(count);
for( i = 0; i < count; i++ )
{
fLocalToWorlds[i].Write(s);
fWorldToLocals[i].Write(s);
fLocalToBones[i].Write(s);
fBoneToLocals[i].Write(s);
}
// Write out the drawInterface index arrays
s->WriteSwap32( fDIIndices.GetCount() );
for( i = 0; i < fDIIndices.GetCount(); i++ )
{
plDISpanIndex *array = fDIIndices[ i ];
s->WriteSwap32( array->fFlags );
s->WriteSwap32( array->GetCount() );
for( j = 0; j < array->GetCount(); j++ )
s->WriteSwap32( (*array)[ j ] );
}
// Write the groups out
count = fGroups.GetCount();
s->WriteSwap( count );
for( i = 0; i < count; i++ )
{
#ifdef VERT_LOG
hsUNIXStream log;
log.Open("log\\GBuf.log", "ab");
char buf[256];
sprintf(buf, "Drawable Span: %s, GroupNum: %u\r\n", GetKeyName(), i);
log.WriteString(buf);
log.Close();
#endif
fGroups[ i ]->Write( s );
}
/// Other stuff
mgr->WriteCreatable(s, fSpaceTree);
mgr->WriteKey(s, fSceneNode);
/// All done!
}
//// AddDISpans //////////////////////////////////////////////////////////////
// Adds a drawInterface's geometry spans to the list to be collapsed into
// buffers.
UInt32 plDrawableSpans::AddDISpans( hsTArray<plGeometrySpan *> &spans, UInt32 index )
{
int i;
UInt32 spanIdx;
plSpan *span;
hsBounds3Ext bounds;
/// Do garbage cleanup first
if( fNeedCleanup )
IRemoveGarbage();
if (index == (UInt32)-1) // need a new one
{
/// Create a lookup entry
index = fDIIndices.GetCount();
fDIIndices.Append( TRACKED_NEW plDISpanIndex );
fDIIndices[ index ]->fFlags = plDISpanIndex::kNone;
}
plDISpanIndex *spanLookup = fDIIndices[ index ];
/// Add the geometry spans to our list. Also add our internal span
/// copies
for( i = 0; i < spans.GetCount(); i++ )
{
spanLookup->Append( fSourceSpans.GetCount() );
spans[ i ]->fSpanRefIndex = fSourceSpans.GetCount();
fSourceSpans.Append( spans[ i ] );
spanIdx = fIcicles.GetCount();
fIcicles.Append( plIcicle() );
plIcicle *icicle = &fIcicles[ spanIdx ];
span = (plSpan *)icicle;
/// Set common stuff
IAssignMatIdxToSpan( span, spans[ i ]->fMaterial );
span->fLocalToWorld = spans[ i ]->fLocalToWorld;
span->fWorldToLocal = spans[ i ]->fWorldToLocal;
span->fProps |= ( spans[ i ]->fProps & plGeometrySpan::kPropRunTimeLight ) ? plSpan::kPropRunTimeLight : 0;
if( spans[i]->fProps & plGeometrySpan::kPropNoShadowCast )
span->fProps |= plSpan::kPropNoShadowCast;
if( spans[i]->fProps & plGeometrySpan::kPropNoShadow )
span->fProps |= plSpan::kPropNoShadow;
if( spans[i]->fProps & plGeometrySpan::kPropForceShadow )
span->fProps |= plSpan::kPropForceShadow;
if( spans[i]->fProps & plGeometrySpan::kPropReverseSort )
span->fProps |= plSpan::kPropReverseSort;
if( spans[i]->fProps & plGeometrySpan::kPartialSort )
span->fProps |= plSpan::kPartialSort;
if( spans[i]->fProps & plGeometrySpan::kVisLOS )
{
span->fProps |= plSpan::kVisLOS;
fProps |= plDrawable::kPropHasVisLOS;
}
span->fNumMatrices = spans[ i ]->fNumMatrices;
span->fBaseMatrix = spans[ i ]->fBaseMatrix;
span->fLocalUVWChans = spans[i]->fLocalUVWChans;
span->fMaxBoneIdx = spans[i]->fMaxBoneIdx;
span->fPenBoneIdx = (UInt16)(spans[i]->fPenBoneIdx);
bounds = spans[ i ]->fLocalBounds;
span->fLocalBounds = bounds;
bounds.Transform( &span->fLocalToWorld );
span->fWorldBounds = bounds;
span->fFogEnvironment = spans[ i ]->fFogEnviron;
/// Add to our source indices
fSpans.Append( span );
fSpanSourceIndices.Append( spanIdx );
}
/// Rebuild the pointer array
IRebuildSpanArray();
SetSpaceTree(nil);
fOptimized = false;
return index;
}
//// Optimize ////////////////////////////////////////////////////////////////
void plDrawableSpans::Optimize( void )
{
int i;
if( fOptimized )
return;
/// Sort all the source spans
if( !(fProps & kPropNoReSort) )
ISortSourceSpans();
/// Pack the source spans into spans and indices
IPackSourceSpans();
/// Now that we're done with the source spans, get rid of them! (BLEAH!)
for( i = 0; i < fSourceSpans.GetCount(); i++ )
delete fSourceSpans[ i ];
fSourceSpans.Reset();
if( fCriteria & kCritSortSpans )
{
if( !(fProps & kPropNoReSort) )
fProps |= kPropSortSpans;
}
if( fCriteria & kCritSortFaces )
{
fProps |= kPropSortFaces;
}
/// Now we do a pass at the buffer groups, asking them to tidy up
for( i = 0; i < fGroups.GetCount(); i++ )
fGroups[ i ]->TidyUp();
// Look to see if we have any materials we aren't using anymore.
for( i = 0; i < fMaterials.GetCount(); i++ )
{
ICheckToRemoveMaterial(i);
}
fReadyToRender = false;
// Make the space tree (hierarchical bounds).
plSpaceTreeMaker maker;
maker.Reset();
for( i = 0; i < GetNumSpans(); i++ )
{
maker.AddLeaf( fSpans[ i ]->fWorldBounds, fSpans[ i ]->fProps & plSpan::kPropNoDraw );
}
plSpaceTree* tree = maker.MakeTree();
SetSpaceTree(tree);
/// All done!
fOptimized = true;
}
static plStatusLog* IStartLog(const char* name, int numSpans)
{
static char buff[256];
sprintf(buff, "x%s.log", name);
plStatusLog* statusLog = plStatusLogMgr::GetInstance().CreateStatusLog(
plStatusLogMgr::kDefaultNumLines,
buff,
plStatusLog::kFilledBackground | plStatusLog::kDeleteForMe );
return statusLog;
}
static plStatusLog* IEndLog(plStatusLog* statusLog)
{
delete statusLog;
return nil;
}
static void ILogSpan(plStatusLog* statusLog, plGeometrySpan* geo, plVertexSpan* span, plGBufferGroup* group)
{
if( span->fTypeMask & plSpan::kIcicleSpan )
{
plIcicle* ice = (plIcicle*)span;
if( geo->fProps & plGeometrySpan::kFirstInstance )
{
plGBufferCell* cell = group->GetCell(span->fVBufferIdx, span->fCellIdx);
UInt32 stride = group->GetVertexSize();
UInt32 ptr = cell->fVtxStart + span->fCellOffset * stride;
statusLog->AddLineF("From obj <%s> mat <%s> size %d bytes grp=%d (%d offset)",
geo->fMaxOwner ? geo->fMaxOwner : "<unknown>",
geo->fMaterial ? geo->fMaterial->GetKey()->GetName() : "<unknown>",
geo->GetVertexSize(geo->fFormat) * geo->fNumVerts + sizeof(UInt16) * geo->fNumIndices,
span->fGroupIdx,
ptr
);
// span->fVBufferIdx,
// span->fCellIdx,
// span->fCellOffset,
// span->fVStartIdx,
// span->fVLength,
// ice->fIBufferIdx,
// ice->fIStartIdx,
// ice->fILength
}
else
{
statusLog->AddLineF("Instanced obj <%s> mat <%s> grp=%d (%d/%d/%d/%d/%d/%d/%d/%d)",
geo->fMaxOwner ? geo->fMaxOwner : "<unknown>",
geo->fMaterial ? geo->fMaterial->GetKey()->GetName() : "<unknown>",
span->fGroupIdx,
span->fVBufferIdx,
span->fCellIdx,
span->fCellOffset,
span->fVStartIdx,
span->fVLength,
ice->fIBufferIdx,
ice->fIStartIdx,
ice->fILength
);
}
}
else
{
if( geo->fProps & plGeometrySpan::kFirstInstance )
{
statusLog->AddLineF("From obj <%s> mat <%s> size %d bytes grp=%d (%d/%d/%d/%d/%d)",
geo->fMaxOwner ? geo->fMaxOwner : "<unknown>",
geo->fMaterial ? geo->fMaterial->GetKey()->GetName() : "<unknown>",
geo->GetVertexSize(geo->fFormat) * geo->fNumVerts + sizeof(UInt16) * geo->fNumIndices,
span->fGroupIdx,
span->fVBufferIdx,
span->fCellIdx,
span->fCellOffset,
span->fVStartIdx,
span->fVLength
);
}
else
{
statusLog->AddLineF("Instanced obj <%s> mat <%s> grp=%d (%d/%d/%d/%d/%d)",
geo->fMaxOwner ? geo->fMaxOwner : "<unknown>",
geo->fMaterial ? geo->fMaterial->GetKey()->GetName() : "<unknown>",
span->fGroupIdx,
span->fVBufferIdx,
span->fCellIdx,
span->fCellOffset,
span->fVStartIdx,
span->fVLength
);
}
}
}
//// IPackSourceSpans ////////////////////////////////////////////////////////
// Takes the array of source spans and converts them to our internal icicle
// spans, vertex buffers and index buffers.
void plDrawableSpans::IPackSourceSpans( void )
{
int i, j;
hsBounds3Ext bounds;
hsBitVector doneSpans;
/// Calc bounds
fLocalBounds.MakeEmpty();
fWorldBounds.MakeEmpty();
for( i = 0; i < fSourceSpans.GetCount(); i++ )
{
hsBounds3Ext bnd = fSourceSpans[ i ]->fLocalBounds;
bnd.Transform( &fSourceSpans[ i ]->fLocalToWorld );
fWorldBounds.Union( &bnd );
}
fLocalBounds = fWorldBounds;
fLocalBounds.Transform( &fWorldToLocal );
fMaxWorldBounds = fWorldBounds;
// It could be that instance refs in spans that we (the drawable) own
// are actually spans in some other drawable. That's not currently handled.
// (Making that case handled would involve rewriting the instancing implementation
// to not suck ass).
// So for each instance set, we make two lists of instance refs, the ones also
// in this drawable (refsHere), and ones not (refsThere). If there are refsThere,
// we split out the refsHere into a new instance group, removing them from the
// refsThere list. If refsThere still contains spans from separate drawables,
// that will be dealt with in those drawables' Optimize calls.
doneSpans.Clear();
for( i = 0; i < fSourceSpans.GetCount(); i++ )
{
if( !doneSpans.IsBitSet(i) )
{
plGeometrySpan* span = fSourceSpans[i];
if( span->fInstanceRefs )
{
hsTArray<plGeometrySpan*>& refs = *(span->fInstanceRefs);
hsTArray<plGeometrySpan*> refsHere;
hsTArray<plGeometrySpan*> refsThere;
int k;
for( k = 0; k < refs.GetCount(); k++ )
{
plGeometrySpan* other = refs[k];
if( other != span )
{
int idx = fSourceSpans.Find(other);
if( fSourceSpans.kMissingIndex == idx )
{
refsThere.Append(other);
}
else
{
refsHere.Append(other);
}
}
}
if( refsThere.GetCount() )
{
if( refsHere.GetCount() )
{
span->BreakInstance();
// Okay, got to form a new instance group out of refsHere.
for( k = 0; k < refsHere.GetCount(); k++ )
{
plGeometrySpan* other = refsHere[k];
other->ChangeInstance(span);
doneSpans.SetBit(other->fSpanRefIndex);
}
}
else
{
span->UnInstance();
}
if( refsThere.GetCount() == 1 )
{
refsThere[0]->UnInstance();
}
}
}
doneSpans.SetBit(i);
}
}
/// Now pack the spans
doneSpans.Clear();
for( i = 0; i < fSourceSpans.GetCount(); i++ )
{
// Now we fill the rest of the data in for our span
if( !doneSpans.IsBitSet( i ) )
{
if( fSourceSpans[ i ]->fProps & plGeometrySpan::kInstanced )
{
// Instanced spans--convert the first as normal, then convert the rest
// using the first as reference
doneSpans.SetBit( i, true );
plIcicle *baseIcicle = (plIcicle *)fSpans[ i ];
IConvertGeoSpanToIcicle( fSourceSpans[ i ], baseIcicle, 0, baseIcicle );
// Loop through the rest
for( j = 0; j < fSourceSpans[ i ]->fInstanceRefs->GetCount(); j++ )
{
plGeometrySpan *other = (*fSourceSpans[ i ]->fInstanceRefs)[ j ];
if( other == fSourceSpans[ i ] )
continue;
#if 0 // What exactly is this supposed to be doing? My guess is, NADA.
if( IConvertGeoSpanToIcicle( other, (plIcicle *)fSpans[ other->fSpanRefIndex ], 0, baseIcicle ) )
baseIcicle = (plIcicle *)fSpans[ other->fSpanRefIndex ];
#else // What exactly is this supposed to be doing? My guess is, NADA.
IConvertGeoSpanToIcicle( other, (plIcicle *)fSpans[ other->fSpanRefIndex ], 0, baseIcicle );
#endif // What exactly is this supposed to be doing? My guess is, NADA.
doneSpans.SetBit( other->fSpanRefIndex, true );
}
}
else
{
// Do normal, uninstanced conversion
IConvertGeoSpanToIcicle( fSourceSpans[ i ], (plIcicle *)fSpans[ i ], 0 );
doneSpans.SetBit( i, true );
}
}
}
#ifdef VERT_LOG
hsTArray<plGeometrySpan*> order;
order.SetCount(fSourceSpans.GetCount());
for( i = 0; i < fSourceSpans.GetCount(); i++ )
{
order[fSourceSpans[i]->fSpanRefIndex] = fSourceSpans[i];
}
plStatusLog* statusLog = IStartLog(GetKey()->GetName(), fSourceSpans.GetCount());
for( i = 0; i < order.GetCount(); i++ )
{
plVertexSpan* vSpan = (plVertexSpan*)fSpans[i];
ILogSpan(statusLog, order[i], vSpan, fGroups[vSpan->fGroupIdx]);
}
statusLog = IEndLog(statusLog);
#endif
}
//// ISortSourceSpans ////////////////////////////////////////////////////////
// Does our actual optimization path by resorting all the spans into the
// most efficient order possible. Also has to re-order the span lookup
// table.
void plDrawableSpans::ISortSourceSpans( void )
{
hsTArray<UInt32> spanReorderTable, spanInverseTable;
int i, j, idx;
plGeometrySpan *tmpSpan;
UInt32 tmpIdx;
plSpan *tmpSpanPtr;
// Init the reorder table
for( i = 0; i < fSourceSpans.GetCount(); i++ )
spanReorderTable.Append( i );
// Do a nice, if naiive, sort by material (hehe by the pointers, no less)
for( i = 0; i < fSourceSpans.GetCount() - 1; i++ )
{
for( j = i + 1, idx = i; j < fSourceSpans.GetCount(); j++ )
{
if( ICompareSpans( fSourceSpans[ j ], fSourceSpans[ idx ] ) < 0 )
idx = j;
}
// Swap idx with i, so we get the smallest pointer on top
if( i != idx )
{
// Swap both the source span and our internal span
tmpSpan = fSourceSpans[ i ];
fSourceSpans[ i ] = fSourceSpans[ idx ];
fSourceSpans[ idx ] = tmpSpan;
fSourceSpans[ i ]->fSpanRefIndex = i;
fSourceSpans[ idx ]->fSpanRefIndex = idx;
tmpSpanPtr = fSpans[ i ];
fSpans[ i ] = fSpans[ idx ];
fSpans[ idx ] = tmpSpanPtr;
// Also swap the entries in the reorder table
tmpIdx = spanReorderTable[ i ];
spanReorderTable[ i ] = spanReorderTable[ idx ];
spanReorderTable[ idx ] = tmpIdx;
}
// Next!
}
/// Problem: our reorder table is inversed(y->x instead of x->y). Either we search for numbers,
/// or we just flip it first...
spanInverseTable.SetCountAndZero( spanReorderTable.GetCount() );
for( i = 0; i < spanReorderTable.GetCount(); i++ )
spanInverseTable[ spanReorderTable[ i ] ] = i;
/// Now update our span xlate table
for( i = 0; i < fDIIndices.GetCount(); i++ )
{
if( !fDIIndices[ i ]->IsMatrixOnly() )
{
for( j = 0; j < fDIIndices[ i ]->GetCount(); j++ )
{
idx = (*fDIIndices[ i ])[ j ];
(*fDIIndices[ i ])[ j ] = spanInverseTable[ idx ];
}
}
}
/// Use our pointer array to rebuild the icicle array (UUUUGLY)
hsTArray<plIcicle> tempIcicles;
plIcicle *newIcicle;
tempIcicles.SetCount( fIcicles.GetCount() );
for( i = 0, newIcicle = tempIcicles.AcquireArray();
i < fSpans.GetCount(); i++ )
{
*newIcicle = *( (plIcicle *)fSpans[ i ] );
fSpans[ i ] = newIcicle;
newIcicle++;
}
/// Swap the two arrays out. This will basically swap the actual memory blocks, so be careful...
fIcicles.Swap( tempIcicles );
tempIcicles.Reset();
}
//// ICompareSpans ///////////////////////////////////////////////////////////
// Sorting function for ISortSpans(). Kinda like strcmp(): returns -1 if
// span1 < span2, 1 if span1 > span2, 0 if "equal".
short plDrawableSpans::ICompareSpans( plGeometrySpan *span1, plGeometrySpan *span2 )
{
hsBool b1, b2;
int i, j, numLayers;
plBitmap *t1, *t2;
/// Quick check--identical materials are easy to compare :)
if( span1->fMaterial == span2->fMaterial )
return 0;
/// Compare features from most to least important...
// Any decal span should come after a non-decal
if( span1->fDecalLevel < span2->fDecalLevel )
return -1;
if( span1->fDecalLevel > span2->fDecalLevel )
return 1;
// Ok, they're equal decal-wise, so find something else to judge on
// Most important: is one of the materials an alpha blend? (if so, gotta
// put at end, so it's "bigger")
if( span1->fMaterial->GetNumLayers() > 0 &&
( span1->fMaterial->GetLayer( 0 )->GetState().fBlendFlags & hsGMatState::kBlendMask ) != 0 )
b1 = true;
else
b1 = false;
if( span2->fMaterial->GetNumLayers() > 0 &&
( span2->fMaterial->GetLayer( 0 )->GetState().fBlendFlags & hsGMatState::kBlendMask ) != 0 )
b2 = true;
else
b2 = false;
if( b1 != b2 )
return( b1 ? 1 : -1 );
// Next is texture (name). We do this kinda like strings: compare the first layer's
// textures and go upwards, so that we group materials together starting with the
// base layer's texture and going upwards
numLayers = span1->fMaterial->GetNumLayers();
if( span2->fMaterial->GetNumLayers() < numLayers )
numLayers = span2->fMaterial->GetNumLayers();
for( i = 0; i < numLayers; i++ )
{
t1 = span1->fMaterial->GetLayer( i )->GetTexture();
t2 = span2->fMaterial->GetLayer( i )->GetTexture();
if( t1 != nil && t2 == nil )
return 1;
else if( t1 == nil && t2 != nil )
return -1;
else if( t1 == nil && t2 == nil )
break; // Textures equal up to here--keep going with rest of tests
if( t1->GetKeyName() != nil && t2->GetKeyName() != nil )
{
j = stricmp( t1->GetKeyName(), t2->GetKeyName() );
if( j != 0 )
return (short)j;
}
}
// Finally, by material itself.
if( span1->fMaterial->GetKeyName() != nil && span2->fMaterial->GetKeyName() != nil )
{
j = stricmp( span1->fMaterial->GetKeyName(), span2->fMaterial->GetKeyName() );
if( j != 0 )
return (short)j;
}
if( span1->fLocalToWorld.fFlags != span2->fLocalToWorld.fFlags )
{
if( span1->fLocalToWorld.fFlags )
return -1;
else
return 1;
}
/// Equal in our book...
return 0;
}

View File

@ -0,0 +1,132 @@
/*==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 "plDynaBulletMgr.h"
#include "plDynaDecal.h"
#include "../plMessage/plBulletMsg.h"
#include "plCutter.h"
#include "plgDispatch.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "hsTimer.h"
#include "../pnMessage/plRefMsg.h"
#include "hsFastMath.h"
#include "../plMath/plRandom.h"
static plRandom sRand;
int plDynaBulletMgr::INewDecal()
{
int idx = fDecals.GetCount();
fDecals.Append(TRACKED_NEW plDynaSplot());
return idx;
}
plDynaBulletMgr::plDynaBulletMgr()
{
}
plDynaBulletMgr::~plDynaBulletMgr()
{
}
void plDynaBulletMgr::Read(hsStream* stream, hsResMgr* mgr)
{
plDynaDecalMgr::Read(stream, mgr);
plgDispatch::Dispatch()->RegisterForExactType(plBulletMsg::Index(), GetKey());
}
void plDynaBulletMgr::Write(hsStream* stream, hsResMgr* mgr)
{
plDynaDecalMgr::Write(stream, mgr);
}
hsBool plDynaBulletMgr::IHandleEnableMsg(const plDynaDecalEnableMsg* enaMsg)
{
return true;
}
hsBool plDynaBulletMgr::IHandleShot(plBulletMsg* bull)
{
hsVector3 up = IRandomUp(bull->Dir());
hsPoint3 pos = bull->From() + bull->Dir() * (bull->Range() * 0.5f);
fCutter->SetLength(hsVector3(bull->Radius() * fScale.fX, bull->Radius() * fScale.fY, bull->Range()));
fCutter->Set(pos, up, -bull->Dir());
plDynaDecalInfo& info = IGetDecalInfo(UInt32(this), GetKey());
if( bull->PartyTime() > 0 )
fPartyTime = bull->PartyTime();
double secs = hsTimer::GetSysSeconds();
if( ICutoutTargets(secs) )
info.fLastTime = secs;
return true;
}
hsBool plDynaBulletMgr::MsgReceive(plMessage* msg)
{
plBulletMsg* bullMsg = plBulletMsg::ConvertNoRef(msg);
if( bullMsg )
{
if( bullMsg->Shot() )
{
return IHandleShot(bullMsg);
}
return true;
}
return plDynaDecalMgr::MsgReceive(msg);
}

View File

@ -0,0 +1,73 @@
/*==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 plDynaBulletMgr_inc
#define plDynaBulletMgr_inc
#include "plDynaDecalMgr.h"
class plBulletMsg;
class plDynaBulletMgr : public plDynaDecalMgr
{
public:
protected:
virtual hsBool IHandleEnableMsg(const plDynaDecalEnableMsg* enaMsg);
virtual int INewDecal();
virtual hsBool IHandleShot(plBulletMsg* bull);
public:
plDynaBulletMgr();
virtual ~plDynaBulletMgr();
CLASSNAME_REGISTER( plDynaBulletMgr );
GETINTERFACE_ANY( plDynaBulletMgr, plDynaDecalMgr );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
#endif // plDynaBulletMgr_inc

View File

@ -0,0 +1,386 @@
/*==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 "plDynaDecal.h"
#include "plAuxSpan.h"
hsBool plDynaSplot::Age(double t, hsScalar ramp, hsScalar decay, hsScalar life)
{
hsScalar age = hsScalar(t - fBirth);
if( age >= life )
return true;
int n = fNumVerts;
if( !n )
return true;
hsScalar atten = fInitAtten;
if( age < ramp )
{
atten *= age / ramp;
fFlags |= kFresh;
}
else if( age > decay )
{
atten *= (life - age) / (life - decay);
fFlags |= kFresh;
}
else if( fFlags & kFresh )
{
fFlags &= ~kFresh;
}
else
{
return false;
}
hsPoint3* origUVW = &fAuxSpan->fOrigUVW[fStartVtx];
if( fFlags & kAttenColor )
{
plDecalVtxFormat* vtx = fVtxBase;
while( n-- )
{
UInt32 diff = UInt32(origUVW->fZ * atten * 255.99f);
vtx->fDiffuse = 0xff000000
| (diff << 16)
| (diff << 8)
| diff;
vtx++;
origUVW++;
}
}
else
if( fAuxSpan->fFlags & plAuxSpan::kRTLit )
{
const int stride = sizeof(plDecalVtxFormat);
hsScalar* sPtr = &origUVW->fZ;
unsigned char* alpha = (unsigned char*)&fVtxBase->fDiffuse;
alpha += 3;
while( n-- )
{
hsScalar initOpac = *sPtr;
*alpha = unsigned char(initOpac * atten * 255.99f);
alpha += stride;
sPtr += 3;
}
}
else
{
hsScalar* sPtr = &origUVW->fZ;
char* oPtr = (char*)&fVtxBase->fUVW[1].fX;
const int stride = sizeof(plDecalVtxFormat);
while( n-- )
{
(*(hsScalar*)oPtr) = *sPtr * atten;
oPtr += stride;
sPtr += 3;
}
}
return false;
}
hsBool plDynaRipple::Age(double t, hsScalar ramp, hsScalar decay, hsScalar life)
{
hsScalar age = hsScalar(t - fBirth);
if( age >= life )
return true;
int n = fNumVerts;
if( !n )
return true;
hsScalar atten = fInitAtten;
if( age < ramp )
{
atten *= age / ramp;
}
else if( age > decay )
{
atten *= (life - age) / (life - decay);
}
hsScalar scaleU = fC1U / (age*fC2U + 1.f);
hsScalar scaleV = fC1V / (age*fC2V + 1.f);
hsPoint3* origUVW = &fAuxSpan->fOrigUVW[fStartVtx];
if( fFlags & kAttenColor )
{
plDecalVtxFormat* vtx = fVtxBase;
while( n-- )
{
UInt32 diff = UInt32(origUVW->fZ * atten * 255.99f);
vtx->fDiffuse = 0xff000000
| (diff << 16)
| (diff << 8)
| diff;
vtx->fUVW[0].fX = (origUVW->fX - 0.5f) * scaleU + 0.5f;
vtx->fUVW[0].fY = (origUVW->fY - 0.5f) * scaleV + 0.5f;
vtx++;
origUVW++;
}
}
else
if( fAuxSpan->fFlags & plAuxSpan::kRTLit )
{
plDecalVtxFormat* vtx = fVtxBase;
while( n-- )
{
unsigned char* alpha = ((unsigned char*)&vtx->fDiffuse) + 3;
*alpha = unsigned char(origUVW->fZ * atten * 255.99f);
vtx->fUVW[0].fX = (origUVW->fX - 0.5f) * scaleU + 0.5f;
vtx->fUVW[0].fY = (origUVW->fY - 0.5f) * scaleV + 0.5f;
vtx++;
origUVW++;
}
}
else
{
plDecalVtxFormat* vtx = fVtxBase;
while( n-- )
{
vtx->fUVW[0].fX = (origUVW->fX - 0.5f) * scaleU + 0.5f;
vtx->fUVW[0].fY = (origUVW->fY - 0.5f) * scaleV + 0.5f;
vtx->fUVW[1].fX = origUVW->fZ * atten;
vtx++;
origUVW++;
}
}
fFlags &= ~kFresh;
return false;
}
hsBool plDynaWake::Age(double t, hsScalar ramp, hsScalar decay, hsScalar life)
{
hsScalar age = hsScalar(t - fBirth);
if( age >= life )
return true;
int n = fNumVerts;
if( !n )
return true;
hsScalar atten = fInitAtten;
if( age < ramp )
{
atten *= age / ramp;
}
else if( age > decay )
{
atten *= (life - age) / (life - decay);
}
hsScalar scaleU = fC1U / (age*fC2U + 1.f);
hsScalar scaleV = fC1V / (age*fC2V + 1.f);
hsPoint3* origUVW = &fAuxSpan->fOrigUVW[fStartVtx];
if( fFlags & kAttenColor )
{
plDecalVtxFormat* vtx = fVtxBase;
while( n-- )
{
UInt32 diff = UInt32(origUVW->fZ * atten * 255.99f);
vtx->fDiffuse = 0xff000000
| (diff << 16)
| (diff << 8)
| diff;
vtx->fUVW[0].fX = (origUVW->fX - 0.5f) * scaleU + 0.5f;
vtx->fUVW[0].fY = origUVW->fY * scaleV;
vtx++;
origUVW++;
}
}
else
if( fAuxSpan->fFlags & plAuxSpan::kRTLit )
{
plDecalVtxFormat* vtx = fVtxBase;
while( n-- )
{
unsigned char* alpha = ((unsigned char*)&vtx->fDiffuse) + 3;
*alpha = unsigned char(origUVW->fZ * atten * 255.99f);
vtx->fUVW[0].fX = (origUVW->fX - 0.5f) * scaleU + 0.5f;
vtx->fUVW[0].fY = origUVW->fY * scaleV;
vtx++;
origUVW++;
}
}
else
{
plDecalVtxFormat* vtx = fVtxBase;
while( n-- )
{
vtx->fUVW[0].fX = (origUVW->fX - 0.5f) * scaleU + 0.5f;
vtx->fUVW[0].fY = origUVW->fY * scaleV;
vtx->fUVW[1].fX = origUVW->fZ * atten;
vtx++;
origUVW++;
}
}
fFlags &= ~kFresh;
return false;
}
hsBool plDynaWave::Age(double t, hsScalar ramp, hsScalar decay, hsScalar life)
{
hsScalar age = hsScalar(t - fBirth);
if( age >= life )
return true;
int n = fNumVerts;
if( !n )
return true;
hsScalar atten = fInitAtten;
if( age < ramp )
{
atten *= age / ramp;
}
else if( age > decay )
{
atten *= (life - age) / (life - decay);
}
hsScalar scale = 1.f + life * fScrollRate;
hsScalar scroll = -fScrollRate * age;
hsPoint3* origUVW = &fAuxSpan->fOrigUVW[fStartVtx];
if( fFlags & kAttenColor )
{
plDecalVtxFormat* vtx = fVtxBase;
while( n-- )
{
UInt32 diff = UInt32(origUVW->fZ * atten * 255.99f);
vtx->fDiffuse = 0xff000000
| (diff << 16)
| (diff << 8)
| diff;
vtx->fUVW[0].fX = origUVW->fX;
vtx->fUVW[0].fY = origUVW->fY * scale + scroll;
vtx++;
origUVW++;
}
}
else
if( fAuxSpan->fFlags & plAuxSpan::kRTLit )
{
plDecalVtxFormat* vtx = fVtxBase;
while( n-- )
{
unsigned char* alpha = ((unsigned char*)&vtx->fDiffuse) + 3;
*alpha = unsigned char(origUVW->fZ * atten * 255.99f);
vtx->fUVW[0].fX = origUVW->fX;
vtx->fUVW[0].fY = origUVW->fY * scale + scroll;
vtx++;
origUVW++;
}
}
else
{
plDecalVtxFormat* vtx = fVtxBase;
while( n-- )
{
vtx->fUVW[0].fX = origUVW->fX;
vtx->fUVW[0].fY = origUVW->fY * scale + scroll;
vtx->fUVW[1].fX = origUVW->fZ * atten;
vtx++;
origUVW++;
}
}
fFlags &= ~kFresh;
return false;
}
hsBool plDynaRippleVS::Age(double t, hsScalar ramp, hsScalar decay, hsScalar life)
{
hsScalar age = hsScalar(t - fBirth);
if( age >= life )
return true;
int n = fNumVerts;
if( !n )
return true;
fFlags &= ~kFresh;
return false;
}

View File

@ -0,0 +1,161 @@
/*==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 plDynaDecal_inc
#define plDynaDecal_inc
#include "hsGeometry3.h"
class plAuxSpan;
class plDynaDecalBin;
class plDecalVtxFormat
{
public:
hsPoint3 fPos;
hsVector3 fNorm;
UInt32 fDiffuse;
UInt32 fSpecular; // Not used anywhere, carried around everywhere.
hsPoint3 fUVW[2];
};
// UVW[0] is the currently used UVW.
// UVW[1] is for the alpha hack (when necessary).
const UInt8 kDecalVtxFormat = 0x2; // Two UVW's, otherwise vanilla.
class plDynaDecal
{
public:
enum
{
kFresh = 0x1,
kAttenColor = 0x2,
kVertexShader = 0x4
};
protected:
// StartVtx and StartIdx are relative to the start of the data
// owned by this decal's span, not relative to the start of the
// underlying buffers.
UInt16 fStartVtx;
UInt16 fNumVerts;
UInt16 fStartIdx;
UInt16 fNumIdx;
double fBirth;
hsScalar fInitAtten;
hsBool fFlags;
plDecalVtxFormat* fVtxBase; // Safe pointer, the buffer data will outlive this decal
plAuxSpan* fAuxSpan;
friend class plDynaDecalMgr;
public:
virtual hsBool Age(double t, hsScalar ramp, hsScalar decay, hsScalar life) = 0;
};
// No expansion
class plDynaSplot : public plDynaDecal
{
protected:
public:
virtual hsBool Age(double t, hsScalar ramp, hsScalar decay, hsScalar life);
};
// Expands radially from center
class plDynaRipple : public plDynaDecal
{
public:
virtual hsBool Age(double t, hsScalar ramp, hsScalar decay, hsScalar life);
hsScalar fC1U;
hsScalar fC2U;
hsScalar fC1V;
hsScalar fC2V;
};
// Expands in V from top (V=0), expands in U from center (U=0.5)
class plDynaWake : public plDynaDecal
{
public:
virtual hsBool Age(double t, hsScalar ramp, hsScalar decay, hsScalar life);
hsScalar fC1U;
hsScalar fC2U;
hsScalar fC1V;
hsScalar fC2V;
};
// Scrolls in V, no change in U
class plDynaWave : public plDynaDecal
{
public:
virtual hsBool Age(double t, hsScalar ramp, hsScalar decay, hsScalar life);
hsScalar fScrollRate;
};
// About the same as a DynaRipple, but implemented with vertex/pixel shaders.
// Only useful with plWaveSet.
class plDynaRippleVS : public plDynaRipple
{
public:
virtual hsBool Age(double t, hsScalar ramp, hsScalar decay, hsScalar life);
};
#endif // plDynaDecal_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,292 @@
/*==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 plDynaDecalMgr_inc
#define plDynaDecalMgr_inc
#include "../pnNetCommon/plSynchedObject.h"
#include "hsTemplates.h"
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "hsStlUtils.h"
class plParticleSystem;
class plPrintShape;
class plDynaDecalEnableMsg;
class plDynaDecal;
class plDrawableSpans;
class plGBufferGroup;
class plIcicle;
class hsGMaterial;
class plBitmap;
class plMipmap;
class plSceneObject;
class plArmatureMod;
class hsStream;
class hsResMgr;
class plMessage;
class plCutter;
class plCutoutPoly;
class plFlatGridMesh;
class plDrawVisList;
class plRenderLevel;
class plAccessSpan;
class plAuxSpan;
class plDecalVtxFormat;
class plPipeline;
// plDynaDecalInfo - information we store specific to what we've
// done about a specific avatar part or scene object.
class plDynaDecalInfo
{
public:
enum
{
kNone = 0x0,
kImmersed = 0x1,
kActive = 0x2
};
plKey fKey;
double fLastTime;
hsPoint3 fLastPos;
double fWetTime;
hsScalar fWetLength;
UInt32 fFlags;
plDynaDecalInfo& Init(const plKey& key);
};
typedef std::map< UInt32, plDynaDecalInfo, std::less<UInt32> > plDynaDecalMap;
// plDynaDecalMgr
// Primary responsibilities:
// Allocation of adequate buffer space in plGBufferGroup
// Setup of decal materials
// Allocation of auxSpans
// Receive lists of polys, translate into drawable tris
// Create DynaDecals and destroy them when they expire.
// Assign vertex and index subsets to DynaDecals
// Call Update on DynaDecals
class plDynaDecalMgr : public plSynchedObject
{
public:
enum DynaRefType
{
kRefMatPreShade,
kRefMatRTShade,
kRefTarget,
kRefAvatar,
kRefPartyObject,
kRefParticles,
kRefNextAvailable = 10
};
protected:
static hsBool fDisableAccumulate;
static hsBool fDisableUpdate;
plDynaDecalMap fDecalMap;
hsTArray<plDynaDecal*> fDecals;
hsTArray<plGBufferGroup*> fGroups;
plCutter* fCutter;
hsTArray<plAuxSpan*> fAuxSpans;
hsGMaterial* fMatPreShade;
hsGMaterial* fMatRTShade;
hsTArray<plSceneObject*> fTargets;
hsTArray<plSceneObject*> fPartyObjects;
hsTArray<plParticleSystem*> fParticles;
hsScalar fPartyTime;
UInt16 fMaxNumVerts;
UInt16 fMaxNumIdx;
UInt32 fWaitOnEnable;
hsScalar fWetLength;
hsScalar fRampEnd;
hsScalar fDecayStart;
hsScalar fLifeSpan;
hsScalar fIntensity;
hsScalar fGridSizeU;
hsScalar fGridSizeV;
hsVector3 fScale;
// some temp calculated stuff
hsScalar fInitAtten;
// These 4 are in normalized units [0..1], not feet.
hsScalar fMinDepth;
hsScalar fMinDepthRange;
hsScalar fMaxDepth;
hsScalar fMaxDepthRange;
hsTArray<UInt32> fPartIDs;
hsTArray<plKey> fNotifies;
const plPrintShape* IGetPrintShape(const plKey& objKey) const;
const plPrintShape* IGetPrintShape(plArmatureMod* avMod, UInt32 id) const;
virtual hsBool IHandleEnableMsg(const plDynaDecalEnableMsg* enaMsg);
void INotifyActive(plDynaDecalInfo& info, const plKey& armKey, UInt32 id) const;
void INotifyInactive(plDynaDecalInfo& info, const plKey& armKey, UInt32 id) const;
hsBool IWetParts(const plDynaDecalEnableMsg* enaMsg);
hsBool IWetPart(UInt32 id, const plDynaDecalEnableMsg* enaMsg);
void IWetInfo(plDynaDecalInfo& info, const plDynaDecalEnableMsg* enaMsg) const;
hsScalar IHowWet(plDynaDecalInfo& info, double t) const;
plDynaDecalInfo& IGetDecalInfo(UInt32 id, const plKey& key);
void IRemoveDecalInfo(UInt32 id);
void IRemoveDecalInfos(const plKey& key);
hsGMaterial* ISetAuxMaterial(plAuxSpan* aux, hsGMaterial* mat, hsBool rtLit);
void IAllocAuxSpan(plAuxSpan* aux, UInt32 maxNumVerts, UInt32 maxNumIdx);
plAuxSpan* IGetAuxSpan(plDrawableSpans* targ, int iSpan, hsGMaterial* mat, UInt16 numVerts, UInt16 numIdx);
hsBool IMakeAuxRefs(plPipeline* pipe);
UInt16* IGetBaseIdxPtr(const plAuxSpan* auxSpan) const;
plDecalVtxFormat* IGetBaseVtxPtr(const plAuxSpan* auxSpan) const;
virtual int INewDecal() = 0;
plDynaDecal* IInitDecal(plAuxSpan* aux, double t, UInt16 numVerts, UInt16 numIdx);
void IKillDecal(int i);
void IUpdateDecals(double t);
void ICountIncoming(hsTArray<plCutoutPoly>& src, UInt16& numVerts, UInt16& numIdx) const;
hsBool IConvertPolysColor(plAuxSpan* auxSpan, plDynaDecal* decal, hsTArray<plCutoutPoly>& src);
hsBool IConvertPolysAlpha(plAuxSpan* auxSpan, plDynaDecal* decal, hsTArray<plCutoutPoly>& src);
hsBool IConvertPolysVS(plAuxSpan* auxSpan, plDynaDecal* decal, hsTArray<plCutoutPoly>& src);
hsBool IConvertPolys(plAuxSpan* auxSpan, plDynaDecal* decal, hsTArray<plCutoutPoly>& src);
hsBool IProcessPolys(plDrawableSpans* targ, int iSpan, double t, hsTArray<plCutoutPoly>& src);
hsBool IHitTestPolys(hsTArray<plCutoutPoly>& src) const;
hsBool IProcessGrid(plDrawableSpans* targ, int iSpan, hsGMaterial* mat, double t, const plFlatGridMesh& grid);
hsBool IConvertFlatGrid(plAuxSpan* auxSpan, plDynaDecal* decal, const plFlatGridMesh& grid) const;
hsBool ICutoutGrid(plDrawableSpans* drawable, int iSpan, hsGMaterial* mat, double secs);
hsBool IHitTestFlatGrid(const plFlatGridMesh& grid) const;
hsBool ICutoutList(hsTArray<plDrawVisList>& drawVis, double secs);
hsBool ICutoutObject(plSceneObject* so, double secs);
hsBool ICutoutTargets(double secs);
void ISetDepthFalloff(); // Sets from current cutter settings.
virtual void ICutoutCallback(const hsTArray<plCutoutPoly>& cutouts, hsBool hasWaterHeight=false, hsScalar waterHeight=0.f);
hsGMaterial* IConvertToEnvMap(hsGMaterial* mat, plBitmap* envMap);
virtual void SetKey(plKey k);
hsVector3 IReflectDir(hsVector3 dir) const;
hsMatrix44 IL2WFromHit(hsPoint3 pos, hsVector3 dir) const;
hsVector3 IRandomUp(hsVector3 dir) const;
void IGetParticles();
public:
plDynaDecalMgr();
virtual ~plDynaDecalMgr();
CLASSNAME_REGISTER( plDynaDecalMgr );
GETINTERFACE_ANY( plDynaDecalMgr, plSynchedObject );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
// This is public, because you need to call it after creating
// a DynaDecalMgr on the fly. It's normally called on Read().
void InitAuxSpans();
void SetScale(const hsVector3& v) { fScale = v; }
const hsVector3& GetScale() const { return fScale; }
void SetWaitOnEnable(hsBool on) { fWaitOnEnable = on; }
hsBool GetWaitOnEnable() const { return fWaitOnEnable; }
void SetWetLength(hsScalar f) { fWetLength = f; }
void SetRampEnd(hsScalar f) { fRampEnd = f; }
void SetDecayStart(hsScalar f) { fDecayStart = f; }
void SetLifeSpan(hsScalar f) { fLifeSpan = f; }
void SetIntensity(hsScalar f) { fIntensity = f; }
hsScalar GetWetLength() const { return fWetLength; }
hsScalar GetRampEnd() const { return fRampEnd; }
hsScalar GetDecayStart() const { return fDecayStart; }
hsScalar GetLifeSpan() const { return fLifeSpan; }
hsScalar GetIntensity() const { return fIntensity; }
void SetPartyTime(hsScalar secs) { fPartyTime = secs; } // Duration of particle spewage
hsScalar GetPartyTime() const { return fPartyTime; }
void ConvertToEnvMap(plBitmap* envMap);
const plMipmap* GetMipmap() const;
void AddNotify(const plKey& k) { fNotifies.Append(k); }
UInt32 GetNumNotifies() const { return fNotifies.GetCount(); }
const plKey& GetNotify(int i) const { return fNotifies[i]; }
static void SetDisableAccumulate(hsBool on) { fDisableAccumulate = on; }
static void ToggleDisableAccumulate() { fDisableAccumulate = !fDisableAccumulate; }
static hsBool GetDisableAccumulate() { return fDisableAccumulate; }
static void SetDisableUpdate(hsBool on) { fDisableUpdate = on; }
static void ToggleDisableUpdate() { fDisableUpdate = !fDisableUpdate; }
static hsBool GetDisableUpdate() { return fDisableUpdate; }
};
#endif // plDynaDecalMgr_inc

View File

@ -0,0 +1,171 @@
/*==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 "plDynaFootMgr.h"
#include "plDynaDecal.h"
#include "plCutter.h"
#include "plPrintShape.h"
#include "plgDispatch.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "hsTimer.h"
#include "../plMessage/plDynaDecalEnableMsg.h"
#include "../plMessage/plAvatarFootMsg.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plMath/plRandom.h"
static plRandom sRand;
static const UInt32 kNumPrintIDs = 2;
static const UInt32 kPrintIDs[kNumPrintIDs] =
{
plAvBrainHuman::RFootPrint,
plAvBrainHuman::LFootPrint
};
int plDynaFootMgr::INewDecal()
{
int idx = fDecals.GetCount();
fDecals.Append(TRACKED_NEW plDynaSplot());
return idx;
}
plDynaFootMgr::plDynaFootMgr()
{
fPartIDs.SetCount(kNumPrintIDs);
int i;
for( i = 0; i < kNumPrintIDs; i++ )
fPartIDs[i] = kPrintIDs[i];
}
plDynaFootMgr::~plDynaFootMgr()
{
}
void plDynaFootMgr::Read(hsStream* stream, hsResMgr* mgr)
{
plDynaDecalMgr::Read(stream, mgr);
plgDispatch::Dispatch()->RegisterForExactType(plAvatarFootMsg::Index(), GetKey());
}
void plDynaFootMgr::Write(hsStream* stream, hsResMgr* mgr)
{
plDynaDecalMgr::Write(stream, mgr);
}
hsBool plDynaFootMgr::MsgReceive(plMessage* msg)
{
plAvatarFootMsg* footMsg = plAvatarFootMsg::ConvertNoRef(msg);
if( footMsg )
{
UInt32 id = footMsg->IsLeft() ? plAvBrainHuman::LFootPrint : plAvBrainHuman::RFootPrint;
plArmatureMod* armMod = footMsg->GetArmature();
const plPrintShape* shape = IGetPrintShape(armMod, id);
if( shape )
{
plDynaDecalInfo& info = IGetDecalInfo(UInt32(shape), shape->GetKey());
if( IPrintFromShape(shape, footMsg->IsLeft()) )
{
INotifyActive(info, armMod->GetKey(), id);
}
else
{
INotifyInactive(info, armMod->GetKey(), id);
}
}
return true;
}
return plDynaDecalMgr::MsgReceive(msg);
}
hsBool plDynaFootMgr::IPrintFromShape(const plPrintShape* shape, hsBool flip)
{
hsBool retVal = false;
if( shape )
{
plDynaDecalInfo& info = IGetDecalInfo(UInt32(shape), shape->GetKey());
double secs = hsTimer::GetSysSeconds();
hsScalar wetness = IHowWet(info, secs);
fInitAtten = wetness;
if( wetness <= 0 )
return true;
hsMatrix44 shapeL2W = shape->GetOwner()->GetLocalToWorld();
hsPoint3 newPos = shapeL2W.GetTranslate();
hsVector3 newDir = shapeL2W.GetAxis(hsMatrix44::kView);
hsVector3 newUp(0.f, 0.f, 1.f);
hsVector3 size(shape->GetWidth() * fScale.fX, shape->GetLength() * fScale.fY, shape->GetHeight() * fScale.fZ * 2.f);
fCutter->SetLength(size);
fCutter->Set(newPos, newDir, newUp, flip);
// Should this be moved inside the if( ICutout() ) clause? I think so. Probably doesn't
// matter for foot prints, but it seems more correct, since fLastPos/fLastTime is the
// last time and position we actually dropped a print, not tried to.
info.fLastPos = newPos;
info.fLastTime = secs;
if( ICutoutTargets(secs) )
{
retVal = true;
}
}
return retVal;
}

View File

@ -0,0 +1,70 @@
/*==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 plDynaFootMgr_inc
#define plDynaFootMgr_inc
#include "plDynaDecalMgr.h"
class plAvatarFootMsg;
class plDynaFootMgr : public plDynaDecalMgr
{
protected:
virtual hsBool IPrintFromShape(const plPrintShape* shape, hsBool flip);
virtual int INewDecal();
public:
plDynaFootMgr();
virtual ~plDynaFootMgr();
CLASSNAME_REGISTER( plDynaFootMgr );
GETINTERFACE_ANY( plDynaFootMgr, plDynaDecalMgr );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
#endif // plDynaFootMgr_inc

View File

@ -0,0 +1,113 @@
/*==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 "plDynaPuddleMgr.h"
#include "plPrintShape.h"
#include "plgDispatch.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "../plMessage/plAvatarFootMsg.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plArmatureMod.h"
static const UInt32 kNumPrintIDs = 2;
static const UInt32 kPrintIDs[kNumPrintIDs] =
{
plAvBrainHuman::RFootPrint,
plAvBrainHuman::LFootPrint
};
plDynaPuddleMgr::plDynaPuddleMgr()
{
fPartIDs.SetCount(kNumPrintIDs);
int i;
for( i = 0; i < kNumPrintIDs; i++ )
fPartIDs[i] = kPrintIDs[i];
}
plDynaPuddleMgr::~plDynaPuddleMgr()
{
}
void plDynaPuddleMgr::Read(hsStream* stream, hsResMgr* mgr)
{
plDynaRippleMgr::Read(stream, mgr);
plgDispatch::Dispatch()->RegisterForExactType(plAvatarFootMsg::Index(), GetKey());
}
hsBool plDynaPuddleMgr::MsgReceive(plMessage* msg)
{
plAvatarFootMsg* footMsg = plAvatarFootMsg::ConvertNoRef(msg);
if( footMsg )
{
int i;
for( i = 0; i < fPartIDs.GetCount(); i++ )
{
plArmatureMod* armMod = footMsg->GetArmature();
const plPrintShape* shape = IGetPrintShape(armMod, fPartIDs[i]);
if( shape )
{
plDynaDecalInfo& info = IGetDecalInfo(UInt32(shape), shape->GetKey());
if( IRippleFromShape(shape, true) )
{
INotifyActive(info, armMod->GetKey(), fPartIDs[i]);
}
else
{
INotifyInactive(info, armMod->GetKey(), fPartIDs[i]);
}
}
}
return true;
}
return plDynaRippleMgr::MsgReceive(msg);
}

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 plDynaPuddleMgr_inc
#define plDynaPuddleMgr_inc
#include "plDynaRippleMgr.h"
class plKey;
class plDynaPuddleMgr : public plDynaRippleMgr
{
protected:
public:
plDynaPuddleMgr();
virtual ~plDynaPuddleMgr();
CLASSNAME_REGISTER( plDynaPuddleMgr );
GETINTERFACE_ANY( plDynaPuddleMgr, plDynaRippleMgr );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
#endif // plDynaPuddleMgr_inc

View File

@ -0,0 +1,249 @@
/*==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 "plDynaRippleMgr.h"
#include "plDynaDecal.h"
#include "plPrintShape.h"
#include "plCutter.h"
#include "plgDispatch.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "hsTimer.h"
#include "../plMessage/plDynaDecalEnableMsg.h"
#include "../plMessage/plRippleShapeMsg.h"
#include "../plMessage/plAvatarMsg.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plMath/plRandom.h"
static plRandom sRand;
#include "plTweak.h"
static const UInt32 kNumPrintIDs = 5;
static const UInt32 kPrintIDs[kNumPrintIDs] =
{
plAvBrainHuman::TrunkPrint,
plAvBrainHuman::LHandPrint,
plAvBrainHuman::RHandPrint,
plAvBrainHuman::LFootPrint,
plAvBrainHuman::RFootPrint
};
int plDynaRippleMgr::INewDecal()
{
int idx = fDecals.GetCount();
#if 1
plDynaRipple* rip = TRACKED_NEW plDynaRipple();
rip->fC1U = fInitUVW.fX;
rip->fC2U = (fInitUVW.fX - fFinalUVW.fX) / (fLifeSpan * fFinalUVW.fX);
rip->fC1V = fInitUVW.fY;
rip->fC2V = (fInitUVW.fY - fFinalUVW.fY) / (fLifeSpan * fFinalUVW.fY);
fDecals.Append(rip);
#else
plDynaWave* wave = TRACKED_NEW plDynaWave();
static hsScalar kDefScrollRate = 0.1f;
wave->fScrollRate = kDefScrollRate;
fDecals.Append(wave);
#endif
return idx;
}
plDynaRippleMgr::plDynaRippleMgr()
:
fInitUVW(1.f,1.f,1.f),
fFinalUVW(1.f,1.f,1.f)
{
fPartIDs.SetCount(kNumPrintIDs);
int i;
for( i = 0; i < kNumPrintIDs; i++ )
fPartIDs[i] = kPrintIDs[i];
}
plDynaRippleMgr::~plDynaRippleMgr()
{
}
void plDynaRippleMgr::Read(hsStream* stream, hsResMgr* mgr)
{
plDynaDecalMgr::Read(stream, mgr);
fInitUVW.Read(stream);
fFinalUVW.Read(stream);
// plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey()); // ###HACKTEST
// plgDispatch::Dispatch()->RegisterForExactType(plListenerMsg::Index(), GetKey()); // ###HACKTEST
plgDispatch::Dispatch()->RegisterForExactType(plArmatureUpdateMsg::Index(), GetKey());
}
void plDynaRippleMgr::Write(hsStream* stream, hsResMgr* mgr)
{
plDynaDecalMgr::Write(stream, mgr);
fInitUVW.Write(stream);
fFinalUVW.Write(stream);
}
hsBool plDynaRippleMgr::MsgReceive(plMessage* msg)
{
plArmatureUpdateMsg* armMsg = plArmatureUpdateMsg::ConvertNoRef(msg);
if( armMsg && !armMsg->IsInvis())
{
int i;
for( i = 0; i < fPartIDs.GetCount(); i++ )
{
const plPrintShape* shape = IGetPrintShape(armMsg->fArmature, fPartIDs[i]);
if( shape )
{
plDynaDecalInfo& info = IGetDecalInfo(UInt32(shape), shape->GetKey());
if( IRippleFromShape(shape, false) )
{
INotifyActive(info, armMsg->fArmature->GetKey(), fPartIDs[i]);
}
else
{
INotifyInactive(info, armMsg->fArmature->GetKey(), fPartIDs[i]);
}
}
}
return true;
}
plRippleShapeMsg* shapeMsg = plRippleShapeMsg::ConvertNoRef(msg);
if( shapeMsg )
{
const plPrintShape* shape = shapeMsg->GetShape();
if( shape )
{
// Note we don't care about the return value here, because we only send notifies
// for avatar based ripples.
IRippleFromShape(shape);
}
return true;
}
return plDynaDecalMgr::MsgReceive(msg);
}
hsBool plDynaRippleMgr::IRippleFromShape(const plPrintShape* shape, hsBool force)
{
if( !shape )
return false;
hsBool retVal = false;
plDynaDecalInfo& info = IGetDecalInfo(UInt32(shape), shape->GetKey());
const hsMatrix44& shapeL2W = shape->GetOwner()->GetLocalToWorld();
plConst(hsScalar) kMinDist(2.0f);
plConst(hsScalar) kMinTime(1.5f);
double t = hsTimer::GetSysSeconds();
hsScalar dt = hsScalar(t - info.fLastTime) * sRand.RandZeroToOne();
hsBool longEnough = (dt >= kMinTime);
hsBool farEnough = (hsVector3(&info.fLastPos, &shapeL2W.GetTranslate()).Magnitude() > kMinDist);
if( force || longEnough || farEnough )
{
hsPoint3 pos = shapeL2W.GetTranslate();
// We'll perturb the position a little so it doesn't look quite so regular,
// but we perturb it more if we're just standing still
hsVector3 randPert(sRand.RandMinusOneToOne(), sRand.RandMinusOneToOne(), 0);
randPert.Normalize();
if( !farEnough )
{
plConst(hsScalar) kRandPert = 0.5f;
randPert *= kRandPert;
}
else
{
plConst(hsScalar) kRandPert = 0.15f;
randPert *= kRandPert;
}
pos += randPert;
hsVector3 dir(0.f, 1.f, 0.f);
hsVector3 up(0.f, 0.f, 1.f);
plConst(hsScalar) kHeightScale = 1.f;
pos.fZ += (shape->GetHeight() * fScale.fZ * kHeightScale) * 0.25f;
hsScalar wid = hsMaximum(shape->GetWidth(), shape->GetLength());
hsVector3 size(wid * fScale.fX, wid * fScale.fY, shape->GetHeight() * fScale.fZ * kHeightScale);
fCutter->SetLength(size);
fCutter->Set(pos, dir, up);
hsBool hit = ICutoutTargets(t);
if( hit )
{
retVal = true;
}
else
{
retVal = false; // No-effect else just for break points.
}
// This isn't ideal, but it's a quick fix. ICutoutTargets returns true if the center
// of our cutter hit a face, which is what we want for notifies. But here we want to
// know whether any decal faces were generated at all. At some point, I'll have ICutoutTargets
// return a bit field, with separate bits for different interesting cases. But for now, we'll
// just keep track of when we last TRIED to throw down a decal. That'll get rid of the
// current problem of tons of decals piling up when you are standing next to a puddle,
// so the center isn't covered, so last time doesn't get set, and there's no throttle
// on how frequently we throw down decals.
info.fLastTime = t;
info.fLastPos = shapeL2W.GetTranslate();
}
return retVal;
}

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 plDynaRippleMgr_inc
#define plDynaRippleMgr_inc
#include "plDynaDecalMgr.h"
class plArmatureUpdateMsg;
class plDynaRippleMgr : public plDynaDecalMgr
{
protected:
hsVector3 fInitUVW;
hsVector3 fFinalUVW;
virtual hsBool IRippleFromShape(const plPrintShape* shape, hsBool force=false);
virtual int INewDecal();
public:
plDynaRippleMgr();
virtual ~plDynaRippleMgr();
CLASSNAME_REGISTER( plDynaRippleMgr );
GETINTERFACE_ANY( plDynaRippleMgr, plDynaDecalMgr );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
void SetUVWAnim(const hsVector3& init, const hsVector3& final) { fInitUVW = init; fFinalUVW = final; }
const hsVector3& GetInitUVW() const { return fInitUVW; }
const hsVector3& GetFinalUVW() const { return fFinalUVW; }
};
#endif // plDynaRippleMgr_inc

View File

@ -0,0 +1,238 @@
/*==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 "plDynaRippleVSMgr.h"
#include "plDynaDecal.h"
#include "plPrintShape.h"
#include "plCutter.h"
#include "plgDispatch.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "hsTimer.h"
#include "plWaveSetBase.h"
#include "plRipVSConsts.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayerInterface.h"
#include "../plMessage/plDynaDecalEnableMsg.h"
#include "../plMessage/plRippleShapeMsg.h"
#include "../plMessage/plAvatarMsg.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plMath/plRandom.h"
static plRandom sRand;
#include "plTweak.h"
int plDynaRippleVSMgr::INewDecal()
{
int idx = fDecals.GetCount();
plDynaRippleVS* rip = TRACKED_NEW plDynaRippleVS();
rip->fC1U = fInitUVW.fX;
rip->fC2U = (fInitUVW.fX - fFinalUVW.fX) / (fLifeSpan * fFinalUVW.fX);
rip->fC1V = fInitUVW.fY;
rip->fC2V = (fInitUVW.fY - fFinalUVW.fY) / (fLifeSpan * fFinalUVW.fY);
fDecals.Append(rip);
return idx;
}
plDynaRippleVSMgr::plDynaRippleVSMgr()
: fWaveSetBase(nil)
{
}
plDynaRippleVSMgr::~plDynaRippleVSMgr()
{
}
void plDynaRippleVSMgr::Read(hsStream* stream, hsResMgr* mgr)
{
plDynaRippleMgr::Read(stream, mgr);
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefWaveSetBase), plRefFlags::kPassiveRef);
}
void plDynaRippleVSMgr::Write(hsStream* stream, hsResMgr* mgr)
{
plDynaRippleMgr::Write(stream, mgr);
mgr->WriteKey(stream, fWaveSetBase);
}
hsBool plDynaRippleVSMgr::MsgReceive(plMessage* msg)
{
hsBool retVal = plDynaRippleMgr::MsgReceive(msg);
if( retVal )
return true;
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef(msg);
if( refMsg )
{
switch( refMsg->fType )
{
case kRefWaveSetBase:
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
fWaveSetBase = plWaveSetBase::ConvertNoRef(refMsg->GetRef());
else
fWaveSetBase = nil;
return true;
}
}
return false;
}
hsBool plDynaRippleVSMgr::ICheckRTMat()
{
if( !fMatRTShade )
return false;
if( !fWaveSetBase )
return false;
if( fMatRTShade->GetLayer(0)->GetVertexShader() )
return true;
plRipVSConsts ripConsts;
ripConsts.fC1U = fInitUVW.fX;
ripConsts.fC2U = (fInitUVW.fX - fFinalUVW.fX) / (fLifeSpan * fFinalUVW.fX);
ripConsts.fC1V = fInitUVW.fY;
ripConsts.fC2V = (fInitUVW.fY - fFinalUVW.fY) / (fLifeSpan * fFinalUVW.fY);
ripConsts.fInitAtten = fInitAtten;
ripConsts.fLife = fLifeSpan;
ripConsts.fDecay = fDecayStart;
ripConsts.fRamp = fRampEnd;
return fWaveSetBase->SetupRippleMat(fMatRTShade, ripConsts);
}
hsBool plDynaRippleVSMgr::IRippleFromShape(const plPrintShape* shape, hsBool force)
{
if( !ICheckRTMat() )
return false;
if( !shape )
return false;
hsBool retVal = false;
plDynaDecalInfo& info = IGetDecalInfo(UInt32(shape), shape->GetKey());
const hsMatrix44& shapeL2W = shape->GetOwner()->GetLocalToWorld();
plConst(hsScalar) kMinDist(2.0f);
plConst(hsScalar) kMinTime(1.5f);
double t = hsTimer::GetSysSeconds();
hsScalar dt = hsScalar(t - info.fLastTime) * sRand.RandZeroToOne();
hsBool longEnough = (dt >= kMinTime);
hsBool farEnough = (hsVector3(&info.fLastPos, &shapeL2W.GetTranslate()).Magnitude() > kMinDist);
if( force || longEnough || farEnough )
{
hsPoint3 pos = shapeL2W.GetTranslate();
// We'll perturb the position a little so it doesn't look quite so regular,
// but we perturb it more if we're just standing still
hsVector3 randPert(sRand.RandMinusOneToOne(), sRand.RandMinusOneToOne(), 0);
randPert.Normalize();
if( !farEnough )
{
plConst(hsScalar) kRandPert = 0.5f;
randPert *= kRandPert;
}
else
{
plConst(hsScalar) kRandPert = 0.15f;
randPert *= kRandPert;
}
pos += randPert;
// Are we potentially touching the water?
hsScalar waterHeight = fWaveSetBase->GetHeight();
if( (pos.fZ - fScale.fZ * shape->GetHeight() < waterHeight)
&&(pos.fZ + fScale.fZ * shape->GetHeight() > waterHeight) )
{
hsVector3 dir(fWaveSetBase->GetWindDir());
hsVector3 up(0.f, 0.f, 1.f);
hsScalar wid = hsMaximum(shape->GetWidth(), shape->GetLength());
plConst(hsScalar) kMaxWaterDepth(1000.f);
hsVector3 size(wid * fScale.fX, wid * fScale.fY, kMaxWaterDepth);
fCutter->SetLength(size);
fCutter->Set(pos, dir, up);
hsBool hit = ICutoutTargets(t);
if( hit )
{
info.fLastTime = t;
info.fLastPos = shapeL2W.GetTranslate();
retVal = true;
}
else
{
retVal = false; // No-effect else just for break points.
}
}
}
return retVal;
}

View File

@ -0,0 +1,79 @@
/*==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 plDynaRippleVSMgr_inc
#define plDynaRippleVSMgr_inc
#include "plDynaRippleMgr.h"
class plWaveSetBase;
class plDynaRippleVSMgr : public plDynaRippleMgr
{
public:
enum {
kRefWaveSetBase = kRefNextAvailable
};
protected:
plWaveSetBase* fWaveSetBase;
virtual hsBool IRippleFromShape(const plPrintShape* shape, hsBool force=false);
virtual int INewDecal();
virtual hsBool ICheckRTMat();
public:
plDynaRippleVSMgr();
virtual ~plDynaRippleVSMgr();
CLASSNAME_REGISTER( plDynaRippleVSMgr );
GETINTERFACE_ANY( plDynaRippleVSMgr, plDynaRippleMgr );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
#endif // plDynaRippleVSMgr_inc

View File

@ -0,0 +1,159 @@
/*==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 "plDynaTorpedoMgr.h"
#include "../plMessage/plBulletMsg.h"
#include "plCutter.h"
#include "plgDispatch.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "hsTimer.h"
#include "plTweak.h"
#include "../plMath/plRandom.h"
static const UInt32 kNumPrintIDs = 0;
static plRandom sRand;
plDynaTorpedoMgr::plDynaTorpedoMgr()
{
fPartIDs.SetCount(kNumPrintIDs);
}
plDynaTorpedoMgr::~plDynaTorpedoMgr()
{
}
void plDynaTorpedoMgr::Read(hsStream* stream, hsResMgr* mgr)
{
plDynaRippleMgr::Read(stream, mgr);
plgDispatch::Dispatch()->RegisterForExactType(plBulletMsg::Index(), GetKey());
}
hsBool plDynaTorpedoMgr::IHandleShot(plBulletMsg* bull)
{
hsScalar partyTime = fPartyTime;
plConst(int) kNumShots(3);
int i;
for( i = 0; i < kNumShots; i++ )
{
hsVector3 up = IRandomUp(bull->Dir());
hsVector3 pert = bull->Dir() % up;
plConst(hsScalar) kMaxPert(1.f);
hsScalar maxPert = i ? kMaxPert * bull->Radius() : 0;
pert *= sRand.RandMinusOneToOne() * maxPert * fScale.fX;
pert += up * (sRand.RandMinusOneToOne() * maxPert * fScale.fY);
hsPoint3 pos = bull->From() + bull->Dir() * (bull->Range() * 0.5f);
pos += pert;
hsScalar scaleX = bull->Radius() * fScale.fX * fInitUVW.fX;
hsScalar scaleY = bull->Radius() * fScale.fY * fInitUVW.fY;
#if 0
plConst(hsScalar) kMinScale(0.5f);
if( i )
{
scaleX *= sRand.RandRangeF(kMinScale, 1.f);
scaleY *= sRand.RandRangeF(kMinScale, 1.f);
}
#elif 0
hsScalar div = 1.f / (1.f + hsScalar(i));
scaleX *= div;
scaleY *= div;
#else
plConst(hsScalar) kMinScale(0.25f);
plConst(hsScalar) kMaxScale(0.75f);
if( i )
{
hsScalar scale = sRand.RandRangeF(kMinScale, kMaxScale);
scaleX *= scale;
scaleY *= scale;
}
#endif
fCutter->SetLength(hsVector3(scaleX, scaleY, bull->Range()));
fCutter->Set(pos, up, -bull->Dir());
plDynaDecalInfo& info = IGetDecalInfo(UInt32(this), GetKey());
if( bull->PartyTime() > 0 )
fPartyTime = bull->PartyTime();
double secs = hsTimer::GetSysSeconds();
if( ICutoutTargets(secs) )
info.fLastTime = secs;
fPartyTime = 0;
}
fPartyTime = partyTime;
return true;
}
hsBool plDynaTorpedoMgr::MsgReceive(plMessage* msg)
{
plBulletMsg* bullMsg = plBulletMsg::ConvertNoRef(msg);
if( bullMsg )
{
if( bullMsg->Shot() )
{
return IHandleShot(bullMsg);
}
return true;
}
return plDynaRippleMgr::MsgReceive(msg);
}

View File

@ -0,0 +1,70 @@
/*==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 plDynaTorpedoMgr_inc
#define plDynaTorpedoMgr_inc
#include "plDynaRippleMgr.h"
class plKey;
class plBulletMsg;
class plDynaTorpedoMgr : public plDynaRippleMgr
{
protected:
virtual hsBool IHandleShot(plBulletMsg* bull);
public:
plDynaTorpedoMgr();
virtual ~plDynaTorpedoMgr();
CLASSNAME_REGISTER( plDynaTorpedoMgr );
GETINTERFACE_ANY( plDynaTorpedoMgr, plDynaRippleMgr );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
#endif // plDynaTorpedoMgr_inc

View File

@ -0,0 +1,159 @@
/*==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 "plDynaTorpedoVSMgr.h"
#include "plDynaDecal.h"
#include "plWaveSetBase.h"
#include "plRipVSConsts.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayerInterface.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "../pnMessage/plRefMsg.h"
plDynaTorpedoVSMgr::plDynaTorpedoVSMgr()
: fWaveSetBase(nil)
{
}
plDynaTorpedoVSMgr::~plDynaTorpedoVSMgr()
{
}
int plDynaTorpedoVSMgr::INewDecal()
{
int idx = fDecals.GetCount();
plDynaRippleVS* rip = TRACKED_NEW plDynaRippleVS();
rip->fC1U = fInitUVW.fX;
rip->fC2U = (fInitUVW.fX - fFinalUVW.fX) / (fLifeSpan * fFinalUVW.fX);
rip->fC1V = fInitUVW.fY;
rip->fC2V = (fInitUVW.fY - fFinalUVW.fY) / (fLifeSpan * fFinalUVW.fY);
fDecals.Append(rip);
return idx;
}
hsBool plDynaTorpedoVSMgr::IHandleShot(plBulletMsg* bull)
{
if( !ICheckRTMat() )
return false;
return plDynaTorpedoMgr::IHandleShot(bull);
}
hsBool plDynaTorpedoVSMgr::ICheckRTMat()
{
if( !fMatRTShade )
return false;
if( !fWaveSetBase )
return false;
if( fMatRTShade->GetLayer(0)->GetVertexShader() )
return true;
plRipVSConsts ripConsts = IGetRippleConsts();
return fWaveSetBase->SetupRippleMat(fMatRTShade, ripConsts);
}
plRipVSConsts plDynaTorpedoVSMgr::IGetRippleConsts() const
{
plRipVSConsts ripConsts;
ripConsts.fC1U = fInitUVW.fX;
ripConsts.fC2U = (fInitUVW.fX - fFinalUVW.fX) / (fLifeSpan * fFinalUVW.fX);
ripConsts.fC1V = fInitUVW.fY;
ripConsts.fC2V = (fInitUVW.fY - fFinalUVW.fY) / (fLifeSpan * fFinalUVW.fY);
ripConsts.fInitAtten = fInitAtten;
ripConsts.fLife = fLifeSpan;
ripConsts.fDecay = fDecayStart;
ripConsts.fRamp = fRampEnd;
return ripConsts;
}
hsBool plDynaTorpedoVSMgr::MsgReceive(plMessage* msg)
{
hsBool retVal = plDynaTorpedoMgr::MsgReceive(msg);
if( retVal )
return true;
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef(msg);
if( refMsg )
{
switch( refMsg->fType )
{
case kRefWaveSetBase:
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
fWaveSetBase = plWaveSetBase::ConvertNoRef(refMsg->GetRef());
else
fWaveSetBase = nil;
return true;
}
}
return false;
}
void plDynaTorpedoVSMgr::Read(hsStream* stream, hsResMgr* mgr)
{
plDynaTorpedoMgr::Read(stream, mgr);
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefWaveSetBase), plRefFlags::kPassiveRef);
}
void plDynaTorpedoVSMgr::Write(hsStream* stream, hsResMgr* mgr)
{
plDynaTorpedoMgr::Write(stream, mgr);
mgr->WriteKey(stream, fWaveSetBase);
}

View File

@ -0,0 +1,80 @@
/*==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 plDynaTorpedoMgrVS_inc
#define plDynaTorpedoMgrVS_inc
#include "plDynaTorpedoMgr.h"
#include "plRipVSConsts.h"
class plWaveSetBase;
class plDynaTorpedoVSMgr : public plDynaTorpedoMgr
{
public:
enum {
kRefWaveSetBase = kRefNextAvailable
};
protected:
plWaveSetBase* fWaveSetBase;
virtual int INewDecal();
virtual hsBool ICheckRTMat();
plRipVSConsts IGetRippleConsts() const;
virtual hsBool IHandleShot(plBulletMsg* bull);
public:
plDynaTorpedoVSMgr();
virtual ~plDynaTorpedoVSMgr();
CLASSNAME_REGISTER( plDynaTorpedoVSMgr );
GETINTERFACE_ANY( plDynaTorpedoVSMgr, plDynaTorpedoMgr );
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
};
#endif // plDynaTorpedoMgrVS_inc

View File

@ -0,0 +1,228 @@
/*==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 "plDynaWakeMgr.h"
#include "plDynaDecal.h"
#include "plPrintShape.h"
#include "plCutter.h"
#include "plgDispatch.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "hsTimer.h"
#include "../plMessage/plDynaDecalEnableMsg.h"
#include "../plMessage/plRippleShapeMsg.h"
#include "../plMessage/plAvatarMsg.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plInterp/plAnimPath.h"
#include "hsFastMath.h"
#include "../plMath/plRandom.h"
static plRandom sRand;
int plDynaWakeMgr::INewDecal()
{
int idx = fDecals.GetCount();
plDynaWake* wake = TRACKED_NEW plDynaWake();
wake->fC1U = fInitUVW.fX;
wake->fC2U = (fInitUVW.fX - fFinalUVW.fX) / (fLifeSpan * fFinalUVW.fX);
wake->fC1V = fInitUVW.fY;
wake->fC2V = (fInitUVW.fY - fFinalUVW.fY) / (fLifeSpan * fFinalUVW.fY);
fDecals.Append(wake);
return idx;
}
plDynaWakeMgr::plDynaWakeMgr()
:
fAnimPath(nil),
fDefaultDir(0.f, 1.f, 0.f),
fAnimWgt(0),
fVelWgt(1.f)
{
}
plDynaWakeMgr::~plDynaWakeMgr()
{
delete fAnimPath;
}
void plDynaWakeMgr::SetAnimPath(plAnimPath* a)
{
delete fAnimPath;
fAnimPath = a;
}
void plDynaWakeMgr::SetDefaultDir(const hsVector3& v)
{
fDefaultDir = v;
hsFastMath::Normalize(fDefaultDir);
}
void plDynaWakeMgr::Read(hsStream* stream, hsResMgr* mgr)
{
plDynaRippleMgr::Read(stream, mgr);
fDefaultDir.Read(stream);
fAnimPath = plAnimPath::ConvertNoRef(mgr->ReadCreatable(stream));
fAnimWgt = stream->ReadSwapScalar();
fVelWgt = stream->ReadSwapScalar();
}
void plDynaWakeMgr::Write(hsStream* stream, hsResMgr* mgr)
{
plDynaRippleMgr::Write(stream, mgr);
fDefaultDir.Write(stream);
mgr->WriteCreatable(stream, fAnimPath);
stream->WriteSwapScalar(fAnimWgt);
stream->WriteSwapScalar(fVelWgt);
}
hsVector3 plDynaWakeMgr::IGetDirection(const plDynaDecalInfo& info, const hsPoint3& pos) const
{
hsVector3 dir = fDefaultDir;
// If we have an animpath, figure a direction based on position here
if( fAnimPath )
{
hsVector3 animDir;
hsPoint3 p = pos;
hsScalar t = fAnimPath->GetExtremePoint(p);
fAnimPath->SetCurTime(t, plAnimPath::kNone);
fAnimPath->GetVelocity(&animDir);
animDir *= fAnimWgt;
dir += animDir;
}
// Now if we want to factor in velocity, we can use (pos - info.fLastPos) / (hsTimer::GetSysSeconds() - info.fLastTime)
hsScalar dt = hsScalar(hsTimer::GetSysSeconds() - info.fLastTime);
const hsScalar kMinDt = 1.e-3f;
if( (info.fFlags & plDynaDecalInfo::kImmersed) && (dt > kMinDt) )
{
hsVector3 velDir(&pos, &info.fLastPos);
velDir *= 1.f / dt * fVelWgt;
dir += velDir;
}
hsFastMath::Normalize(dir);
return dir;
}
hsBool plDynaWakeMgr::IRippleFromShape(const plPrintShape* shape, hsBool force)
{
if( !shape )
return false;
hsBool retVal = false;
plDynaDecalInfo& info = IGetDecalInfo(UInt32(shape), shape->GetKey());
const hsMatrix44& shapeL2W = shape->GetOwner()->GetLocalToWorld();
static hsScalar kMinDist = 1.0f;
static hsScalar kMinTime = 0.25f;
double t = hsTimer::GetSysSeconds();
hsScalar dt = hsScalar(t - info.fLastTime) * sRand.RandZeroToOne();
hsBool longEnough = (dt >= kMinTime);
hsBool farEnough = (hsVector3(&info.fLastPos, &shapeL2W.GetTranslate()).Magnitude() > kMinDist);
if( force || longEnough || farEnough )
{
hsPoint3 pos = shapeL2W.GetTranslate();
// Base the direction on the unperturbed pos.
hsVector3 dir = IGetDirection(info, pos);
// We'll perturb the position a little so it doesn't look quite so regular,
// but we perturb it more if we're just standing still
hsVector3 randPert(sRand.RandMinusOneToOne(), sRand.RandMinusOneToOne(), 0);
randPert.Normalize();
if( !farEnough )
{
static hsScalar kRandPert = 0.05f;
randPert *= kRandPert * shape->GetWidth();
}
else
{
static hsScalar kRandPert = 0.05f;
randPert *= kRandPert * shape->GetWidth();
}
pos += randPert;
hsVector3 up(0.f, 0.f, 1.f);
static hsScalar kHeightScale = 1.f;
pos.fZ += (shape->GetHeight() * fScale.fZ * kHeightScale) * 0.25f;
pos += dir * shape->GetLength() * 0.5f * (1.f - fScale.fY);
hsVector3 size(shape->GetWidth() * fScale.fX, shape->GetLength() * fScale.fY, shape->GetHeight() * fScale.fZ * kHeightScale);
fCutter->SetLength(size);
fCutter->Set(pos, dir, up);
info.fLastTime = t;
info.fLastPos = shapeL2W.GetTranslate();
hsBool hit = ICutoutTargets(t);
if( hit )
retVal = true;
}
return retVal;
}

View File

@ -0,0 +1,89 @@
/*==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 plDynaWakeMgr_inc
#define plDynaWakeMgr_inc
#include "plDynaRippleMgr.h"
class plArmatureUpdateMsg;
class plAnimPath;
class plDynaWakeMgr : public plDynaRippleMgr
{
protected:
hsVector3 fDefaultDir;
plAnimPath* fAnimPath;
hsScalar fAnimWgt;
hsScalar fVelWgt;
virtual hsVector3 IGetDirection(const plDynaDecalInfo& info, const hsPoint3& pos) const;
virtual hsBool IRippleFromShape(const plPrintShape* shape, hsBool force=false);
virtual int INewDecal();
public:
plDynaWakeMgr();
virtual ~plDynaWakeMgr();
CLASSNAME_REGISTER( plDynaWakeMgr );
GETINTERFACE_ANY( plDynaWakeMgr, plDynaRippleMgr );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void SetAnimPath(plAnimPath* a);
plAnimPath* GetAnimPath() const { return fAnimPath; }
void SetDefaultDir(const hsVector3& v);
const hsVector3& GetDefaultDir() const { return fDefaultDir; }
void SetAnimWeight(hsScalar f) { fAnimWgt = f; }
hsScalar GetAnimWeight() const { return fAnimWgt; }
void SetVelocityWeight(hsScalar f) { fVelWgt = f; }
hsScalar GetVelocityWeight() const { return fVelWgt; }
};
#endif // plDynaWakeMgr_inc

View File

@ -0,0 +1,209 @@
/*==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 "plFixedWaterState7.h"
#include "hsStream.h"
void plFixedWaterState7::WaveState::Set(const plFixedWaterState7::WaveState& w, hsScalar secs)
{
fMaxLength.Set(w.fMaxLength, secs);
fMinLength.Set(w.fMinLength, secs);
fAmpOverLen.Set(w.fAmpOverLen, secs);
fChop.Set(w.fChop, secs);
fAngleDev.Set(w.fAngleDev, secs);
}
void plFixedWaterState7::Set(const plFixedWaterState7& t, hsScalar secs)
{
fWindDir.Set(t.fWindDir, secs);
fGeoState.Set(t.fGeoState, secs);
fTexState.Set(t.fTexState, secs);
fRippleScale.Set(t.fRippleScale, secs);
fSpecVec.Set(t.fSpecVec, secs);
fWaterHeight.Set(t.fWaterHeight, secs);
fWaterOffset.Set(t.fWaterOffset, secs);
fMaxAtten.Set(t.fMaxAtten, secs);
fMinAtten.Set(t.fMinAtten, secs);
fDepthFalloff.Set(t.fDepthFalloff, secs);
fWispiness.Set(t.fWispiness, secs);
fShoreTint.Set(t.fShoreTint, secs);
fMaxColor.Set(t.fMaxColor, secs);
fMinColor.Set(t.fMinColor, secs);
fEdgeOpac.Set(t.fEdgeOpac, secs);
fEdgeRadius.Set(t.fEdgeRadius, secs);
fPeriod.Set(t.fPeriod, secs);
fFingerLength.Set(t.fFingerLength, secs);
fWaterTint.Set(t.fWaterTint, secs);
fSpecularTint.Set(t.fSpecularTint, secs);
fEnvCenter.Set(t.fEnvCenter, secs);
fEnvRefresh.Set(t.fEnvRefresh, secs);
fEnvRadius.Set(t.fEnvRadius, secs);
}
void plFixedWaterState7::WaveState::Read(hsStream* s)
{
fMaxLength.Read(s);
fMinLength.Read(s);
fAmpOverLen.Read(s);
fChop.Read(s);
fAngleDev.Read(s);
}
void plFixedWaterState7::WaveState::Write(hsStream* s) const
{
fMaxLength.Write(s);
fMinLength.Write(s);
fAmpOverLen.Write(s);
fChop.Write(s);
fAngleDev.Write(s);
}
void plFixedWaterState7::Read(hsStream* s)
{
// Geometric waves
fGeoState.Read(s);
// Texture waves
fTexState.Read(s);
fRippleScale.Read(s);
// Geometric and Texture share wind direction
fWindDir.Read(s);
// Level of noise added during summation of texture waves
fSpecVec.Read(s);
// Depth parameters. Affect how the depth of
// the water vertex is interpreted into water
// surface properties.
fWaterHeight.Read(s);
fWaterOffset.Read(s);
fMaxAtten.Read(s);
fMinAtten.Read(s);
fDepthFalloff.Read(s);
// Shore parameters
// Appearance
fWispiness.Read(s);
fShoreTint.Read(s);
// Next two only used in generation of bubble layer
fMaxColor.Read(s);
fMinColor.Read(s);
fEdgeOpac.Read(s);
fEdgeRadius.Read(s);
// Simulation
fPeriod.Read(s);
fFingerLength.Read(s);
// Water appearance.
fWaterTint.Read(s);
fSpecularTint.Read(s);
fEnvCenter.Read(s);
fEnvRefresh.Read(s);
fEnvRadius.Read(s);
}
void plFixedWaterState7::Write(hsStream* s) const
{
// Geometric waves
fGeoState.Write(s);
// Texture waves
fTexState.Write(s);
fRippleScale.Write(s);
// Geometric and Texture share wind direction
fWindDir.Write(s);
// Level of noise added during summation of texture waves
fSpecVec.Write(s);
// Depth parameters. Affect how the depth of
// the water vertex is interpreted into water
// surface properties.
fWaterHeight.Write(s);
fWaterOffset.Write(s);
fMaxAtten.Write(s);
fMinAtten.Write(s);
fDepthFalloff.Write(s);
// Shore parameters
// Appearance
fWispiness.Write(s);
fShoreTint.Write(s);
// Next two only used in generation of bubble layer
fMaxColor.Write(s);
fMinColor.Write(s);
fEdgeOpac.Write(s);
fEdgeRadius.Write(s);
// Simulation
fPeriod.Write(s);
fFingerLength.Write(s);
// Water appearance.
fWaterTint.Write(s);
fSpecularTint.Write(s);
fEnvCenter.Write(s);
fEnvRefresh.Write(s);
fEnvRadius.Write(s);
}

View File

@ -0,0 +1,132 @@
/*==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 plFixedWaterState7_inc
#define plFixedWaterState7_inc
#include "hsGeometry3.h"
#include "hsColorRGBA.h"
#include "../pnTimer/plTimedValue.h"
class hsStream;
class plFixedWaterState7
{
public:
class WaveState
{
public:
plTimedSimple<hsScalar> fMaxLength;
plTimedSimple<hsScalar> fMinLength;
plTimedSimple<hsScalar> fAmpOverLen;
plTimedSimple<hsScalar> fChop;
plTimedSimple<hsScalar> fAngleDev;
void Set(const WaveState& w, hsScalar secs);
void Read(hsStream* s);
void Write(hsStream* s) const;
};
// Main body of water state
// Geometric waves
WaveState fGeoState;
// Texture waves
WaveState fTexState;
plTimedSimple<hsScalar> fRippleScale;
// Geometric and Texture share wind direction
plTimedCompound<hsVector3> fWindDir;
// Level of noise added during summation of texture waves
enum {
kNoise = 0,
kSpecStart = 1,
kSpecEnd = 2
};
plTimedCompound<hsVector3> fSpecVec; // (Noise, SpecStart, SpecEnd);
// Depth parameters. Affect how the depth of
// the water vertex is interpreted into water
// surface properties.
plTimedSimple<hsScalar> fWaterHeight;
plTimedCompound<hsVector3> fWaterOffset;
plTimedCompound<hsVector3> fMaxAtten;
plTimedCompound<hsVector3> fMinAtten;
plTimedCompound<hsVector3> fDepthFalloff;
// Shore parameters
// Appearance
plTimedSimple<hsScalar> fWispiness;
plTimedCompound<hsColorRGBA> fShoreTint;
// Next two only used in generation of bubble layer
plTimedCompound<hsColorRGBA> fMaxColor;
plTimedCompound<hsColorRGBA> fMinColor;
plTimedSimple<hsScalar> fEdgeOpac;
plTimedSimple<hsScalar> fEdgeRadius;
// Simulation
plTimedSimple<hsScalar> fPeriod;
plTimedSimple<hsScalar> fFingerLength;
// The rest aren't really part of the state, that is they are normally controlled
// by something exterior to the state. They are included here to allow a convenient
// override during development.
// Water appearance.
plTimedCompound<hsColorRGBA> fWaterTint;
plTimedCompound<hsColorRGBA> fSpecularTint;
plTimedCompound<hsPoint3> fEnvCenter;
plTimedSimple<hsScalar> fEnvRefresh;
plTimedSimple<hsScalar> fEnvRadius;
void Set(const plFixedWaterState7& s, hsScalar secs);
void Read(hsStream* s);
void Write(hsStream* s) const;
};
#endif // plFixedWaterState7_inc

View File

@ -0,0 +1,334 @@
/*==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 "memory.h"
#include "hsTypes.h"
#include "plGeoSpanDice.h"
#include "plGeometrySpan.h"
plGeoSpanDice::plGeoSpanDice()
: fMinFaces(0),
fMaxFaces(0)
{
fMaxSize.Set(0,0,0);
}
plGeoSpanDice::~plGeoSpanDice()
{
}
hsBool plGeoSpanDice::Dice(hsTArray<plGeometrySpan*>& spans) const
{
int startingCount = spans.GetCount();
hsTArray<plGeometrySpan*> out;
hsTArray<plGeometrySpan*> next;
while(spans.GetCount())
{
int i;
for( i = 0; i < spans.GetCount(); i++ )
{
if( !IHalf(spans[i], next) )
{
out.Append(spans[i]);
}
}
spans.Swap(next);
next.SetCount(0);
}
spans.Swap(out);
return spans.GetCount() != startingCount;
}
hsBool plGeoSpanDice::INeedSplitting(plGeometrySpan* src) const
{
// Do we have enough faces to bother?
if( fMinFaces )
{
if( src->fNumIndices < fMinFaces * 3 )
return false;
}
// Do we have enough faces to bother no matter how small we are?
if( fMaxFaces )
{
if( src->fNumIndices > fMaxFaces * 3 )
return true;
}
// Are we big enough to bother?
if( (fMaxSize.fX > 0) || (fMaxSize.fY > 0) || (fMaxSize.fZ > 0) )
{
hsPoint3 size = src->fLocalBounds.GetMaxs() - src->fLocalBounds.GetMins();
if( size.fX > fMaxSize.fX )
return true;
if( size.fY > fMaxSize.fY )
return true;
if( size.fZ > fMaxSize.fZ )
return true;
}
return false;
}
hsBool plGeoSpanDice::IHalf(plGeometrySpan* src, hsTArray<plGeometrySpan*>& out, int exclAxis) const
{
if( !INeedSplitting(src) )
return false;
int iAxis = ISelectAxis(exclAxis, src);
// Ran out of axes to try.
if( iAxis < 0 )
return false;
hsScalar midPoint = src->fLocalBounds.GetCenter()[iAxis];
hsTArray<UInt32> loTris;
hsTArray<UInt32> hiTris;
UInt16* indexData = src->fIndexData;
int numTris = src->fNumIndices / 3;
int stride = src->GetVertexSize(src->fFormat);
int i;
for( i = 0; i < numTris; i++ )
{
hsPoint3& pos0 = *(hsPoint3*)(src->fVertexData + *indexData++ * stride);
hsPoint3& pos1 = *(hsPoint3*)(src->fVertexData + *indexData++ * stride);
hsPoint3& pos2 = *(hsPoint3*)(src->fVertexData + *indexData++ * stride);
if( (pos0[iAxis] >= midPoint)
&&(pos1[iAxis] >= midPoint)
&&(pos2[iAxis] >= midPoint) )
{
hiTris.Append(i);
}
else
{
loTris.Append(i);
}
}
// This axis isn't working out, try another.
if( !hiTris.GetCount() || !loTris.GetCount() )
return IHalf(src, out, exclAxis | (1 << iAxis));
plGeometrySpan* loDst = IExtractTris(src, loTris);
plGeometrySpan* hiDst = IExtractTris(src, hiTris);
delete src;
out.Append(loDst);
out.Append(hiDst);
return true;
}
int plGeoSpanDice::ISelectAxis(int exclAxis, plGeometrySpan* src) const
{
int iAxis = -1;
hsScalar maxDim = 0;
int i;
for( i = 0; i < 3; i++ )
{
// Check to see if we've already tried this one.
if( exclAxis & (1 << i) )
continue;
hsScalar dim = src->fLocalBounds.GetMaxs()[i] - src->fLocalBounds.GetMins()[i];
if( dim > maxDim )
{
maxDim = dim;
iAxis = i;
}
}
return iAxis;
}
plGeometrySpan* plGeoSpanDice::IExtractTris(plGeometrySpan* src, hsTArray<UInt32>& tris) const
{
// First off, find out how many and which vers we're talking here.
// Easiest way is while we're building the LUTs we'll want later anyway.
hsTArray<Int16> fwdLUT;
fwdLUT.SetCount(src->fNumVerts);
memset(fwdLUT.AcquireArray(), -1, src->fNumVerts * sizeof(*fwdLUT.AcquireArray()));
hsTArray<UInt16> bckLUT;
bckLUT.SetCount(0);
int i;
for( i = 0; i < tris.GetCount(); i++ )
{
UInt16* idx = src->fIndexData + tris[i] * 3;
if( fwdLUT[*idx] < 0 )
{
fwdLUT[*idx] = bckLUT.GetCount();
bckLUT.Append(*idx);
}
idx++;
if( fwdLUT[*idx] < 0 )
{
fwdLUT[*idx] = bckLUT.GetCount();
bckLUT.Append(*idx);
}
idx++;
if( fwdLUT[*idx] < 0 )
{
fwdLUT[*idx] = bckLUT.GetCount();
bckLUT.Append(*idx);
}
}
int numVerts = bckLUT.GetCount();
int numTris = tris.GetCount();
plGeometrySpan* dst = IAllocSpace(src, numVerts, numTris);
// Okay, set the index data.
UInt16* idxTrav = dst->fIndexData;
for( i = 0; i < tris.GetCount(); i++ )
{
*idxTrav++ = fwdLUT[src->fIndexData[ tris[i] * 3 + 0] ];
*idxTrav++ = fwdLUT[src->fIndexData[ tris[i] * 3 + 1] ];
*idxTrav++ = fwdLUT[src->fIndexData[ tris[i] * 3 + 2] ];
}
// Copy over the basic vertex data
// We'll update the bounds as we go.
int stride = src->GetVertexSize(src->fFormat);
hsBounds3Ext localBnd;
localBnd.MakeEmpty();
UInt8* vtxTrav = dst->fVertexData;
for( i = 0; i < numVerts; i++ )
{
memcpy(vtxTrav, src->fVertexData + bckLUT[i] * stride, stride);
hsPoint3* pos = (hsPoint3*)vtxTrav;
localBnd.Union(pos);
vtxTrav += stride;
}
if( src->fProps & plGeometrySpan::kWaterHeight )
{
src->AdjustBounds(localBnd);
}
dst->fLocalBounds = localBnd;
// Now the rest of this optional garbage.
if( src->fMultColor )
{
for( i = 0; i < numVerts; i++ )
{
dst->fMultColor[i] = src->fMultColor[bckLUT[i]];
}
}
if( src->fAddColor )
{
for( i = 0; i < numVerts; i++ )
{
dst->fAddColor[i] = src->fAddColor[bckLUT[i]];
}
}
if( src->fDiffuseRGBA )
{
for( i = 0; i < numVerts; i++ )
{
dst->fDiffuseRGBA[i] = src->fDiffuseRGBA[bckLUT[i]];
}
}
if( src->fSpecularRGBA )
{
for( i = 0; i < numVerts; i++ )
{
dst->fSpecularRGBA[i] = src->fSpecularRGBA[bckLUT[i]];
}
}
dst->fMaxOwner = src->fMaxOwner;
return dst;
}
plGeometrySpan* plGeoSpanDice::IAllocSpace(plGeometrySpan* src, int numVerts, int numTris) const
{
plGeometrySpan* dst = TRACKED_NEW plGeometrySpan;
// Do a structure copy here. That's okay, because we're going to immediately
// fix up the pointers and counters that shouldn't have been copied. If
// plGeometrySpan ever gets a copy constructor, this'll blow wide open.
*dst = *src;
int stride = src->GetVertexSize(src->fFormat);
dst->fNumIndices = numTris * 3;
dst->fIndexData = TRACKED_NEW UInt16[dst->fNumIndices];
dst->fNumVerts = numVerts;
dst->fVertexData = TRACKED_NEW UInt8[numVerts * stride];
if( src->fMultColor )
{
dst->fMultColor = TRACKED_NEW hsColorRGBA[numVerts];
}
if( src->fAddColor )
{
dst->fAddColor = TRACKED_NEW hsColorRGBA[numVerts];
}
if( src->fDiffuseRGBA )
{
dst->fDiffuseRGBA = TRACKED_NEW UInt32[numVerts];
}
if( src->fSpecularRGBA )
{
dst->fSpecularRGBA = TRACKED_NEW UInt32[numVerts];
}
return dst;
}

View File

@ -0,0 +1,80 @@
/*==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 plGeoSpanDice_inc
#define plGeoSpanDice_inc
#include "hsGeometry3.h"
#include "hsTemplates.h"
class plGeometrySpan;
class plGeoSpanDice
{
protected:
UInt32 fMinFaces;
UInt32 fMaxFaces;
hsPoint3 fMaxSize;
hsBool INeedSplitting(plGeometrySpan* src) const;
plGeometrySpan* IAllocSpace(plGeometrySpan* src, int numVerts, int numTris) const;
plGeometrySpan* IExtractTris(plGeometrySpan* src, hsTArray<UInt32>& tris) const;
int ISelectAxis(int exclAxis, plGeometrySpan* src) const;
hsBool IHalf(plGeometrySpan* src, hsTArray<plGeometrySpan*>& out, int exclAxis=0) const;
public:
plGeoSpanDice();
virtual ~plGeoSpanDice();
hsBool Dice(hsTArray<plGeometrySpan*>& spans) const;
void SetMaxSize(const hsPoint3& size) { fMaxSize = size; }
hsPoint3 GetMaxSize() const { return fMaxSize; }
void SetMinFaces(int n) { fMinFaces = n; }
int GetMinFaces() const { return fMinFaces; }
void SetMaxFaces(int n) { fMaxFaces = n; }
int GetMaxFaces() const { return fMaxFaces; }
};
#endif // plGeoSpanDice_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,312 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plGeometrySpan Header //
// //
// plGeometrySpans are abstract reprentations of Plasma 2.0 geometry data. //
// They consist of a material, a transform, bounds and an abstract vertex //
// and index buffer pair. plGeometrySpans is what is fed to plDrawableIce //
// to convert into its own internal data structures; the format for the //
// vertex and index data is (or should be) identical. More or less, they //
// are identical to Ice's plIcicle, but this is more abstract (read: not //
// internal to Ice). //
// //
// Also included is a temporary hacked triMesh-to-geometrySpan[] converter //
// for everyone's convenience until triMeshes disappear. //
// //
//// Version History /////////////////////////////////////////////////////////
// //
// Created 3.8.2001 mcn //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plGeometrySpan_h
#define _plGeometrySpan_h
#include "hsTemplates.h"
#include "hsBounds.h"
#include "hsMatrix44.h"
#include "hsColorRGBA.h"
#include "hsBitVector.h"
class hsGMaterial;
class plFogEnvironment;
//// plGeometrySpan Class Definition /////////////////////////////////////////
class plGeometrySpan
{
public:
enum
{
kMaxNumUVChannels = 8
};
/// Duplication of the formats from plGBufferGroup; theoretically, they
/// could be different, but they're identical for now
enum Formats
{
kUVCountMask = 0x0f, // Problem is, we need enough bits to store the max #, which means
// we really want ( max # << 1 ) - 1
kSkinNoWeights = 0x00, // 0000000
kSkin1Weight = 0x10, // 0010000
kSkin2Weights = 0x20, // 0100000
kSkin3Weights = 0x30, // 0110000
kSkinWeightMask = 0x30, // 0110000
kSkinIndices = 0x40, // 1000000
};
enum Properties
{
kPropRunTimeLight = 0x01,
kPropNoPreShade = 0x02,
kLiteMaterial = 0x00,
kLiteVtxPreshaded = 0x04,
kLiteVtxNonPreshaded = 0x08,
kLiteMask = 0x0c,
kRequiresBlending = 0x10,
kInstanced = 0x20,
kUserOwned = 0x40,
kPropNoShadow = 0x80,
kPropForceShadow = 0x100,
kDiffuseFoldedIn = 0x200, // Sometimes we want to fold the diffuse color of the material into the vertex color (but only once).
kPropReverseSort = 0x400,
kWaterHeight = 0x800,
kFirstInstance = 0x1000,
kPartialSort = 0x2000,
kVisLOS = 0x4000,
kPropNoShadowCast = 0x8000
};
enum
{
kNoGroupID = 0
};
// Note: these are public because this is really just a glorified
// struct; no data hiding here
hsGMaterial *fMaterial;
hsMatrix44 fLocalToWorld;
hsMatrix44 fWorldToLocal;
hsBounds3Ext fLocalBounds;
hsBounds3Ext fWorldBounds;
plFogEnvironment *fFogEnviron;
UInt32 fBaseMatrix;
UInt8 fNumMatrices;
UInt16 fLocalUVWChans;
UInt16 fMaxBoneIdx;
UInt32 fPenBoneIdx;
hsScalar fMinDist;
hsScalar fMaxDist;
hsScalar fWaterHeight;
UInt8 fFormat;
UInt32 fProps;
UInt32 fNumVerts, fNumIndices;
/// Current vertex format:
/// float position[ 3 ];
/// float normal[ 3 ];
/// float uvCoords[ ][ 3 ];
/// float weights[]; // 0-3 blending weights
/// UInt32 weightIndices; // Only if there are >= 1 blending weights
UInt8* fVertexData;
UInt16* fIndexData;
UInt32 fDecalLevel;
hsColorRGBA* fMultColor;
hsColorRGBA* fAddColor;
UInt32* fDiffuseRGBA;
UInt32* fSpecularRGBA;
mutable hsTArray<plGeometrySpan *>* fInstanceRefs;
mutable UInt32 fInstanceGroupID; // For writing out/reading in instance refs
// The following is only used for logging during export. It is never set
// at runtime. Don't even think about using it for anything.
const char* fMaxOwner;
// The following is ONLY used during pack; it's so we can do a reverse lookup
// from the instanceRefs list to the correct span in the drawable
UInt32 fSpanRefIndex;
// These two matrices are inverses of each other (duh). They are only used on computing the local
// bounds. fLocalBounds is always the bounds in the space defined by fWorldToLocal, but the bounds
// are an OBB, and the orientation of the OBB isn't necessarily the same as fLocalToWorld's axes.
// For now, it is the orientation of the pivot point in max (but might be further optimized).
hsMatrix44 fLocalToOBB;
hsMatrix44 fOBBToLocal;
plGeometrySpan();
plGeometrySpan( const plGeometrySpan *instance );
~plGeometrySpan();
/// UV stuff
UInt8 GetNumUVs( void ) const { return ( fFormat & kUVCountMask ); }
void SetNumUVs( UInt8 numUVs )
{
hsAssert( numUVs < kMaxNumUVChannels, "Invalid UV count to plGeometrySpan" );
fFormat = ( fFormat & ~kUVCountMask ) | numUVs;
}
static UInt8 CalcNumUVs( UInt8 format ) { return ( format & kUVCountMask ); }
static UInt8 UVCountToFormat( UInt8 numUVs ) { return numUVs & kUVCountMask; }
/// Creation functions
void BeginCreate( hsGMaterial *material, const hsMatrix44 &l2wMatrix, UInt8 format );
// Phasing these in...
// Note: uvArray should be a fixed array with enough pointers for the max # of uv channels.
// Any unused UVs should be nil
UInt16 AddVertex( hsPoint3 *position, hsPoint3 *normal, hsColorRGBA& multColor, hsColorRGBA& addColor,
hsPoint3 **uvPtrArray, float weight1 = -1.0f, float weight2 = -1.0f, float weight3 = -1.0f, UInt32 weightIndices = 0 );
UInt16 AddVertex( hsPoint3 *position, hsPoint3 *normal, UInt32 hexColor, UInt32 specularColor = 0,
hsPoint3 **uvPtrArray = nil, float weight1 = -1.0f, float weight2 = -1.0f, float weight3 = -1.0f, UInt32 weightIndices = 0 );
void AddIndex( UInt16 index );
void AddTriIndices( UInt16 index1, UInt16 index2, UInt16 index3 );
void AddTriangle( hsPoint3 *vert1, hsPoint3 *vert2, hsPoint3 *vert3, UInt32 color );
// uvws is an array count*uvwsPerVtx long in order [uvw(s) for vtx0, uvw(s) for vtx1, ...], or is nil
void AddVertexArray( UInt32 count, hsPoint3 *positions, hsVector3 *normals, UInt32 *colors, hsPoint3 *uvws=nil, int uvwsPerVtx=0 );
void AddIndexArray( UInt32 count, UInt16 *indices );
void EndCreate( void );
/// Manipulation--currently only used for applying static lighting, which of course needs individual vertices
// Wrong. Also used for the interleaving of the multiple vertex data streams here into single vertex
// stream within the plGBufferGroups. mf.
void ExtractInitColor( UInt32 index, hsColorRGBA *multColor, hsColorRGBA *addColor) const;
void ExtractVertex( UInt32 index, hsPoint3 *pos, hsVector3 *normal, hsColorRGBA *color, hsColorRGBA *specColor = nil );
void ExtractVertex( UInt32 index, hsPoint3 *pos, hsVector3 *normal, UInt32 *color, UInt32 *specColor = nil );
void ExtractUv( UInt32 vIdx, UInt8 uvIdx, hsPoint3* uv );
void ExtractWeights( UInt32 vIdx, float *weightArray, UInt32 *indices );
void StuffVertex( UInt32 index, hsPoint3 *pos, hsPoint3 *normal, hsColorRGBA *color, hsColorRGBA *specColor = nil );
void StuffVertex( UInt32 index, hsColorRGBA *color, hsColorRGBA *specColor = nil );
// Clear out the buffers
void ClearBuffers( void );
// Duplicate this span from a given span
void CopyFrom( const plGeometrySpan *source );
// Make this span an instance of the given span. Handles the instance ref array as well as copying over pointers
void MakeInstanceOf( const plGeometrySpan *instance );
// Get the size of one vertex in a span, based on a format
static UInt32 GetVertexSize( UInt8 format );
void Read( hsStream *stream );
void Write( hsStream *stream );
static UInt32 AllocateNewGroupID() { return IAllocateNewGroupID(); }
void BreakInstance();
void ChangeInstance(plGeometrySpan* newInstance);
void UnInstance();
void AdjustBounds(hsBounds3Ext& bnd) const;
protected:
struct TempVertex
{
hsPoint3 fPosition;
hsPoint3 fNormal;
UInt32 fColor, fSpecularColor;
hsColorRGBA fMultColor, fAddColor;
hsPoint3 fUVs[ kMaxNumUVChannels ];
float fWeights[ 3 ];
UInt32 fIndices;
};
hsBool fCreating;
hsTArray<TempVertex> fVertAccum;
hsTArray<UInt16> fIndexAccum;
void IUnShareData();
void IDuplicateUniqueData( const plGeometrySpan *source );
void IClearMembers( void );
// Please don't yell at me. We can't write out the instanceRef pointers, and we can't write
// out keys because we're not keyed objects, and we can't be keyed objects because we need
// to be deleted eventually. So instead, we assign each geoSpan a instanceGroupID, unique
// for each instance group but identical among all geoSpans in a given group (i.e. all
// members of the instanceRef list). We write these IDs out, then on read, we rebuild the
// instanceRef arrays by using a hash table to find insert new hsTArrays at the given groupID,
// and looking up in that hash table to get pointers for each geoSpan's instanceRef array.
// THIS is because we need a way of assigning unique, unused groupIDs to each geoSpan instance
// group, and since we only need to know if the ID has been used yet, we can just use a bitVector.
// NOTE: Group IDs start at 1, not 0, because 0 is reserved for "no instance group". So subtract
// 1 from the group ID when accessing this array...
// ....Please don't yell at me :(
static hsBitVector fInstanceGroupIDFlags;
// The following is for rebuilding the said groups on read. The sad thing is that we also
// have to write out the instanceRef array count for each geoSpan, so that when we read in
// to do the lookup here, we know that we've read everything and can dump the entry in this
// table.
static hsTArray<hsTArray<plGeometrySpan *> *> fInstanceGroups;
// THIS is so we can clear fInstanceGroups as early and as efficiently as possible; see
// the notes on IGetInstanceGroup().
static UInt32 fHighestReadInstanceGroup;
static UInt32 IAllocateNewGroupID( void );
static void IClearGroupID( UInt32 groupID );
static hsTArray<plGeometrySpan *> *IGetInstanceGroup( UInt32 groupID, UInt32 expectedCount );
};
#endif // _plGeometrySpan_h

View File

@ -0,0 +1,248 @@
/*==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 "plInstanceDrawInterface.h"
#include "plSharedMesh.h"
#include "plMorphSequence.h"
#include "../plMessage/plReplaceGeometryMsg.h"
#include "plDrawableSpans.h"
#include "plGeometrySpan.h"
#include "../plScene/plSceneNode.h"
#include "../pnMessage/plDISpansMsg.h"
#include "hsResMgr.h"
plInstanceDrawInterface::plInstanceDrawInterface() : plDrawInterface(), fTargetID(-1) {}
plInstanceDrawInterface::~plInstanceDrawInterface() {}
void plInstanceDrawInterface::Read(hsStream* stream, hsResMgr* mgr)
{
plDrawInterface::Read(stream, mgr);
fTargetID = stream->ReadSwap32();
plSwapSpansRefMsg *sMsg = TRACKED_NEW plSwapSpansRefMsg(GetKey(), plRefMsg::kOnCreate, -1, -1);
mgr->ReadKeyNotifyMe(stream, sMsg, plRefFlags::kActiveRef);
}
void plInstanceDrawInterface::Write(hsStream* stream, hsResMgr* mgr)
{
plDrawInterface::Write(stream, mgr);
stream->WriteSwap32(fTargetID);
mgr->WriteKey(stream, fDrawable->GetKey());
}
hsBool plInstanceDrawInterface::MsgReceive(plMessage* msg)
{
#if 0 // UNUSED
// This currently isn't being used, so I'm commenting it out at
// Bob's preference. If it does come back into play, the plReplaceGeometryMsg should also
// contain an LOD field, saying which avatar LOD this is targetted for.
// Just always specifying 0 won't break anything, it just circumvents some
// optimizations the pipeline can make, so it'll look right, just slower.
plReplaceGeometryMsg *rMsg = plReplaceGeometryMsg::ConvertNoRef(msg);
if (rMsg)
{
if (rMsg->fFlags & rMsg->kAddingGeom)
AddSharedMesh(rMsg->fMesh, rMsg->fMaterial, rMsg->fFlags & rMsg->kAddToFront);
else
RemoveSharedMesh(rMsg->fMesh);
return true;
}
#endif // UNUSED
plSwapSpansRefMsg* refMsg = plSwapSpansRefMsg::ConvertNoRef(msg);
if (refMsg)
{
if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
fDrawable = nil;
else
fDrawable = plDrawableSpans::ConvertNoRef(refMsg->GetRef());
return true;
}
return plDrawInterface::MsgReceive(msg);
}
void plInstanceDrawInterface::AddSharedMesh(plSharedMesh *mesh, hsGMaterial *mat, hsBool addToFront, int lod, hsBool partialSort)
{
if (fDrawable == nil)
{
hsAssert(false, "Missing drawable when instancing a shared mesh. Ignoring instance.");
return;
}
#ifdef MF_NOSHADOW_ACC
// TESTHACKERY FOLLOWS - GlassesNoShadow
UInt32 noShadHack = 0;
if( mesh->GetKey() && (strstr(mesh->GetKey()->GetName(), "lasses") || strstr(mesh->GetKey()->GetName(), "oggles")) )
noShadHack = plGeometrySpan::kPropNoShadowCast;
#endif // MF_NOSHADOW_ACC
int i;
for (i = 0; i < mesh->fSpans.GetCount(); i++)
{
mesh->fSpans[i]->fMaterial = mat;
if( partialSort )
{
mesh->fSpans[i]->fProps |= plGeometrySpan::kPartialSort;
}
else
mesh->fSpans[i]->fProps &= ~plGeometrySpan::kPartialSort;
#ifdef MF_NOSHADOW_ACC
mesh->fSpans[i]->fProps |= noShadHack;
#endif // MF_NOSHADOW_ACC
}
// Add the spans to the drawable
UInt32 index = (UInt32)-1;
index = fDrawable->AppendDISpans(mesh->fSpans, index, false, true, addToFront, lod);
// Tell the drawInterface what drawable and index it wants.
UInt8 iDraw = (UInt8)GetNumDrawables();
ISetDrawable(iDraw, fDrawable);
SetDrawableMeshIndex(iDraw, index);
SetSharedMesh(iDraw, mesh);
if (GetProperty(kDisable))
fDrawables[iDraw]->SetProperty(fDrawableIndices[iDraw], kDisable, true);
#ifdef HS_DEBUGGING
plDISpansMsg* diMsg = TRACKED_NEW plDISpansMsg(fDrawable->GetKey(), plDISpansMsg::kAddingSpan, index, plDISpansMsg::kLeaveEmptyDrawable);
diMsg->SetSender(GetKey());
diMsg->Send();
#endif
plSharedMeshBCMsg *smMsg = TRACKED_NEW plSharedMeshBCMsg;
smMsg->SetSender(GetKey());
smMsg->fDraw = fDrawable;
smMsg->fMesh = mesh;
smMsg->fIsAdding = true;
smMsg->Send();
if (mesh->fMorphSet)
{
plMorphSequence *morph = const_cast<plMorphSequence*>(plMorphSequence::ConvertNoRef(fOwner->GetModifierByType(plMorphSequence::Index())));
if (morph)
{
//hsgResMgr::ResMgr()->AddViaNotify(mesh->GetKey(), TRACKED_NEW plGenRefMsg(morph->GetKey(), plRefMsg::kOnCreate, -1, -1), plRefFlags::kPassiveRef);
morph->AddSharedMesh(mesh);
}
}
}
void plInstanceDrawInterface::RemoveSharedMesh(plSharedMesh *mesh)
{
UInt32 geoIndex = fMeshes.Find(mesh);
if (geoIndex != fMeshes.kMissingIndex)
{
IClearIndex((UInt8)geoIndex);
plSharedMeshBCMsg *smMsg = TRACKED_NEW plSharedMeshBCMsg;
smMsg->SetSender(GetKey());
smMsg->fDraw = fDrawable;
smMsg->fMesh = mesh;
smMsg->fIsAdding = false;
smMsg->Send();
if (mesh->fMorphSet)
{
plMorphSequence *morph = const_cast<plMorphSequence*>(plMorphSequence::ConvertNoRef(fOwner->GetModifierByType(plMorphSequence::Index())));
if (morph)
{
//morph->GetKey()->Release(mesh->GetKey());
morph->RemoveSharedMesh(mesh);
}
}
}
}
void plInstanceDrawInterface::ICheckDrawableIndex(UInt8 which)
{
if( which >= fMeshes.GetCount() )
{
fMeshes.ExpandAndZero(which+1);
}
plDrawInterface::ICheckDrawableIndex(which);
}
void plInstanceDrawInterface::ReleaseData()
{
fMeshes.Reset();
plDrawInterface::ReleaseData();
}
void plInstanceDrawInterface::SetSharedMesh(UInt8 which, plSharedMesh *mesh)
{
ICheckDrawableIndex(which);
fMeshes[which] = mesh;
}
void plInstanceDrawInterface::IClearIndex(UInt8 which)
{
plDrawableSpans *drawable = plDrawableSpans::ConvertNoRef(fDrawables[which]);
if (drawable != nil)
{
plDISpansMsg* diMsg = TRACKED_NEW plDISpansMsg(fDrawable->GetKey(), plDISpansMsg::kRemovingSpan, fDrawableIndices[which], plDISpansMsg::kLeaveEmptyDrawable);
diMsg->SetSender(GetKey());
diMsg->Send();
}
fDrawables.Remove(which);
fDrawableIndices.Remove(which);
fMeshes.Remove(which);
}
// Temp testing - not really ideal. Check with Bob for real soln.
Int32 plInstanceDrawInterface::GetSharedMeshIndex(const plSharedMesh *mesh) const
{
int i;
for( i = 0; i < fMeshes.GetCount(); i++ )
{
if( fMeshes[i] == mesh )
return i;
}
return -1;
}

View File

@ -0,0 +1,84 @@
/*==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 plInstanceDrawInterface_inc
#define plInstanceDrawInterface_inc
#include "../pnSceneObject/plDrawInterface.h"
class plDrawableSpans;
class plSharedMesh;
class plInstanceDrawInterface : public plDrawInterface
{
protected:
plDrawableSpans *fDrawable;
hsTArray<plSharedMesh*> fMeshes;
virtual void ICheckDrawableIndex(UInt8 which);
public:
UInt32 fTargetID;
plInstanceDrawInterface();
virtual ~plInstanceDrawInterface();
CLASSNAME_REGISTER( plInstanceDrawInterface );
GETINTERFACE_ANY( plInstanceDrawInterface, plDrawInterface );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
void AddSharedMesh(plSharedMesh *mesh, hsGMaterial *mat, hsBool addToFront, int LOD, hsBool partialSort);
void RemoveSharedMesh(plSharedMesh *mesh);
virtual void ReleaseData();
virtual void SetSharedMesh(UInt8 which, plSharedMesh *mesh);
virtual void IClearIndex(UInt8 which);
plDrawableSpans *GetInstanceDrawable() const { return fDrawable; }
Int32 GetSharedMeshIndex(const plSharedMesh *mesh) const;
};
#endif // plInstanceDrawInterface_inc

View File

@ -0,0 +1,248 @@
/*==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 "plInterMeshSmooth.h"
#include "plDrawableSpans.h"
class EdgeBin
{
public:
UInt16 fVtx;
UInt16 fCount;
EdgeBin() : fVtx(0), fCount(0) {}
};
void plInterMeshSmooth::FindEdges(UInt32 maxVtxIdx, UInt32 nTris, UInt16* idxList, hsTArray<UInt16>& edgeVerts)
{
hsTArray<EdgeBin>* bins = TRACKED_NEW hsTArray<EdgeBin>[maxVtxIdx+1];
hsBitVector edgeVertBits;
// For each vert pair (edge) in idxList
int i;
for( i = 0; i < nTris; i++ )
{
int j;
for( j = 0; j < 3; j++ )
{
int jPlus = j < 2 ? j+1 : 0;
int idx0 = idxList[i*3 + j];
int idx1 = idxList[i*3 + jPlus];
int lo, hi;
// Look in the LUT for the lower index.
if( idx0 < idx1 )
{
lo = idx0;
hi = idx1;
}
else
{
lo = idx1;
hi = idx0;
}
hsTArray<EdgeBin>& loBin = bins[lo];
// In that bucket, look for the higher index.
int k;
for( k = 0; k < loBin.GetCount(); k++ )
{
if( loBin[k].fVtx == hi )
break;
}
// If we find it, increment it's count,
// else add it.
if( k < loBin.GetCount() )
{
loBin[k].fCount++;
}
else
{
EdgeBin* b = loBin.Push();
b->fVtx = hi;
b->fCount = 1;
}
}
}
// For each bucket in the LUT,
for( i = 0; i < maxVtxIdx+1; i++ )
{
hsTArray<EdgeBin>& loBin = bins[i];
// For each higher index
int j;
for( j = 0; j < loBin.GetCount(); j++ )
{
// If the count is one, it's an edge, so set the edge bit for both indices (hi and lo)
if( 1 == loBin[j].fCount )
{
edgeVertBits.SetBit(i);
edgeVertBits.SetBit(loBin[j].fVtx);
}
}
}
// Now translate the bitvector to a list of indices.
for( i = 0; i < maxVtxIdx+1; i++ )
{
if( edgeVertBits.IsBitSet(i) )
edgeVerts.Append(i);
}
delete [] bins;
}
void plInterMeshSmooth::FindEdges(hsTArray<plSpanHandle>& sets, hsTArray<UInt16>* edgeVerts)
{
int i;
for( i = 0; i < sets.GetCount(); i++ )
{
const plSpan* span = sets[i].fDrawable->GetSpan(sets[i].fSpanIdx);
if( !(span->fTypeMask & plSpan::kIcicleSpan) )
continue;
UInt32 nTris = sets[i].fDrawable->CvtGetNumTris(sets[i].fSpanIdx);
UInt16* idxList = sets[i].fDrawable->CvtGetIndexList(sets[i].fSpanIdx);
UInt32 maxVertIdx = sets[i].fDrawable->CvtGetNumVerts(sets[i].fSpanIdx)-1;
FindEdges(maxVertIdx, nTris, idxList, edgeVerts[i]);
}
}
void plInterMeshSmooth::SmoothNormals(hsTArray<plSpanHandle>& sets)
{
hsTArray<UInt16>* shareVtx = TRACKED_NEW hsTArray<UInt16>[sets.GetCount()];
hsTArray<UInt16>* edgeVerts = TRACKED_NEW hsTArray<UInt16>[sets.GetCount()];
FindEdges(sets, edgeVerts);
int i;
for( i = 0; i < sets.GetCount()-1; i++ )
{
int j;
for( j = edgeVerts[i].GetCount()-1; j >= 0; --j )
{
hsPoint3 pos = GetPosition(sets[i], edgeVerts[i][j]);
hsVector3 normAccum = GetNormal(sets[i], edgeVerts[i][j]);;
shareVtx[i].Append(edgeVerts[i][j]);
int k;
for( k = i+1; k < sets.GetCount(); k++ )
{
FindSharedVerts(pos, sets[k], edgeVerts[k], shareVtx[k], normAccum);
}
normAccum.Normalize();
GetNormal(sets[i], edgeVerts[i][j]) = normAccum;
for( k = i+1; k < sets.GetCount(); k++ )
{
SetNormals(sets[k], shareVtx[k], normAccum);
}
// Now remove all the shared verts (which we just processed)
// from edgeVerts so we don't process them again.
for( k = i; k < sets.GetCount(); k++ )
{
int m;
for( m = 0; m < shareVtx[k].GetCount(); m++ )
{
int idx = edgeVerts[k].Find(shareVtx[k][m]);
hsAssert(idx != edgeVerts[k].kMissingIndex, "Lost vertex between find and remove");
edgeVerts[k].Remove(idx);
}
shareVtx[k].SetCount(0);
}
}
}
delete [] shareVtx;
delete [] edgeVerts;
}
void plInterMeshSmooth::FindSharedVerts(hsPoint3& searchPos, plSpanHandle& set, hsTArray<UInt16>& edgeVerts, hsTArray<UInt16>& shareVtx, hsVector3& normAccum)
{
int i;
for( i = 0; i < edgeVerts.GetCount(); i++ )
{
hsPoint3 pos = GetPosition(set, edgeVerts[i]);
hsVector3 norm = GetNormal(set, edgeVerts[i]);
if( searchPos == pos )
{
if( norm.InnerProduct(normAccum) > fMinNormDot )
{
shareVtx.Append(edgeVerts[i]);
normAccum += norm;
}
}
}
}
void plInterMeshSmooth::SetNormals(plSpanHandle& set, hsTArray<UInt16>& shareVtx, hsVector3& norm)
{
int i;
for( i = 0; i < shareVtx.GetCount(); i++ )
GetNormal(set, shareVtx[i]) = norm;
}
hsPoint3& plInterMeshSmooth::GetPosition(plSpanHandle& set, UInt16 idx)
{
return set.fDrawable->CvtGetPosition(set.fSpanIdx, idx);
}
hsVector3& plInterMeshSmooth::GetNormal(plSpanHandle& set, UInt16 idx)
{
return set.fDrawable->CvtGetNormal(set.fSpanIdx, idx);
}
void plInterMeshSmooth::SetAngle(hsScalar degs)
{
fMinNormDot = hsCosine(hsScalarDegToRad(degs));
}
hsScalar plInterMeshSmooth::GetAngle() const
{
return hsScalarRadToDeg(hsACosine(fMinNormDot));
}

View File

@ -0,0 +1,80 @@
/*==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 plInterMeshSmooth_inc
#define plInterMeshSmooth_inc
#include "hsTemplates.h"
class plDrawableSpans;
struct hsPoint3;
struct hsVector3;
class plSpanHandle
{
public:
plDrawableSpans* fDrawable;
UInt32 fSpanIdx;
};
class plInterMeshSmooth
{
protected:
hsScalar fMinNormDot;
void FindEdges(UInt32 maxVtxIdx, UInt32 nTris, UInt16* idxList, hsTArray<UInt16>& edgeVerts);
void FindEdges(hsTArray<plSpanHandle>& sets, hsTArray<UInt16>* edgeVerts);
void FindSharedVerts(hsPoint3& searchPos, plSpanHandle& set, hsTArray<UInt16>& edgeVerts, hsTArray<UInt16>& shareVtx, hsVector3& normAccum);
void SetNormals(plSpanHandle& set, hsTArray<UInt16>& shareVtx, hsVector3& norm);
hsPoint3& GetPosition(plSpanHandle& set, UInt16 idx);
hsVector3& GetNormal(plSpanHandle& set, UInt16 idx);
public:
plInterMeshSmooth() : fMinNormDot(0.25f) {}
void SetAngle(hsScalar degs);
hsScalar GetAngle() const; // returns degrees
void SmoothNormals(hsTArray<plSpanHandle>& sets);
};
#endif // plInterMeshSmooth_inc

View File

@ -0,0 +1,100 @@
/*==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 "plMorphArray.h"
plMorphArray::plMorphArray()
{
}
plMorphArray::~plMorphArray()
{
}
// MorphArray - Apply
void plMorphArray::Apply(hsTArray<plAccessSpan>& dst, hsTArray<hsScalar>* weights /* = nil */) const
{
// Have our choice of cache thrashing here
// We can for each delta/for each vert
// or for each vert/for each delta
// I'll go for the former, though I can't say why at the moment.
// A nice thing about the outer loop being for each delta is
// that a delta with a weight of zero can just bag it with one if.
//
// For each delta
int i;
for( i = 0; i < fDeltas.GetCount(); i++ )
{
// delta->Apply
fDeltas[i].Apply(dst, (weights ? weights->Get(i) : -1.f));
}
}
void plMorphArray::Read(hsStream* s, hsResMgr* mgr)
{
int n = s->ReadSwap32();
fDeltas.SetCount(n);
int i;
for( i = 0; i < n; i++ )
fDeltas[i].Read(s, mgr);
}
void plMorphArray::Write(hsStream* s, hsResMgr* mgr)
{
s->WriteSwap32(fDeltas.GetCount());
int i;
for( i = 0; i < fDeltas.GetCount(); i++ )
fDeltas[i].Write(s, mgr);
}
void plMorphArray::Reset()
{
fDeltas.Reset();
}
void plMorphArray::AddDelta(const plMorphDelta& delta)
{
fDeltas.Append(delta);
}

View File

@ -0,0 +1,69 @@
/*==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 plMorphArray_inc
#define plMorphArray_inc
#include "plMorphDelta.h"
class plMorphArray
{
protected:
hsTArray<plMorphDelta> fDeltas;
public:
plMorphArray();
virtual ~plMorphArray();
void Apply(hsTArray<plAccessSpan>& dst, hsTArray<hsScalar>* weights = nil) const;
void Read(hsStream* s, hsResMgr* mgr);
void Write(hsStream* s, hsResMgr* mgr);
void Reset();
void AddDelta(const plMorphDelta& delta);
int GetNumDeltas() const { return fDeltas.GetCount(); }
hsScalar GetWeight(int iDel) { return fDeltas[iDel].GetWeight(); }
void SetWeight(int iDel, hsScalar w) { if( iDel < fDeltas.GetCount() )fDeltas[iDel].SetWeight(w); }
};
#endif // plMorphArray_inc

View File

@ -0,0 +1,353 @@
/*==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 "plMorphDelta.h"
#include "hsStream.h"
#include "hsMemory.h"
#include "plAccessGeometry.h"
#include "plAccessSpan.h"
#include "plAccessVtxSpan.h"
#include "plGeometrySpan.h"
#include "plTweak.h"
static const hsScalar kMinWeight = 1.e-2f;
plMorphSpan::plMorphSpan()
: fUVWs(nil),
fNumUVWChans(0)
{
}
plMorphSpan::~plMorphSpan()
{
delete [] fUVWs;
}
plMorphDelta::plMorphDelta()
: fWeight(0)
{
}
plMorphDelta::~plMorphDelta()
{
}
plMorphDelta::plMorphDelta(const plMorphDelta& src)
{
*this = src;
}
plMorphDelta& plMorphDelta::operator=(const plMorphDelta& src)
{
SetNumSpans(src.GetNumSpans());
int i;
for( i = 0; i < fSpans.GetCount(); i++ )
{
SetDeltas(i, src.fSpans[i].fDeltas, src.fSpans[i].fNumUVWChans, src.fSpans[i].fUVWs);
}
return *this;
}
void plMorphDelta::Apply(hsTArray<plAccessSpan>& dst, hsScalar weight /* = -1.f */) const
{
if( weight == -1.f)
weight = fWeight; // None passed in, use our stored value
if( weight <= kMinWeight )
return;
// Easy
// For each span
int iSpan;
for( iSpan = 0; iSpan < fSpans.GetCount(); iSpan++ )
{
plAccessVtxSpan& vtxDst = dst[iSpan].AccessVtx();
plMorphSpan& span = fSpans[iSpan];
// For each vertDelta
const hsPoint3* uvwDel = span.fUVWs;
int iDelta;
for( iDelta = 0; iDelta < span.fDeltas.GetCount(); iDelta++ )
{
const plVertDelta& delta = span.fDeltas[iDelta];
// Add delPos * wgt to position
// Add delNorm * wgt to normal
vtxDst.Position(delta.fIdx) += delta.fPos * weight;
vtxDst.Normal(delta.fIdx) += delta.fNorm * weight;
// Leave skin weights and indices alone?
// Skip color for now, since diffuse and specular are
// ignored on the avatar?
// // Add delDiff * wgt to diffuse
// // Add delSpec * wgt to specular
// For each UVW
hsPoint3* uvws = vtxDst.UVWs(delta.fIdx);
int iUVW;
for( iUVW = 0; iUVW < span.fNumUVWChans; iUVW++ )
{
// Add delUVW * wgt to uvw
*uvws += *uvwDel * weight;
uvws++;
uvwDel++;
}
}
}
}
// MorphDelta - ComputeDeltas
void plMorphDelta::ComputeDeltas(const hsTArray<plAccessSpan>& base, const hsTArray<plAccessSpan>& moved)
{
SetNumSpans(base.GetCount());
// For each span
{
// for( i = 0; i < numVerts; i++ )
{
// NOTE: we want to discard zero deltas, but a
// delta in any channel forces us to save the whole thing.
// But we don't want to compare to zero (because we'll end
// up with a lot of near zero deltas), but the epsilon we
// compare to needs to be different for comparing something
// like a normal delta and a position delta.
//
// For position, normal, color and all uvws
// Calc del and delLenSq
// If any delLenSq big enough, set nonZero to true
// If nonZero
{
// Append to deltas (i, del's)
}
}
}
}
// MorphDelta - ComputeDeltas
void plMorphDelta::ComputeDeltas(const hsTArray<plGeometrySpan*>& base, const hsTArray<plGeometrySpan*>& moved, const hsMatrix44& d2b, const hsMatrix44& d2bTInv)
{
SetNumSpans(base.GetCount());
hsPoint3 delUVWs[8];
// For each span
int iSpan;
for( iSpan = 0; iSpan < base.GetCount(); iSpan++ )
{
plAccessSpan baseAcc;
plAccessGeometry::Instance()->AccessSpanFromGeometrySpan(baseAcc, base[iSpan]);
plAccessSpan movedAcc;
plAccessGeometry::Instance()->AccessSpanFromGeometrySpan(movedAcc, moved[iSpan]);
plAccPosNormUVWIterator baseIter(&baseAcc.AccessVtx());
plAccPosNormUVWIterator movedIter(&movedAcc.AccessVtx());
plMorphSpan& dst = fSpans[iSpan];
const UInt16 numUVWs = baseAcc.AccessVtx().NumUVWs();
hsTArray<plVertDelta> deltas;
hsTArray<hsPoint3> uvws;
deltas.SetCount(0);
uvws.SetCount(0);
int iVert = 0;;
for( baseIter.Begin(), movedIter.Begin(); baseIter.More(); baseIter.Advance(), movedIter.Advance() )
{
// NOTE: we want to discard zero deltas, but a
// delta in any channel forces us to save the whole thing.
// But we don't want to compare to zero (because we'll end
// up with a lot of near zero deltas), but the epsilon we
// compare to needs to be different for comparing something
// like a normal delta and a position delta.
//
// For position, normal, color and all uvws
// Calc del and delLenSq
// If any delLenSq big enough, set nonZero to true
hsBool nonZero = false;
// These are actually min del SQUARED.
plConst(hsScalar) kMinDelPos(1.e-4f); // From Budtpueller's Handbook of Constants
plConst(hsScalar) kMinDelNorm(3.e-2f); // About 10 degrees
plConst(hsScalar) kMinDelUVW(1.e-4f); // From BHC
hsPoint3 mPos = d2b * *movedIter.Position();
hsVector3 delPos( &mPos, baseIter.Position());
hsScalar delPosSq = delPos.MagnitudeSquared();
if( delPosSq > kMinDelPos )
nonZero = true;
else
delPos.Set(0,0,0);
hsVector3 delNorm = (d2bTInv * *movedIter.Normal()) - *baseIter.Normal();
hsScalar delNormSq = delNorm.MagnitudeSquared();
if( delNormSq > kMinDelNorm )
nonZero = true;
else
delNorm.Set(0,0,0);
int i;
for( i = 0; i < numUVWs; i++ )
{
delUVWs[i] = *movedIter.UVW(i) - *baseIter.UVW(i);
hsScalar delUVWSq = delUVWs[i].MagnitudeSquared();
if( delUVWSq > kMinDelUVW )
nonZero = true;
else
delUVWs[i].Set(0,0,0);
}
if( nonZero )
{
// Append to deltas (i, del's)
plVertDelta del;
del.fIdx = iVert;
del.fPos = delPos;
del.fNorm = delNorm;
deltas.Append(del);
for( i = 0; i < numUVWs; i++ )
uvws.Append(delUVWs[i]);
}
else
{
nonZero = false; // Breakpoint.
}
iVert++;
}
SetDeltas(iSpan, deltas, numUVWs, uvws.AcquireArray());
}
}
void plMorphDelta::SetNumSpans(int n)
{
fSpans.Reset();
fSpans.SetCount(n);
}
void plMorphDelta::AllocDeltas(int iSpan, int nDel, int nUVW)
{
fSpans[iSpan].fDeltas.SetCount(nDel);
fSpans[iSpan].fNumUVWChans = nUVW;
delete [] fSpans[iSpan].fUVWs;
int uvwCnt = nDel * nUVW;
if( uvwCnt )
fSpans[iSpan].fUVWs = TRACKED_NEW hsPoint3[uvwCnt];
else
fSpans[iSpan].fUVWs = nil;
}
void plMorphDelta::SetDeltas(int iSpan, const hsTArray<plVertDelta>& deltas, int numUVWChans, const hsPoint3* uvws)
{
AllocDeltas(iSpan, deltas.GetCount(), numUVWChans);
if( deltas.GetCount() )
{
HSMemory::BlockMove(&deltas[0], fSpans[iSpan].fDeltas.AcquireArray(), deltas.GetCount() * sizeof(plVertDelta));
if( numUVWChans )
HSMemory::BlockMove(uvws, fSpans[iSpan].fUVWs, deltas.GetCount() * numUVWChans * sizeof(*uvws));
}
}
void plMorphDelta::Read(hsStream* s, hsResMgr* mgr)
{
fWeight = s->ReadSwapScalar();
int n = s->ReadSwap32();
SetNumSpans(n);
int iSpan;
for( iSpan = 0; iSpan < n; iSpan++ )
{
int nDel = s->ReadSwap32();
int nUVW = s->ReadSwap32();
AllocDeltas(iSpan, nDel, nUVW);
if( nDel )
{
s->Read(nDel * sizeof(plVertDelta), fSpans[iSpan].fDeltas.AcquireArray());
if( nUVW )
s->Read(nDel * nUVW * sizeof(hsPoint3), fSpans[iSpan].fUVWs);
}
}
}
void plMorphDelta::Write(hsStream* s, hsResMgr* mgr)
{
s->WriteSwapScalar(fWeight);
s->WriteSwap32(fSpans.GetCount());
int iSpan;
for( iSpan = 0; iSpan < fSpans.GetCount(); iSpan++ )
{
int nDel = fSpans[iSpan].fDeltas.GetCount();
int nUVW = fSpans[iSpan].fNumUVWChans;
s->WriteSwap32(nDel);
s->WriteSwap32(nUVW);
if( nDel )
{
// Initialize our padding here, so we don't write random data
for (int i = 0; i < nDel; i++)
{
plVertDelta& delta = fSpans[iSpan].fDeltas[i];
delta.fPadding = 0;
}
s->Write(nDel * sizeof(plVertDelta), fSpans[iSpan].fDeltas.AcquireArray());
if( nUVW )
s->Write(nDel * nUVW * sizeof(hsPoint3), fSpans[iSpan].fUVWs);
}
}
}

View File

@ -0,0 +1,108 @@
/*==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 plMorphDelta_inc
#define plMorphDelta_inc
#include "hsTemplates.h"
#include "hsGeometry3.h"
#include "../pnFactory/plCreatable.h"
#include "plAccessSpan.h"
class plVertDelta
{
public:
UInt16 fIdx;
UInt16 fPadding;
hsVector3 fPos;
hsVector3 fNorm;
};
class plMorphSpan
{
public:
plMorphSpan();
virtual ~plMorphSpan();
hsTArray<plVertDelta> fDeltas;
UInt16 fNumUVWChans;
hsPoint3* fUVWs; // Length is fUVWChans*fDeltas.GetCount() (*sizeof(hsPoint3) in bytes).
};
class plMorphDelta : public plCreatable
{
protected:
hsTArray<plMorphSpan> fSpans;
hsScalar fWeight;
public:
plMorphDelta();
virtual ~plMorphDelta();
plMorphDelta(const plMorphDelta& src);
plMorphDelta& operator=(const plMorphDelta& src);
CLASSNAME_REGISTER( plMorphDelta );
GETINTERFACE_ANY( plMorphDelta, plCreatable );
void SetWeight(hsScalar w) { fWeight = w; }
hsScalar GetWeight() const { return fWeight; }
void Apply(hsTArray<plAccessSpan>& dst, hsScalar weight = -1.f) const;
void ComputeDeltas(const hsTArray<plAccessSpan>& base, const hsTArray<plAccessSpan>& moved);
void ComputeDeltas(const hsTArray<plGeometrySpan*>& base, const hsTArray<plGeometrySpan*>& moved, const hsMatrix44& d2b, const hsMatrix44& d2bTInv);
UInt32 GetNumSpans() const { return fSpans.GetCount(); }
void SetNumSpans(int n);
void SetDeltas(int iSpan, const hsTArray<plVertDelta>& deltas, int numUVWChans, const hsPoint3* uvws); // len uvws is deltas.GetCount() * numUVWChans
void AllocDeltas(int iSpan, int nDel, int nUVW);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
};
#endif // plMorphDelta_inc

View File

@ -0,0 +1,823 @@
/*==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 "plMorphSequence.h"
#include "plMorphSequenceSDLMod.h"
#include "plAccessGeometry.h"
#include "plAccessVtxSpan.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plDrawInterface.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "plDrawableSpans.h"
#include "plInstanceDrawInterface.h"
#include "hsResMgr.h"
#include "plgDispatch.h"
#include "../plMessage/plRenderMsg.h"
#include "plSharedMesh.h"
#include "plTweak.h"
#include "hsTimer.h"
#include "hsFastMath.h"
///////////////////////////////////////////////////////////////////////////
void plMorphDataSet::Read(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Read(s, mgr);
int n = s->ReadSwap32();
fMorphs.SetCount(n);
int i;
for( i = 0; i < n; i++ )
fMorphs[i].Read(s, mgr);
}
void plMorphDataSet::Write(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Write(s, mgr);
s->WriteSwap32(fMorphs.GetCount());
int i;
for( i = 0; i < fMorphs.GetCount(); i++ )
fMorphs[i].Write(s, mgr);
}
///////////////////////////////////////////////////////////////////////////
const UInt32 kChanMask = plAccessVtxSpan::kPositionMask
| plAccessVtxSpan::kNormalMask
| plAccessVtxSpan::kUVWMask;
// Probably want another type which is just initialize/override
// so we can set the mesh to whatever base set we want, as if
// that's what got loaded from disk.
// Use Access RW. That might already be handled in the customization stuff.
plConst(hsScalar) kMorphTime(0.5);
class plMorphTarget
{
public:
UInt16 fLayer;
UInt16 fDelta;
hsScalar fWeight;
};
hsTArray<plMorphTarget> fTgtWgts;
plMorphSequence::plMorphSequence()
: fMorphFlags(0),
fMorphSDLMod(nil),
fGlobalLayerRef(-1)
{
}
plMorphSequence::~plMorphSequence()
{
DeInit();
}
hsBool plMorphSequence::MsgReceive(plMessage* msg)
{
plRenderMsg* rend = plRenderMsg::ConvertNoRef(msg);
if( rend )
{
// For now, I'm ignoring the target weight stuff for shared meshes.
// Can always add it in later if desired.
if( fTgtWgts.GetCount() )
{
hsScalar delWgt = hsTimer::GetDelSysSeconds() / (kMorphTime > 0 ? kMorphTime : 1.e-3f);
int i;
for( i = 0; i < fTgtWgts.GetCount(); i++ )
{
hsScalar currWgt = GetWeight(fTgtWgts[i].fLayer, fTgtWgts[i].fDelta);
if( fTgtWgts[i].fWeight < currWgt )
{
if( fTgtWgts[i].fWeight >= (currWgt -= delWgt) )
currWgt = fTgtWgts[i].fWeight;
}
else if( fTgtWgts[i].fWeight > currWgt )
{
if( fTgtWgts[i].fWeight <= (currWgt += delWgt) )
currWgt = fTgtWgts[i].fWeight;
}
fMorphs[fTgtWgts[i].fLayer].SetWeight(fTgtWgts[i].fDelta, currWgt);
if( fTgtWgts[i].fWeight == currWgt )
{
fTgtWgts.Remove(i);
i--;
}
}
ISetDirty(true);
}
if( !(fMorphFlags & kDirty) )
{
// We went a whole frame without getting dirty,
// we can stop refreshing now.
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
return true;
}
ISetDirty(false);
if( fMorphFlags & kDirtyIndices )
IFindIndices();
if( fMorphFlags & kHaveShared )
{
IApplyShared();
}
else
{
Apply();
}
return true;
}
plSharedMeshBCMsg *smMsg = plSharedMeshBCMsg::ConvertNoRef(msg);
if (smMsg)
{
if (IGetDrawInterface()->GetKey() == smMsg->GetSender() || IIsUsingDrawable(smMsg->fDraw))
fMorphFlags |= kDirtyIndices;
}
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef(msg);
if (refMsg)
{
plSharedMesh *mesh = plSharedMesh::ConvertNoRef(refMsg->GetRef());
if (mesh)
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest) )
{
AddSharedMesh(mesh);
}
else if( refMsg->GetContext() & plRefMsg::kOnReplace)
{
plSharedMesh *oldMesh = plSharedMesh::ConvertNoRef(refMsg->GetOldRef());
if (oldMesh)
RemoveSharedMesh(oldMesh);
AddSharedMesh(mesh);
}
else if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
RemoveSharedMesh(mesh);
return true;
}
}
return plSingleModifier::MsgReceive(msg);
}
int plMorphSequence::GetNumLayers(plKey meshKey /* = nil */) const
{
int index = IFindSharedMeshIndex(meshKey);
if (index < 0)
return fMorphs.GetCount();
else
return fSharedMeshes[index].fMesh->fMorphSet->fMorphs.GetCount();
}
int plMorphSequence::GetNumDeltas(int iLay, plKey meshKey /* = nil */) const
{
int index = IFindSharedMeshIndex(meshKey);
if (index < 0)
return fMorphs[iLay].GetNumDeltas();
else
return fSharedMeshes[index].fMesh->fMorphSet->fMorphs[iLay].GetNumDeltas();
}
hsScalar plMorphSequence::GetWeight(int iLay, int iDel, plKey meshKey /* = nil */) const
{
int index = IFindSharedMeshIndex(meshKey);
if (index == -1)
return fMorphs[iLay].GetWeight(iDel);
else
return fSharedMeshes[index].fArrayWeights[iLay].fDeltaWeights[iDel];
}
void plMorphSequence::SetWeight(int iLay, int iDel, hsScalar w, plKey meshKey /* = nil */)
{
int index = IFindSharedMeshIndex(meshKey);
// Only dirty if the weight isn't for a pending mesh
if(meshKey == nil || index >= 0)
ISetDirty(true);
if (meshKey == nil)
{
if( iLay < fMorphs.GetCount() )
{
if( kMorphTime > 0 )
{
plMorphTarget tgt;
tgt.fLayer = iLay;
tgt.fDelta = iDel;
tgt.fWeight = w;
fTgtWgts.Append(tgt);
}
else
{
fMorphs[iLay].SetWeight(iDel, w);
}
}
}
else if (index >= 0)
{
fSharedMeshes[index].fArrayWeights[iLay].fDeltaWeights[iDel] = w;
fSharedMeshes[index].fFlags |= plSharedMeshInfo::kInfoDirtyMesh;
if (index == fGlobalLayerRef)
ISetAllSharedToGlobal();
}
else
{
// Setting weight for a mesh we haven't added yet (loading state)
index = IFindPendingStateIndex(meshKey);
if (index < 0)
{
fPendingStates.Push();
index = fPendingStates.GetCount() - 1;
fPendingStates[index].fSharedMeshKey = meshKey;
}
if (fPendingStates[index].fArrayWeights.GetCount() <= iLay)
{
int had = fPendingStates[index].fArrayWeights.GetCount();
hsTArray<plMorphArrayWeights> temp(iLay + 1);
temp = fPendingStates[index].fArrayWeights;
temp.SetCount(iLay + 1);
fPendingStates[index].fArrayWeights.Swap(temp);
int i;
for( i = had; i < iLay+1; i++ )
fPendingStates[index].fArrayWeights[i].fDeltaWeights.Reset();
}
if (fPendingStates[index].fArrayWeights[iLay].fDeltaWeights.GetCount() <= iDel)
fPendingStates[index].fArrayWeights[iLay].fDeltaWeights.ExpandAndZero(iDel + 1);
fPendingStates[index].fArrayWeights[iLay].fDeltaWeights[iDel] = w;
}
}
void plMorphSequence::ISetDirty(hsBool on)
{
if( on )
{
if( !(fMorphFlags & kDirty) )
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
fMorphFlags |= kDirty;
// Even if we know we're already dirty, there could be new info this frame.
// Need to tell our scene object
//
// Actually, in the case of the avatar, this sends an insane flurry of messages to the server
// when we drag (or even just hold the mouse button down on) the morph scrollbars.
// These messages are completely unneccessary. We broadcast our state when we join a new age, and that's enough.
// Non-avatar related morphs (if they ever exist) will need to call DirtySynchState some special
// way. Not here.
//
//if (GetTarget(0))
// GetTarget(0)->DirtySynchState(kSDLMorphSequence, 0);
}
else
{
fMorphFlags &= ~kDirty;
}
}
// MorphSequence - Init
void plMorphSequence::Init()
{
if( fMorphFlags & kHaveShared )
{
IFindIndices();
}
else
{
if( !GetHaveSnap() )
{
// Take an access snapshot of all our spans
const plDrawInterface* di = IGetDrawInterface();
plAccessGeometry::Instance()->TakeSnapShot(di, kChanMask);
ISetHaveSnap(true);
}
}
}
void plMorphSequence::Activate()
{
Init();
ISetDirty(true);
}
void plMorphSequence::DeActivate()
{
if( fMorphFlags & kHaveShared )
{
IReleaseIndices();
}
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
}
// MorphSequence - DeInit
void plMorphSequence::DeInit()
{
if( fMorphFlags & kHaveShared )
{
IReleaseIndices();
}
else
{
if( GetHaveSnap() )
{
// Release all our snapshot data
const plDrawInterface* di = IGetDrawInterface();
if( di )
plAccessGeometry::Instance()->ReleaseSnapShot(di);
ISetHaveSnap(false);
}
}
}
void plMorphSequence::IRenormalize(hsTArray<plAccessSpan>& dst) const
{
int i;
for( i = 0; i < dst.GetCount(); i++ )
{
hsAssert(dst[i].HasAccessVtx(), "Come on, everyone has vertices");
plAccessVtxSpan& accVtx = dst[i].AccessVtx();
int j;
for( j = 0; j < accVtx.VertCount(); j++ )
{
hsFastMath::Normalize(accVtx.Normal(j));
}
}
}
// MorphSequence - Apply
void plMorphSequence::Apply() const
{
const plDrawInterface* di = IGetDrawInterface();
if( !di )
return;
// Reset to initial.
Reset(di);
// We'll be accumulating into the buffer, so open RW
hsTArray<plAccessSpan> dst;
plAccessGeometry::Instance()->OpenRW(di, dst);
// For each MorphArray
int i;
for( i = 0; i < fMorphs.GetCount(); i++ )
{
// Apply Delta
fMorphs[i].Apply(dst);
}
IRenormalize(dst);
// Close up the access spans
plAccessGeometry::Instance()->Close(dst);
}
// MorphSequence - Reset to initial
void plMorphSequence::Reset(const plDrawInterface* di) const
{
if( !di )
{
di = IGetDrawInterface();
}
// Use access span RestoreSnapshot
if( di )
plAccessGeometry::Instance()->RestoreSnapShot(di, kChanMask);
}
const plDrawInterface* plMorphSequence::IGetDrawInterface() const
{
plSceneObject* so = GetTarget();
if( !so )
return nil;
const plDrawInterface* di = so->GetDrawInterface();
return di;
}
void plMorphSequence::AddTarget(plSceneObject* so)
{
plSingleModifier::AddTarget(so);
if (!fMorphSDLMod)
{
fMorphSDLMod = TRACKED_NEW plMorphSequenceSDLMod;
so->AddModifier(fMorphSDLMod);
}
}
void plMorphSequence::RemoveTarget(plSceneObject *so)
{
plSingleModifier::RemoveTarget(so);
if (so)
if (fMorphSDLMod)
so->RemoveModifier(fMorphSDLMod);
delete fMorphSDLMod;
fMorphSDLMod = nil;
}
void plMorphSequence::Read(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Read(s, mgr);
fMorphFlags = 0;
int n = s->ReadSwap32();
fMorphs.SetCount(n);
int i;
for( i = 0; i < n; i++ )
fMorphs[i].Read(s, mgr);
n = s->ReadSwap32();
for( i = 0; i < n; i++)
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, -1), plRefFlags::kActiveRef);
}
void plMorphSequence::Write(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Write(s, mgr);
s->WriteSwap32(fMorphs.GetCount());
int i;
for( i = 0; i < fMorphs.GetCount(); i++ )
fMorphs[i].Write(s, mgr);
s->WriteSwap32(fSharedMeshes.GetCount());
for( i = 0; i < fSharedMeshes.GetCount(); i++ )
mgr->WriteKey(s, fSharedMeshes[i].fMesh);
}
// Normal sequence of calls:
// 1) on notification that meshes have changed (or activate)
// IFindIndices() - Sets up indices
// IApplyShared() - Find which mesh is active and
// IResetShared(iActive);
// IApplyShared(iActive);
// go dormant
// 2) on weight change
// SetWeight() - Register for render message and set the new weight
// 3) on render msg:
// if dirty
// IApplyShared() - Find which mesh is active and
// IResetShared(iActive);
// IApplyShared(iActive);
// else
// Unregister for render message.
// 4) on deinit
// IReleaseIndices() - Just let's us know there's nothing much to be done.
//
void plMorphSequence::IResetShared()
{
int i;
for (i = 0; i < fSharedMeshes.GetCount(); i++)
IResetShared(i);
}
void plMorphSequence::IApplyShared()
{
int i;
for (i = 0; i < fSharedMeshes.GetCount(); i++)
{
IResetShared(i);
IApplyShared(i);
}
}
void plMorphSequence::IFindIndices()
{
fMorphFlags &= ~kDirtyIndices;
int i;
for( i = 0; i < fSharedMeshes.GetCount(); i++ )
IFindIndices(i);
}
void plMorphSequence::IReleaseIndices()
{
int i;
for( i = 0; i < fSharedMeshes.GetCount(); i++ )
IReleaseIndices(i);
}
void plMorphSequence::IApplyShared(int iShare)
{
if( iShare >= fSharedMeshes.GetCount() || fSharedMeshes[iShare].fCurrDraw == nil)
return;
plSharedMeshInfo& mInfo = fSharedMeshes[iShare];
hsTArray<plAccessSpan> dst;
// Now copy each shared mesh geometryspan into the drawable
// to get it back to it's pristine condition.
int i;
for( i = 0; i < mInfo.fMesh->fSpans.GetCount(); i++ )
{
plAccessSpan dstAcc;
plAccessGeometry::Instance()->OpenRW(mInfo.fCurrDraw, mInfo.fCurrIdx[i], dstAcc);
dst.Append(dstAcc);
}
// For each MorphArray
for( i = 0; i < mInfo.fMesh->fMorphSet->fMorphs.GetCount(); i++ )
{
// Apply Delta
mInfo.fMesh->fMorphSet->fMorphs[i].Apply(dst, &mInfo.fArrayWeights[i].fDeltaWeights);
}
IRenormalize(dst);
// Close up the access spans
plAccessGeometry::Instance()->Close(dst);
mInfo.fFlags &= ~plSharedMeshInfo::kInfoDirtyMesh;
}
hsBool plMorphSequence::IResetShared(int iShare)
{
if( iShare >= fSharedMeshes.GetCount() || fSharedMeshes[iShare].fCurrDraw == nil)
return false;
plSharedMeshInfo& mInfo = fSharedMeshes[iShare];
// Now copy each shared mesh geometryspan into the drawable
// to get it back to it's pristine condition.
int i;
for( i = 0; i < mInfo.fMesh->fSpans.GetCount(); i++ )
{
plAccessSpan srcAcc;
plAccessGeometry::Instance()->AccessSpanFromGeometrySpan(srcAcc, mInfo.fMesh->fSpans[i]);
plAccessSpan dstAcc;
plAccessGeometry::Instance()->OpenRW(mInfo.fCurrDraw, mInfo.fCurrIdx[i], dstAcc);
plAccPosNormUVWIterator srcIter(&srcAcc.AccessVtx());
plAccPosNormUVWIterator dstIter(&dstAcc.AccessVtx());
const int numUVWs = srcAcc.AccessVtx().NumUVWs();
for( srcIter.Begin(), dstIter.Begin(); srcIter.More(); srcIter.Advance(), dstIter.Advance() )
{
*dstIter.Position() = *srcIter.Position();
*dstIter.Normal() = *srcIter.Normal();
int j;
for( j = 0; j < numUVWs; j++ )
*dstIter.UVW(j) = *srcIter.UVW(j);
}
}
return true;
}
hsBool plMorphSequence::IFindIndices(int iShare)
{
plSharedMeshInfo& mInfo = fSharedMeshes[iShare];
mInfo.fCurrDraw = nil; // In case we fail.
const plInstanceDrawInterface* di = plInstanceDrawInterface::ConvertNoRef(IGetDrawInterface());
if( !di )
return false;
Int32 meshIdx = di->GetSharedMeshIndex(mInfo.fMesh);
if( meshIdx < 0 )
return false;
plDrawableSpans* dr = plDrawableSpans::ConvertNoRef(di->GetDrawable((UInt8)meshIdx));
if( !dr )
return false;
mInfo.fCurrDraw = dr;
plDISpanIndex& diIndex = dr->GetDISpans(di->GetDrawableMeshIndex((UInt8)meshIdx));
hsAssert(mInfo.fMesh->fSpans.GetCount() == diIndex.GetCount(), "Mismatch between geometry and indices");
mInfo.fCurrIdx.SetCount(diIndex.GetCount());
int i;
for( i = 0; i < diIndex.GetCount(); i++ )
mInfo.fCurrIdx[i] = diIndex[i];
return true;
}
void plMorphSequence::IReleaseIndices(int iShare)
{
plSharedMeshInfo& mInfo = fSharedMeshes[iShare];
mInfo.fCurrDraw = nil;
}
Int32 plMorphSequence::IFindSharedMeshIndex(plKey meshKey) const
{
int i;
for( i = 0; i < fSharedMeshes.GetCount(); i++ )
{
if (fSharedMeshes[i].fMesh->GetKey() == meshKey)
return i;
}
return -1;
}
Int32 plMorphSequence::IFindPendingStateIndex(plKey meshKey) const
{
int i;
for( i = 0; i < fPendingStates.GetCount(); i++ )
{
if (fPendingStates[i].fSharedMeshKey == meshKey)
return i;
}
return -1;
}
hsBool plMorphSequence::IIsUsingDrawable(plDrawable *draw)
{
int i;
for (i = 0; i < fSharedMeshes.GetCount(); i++)
{
if (fSharedMeshes[i].fCurrDraw == draw)
return true;
}
return false;
}
void plMorphSequence::AddSharedMesh(plSharedMesh* mesh)
{
// This happens if SDL state tells us to use a mesh without morph info
// (Either because the object used to but no longer does, or because
// the SDL is giving us the wrong key.)
if (!mesh->fMorphSet)
return;
if (fSharedMeshes.GetCount() == 0)
plgDispatch::Dispatch()->RegisterForExactType(plSharedMeshBCMsg::Index(), GetKey());
if (IFindSharedMeshIndex(mesh->GetKey()) >= 0)
return; // We already have it.
hsAssert(fSharedMeshes.GetCount() < 127, "Too many meshes for one morph sequence.");
SetUseSharedMesh(true);
int pendingIndex = IFindPendingStateIndex(mesh->GetKey());
plSharedMeshInfo mInfo;
mInfo.fMesh = mesh;
mInfo.fCurrDraw = nil;
// Intialize our weights to zero.
mInfo.fArrayWeights.Reset();
mInfo.fArrayWeights.SetCount(mesh->fMorphSet->fMorphs.GetCount());
int i, j;
for (i = 0; i < mesh->fMorphSet->fMorphs.GetCount(); i++)
mInfo.fArrayWeights[i].fDeltaWeights.ExpandAndZero(mesh->fMorphSet->fMorphs[i].GetNumDeltas());
// Aha, we have some pending weights. Copy them in!
if (pendingIndex >= 0)
{
// Filter in any data that's valid
for (i = 0; i < mInfo.fArrayWeights.GetCount() && i < fPendingStates[pendingIndex].fArrayWeights.GetCount(); i++)
{
for (j = 0; j < mInfo.fArrayWeights[i].fDeltaWeights.GetCount() &&
j < fPendingStates[pendingIndex].fArrayWeights[i].fDeltaWeights.GetCount(); j++)
{
mInfo.fArrayWeights[i].fDeltaWeights[j] = fPendingStates[pendingIndex].fArrayWeights[i].fDeltaWeights[j];
}
}
fPendingStates.Remove(pendingIndex);
mInfo.fFlags |= plSharedMeshInfo::kInfoDirtyMesh;
ISetDirty(true);
}
fSharedMeshes.Append(mInfo);
IFindIndices(fSharedMeshes.GetCount() - 1);
if (mesh->fFlags & plSharedMesh::kLayer0GlobalToMod)
{
fGlobalLayerRef = fSharedMeshes.GetCount() - 1;
ISetAllSharedToGlobal();
}
else
ISetSingleSharedToGlobal(fSharedMeshes.GetCount() - 1);
}
void plMorphSequence::RemoveSharedMesh(plSharedMesh* mesh)
{
int idx = IFindSharedMeshIndex(mesh->GetKey());
if (idx < 0)
return; // Don't have it... can't remove it can we?
fSharedMeshes.Remove(idx);
fGlobalLayerRef = -1;
int i;
for (i = 0; i < fSharedMeshes.GetCount(); i++)
{
if (fSharedMeshes[i].fMesh->fFlags & plSharedMesh::kLayer0GlobalToMod)
{
fGlobalLayerRef = i;
break;
}
}
if (fSharedMeshes.GetCount() == 0)
plgDispatch::Dispatch()->UnRegisterForExactType(plSharedMeshBCMsg::Index(), GetKey());
}
void plMorphSequence::FindMorphMods(const plSceneObject *so, hsTArray<const plMorphSequence*> &mods)
{
const plMorphSequence *morph = plMorphSequence::ConvertNoRef(so->GetModifierByType(plMorphSequence::Index()));
if (morph)
mods.Append(morph);
const plCoordinateInterface *ci = so->GetCoordinateInterface();
int i;
for (i = 0; i < ci->GetNumChildren(); i++)
FindMorphMods(ci->GetChild(i)->GetOwner(), mods);
}
void plMorphSequence::ISetAllSharedToGlobal()
{
int i;
for (i = 0; i < fSharedMeshes.GetCount(); i++)
{
if (i != fGlobalLayerRef)
ISetSingleSharedToGlobal(i);
}
}
void plMorphSequence::ISetSingleSharedToGlobal(int idx)
{
if (fGlobalLayerRef < 0)
return;
int i;
for (i = 0; i < fSharedMeshes[fGlobalLayerRef].fArrayWeights[0].fDeltaWeights.GetCount(); i++)
SetWeight(0, i, fSharedMeshes[fGlobalLayerRef].fArrayWeights[0].fDeltaWeights[i], fSharedMeshes[idx].fMesh->GetKey());
}

View File

@ -0,0 +1,190 @@
/*==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 plMorphSequence_inc
#define plMorphSequence_inc
#include "../pnModifier/plSingleModifier.h"
#include "plMorphArray.h"
class plDrawable;
class plDrawInterface;
class plSharedMesh;
class plMorphSequenceSDLMod;
class plMorphArrayWeights
{
public:
hsTArray<hsScalar> fDeltaWeights;
};
class plSharedMeshInfo
{
public:
enum
{
kInfoDirtyMesh = 0x1
};
plSharedMesh* fMesh;
hsTArray<Int32> fCurrIdx;
plDrawable* fCurrDraw;
hsTArray<plMorphArrayWeights> fArrayWeights;
UInt8 fFlags;
plSharedMeshInfo() : fMesh(nil), fCurrDraw(nil), fFlags(0) {}
};
// Keyed storage class for morph arrays/deltas
// supply your own weights.
class plMorphDataSet : public hsKeyedObject
{
public:
hsTArray<plMorphArray> fMorphs;
CLASSNAME_REGISTER( plMorphDataSet );
GETINTERFACE_ANY( plMorphDataSet, hsKeyedObject );
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
};
// A place to hold incoming state while we're still waiting for the
// mesh and morph data to load.
class plMorphState
{
public:
plKey fSharedMeshKey;
hsTArray<plMorphArrayWeights> fArrayWeights;
};
class plMorphSequence : public plSingleModifier
{
friend class plMorphSequenceSDLMod;
protected:
enum
{
kDirty = 0x1,
kHaveSnap = 0x2,
kHaveShared = 0x4,
kDirtyIndices = 0x8
};
UInt32 fMorphFlags;
hsTArray<plMorphArray> fMorphs;
//Int32 fActiveMesh; // Doesn't appear to be used.
hsTArray<plSharedMeshInfo> fSharedMeshes;
hsTArray<plMorphState> fPendingStates;
plMorphSequenceSDLMod* fMorphSDLMod;
Int8 fGlobalLayerRef;
const plDrawInterface* IGetDrawInterface() const;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return false; }
void ISetHaveSnap(hsBool on) { if(on)fMorphFlags |= kHaveSnap; else fMorphFlags &= ~kHaveSnap; }
void ISetDirty(hsBool on);
hsBool IResetShared(int iShare);
void IApplyShared(int iShare);
hsBool IFindIndices(int iShare);
void IReleaseIndices(int iShare);
void IRenormalize(hsTArray<plAccessSpan>& dst) const;
void IResetShared();
void IReleaseIndices(); // Puts everyone inactive
void IFindIndices(); // Refresh Indicies
void IApplyShared(); // Apply whatever morphs are active
Int32 IFindPendingStateIndex(plKey meshKey) const; // Do we have pending state for this mesh?
Int32 IFindSharedMeshIndex(plKey meshKey) const; // What's this mesh's index in our array?
hsBool IIsUsingDrawable(plDrawable *draw); // Are we actively looking at spans in this drawable?
// Internal functions for maintaining that all meshes share the same global weight(s) (fGlobalLayerRef)
void ISetAllSharedToGlobal();
void ISetSingleSharedToGlobal(int idx);
public:
plMorphSequence();
virtual ~plMorphSequence();
CLASSNAME_REGISTER( plMorphSequence );
GETINTERFACE_ANY( plMorphSequence, plSingleModifier );
virtual hsBool MsgReceive(plMessage* msg);
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
void Init();
void Activate();
void DeInit();
void DeActivate();
void Apply() const;
void Reset(const plDrawInterface* di=nil) const;
int GetNumLayers(plKey meshKey = nil) const;
void AddLayer(const plMorphArray& ma) { fMorphs.Append(ma); }
int GetNumDeltas(int iLay, plKey meshKey = nil) const;
hsScalar GetWeight(int iLay, int iDel, plKey meshKey = nil) const;
void SetWeight(int iLay, int iDel, hsScalar w, plKey meshKey = nil);
hsBool GetHaveSnap() const { return 0 != (fMorphFlags & kHaveSnap); }
hsBool GetDirty() const { return 0 != (fMorphFlags & kDirty); }
hsBool GetUseSharedMesh() const { return 0 != (fMorphFlags & kHaveShared); }
void SetUseSharedMesh(hsBool on) { if(on)fMorphFlags |= kHaveShared; else fMorphFlags &= ~kHaveShared; }
void AddSharedMesh(plSharedMesh* mesh);
void RemoveSharedMesh(plSharedMesh* mesh);
static void FindMorphMods(const plSceneObject *so, hsTArray<const plMorphSequence*> &mods);
plMorphSequenceSDLMod *GetSDLMod() const { return fMorphSDLMod; }
};
#endif // plMorphSequence_inc

View File

@ -0,0 +1,184 @@
/*==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 "plMorphSequenceSDLMod.h"
#include "plMorphSequence.h"
#include "plSharedMesh.h"
#include "hsResMgr.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnMessage/plSDLModifierMsg.h"
#include "../plSDL/plSDL.h"
// static vars
char plMorphSequenceSDLMod::kStrMorphArrayDescName[]="MorphArray";
char plMorphSequenceSDLMod::kStrWeights[]="weights";
char plMorphSequenceSDLMod::kStrMorphSetDescName[]="MorphSet";
char plMorphSequenceSDLMod::kStrMesh[]="mesh";
char plMorphSequenceSDLMod::kStrArrays[]="arrays";
char plMorphSequenceSDLMod::kStrTargetID[]="targetID";
char plMorphSequenceSDLMod::kStrMorphs[]="morphs";
void plMorphSequenceSDLMod::PutCurrentStateIn(plStateDataRecord* dstState)
{
IPutCurrentStateIn(dstState);
}
void plMorphSequenceSDLMod::IPutCurrentStateIn(plStateDataRecord* dstState)
{
plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plMorphSequenceSDLMod, nil target");
const plMorphSequence *kMorphMod = nil;
int i, j;
kMorphMod = plMorphSequence::ConvertNoRef(sobj->GetModifierByType(plMorphSequence::Index()));
if (!kMorphMod)
{
hsAssert(false, "Couldn't find a morph sequence.");
return;
}
plMorphSequence *morphMod = const_cast<plMorphSequence*>(kMorphMod);
//dstState->FindVar(kStrTarget)->Set(morphMod->GetKey());
plSDStateVariable *morphSD = dstState->FindSDVar(kStrMorphs);
int numMorphs = morphMod->fSharedMeshes.GetCount() + 1; // 1 for the non-sharedMesh morph
hsTArray<plKey> keys;
for (i = 0; i < numMorphs; i++)
{
if (i == morphMod->fSharedMeshes.GetCount())
{
// the non-sharedMesh morph
if (morphMod->GetNumLayers(nil) != 0)
keys.Append(nil);
}
else
{
if (!(morphMod->fSharedMeshes[i].fMesh->fFlags & plSharedMesh::kDontSaveMorphState))
keys.Append(morphMod->fSharedMeshes[i].fMesh->GetKey());
}
}
if (morphSD->GetCount() != keys.GetCount())
morphSD->Alloc(keys.GetCount());
for (i = 0; i < keys.GetCount(); i++)
{
plKey meshKey = keys[i];
morphSD->GetStateDataRecord(i)->FindVar(kStrMesh)->Set(meshKey);
plSimpleStateVariable *weights = morphSD->GetStateDataRecord(i)->FindVar(kStrWeights);
int numLayers = morphMod->GetNumLayers(meshKey);
if (weights->GetCount() != numLayers)
weights->Alloc(numLayers);
for (j = 0; j < numLayers; j++)
{
int numDeltas = morphMod->GetNumDeltas(j, meshKey);
if (numDeltas != 2)
continue; // plMorphSequenceSDLMod assumes 2 deltas (pos/neg) per layer, so that we can
// store both in a single byte
// Translate the range [-1.0, 1.0] into a 0-255 byte
UInt8 weight = (UInt8)((1.f + morphMod->GetWeight(j, 0, meshKey) - morphMod->GetWeight(j, 1, meshKey)) * 255 / 2);
weights->Set(&weight, j);
}
}
}
void plMorphSequenceSDLMod::SetCurrentStateFrom(const plStateDataRecord* srcState)
{
ISetCurrentStateFrom(srcState);
}
void plMorphSequenceSDLMod::ISetCurrentStateFrom(const plStateDataRecord* srcState)
{
plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plMorphSequenceSDLMod, nil target");
if (strcmp(srcState->GetDescriptor()->GetName(), kSDLMorphSequence))
{
hsAssert(false, "Wrong type of state data record passed into plMorphSequenceSDLMod.");
return;
}
int i, j;
const plMorphSequence *kMorphMod = plMorphSequence::ConvertNoRef(sobj->GetModifierByType(plMorphSequence::Index()));
if (!kMorphMod)
{
hsAssert(false, "Couldn't find a morph sequence.");
return;
}
plMorphSequence *morphMod = const_cast<plMorphSequence*>(kMorphMod);
plSDStateVariable *morphSD = srcState->FindSDVar(kStrMorphs);
for (i = 0; i < morphSD->GetCount(); i++)
{
plKey meshKey;
morphSD->GetStateDataRecord(i)->FindVar(kStrMesh)->Get(&meshKey);
if (meshKey && !meshKey->GetUoid().GetClassType() == plSharedMesh::Index())
continue;
// meshKey will be nil when dealing with non-sharedMesh data
if (meshKey)
hsgResMgr::ResMgr()->AddViaNotify(meshKey, TRACKED_NEW plGenRefMsg(morphMod->GetKey(), plRefMsg::kOnCreate, -1, -1), plRefFlags::kPassiveRef);
plSimpleStateVariable *weights = morphSD->GetStateDataRecord(i)->FindVar(kStrWeights);
// Count down so that we do the high index first and the pending state struct
// of plMorphSequence only has to resize the array once.
for (j = weights->GetCount() - 1; j >= 0; j--)
{
UInt8 weight;
weights->Get(&weight, j);
hsScalar posWeight = weight * 2.f / 255.f - 1.f;
hsScalar negWeight = 0;
if (posWeight < 0)
{
negWeight = -posWeight;
posWeight = 0;
}
morphMod->SetWeight(j, 1, negWeight, meshKey);
morphMod->SetWeight(j, 0, posWeight, meshKey);
}
}
}

View File

@ -0,0 +1,95 @@
/*==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 plMorphSequenceSDLMod_inc
#define plMorphSequenceSDLMod_inc
#include "../plModifier/plSDLModifier.h"
#include "hsTypes.h"
//
// This modifier is responsible for sending and recving
// state for morphed objects.
//
class plMorphSequenceSDLMod : public plSDLModifier
{
protected:
void IPutCurrentStateIn(plStateDataRecord* dstState);
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
UInt32 IApplyModFlags(UInt32 sendFlags)
{
if (fIsAvatar)
return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState);
else
return sendFlags;
}
bool fIsAvatar;
public:
// var labels
static char kStrMorphArrayDescName[];
static char kStrWeights[];
static char kStrMorphSetDescName[];
static char kStrMesh[];
static char kStrArrays[];
static char kStrTargetID[];
static char kStrMorphs[];
CLASSNAME_REGISTER( plMorphSequenceSDLMod );
GETINTERFACE_ANY( plMorphSequenceSDLMod, plSDLModifier);
plMorphSequenceSDLMod() : fIsAvatar(false) {}
void SetCurrentStateFrom(const plStateDataRecord* srcState);
void PutCurrentStateIn(plStateDataRecord* dstState);
const char* GetSDLName() const { return kSDLMorphSequence; }
void SetIsAvatar(bool avatar) { fIsAvatar = avatar; }
};
#endif // plMorphSequenceSDLMod_inc

View File

@ -0,0 +1,816 @@
/*==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 "plParticleFiller.h"
// Core background
#include "hsTemplates.h"
#include "hsFastMath.h"
#include "plPipeline.h"
#include "plViewTransform.h"
// Getting at the destination data
#include "../pnSceneObject/plDrawInterface.h"
#include "../plDrawable/plDrawableSpans.h"
#include "../plPipeline/plGBufferGroup.h"
// For shading
#include "../plGLight/plLightInfo.h"
// Getting at the source data
#include "../plParticleSystem/plParticleEmitter.h"
#include "../plParticleSystem/plParticle.h"
static hsScalar sInvDelSecs;
//// Local Static Stuff ///////////////////////////////////////////////////////
/// Macros for getting/setting data in a D3D vertex buffer
#define STUFF_POINT( ptr, point ) { float *fPtr = (float *)ptr; \
fPtr[ 0 ] = point.fX; fPtr[ 1 ] = point.fY; fPtr[ 2 ] = point.fZ; \
ptr += sizeof( float ) * 3; }
#define STUFF_UINT32( ptr, uint ) { UInt32 *dPtr = (UInt32 *)ptr; \
dPtr[ 0 ] = uint; ptr += sizeof( UInt32 ); }
#define EXTRACT_POINT( ptr, pt ) { float *fPtr = (float *)ptr; \
pt.fX = fPtr[ 0 ]; pt.fY = fPtr[ 1 ]; pt.fZ = fPtr[ 2 ]; \
ptr += sizeof( float ) * 3; }
#define EXTRACT_FLOAT( ptr, f ) { float *fPtr = (float *)ptr; \
f = fPtr[ 0 ]; \
ptr += sizeof( float ); }
#define EXTRACT_UINT32( ptr, uint ) { UInt32 *dPtr = (UInt32 *)ptr; \
uint = dPtr[ 0 ]; ptr += sizeof( UInt32 ); }
static hsScalar sCurrMinWidth = 0;
///////////////////////////////////////////////////////////////////////////////
//// Particles ////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//// Particle Processing Inlines //////////////////////////////////////////////
// Thanks to the <cough> beauty of C++, the internal loop of
// IFillParticlePolys would be horrendous without these inlines (with them,
// it's just slightly annoying). The goal is to make the code easier to
// maintain without loosing speed (hence the inlines, which will *hopefully*
// remove the function call overhead....)
void inline IInlSetParticlePathFollow( const plParticleCore &particle, const hsMatrix44& viewToWorld,
hsVector3 &xVec, hsVector3 &yVec, hsVector3 &zVec )
{
/// Follow path specified by interpreting orientation as a velocity vector.
hsVector3 viewDir(&particle.fPos, &viewToWorld.GetTranslate());
hsFastMath::NormalizeAppr(viewDir);
zVec = viewDir;
const hsVector3& orientation = (const hsVector3)(particle.fOrientation);
yVec = orientation - orientation.InnerProduct(viewDir) * viewDir;
hsFastMath::NormalizeAppr(yVec);
xVec = yVec % viewDir;
hsFastMath::NormalizeAppr(xVec);
xVec *= particle.fHSize;
yVec *= particle.fVSize;
}
void inline IInlSetParticlePathStretch( const plParticleCore &particle, const hsMatrix44& viewToWorld,
hsVector3 &xVec, hsVector3 &yVec, hsVector3 &zVec )
{
/// Follow path specified by interpreting orientation as a velocity vector.
// Well, that's one way to do it, but it has a bit of a flaw. If the length of the
// particle doesn't match the distance it's moved each frame, you get a nasty strobing
// effect, particularly as particles move faster. One of those things they don't teach
// you in the math class you slept through.
// So what we want is for the tail of the particle this frame to be where the head of
// the particle was last frame.
// First thing changed was the orientation passed in is now the change in position for
// this frame (was the last frame's velocity).
// zVec will still be the normalized vector from the eye to the particle (in world space).
// Does zVec ever get used? Hmm, only gets used for the normal facing the camera.
// This thing gets a lot faster and cleaner when we just use the view axes to compute.
// So zVec is just -viewDir.
// yVec = orientation - orientation.InnerProduct(zVec) * zVec
// xVec = yVec % zVec
// To be really correct, you can normalize xVec, because the particle doesn't get fatter
// as it goes faster, just longer. Costs a little more, but...
// And it also raises the question of what to do with the user supplied sizes. Again,
// for correctness, we want to add the size to the length of the displacement.
// We could afford that (maybe) by doing a fast normalize on yVec, then multiplying
// by orientation.InnerProduct(yVec) + fVSize.
// So the new stuff we need here are:
// The particle (to get the size out of).
// The viewToWorld transform (we can pull the eyePt and viewDir out of that.
// Note that we could probably slim away a normalize or two, but the actual number
// of normalizes we're doing hasn't gone up, I've just moved them up from IInlSetParticlePoints().
hsVector3 viewDir(&particle.fPos, &viewToWorld.GetTranslate());
hsScalar invD = hsFastMath::InvSqrtAppr(viewDir.MagnitudeSquared());
viewDir *= invD;
zVec = viewDir;
const hsVector3& orientation = (const hsVector3)(particle.fOrientation);
// We don't want the projection of orientation orthogonal to viewDir here,
// it's okay (and looks better) if yVec isn't in the image plane, we just
// want to make sure that xVec is in the image plane. Might want to make
// the same change to IInlSetParticlePathFollow(), but I haven't checked
// that yet. Artifact to look for is particles starting to look goofy
// as their orientation gets close in direction to viewDir. mf
yVec = orientation;
hsFastMath::NormalizeAppr(yVec);
xVec = yVec % viewDir; // cross product of two orthonormal vectors, no need to normalize.
hsScalar xLen = particle.fHSize;
if( xLen * invD < sCurrMinWidth )
xLen = sCurrMinWidth / invD;
xVec *= xLen;
hsScalar len = yVec.InnerProduct(orientation);
// Might want to give it a little boost to overlap itself (and compensate for the massive
// transparent border the artists love). But they can do that themselves with the VSize.
// len *= 1.5f;
len += particle.fVSize;
yVec *= len * -1.f;
}
void inline IInlSetParticlePathFlow( const plParticleCore &particle, const hsMatrix44& viewToWorld,
hsVector3 &xVec, hsVector3 &yVec, hsVector3 &zVec )
{
// Okay, all the notes for SetParticlePathStretch apply here too. The only
// difference is that we're going to keep the area of the particle constant,
// so the longer it stretches, the narrower it gets orthogonal to the velocity.
hsVector3 viewDir(&particle.fPos, &viewToWorld.GetTranslate());
hsScalar invD = hsFastMath::InvSqrtAppr(viewDir.MagnitudeSquared());
viewDir *= invD;
zVec = viewDir;
const hsVector3& orientation = (const hsVector3)(particle.fOrientation);
// We don't want the projection of orientation orthogonal to viewDir here,
// it's okay (and looks better) if yVec isn't in the image plane, we just
// want to make sure that xVec is in the image plane. Might want to make
// the same change to IInlSetParticlePathFollow(), but I haven't checked
// that yet. Artifact to look for is particles starting to look goofy
// as their orientation gets close in direction to viewDir. mf
yVec = orientation;
hsFastMath::NormalizeAppr(yVec);
xVec = yVec % viewDir; // cross product of two orthonormal vectors, no need to normalize.
hsScalar len = yVec.InnerProduct(orientation);
hsScalar xLen = particle.fHSize * hsFastMath::InvSqrtAppr(1.f + len * sInvDelSecs);
if( xLen * invD < sCurrMinWidth )
xLen = sCurrMinWidth / invD;
xVec *= xLen;
// Might want to give it a little boost to overlap itself (and compensate for the massive
// transparent border the artists love). But they can do that themselves with the VSize.
len += particle.fVSize;
yVec *= len * -2.f;
}
void inline IInlSetParticleExplicit( const hsMatrix44 &viewToWorld, const plParticleCore &particle,
hsVector3 &xVec, hsVector3 &yVec, hsVector3 &zVec )
{
const hsVector3& orientation = (const hsVector3)(particle.fOrientation);
#if 0 // See notes below - mf
zVec.Set( 0, 0, -1 );
yVec.Set( &orientation );
zVec = viewToWorld * zVec;
yVec = viewToWorld * yVec;
xVec = yVec % zVec;
#else // See notes below - mf
// The above has a bit of a problem with wide field of view. All of the
// particles are facing the same direction with respect to lighting,
// even though some are to the left and some are to the right of the camera
// (when facing the center of the system). We'll also start seeing them side on
// as they get to the edge of the screen. Fortunately, it's actually faster
// to calculate the vector from camera to particle and normalize it than
// to transform the vector (0,0,-1) (though not as fast as pulling the
// camera direction directly from the viewToWorld).
hsVector3 del(&particle.fPos, &viewToWorld.GetTranslate());
hsFastMath::NormalizeAppr(del);
zVec = del;
yVec.Set(&(viewToWorld * orientation));
xVec = yVec % zVec;
#endif // See notes below - mf
xVec = hsFastMath::NormalizeAppr( xVec ) * particle.fHSize;
yVec = hsFastMath::NormalizeAppr( yVec ) * particle.fVSize;
}
void inline IInlSetParticlePoints( const hsVector3 &xVec, const hsVector3 &yVec, const plParticleCore &particle,
hsPoint3 *partPts, UInt32 &partColor )
{
/// Do the 4 verts for this particle
partPts[ 0 ] = partPts[ 1 ] = partPts[ 2 ] = partPts[ 3 ] = particle.fPos;
partPts[ 0 ] += xVec - yVec;
partPts[ 1 ] += -xVec - yVec;
partPts[ 2 ] += -xVec + yVec;
partPts[ 3 ] += xVec + yVec;
partColor = particle.fColor;
}
void inline IInlSetParticlePointsStretch( const hsVector3 &xVec, const hsVector3 &yVec, const plParticleCore &particle,
hsPoint3 *partPts, UInt32 &partColor )
{
/// Do the 4 verts for this particle
partPts[ 0 ] = partPts[ 1 ] = partPts[ 2 ] = partPts[ 3 ] = particle.fPos;
partPts[ 0 ] += xVec + yVec;
partPts[ 1 ] += -xVec + yVec;
partPts[ 2 ] += -xVec;
partPts[ 3 ] += xVec;
partColor = particle.fColor;
}
void inline IInlStuffParticle1UV( UInt8 *&destPtr, const hsPoint3 *partPts, const hsVector3 &partNorm,
const UInt32 &partColor, const plParticleCore &particle )
{
UInt8 j;
for( j = 0; j < 4; j++ )
{
STUFF_POINT( destPtr, partPts[ j ] );
STUFF_POINT( destPtr, partNorm );
STUFF_UINT32( destPtr, partColor );
STUFF_UINT32( destPtr, 0 );
STUFF_POINT( destPtr, particle.fUVCoords[ j ] );
}
}
void inline IInlStuffParticleNoUVs( UInt8 *&destPtr, const hsPoint3 *partPts, const hsVector3 &partNorm,
const UInt32 &partColor )
{
UInt8 j;
for( j = 0; j < 4; j++ )
{
STUFF_POINT( destPtr, partPts[ j ] );
STUFF_POINT( destPtr, partNorm );
STUFF_UINT32( destPtr, partColor );
STUFF_UINT32( destPtr, 0 );
}
}
void inline IInlSetNormalViewFace( hsVector3 &partNorm, const hsVector3 &zVec )
{
partNorm = -zVec;
}
void inline IInlSetNormalStrongestLight( hsVector3 &partNorm, const plParticleCore &particle,
const plOmniLightInfo *omniLight, const plDirectionalLightInfo *directionLight, const hsVector3 &zVec )
{
if( omniLight != nil )
{
partNorm.Set( &particle.fPos, &omniLight->GetWorldPosition() );
partNorm = -partNorm;
}
else if( directionLight != nil )
{
partNorm = -directionLight->GetWorldDirection();
}
else
partNorm = -zVec;
partNorm = hsFastMath::NormalizeAppr( partNorm );
}
void inline IInlSetNormalExplicit( hsVector3 &partNorm, const plParticleCore &particle )
{
partNorm = particle.fNormal;
}
//// IIPL Functions (Internal-Inline-Particle-Loop) ///////////////////////////
// Function names go as follows:
// IIPL_u_o_n()
// where u is 1UV or 0UV (for 1 UV channel or no UV channels),
// o is OVel (for orientation-follows-velocity) or OExp (for orientation-is-explicit)
// and n is NViewFace (for normals facing view), NLite (for facing strongest light)
// or NExp (for explicit)
#define IIPL_PROLOG \
UInt32 i, partColor; \
hsVector3 xVec, yVec, zVec, partNorm; \
hsPoint3 partPts[ 4 ]; \
for( i = 0; i < numParticles; i++ )
void inline IIPL_1UV_OVel_NViewFace( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathFollow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalViewFace( partNorm, zVec );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_1UV_OVel_NLite( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr,
const plOmniLightInfo *omniLight, const plDirectionalLightInfo *directionLight )
{
IIPL_PROLOG
{
IInlSetParticlePathFollow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalStrongestLight( partNorm, particles[ i ], omniLight, directionLight, zVec );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_1UV_OVel_NExp( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathFollow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalExplicit( partNorm, particles[ i ] );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_1UV_OStr_NViewFace( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathStretch( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalViewFace( partNorm, zVec );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_1UV_OStr_NLite( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr,
const plOmniLightInfo *omniLight, const plDirectionalLightInfo *directionLight )
{
IIPL_PROLOG
{
IInlSetParticlePathStretch( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalStrongestLight( partNorm, particles[ i ], omniLight, directionLight, zVec );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_1UV_OStr_NExp( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathStretch( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalExplicit( partNorm, particles[ i ] );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_1UV_OFlo_NViewFace( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathFlow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalViewFace( partNorm, zVec );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_1UV_OFlo_NLite( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr,
const plOmniLightInfo *omniLight, const plDirectionalLightInfo *directionLight )
{
IIPL_PROLOG
{
IInlSetParticlePathFlow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalStrongestLight( partNorm, particles[ i ], omniLight, directionLight, zVec );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_1UV_OFlo_NExp( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathFlow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalExplicit( partNorm, particles[ i ] );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_1UV_OExp_NViewFace( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticleExplicit( viewToWorld, particles[ i ], xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalViewFace( partNorm, zVec );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_1UV_OExp_NLite( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr,
const plOmniLightInfo *omniLight, const plDirectionalLightInfo *directionLight )
{
IIPL_PROLOG
{
IInlSetParticleExplicit( viewToWorld, particles[ i ], xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalStrongestLight( partNorm, particles[ i ], omniLight, directionLight, zVec );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_1UV_OExp_NExp( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticleExplicit( viewToWorld, particles[ i ], xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalExplicit( partNorm, particles[ i ] );
IInlStuffParticle1UV( destPtr, partPts, partNorm, partColor, particles[ i ] );
}
}
void inline IIPL_0UV_OVel_NViewFace( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathFollow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalViewFace( partNorm, zVec );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
void inline IIPL_0UV_OVel_NLite( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr,
const plOmniLightInfo *omniLight, const plDirectionalLightInfo *directionLight )
{
IIPL_PROLOG
{
IInlSetParticlePathFollow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalStrongestLight( partNorm, particles[ i ], omniLight, directionLight, zVec );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
void inline IIPL_0UV_OVel_NExp( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathFollow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalExplicit( partNorm, particles[ i ] );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
void inline IIPL_0UV_OStr_NViewFace( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathStretch( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalViewFace( partNorm, zVec );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
void inline IIPL_0UV_OStr_NLite( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr,
const plOmniLightInfo *omniLight, const plDirectionalLightInfo *directionLight )
{
IIPL_PROLOG
{
IInlSetParticlePathStretch( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalStrongestLight( partNorm, particles[ i ], omniLight, directionLight, zVec );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
void inline IIPL_0UV_OStr_NExp( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathStretch( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalExplicit( partNorm, particles[ i ] );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
void inline IIPL_0UV_OFlo_NViewFace( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathFlow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalViewFace( partNorm, zVec );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
void inline IIPL_0UV_OFlo_NLite( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr,
const plOmniLightInfo *omniLight, const plDirectionalLightInfo *directionLight )
{
IIPL_PROLOG
{
IInlSetParticlePathFlow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalStrongestLight( partNorm, particles[ i ], omniLight, directionLight, zVec );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
void inline IIPL_0UV_OFlo_NExp( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticlePathFlow( particles[ i ], viewToWorld, xVec, yVec, zVec );
IInlSetParticlePointsStretch( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalExplicit( partNorm, particles[ i ] );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
void inline IIPL_0UV_OExp_NViewFace( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticleExplicit( viewToWorld, particles[ i ], xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalViewFace( partNorm, zVec );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
void inline IIPL_0UV_OExp_NLite( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr,
const plOmniLightInfo *omniLight, const plDirectionalLightInfo *directionLight )
{
IIPL_PROLOG
{
IInlSetParticleExplicit( viewToWorld, particles[ i ], xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalStrongestLight( partNorm, particles[ i ], omniLight, directionLight, zVec );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
void inline IIPL_0UV_OExp_NExp( const UInt32 &numParticles, const plParticleCore *particles, const hsMatrix44& viewToWorld, UInt8 *&destPtr )
{
IIPL_PROLOG
{
IInlSetParticleExplicit( viewToWorld, particles[ i ], xVec, yVec, zVec );
IInlSetParticlePoints( xVec, yVec, particles[ i ], partPts, partColor );
IInlSetNormalExplicit( partNorm, particles[ i ] );
IInlStuffParticleNoUVs( destPtr, partPts, partNorm, partColor );
}
}
//// IFillParticlePolys ///////////////////////////////////////////////////////
// Takes a list of particles and makes the polys for them.
#include "hsTimer.h"
#include "plProfile.h"
plProfile_CreateTimer("Fill Polys", "Particles", ParticleFillPoly);
void plParticleFiller::FillParticles(plPipeline* pipe, plDrawableSpans* drawable, plParticleSpan* span)
{
if (!span->fSource || span->fNumParticles <= 0)
return;
plProfile_BeginTiming(ParticleFillPoly);
sInvDelSecs = hsTimer::GetDelSysSeconds();
if( sInvDelSecs > 0 )
sInvDelSecs = 1.f / sInvDelSecs;
const plParticleCore* particles = span->fSource->GetParticleArray();
const UInt32 numParticles = span->fNumParticles;
plGBufferGroup* group = drawable->GetBufferGroup(span->fGroupIdx);
UInt8* destPtr = group->GetVertBufferData(span->fVBufferIdx);
destPtr += span->fVStartIdx * group->GetVertexSize();
/// Get the z vector (pointing away from the camera) in worldspace
hsMatrix44 viewToWorld = pipe->GetCameraToWorld();
plOmniLightInfo* omniLight = nil;
plDirectionalLightInfo* directionLight = nil;
/// Get strongest light, if there is one, for normal generation
if( span->GetNumLights( false ) > 0 )
{
omniLight = plOmniLightInfo::ConvertNoRef( span->GetLight( 0, false ) );
directionLight = plDirectionalLightInfo::ConvertNoRef( span->GetLight( 0, false ) );
}
/// Fill with 1 UV channel
if( group->GetNumUVs() == 1 )
{
/// Switch on orientation
if( span->fSource->fMiscFlags & plParticleEmitter::kOrientationVelocityBased )
{
/// Switch on normal generation
if( span->fSource->fMiscFlags & plParticleEmitter::kNormalViewFacing )
IIPL_1UV_OVel_NViewFace( numParticles, particles, viewToWorld, destPtr );
else if( span->fSource->fMiscFlags & plParticleEmitter::kNormalNearestLight )
IIPL_1UV_OVel_NLite( numParticles, particles, viewToWorld, destPtr, omniLight, directionLight );
else
IIPL_1UV_OVel_NExp( numParticles, particles, viewToWorld, destPtr );
}
else if( span->fSource->fMiscFlags & plParticleEmitter::kOrientationVelocityStretch )
{
sCurrMinWidth = pipe->GetViewTransform().GetOrthoWidth() / pipe->GetViewTransform().GetScreenWidth() * 0.75f;
/// Switch on normal generation
if( span->fSource->fMiscFlags & plParticleEmitter::kNormalViewFacing )
IIPL_1UV_OStr_NViewFace( numParticles, particles, viewToWorld, destPtr );
else if( span->fSource->fMiscFlags & plParticleEmitter::kNormalNearestLight )
IIPL_1UV_OStr_NLite( numParticles, particles, viewToWorld, destPtr, omniLight, directionLight );
else
IIPL_1UV_OStr_NExp( numParticles, particles, viewToWorld, destPtr );
}
else if( span->fSource->fMiscFlags & plParticleEmitter::kOrientationVelocityFlow )
{
sCurrMinWidth = pipe->GetViewTransform().GetOrthoWidth() / pipe->GetViewTransform().GetScreenWidth() * 0.75f;
/// Switch on normal generation
if( span->fSource->fMiscFlags & plParticleEmitter::kNormalViewFacing )
IIPL_1UV_OFlo_NViewFace( numParticles, particles, viewToWorld, destPtr );
else if( span->fSource->fMiscFlags & plParticleEmitter::kNormalNearestLight )
IIPL_1UV_OFlo_NLite( numParticles, particles, viewToWorld, destPtr, omniLight, directionLight );
else
IIPL_1UV_OFlo_NExp( numParticles, particles, viewToWorld, destPtr );
}
else // Orientation explicit
{
/// Switch on normal generation
if( span->fSource->fMiscFlags & plParticleEmitter::kNormalViewFacing )
IIPL_1UV_OExp_NViewFace( numParticles, particles, viewToWorld, destPtr );
else if( span->fSource->fMiscFlags & plParticleEmitter::kNormalNearestLight )
IIPL_1UV_OExp_NLite( numParticles, particles, viewToWorld, destPtr, omniLight, directionLight );
else
IIPL_1UV_OExp_NExp( numParticles, particles, viewToWorld, destPtr );
}
}
else
/// Fill with no UV channels
{
/// Switch on orientation
if( span->fSource->fMiscFlags & plParticleEmitter::kOrientationVelocityBased )
{
/// Switch on normal generation
if( span->fSource->fMiscFlags & plParticleEmitter::kNormalViewFacing )
IIPL_0UV_OVel_NViewFace( numParticles, particles, viewToWorld, destPtr );
else if( span->fSource->fMiscFlags & plParticleEmitter::kNormalNearestLight )
IIPL_0UV_OVel_NLite( numParticles, particles, viewToWorld, destPtr, omniLight, directionLight );
else
IIPL_0UV_OVel_NExp( numParticles, particles, viewToWorld, destPtr );
}
else if( span->fSource->fMiscFlags & plParticleEmitter::kOrientationVelocityStretch )
{
sCurrMinWidth = pipe->GetViewTransform().GetOrthoWidth() / pipe->GetViewTransform().GetScreenWidth() * 0.75f;
/// Switch on normal generation
if( span->fSource->fMiscFlags & plParticleEmitter::kNormalViewFacing )
IIPL_0UV_OStr_NViewFace( numParticles, particles, viewToWorld, destPtr );
else if( span->fSource->fMiscFlags & plParticleEmitter::kNormalNearestLight )
IIPL_0UV_OStr_NLite( numParticles, particles, viewToWorld, destPtr, omniLight, directionLight );
else
IIPL_0UV_OStr_NExp( numParticles, particles, viewToWorld, destPtr );
}
else if( span->fSource->fMiscFlags & plParticleEmitter::kOrientationVelocityFlow )
{
sCurrMinWidth = pipe->GetViewTransform().GetOrthoWidth() / pipe->GetViewTransform().GetScreenWidth() * 0.75f;
/// Switch on normal generation
if( span->fSource->fMiscFlags & plParticleEmitter::kNormalViewFacing )
IIPL_0UV_OFlo_NViewFace( numParticles, particles, viewToWorld, destPtr );
else if( span->fSource->fMiscFlags & plParticleEmitter::kNormalNearestLight )
IIPL_0UV_OFlo_NLite( numParticles, particles, viewToWorld, destPtr, omniLight, directionLight );
else
IIPL_0UV_OFlo_NExp( numParticles, particles, viewToWorld, destPtr );
}
else // Orientation explicit
{
/// Switch on normal generation
if( span->fSource->fMiscFlags & plParticleEmitter::kNormalViewFacing )
IIPL_0UV_OExp_NViewFace( numParticles, particles, viewToWorld, destPtr );
else if( span->fSource->fMiscFlags & plParticleEmitter::kNormalNearestLight )
IIPL_0UV_OExp_NLite( numParticles, particles, viewToWorld, destPtr, omniLight, directionLight );
else
IIPL_0UV_OExp_NExp( numParticles, particles, viewToWorld, destPtr );
}
}
/// All done!
plProfile_EndTiming(ParticleFillPoly);
}
void plParticleFiller::FillParticlePolys(plPipeline* pipe, plDrawInterface* di)
{
if( !di )
return; // should probably be an asserted error.
plDrawableSpans* drawable = plDrawableSpans::ConvertNoRef(di->GetDrawable(0));
if( !drawable )
return;
// Currently, the di always points to exactly 1 drawable with 1 span index. If
// that changes, this would just become a loop.
UInt32 diIndex = di->GetDrawableMeshIndex(0);
hsAssert(diIndex >= 0, "Bogus input to fill particles");
const plDISpanIndex& diSpans = drawable->GetDISpans(diIndex);
int i;
for( i = 0; i < diSpans.GetCount(); i++ )
{
UInt32 spanIdx = diSpans[i];
hsAssert(drawable->GetSpan(spanIdx), "Bogus input to fill particles");
hsAssert(drawable->GetSpan(spanIdx)->fTypeMask & plSpan::kParticleSpan, "Bogus input to fill particles");
// Safe cast, since we just checked the type mask.
plParticleSpan* span = (plParticleSpan*)drawable->GetSpan(spanIdx);
if( !span->fSource )
return; // Nothing to do, it's idle.
FillParticles(pipe, drawable, span);
}
}

View File

@ -0,0 +1,57 @@
/*==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 plParticleFiller_inc
#define plParticleFiller_inc
class plDrawInterface;
class plPipeline;
class plParticleSpan;
class plDrawableSpans;
namespace plParticleFiller
{
void FillParticles(plPipeline* pipe, plDrawableSpans* drawable, plParticleSpan* span);
void FillParticlePolys(plPipeline* pipe, plDrawInterface* di);
};
#endif // plParticleFiller_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==*/
#include "hsTypes.h"
#include "plPrintShape.h"
#include "hsStream.h"
#include "hsResMgr.h"
plPrintShape::plPrintShape()
: fWidth(0.5f),
fLength(1.f),
fHeight(1.f)
{
}
plPrintShape::~plPrintShape()
{
}
void plPrintShape::Read(hsStream* stream, hsResMgr* mgr)
{
plObjInterface::Read(stream, mgr);
fWidth = stream->ReadSwapScalar();
fLength = stream->ReadSwapScalar();
fHeight = stream->ReadSwapScalar();
}
void plPrintShape::Write(hsStream* stream, hsResMgr* mgr)
{
plObjInterface::Write(stream, mgr);
stream->WriteSwapScalar(fWidth);
stream->WriteSwapScalar(fLength);
stream->WriteSwapScalar(fHeight);
}

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 plPrintShape_inc
#define plPrintShape_inc
#include "../pnSceneObject/plObjInterface.h"
class plPrintShape : public plObjInterface
{
protected:
hsScalar fWidth;
hsScalar fLength;
hsScalar fHeight;
public:
plPrintShape();
virtual ~plPrintShape();
CLASSNAME_REGISTER( plPrintShape );
GETINTERFACE_ANY( plPrintShape, plObjInterface );
virtual Int32 GetNumProperties() const { return 1; }
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l) {}
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
hsScalar GetWidth() const { return fWidth; }
hsScalar GetLength() const { return fLength; }
hsScalar GetHeight() const { return fHeight; }
void SetWidth(hsScalar f) { fWidth = f; }
void SetLength(hsScalar f) { fLength = f; }
void SetHeight(hsScalar f) { fHeight = f; }
};
#endif // plPrintShape_inc

View File

@ -0,0 +1,368 @@
/*==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 "plProxyGen.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayer.h"
#include "../plDrawable/plDrawableSpans.h"
#include "../plDrawable/plDrawableGenerator.h"
#include "../pnMessage/plProxyDrawMsg.h"
#include "../pnKeyedObject/plKey.h"
#include "../pnMessage/plRefMsg.h"
#include "../pnMessage/plNodeRefMsg.h"
#include "plgDispatch.h"
#include "hsResMgr.h"
static hsTArray<plDrawableSpans*> fProxyDrawables;
static hsTArray<hsGMaterial*> fProxyMaterials;
static UInt32 fProxyKeyCounter = 0;
plProxyGen::plProxyGen(const hsColorRGBA& amb, const hsColorRGBA& dif, hsScalar opac)
: fProxyMsgType(0),
fProxyDraw(nil),
fProxyMat(nil)
{
fAmbient = amb;
fColor = dif;
fAmbient.a = opac;
}
plProxyGen::~plProxyGen()
{
if( fProxyDraw )
GetKey()->Release(fProxyDraw->GetKey());
if( fProxyMat )
GetKey()->Release(fProxyMat->GetKey());
}
void plProxyGen::Init(const hsKeyedObject* owner)
{
if( !GetKey() )
{
char buff[256];
plLocation loc;
if( owner->GetKey() )
{
sprintf(buff, "%s_%s_%d_%d", owner->GetKey()->GetName(), "ProxyGen", owner->GetKey()->GetUoid().GetClonePlayerID(), fProxyKeyCounter++);
loc = owner->GetKey()->GetUoid().GetLocation();
}
else
{
sprintf( buff, "ProxyGen%d", fProxyKeyCounter++ );
loc = plLocation::kGlobalFixedLoc;
}
hsgResMgr::ResMgr()->NewKey( buff, this, loc );
plgDispatch::Dispatch()->RegisterForExactType(plProxyDrawMsg::Index(), GetKey());
}
}
UInt32 plProxyGen::IGetDrawableType() const
{
switch( fProxyMsgType & plProxyDrawMsg::kAllTypes )
{
case plProxyDrawMsg::kLight:
return plDrawable::kLightProxy;
case plProxyDrawMsg::kPhysical:
return plDrawable::kPhysicalProxy;
case plProxyDrawMsg::kOccluder:
return plDrawable::kOccluderProxy;
case plProxyDrawMsg::kAudible:
return plDrawable::kAudibleProxy;
case plProxyDrawMsg::kCoordinate:
return plDrawable::kCoordinateProxy;
case plProxyDrawMsg::kCamera:
return plDrawable::kCameraProxy;
}
hsAssert(false, "Unknown proxy type");
return plDrawable::kGenericProxy;
}
UInt32 plProxyGen::IGetProxyIndex() const
{
plKey sceneNode = IGetNode();
UInt32 drawType = IGetDrawableType();
int firstNil = -1;
int firstMatch = -1;
int i;
for( i = 0; i < fProxyDrawables.GetCount(); i++ )
{
if( fProxyDrawables[i] )
{
if( (fProxyDrawables[i]->GetType() & drawType)
&&(fProxyDrawables[i]->GetSceneNode() == sceneNode) )
{
return i;
}
}
else if( firstNil < 0 )
firstNil = i;
}
if( firstNil < 0 )
firstNil = fProxyDrawables.GetCount();
fProxyDrawables.ExpandAndZero(firstNil+1);
return firstNil;
}
hsGMaterial* plProxyGen::IMakeProxyMaterial() const
{
const hsColorRGBA& amb = fAmbient;
const hsColorRGBA& dif = fColor;
hsScalar opac = fAmbient.a;
hsGMaterial* retVal = TRACKED_NEW hsGMaterial();
char buff[256];
if( GetKey()->GetName() )
sprintf(buff, "%s_%s", GetKey()->GetName(), "Material");
else
strcpy(buff, "ProxyMaterial");
hsgResMgr::ResMgr()->NewKey( buff, retVal, GetKey() ? GetKey()->GetUoid().GetLocation() : plLocation::kGlobalFixedLoc );
plLayer *lay = retVal->MakeBaseLayer();
lay->SetRuntimeColor(dif);
lay->SetPreshadeColor(dif);
lay->SetAmbientColor(amb);
lay->SetOpacity(opac);
if( opac < 1.f )
{
lay->SetBlendFlags(lay->GetBlendFlags() | hsGMatState::kBlendAlpha);
lay->SetMiscFlags(hsGMatState::kMiscTwoSided);
lay->SetZFlags(hsGMatState::kZNoZWrite);
}
return retVal;
}
hsGMaterial* plProxyGen::IFindProxyMaterial() const
{
for (int i = 0; i < fProxyMaterials.GetCount(); i++)
{
hsGMaterial* mat = fProxyMaterials[i];
if (!mat)
continue;
plLayer* lay = plLayer::ConvertNoRef(mat->GetLayer(0));
if (lay &&
lay->GetAmbientColor() == fAmbient &&
lay->GetRuntimeColor() == fColor &&
lay->GetOpacity() == fAmbient.a)
return mat;
}
return nil;
}
hsGMaterial* plProxyGen::IGetProxyMaterial() const
{
// If we already have a material, return that
if (fProxyMat)
return fProxyMat;
// If there's one existing (for another proxy) that is setup the same as ours, use that
hsGMaterial* mat = IFindProxyMaterial();
if (mat)
return mat;
// Have to make a new one
mat = IMakeProxyMaterial();
fProxyMaterials.Append(mat);
return mat;
}
void plProxyGen::IGenerateProxy()
{
if( !IGetNode() )
return;
UInt32 idx = IGetProxyIndex();
hsGMaterial* mat = IGetProxyMaterial();
hsAssert(mat, "Failed to create proxy material");
hsBool onCreate = !fProxyDrawables[idx];
fProxyIndex.SetCount(0);
fProxyDrawables[idx] = ICreateProxy(mat, fProxyIndex, fProxyDrawables[idx]);
if( fProxyDrawables[idx] && !fProxyDrawables[idx]->GetKey() )
{
char buff[256];
if( GetKey()->GetName() )
sprintf(buff, "%s_%s", GetKey()->GetName(), "ProxyDrawable");
else
strcpy(buff, "ProxyDrawable");
hsgResMgr::ResMgr()->NewKey( buff, fProxyDrawables[ idx ], GetKey() ? GetKey()->GetUoid().GetLocation() : plLocation::kGlobalFixedLoc );
}
if( fProxyDrawables[idx] )
{
fProxyDrawables[idx]->SetType(IGetDrawableType());
IApplyProxy(idx);
plGenRefMsg* msg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnRequest, idx, 0);
hsgResMgr::ResMgr()->AddViaNotify(mat->GetKey(), msg, plRefFlags::kActiveRef);
fProxyMat = mat;
plNodeRefMsg* refMsg = TRACKED_NEW plNodeRefMsg( GetKey(), plNodeRefMsg::kOnRequest, (Int8)idx, plNodeRefMsg::kDrawable );
hsgResMgr::ResMgr()->AddViaNotify(fProxyDrawables[idx]->GetKey(), refMsg, plRefFlags::kActiveRef);
fProxyDraw = fProxyDrawables[idx];
}
}
//// IApplyProxy
// Add our proxy to our scenenode for rendering.
void plProxyGen::IApplyProxy(UInt32 idx) const
{
if( fProxyDrawables[idx] && IGetNode() && (fProxyDrawables[idx]->GetSceneNode() != IGetNode()) )
{
fProxyDrawables[idx]->SetSceneNode(IGetNode());
}
}
//// IRemoveProxy
// Remove our proxy from our scenenode.
void plProxyGen::IRemoveProxy(UInt32 idx) const
{
if( fProxyDrawables[idx] )
{
fProxyDrawables[idx]->SetSceneNode(nil);
}
}
/// Destroy the proxy. Duh.
void plProxyGen::IDestroyProxy()
{
if( fProxyDraw )
{
if( fProxyDraw->GetSceneNode() )
fProxyDraw->SetSceneNode(nil);
GetKey()->Release(fProxyDraw->GetKey());
fProxyDraw = nil;
}
if( fProxyMat )
{
GetKey()->Release(fProxyMat->GetKey());
fProxyMat = nil;
}
fProxyDrawables.Reset();
fProxyMaterials.Reset();
}
hsBool plProxyGen::MsgReceive(plMessage* msg)
{
plProxyDrawMsg* pDraw = plProxyDrawMsg::ConvertNoRef(msg);
if( pDraw && (pDraw->GetProxyFlags() & IGetProxyMsgType()) )
{
if( pDraw->GetProxyFlags() & plProxyDrawMsg::kCreate )
{
if( fProxyDraw == nil )
IGenerateProxy();
}
else if( pDraw->GetProxyFlags() & plProxyDrawMsg::kDestroy )
{
if( fProxyDraw != nil )
IDestroyProxy();
}
else if( pDraw->GetProxyFlags() & plProxyDrawMsg::kToggle )
{
if( fProxyDraw == nil )
IGenerateProxy();
else
IDestroyProxy();
}
return true;
}
plNodeRefMsg* nodeRef = plNodeRefMsg::ConvertNoRef(msg);
if( nodeRef )
{
if( nodeRef->GetContext() & (plRefMsg::kOnDestroy | plRefMsg::kOnRemove) )
{
if( nodeRef->fWhich < fProxyDrawables.GetCount() )
fProxyDrawables[nodeRef->fWhich] = nil;
}
return true;
}
plGenRefMsg* genMsg = plGenRefMsg::ConvertNoRef(msg);
if( genMsg )
{
if( genMsg->GetContext() & (plRefMsg::kOnDestroy | plRefMsg::kOnRemove) )
{
if( genMsg->fWhich < fProxyMaterials.GetCount() )
fProxyMaterials[genMsg->fWhich] = nil;
}
return true;
}
return hsKeyedObject::MsgReceive(msg);
}
void plProxyGen::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
{
UInt32 idx = IGetProxyIndex();
if( fProxyDrawables[idx] )
{
int i;
for( i = 0; i < fProxyIndex.GetCount(); i++ )
fProxyDrawables[idx]->SetTransform(fProxyIndex[i], l2w, w2l);
}
}
void plProxyGen::SetDisable(hsBool on)
{
UInt32 idx = IGetProxyIndex();
if( fProxyDrawables[idx] )
{
int i;
for( i = 0; i < fProxyIndex.GetCount(); i++ )
fProxyDrawables[idx]->SetNativeProperty(fProxyIndex[i], plDrawable::kPropNoDraw, on);
}
}

View File

@ -0,0 +1,132 @@
/*==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 plProxyGen_inc
#define plProxyGen_inc
#include "../pnKeyedObject/hsKeyedObject.h"
#include "hsColorRGBA.h"
#include "hsTemplates.h"
class plDrawableSpans;
class hsGMaterial;
struct hsMatrix44;
//
// Making your own ProxyGen suitable for visualizing class YourObject.
//
// Derive YourObjectProxy() from ProxyGen.
// YourObjectProxy() should set fProxyMsgType and the colors fAmbient,fColor, either
// in the constructor or in Init().
// Implement IGetNode() (see below).
// Implement ICreateProxy() (see below).
// Implement a CreateProxy() member to YourObject (see below).
// Add DrawableType kYourObjectProxy to plDrawable.h
// Add console commands under Graphics.Show.YourObjectProxy.
//
// See plLightSpace and plLightProxy for examples.
//
// More details.
// ============
// To make your own ProxyGen, you should subclass plProxyGen and override Init()
// because you'll probably want to keep a pointer to your owner (of type only you
// need to understand).
//
// The IGetNode() function lets your owner specify which plSceneNode to place the
// drawable in. That will normally just return your owner's GetSceneNode() call.
//
// ICreateProxy() let's your ProxyGen do any tweaking before calling CreateProxy()
// on your object. Your ProxyGen::ICreateProxy() could just do the work itself, but
// normally doesn't have enough protected information to really do the job.
//
// Typically your object's CreateProxy() function will just translate its internal
// data to a form suitable for the plDrawableGenerator suite of helper functions
// and return the result of a call into one of them.
//
class plProxyGen : public hsKeyedObject
{
protected:
hsColorRGBA fAmbient; // opacity in ambient.a
hsColorRGBA fColor;
plDrawableSpans* fProxyDraw;
hsGMaterial* fProxyMat;
UInt32 fProxyMsgType;
hsTArray<UInt32> fProxyIndex;
// These must be implemented by the specific type, so we know what to draw.
virtual plDrawableSpans* ICreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo=nil) = 0; // called by IGenerate
virtual plKey IGetNode() const = 0;
// Derived type should set fProxyMsgType as one of plProxyDrawMsg::types
UInt32 IGetProxyMsgType() const { return fProxyMsgType; }
// These are all fine by default.
UInt32 IGetProxyIndex() const;
UInt32 IGetDrawableType() const;
virtual hsGMaterial* IMakeProxyMaterial() const;
virtual hsGMaterial* IGetProxyMaterial() const; // will make material if needed.
hsGMaterial* IFindProxyMaterial() const;
virtual void IGenerateProxy();
virtual void IApplyProxy(UInt32 drawIdx) const; // called by IGenerate
virtual void IRemoveProxy(UInt32 drawIdx) const;
virtual void IDestroyProxy();
public:
plProxyGen(const hsColorRGBA& amb, const hsColorRGBA& dif, hsScalar opac);
virtual ~plProxyGen();
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual void SetDisable(hsBool on);
virtual void Init(const hsKeyedObject* owner);
virtual hsBool MsgReceive(plMessage* msg);
};
#endif // plProxyGen_inc

View File

@ -0,0 +1,62 @@
/*==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 plRipVSConsts_inc
#define plRipVSConsts_inc
class plRipVSConsts
{
public:
hsScalar fC1U;
hsScalar fC2U;
hsScalar fC1V;
hsScalar fC2V;
hsScalar fInitAtten;
hsScalar fLife;
hsScalar fDecay;
hsScalar fRamp;
};
#endif // plRipVSConsts_inc

View File

@ -0,0 +1,137 @@
/*==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 "hsTemplates.h"
#include "plSharedMesh.h"
#include "plGeometrySpan.h"
#include "plInstanceDrawInterface.h"
#include "plDrawableSpans.h"
#include "plMorphSequence.h"
plSharedMesh::plSharedMesh() : fMorphSet(nil), fFlags(0)
{
}
plSharedMesh::~plSharedMesh()
{
hsAssert(fActiveInstances.GetCount() == 0, "Tried to delete a shared mesh that has active instances.");
while (fSpans.GetCount() > 0)
delete fSpans.Pop();
}
/*
void plSharedMesh::CreateInstance(plSceneObject *so, UInt8 boneIndex)
{
plDrawInterface *di = so->GetVolatileDrawInterface();
// hsAssert((fActiveInstances.GetCount == 0) ||
// (di->GetDrawable() == fActiveInstances[0]->GetDrawInterface()->GetDrawable()),
// "Trying to share a mesh between two seperate drawables. No can do.");
fActiveInstances.Append(so);
}
void plSharedMesh::RemoveInstance(plSceneObject *so)
{
so->GetVolatileDrawInterface()->ReleaseData();
fActiveInstances.RemoveItem(so);
}
*/
hsBool plSharedMesh::MsgReceive(plMessage* msg)
{
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef(msg);
if (refMsg)
{
plMorphDataSet *set = plMorphDataSet::ConvertNoRef(refMsg->GetRef());
if (set)
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
{
fMorphSet = plMorphDataSet::ConvertNoRef(refMsg->GetRef());
}
else if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
{
fMorphSet = nil;
}
return true;
}
}
return hsKeyedObject::MsgReceive(msg);
}
// Currently, active instances are not meant to be created at export and written to disk.
void plSharedMesh::Read(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Read(s, mgr);
int i;
fSpans.SetCount(s->ReadSwap32());
for (i = 0; i < fSpans.GetCount(); i++)
{
fSpans[i] = TRACKED_NEW plGeometrySpan;
fSpans[i]->Read(s);
}
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, -1), plRefFlags::kActiveRef);
fFlags = s->ReadByte();
}
void plSharedMesh::Write(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Write(s, mgr);
int i;
s->WriteSwap32(fSpans.GetCount());
for (i = 0; i < fSpans.GetCount(); i++)
fSpans[i]->Write(s);
mgr->WriteKey(s, (fMorphSet ? fMorphSet->GetKey() : nil));
s->WriteByte(fFlags);
}
//////////////////////////////////////////////////////////////////////////////////////
plSharedMeshBCMsg::plSharedMeshBCMsg() : plMessage(), fMesh(nil), fIsAdding(true) { SetBCastFlag(plMessage::kBCastByExactType); }

View File

@ -0,0 +1,103 @@
/*==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 PLSHAREDMESH_INC
#define PLSHAREDMESH_INC
#include "../pnKeyedObject/hsKeyedObject.h"
#include "../pnMessage/plMessage.h"
class plGeometrySpan;
class plDrawableSpans;
class plSceneObject;
class hsStream;
class hsResMgr;
class plMorphDataSet;
class plSharedMesh : public hsKeyedObject
{
public:
enum
{
kDontSaveMorphState = 0x1, // Don't save state (duh). Used for a morph that only has global layers
kLayer0GlobalToMod = 0x2 // This mesh's weight for layer 0 should be applied to all meshes on
// the same morph mod.
};
hsTArray<plGeometrySpan *>fSpans;
hsTArray<const plSceneObject *> fActiveInstances;
plMorphDataSet *fMorphSet;
UInt8 fFlags;
plSharedMesh();
~plSharedMesh();
void CreateInstance(plSceneObject *so, UInt8 boneIndex);
void RemoveInstance(plSceneObject *so);
CLASSNAME_REGISTER( plSharedMesh );
GETINTERFACE_ANY( plSharedMesh, hsKeyedObject );
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
};
class plSharedMeshBCMsg : public plMessage
{
public:
plDrawableSpans *fDraw;
plSharedMesh *fMesh;
hsBool fIsAdding;
plSharedMeshBCMsg();
~plSharedMeshBCMsg() {}
CLASSNAME_REGISTER( plSharedMeshBCMsg );
GETINTERFACE_ANY( plSharedMeshBCMsg, plMessage );
virtual void Read(hsStream* s, hsResMgr* mgr) {}
virtual void Write(hsStream* s, hsResMgr* mgr) {}
};
#endif

View File

@ -0,0 +1,598 @@
/*==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 "plSpaceTree.h"
#include "hsStream.h"
#include "hsBitVector.h"
#include "plProfile.h"
#include "../plIntersect/plVolumeIsect.h"
#include "../plMath/hsRadixSort.h"
static hsBitVector scratchTotVec;
static hsBitVector scratchBitVec;
static hsTArray<Int16> scratchList;
static hsTArray<hsRadixSort::Elem> scratchSort;
plProfile_CreateCounter("Harvest Leaves", "Draw", HarvestLeaves);
void plSpaceTreeNode::Read(hsStream* s)
{
fWorldBounds.Read(s);
fFlags = s->ReadSwap16();
fParent = s->ReadSwap16();
fChildren[0] = s->ReadSwap16();
fChildren[1] = s->ReadSwap16();
}
void plSpaceTreeNode::Write(hsStream* s)
{
fWorldBounds.Write(s);
s->WriteSwap16(fFlags);
s->WriteSwap16(fParent);
s->WriteSwap16(fChildren[0]);
if( fFlags & kIsLeaf )
// Temp for now to play nice with binary patches
s->WriteSwap16( 0 );
else
s->WriteSwap16(fChildren[1]);
}
plSpaceTree::plSpaceTree()
: fCullFunc(nil),
fNumLeaves(0),
fCache(nil)
{
}
plSpaceTree::~plSpaceTree()
{
}
void plSpaceTree::IRefreshRecur(Int16 which)
{
plSpaceTreeNode& sub = fTree[which];
if( sub.fFlags & plSpaceTreeNode::kIsLeaf )
{
sub.fFlags &= ~plSpaceTreeNode::kDirty;
return;
}
if( sub.fFlags & plSpaceTreeNode::kDirty )
{
IRefreshRecur(sub.fChildren[0]);
IRefreshRecur(sub.fChildren[1]);
sub.fWorldBounds.MakeEmpty();
if( !(fTree[sub.fChildren[0]].fFlags & plSpaceTreeNode::kDisabled) )
sub.fWorldBounds.Union(&fTree[sub.fChildren[0]].fWorldBounds);
if( !(fTree[sub.fChildren[1]].fFlags & plSpaceTreeNode::kDisabled) )
sub.fWorldBounds.Union(&fTree[sub.fChildren[1]].fWorldBounds);
sub.fFlags &= ~plSpaceTreeNode::kDirty;
}
}
void plSpaceTree::Refresh()
{
if( !IsEmpty() )
IRefreshRecur(fRoot);
}
void plSpaceTree::SetTreeFlag(UInt16 f, hsBool on)
{
if( IsEmpty() )
return;
if( !on )
{
ClearTreeFlag(f);
return;
}
int i;
for( i = 0; i < fTree.GetCount(); i++ )
fTree[i].fFlags |= f;
}
void plSpaceTree::ClearTreeFlag(UInt16 f)
{
if( IsEmpty() )
return;
int i;
for( i = 0; i < fTree.GetCount(); i++ )
fTree[i].fFlags &= ~f;
}
void plSpaceTree::SetLeafFlag(Int16 idx, UInt16 f, hsBool on)
{
if( IsEmpty() )
return;
hsAssert(idx == fTree[idx].fLeafIndex, "Some scrambling of indices");
if( !on )
{
ClearLeafFlag(idx, f);
return;
}
fTree[idx].fFlags |= f;
idx = fTree[idx].fParent;
while( idx != kRootParent )
{
if( (fTree[idx].fFlags & f)
|| !(fTree[fTree[idx].fChildren[0]].fFlags & fTree[fTree[idx].fChildren[1]].fFlags & f) )
{
idx = kRootParent;
}
else
{
fTree[idx].fFlags |= f;
idx = fTree[idx].fParent;
}
}
}
void plSpaceTree::ClearLeafFlag(Int16 idx, UInt16 f)
{
hsAssert(idx == fTree[idx].fLeafIndex, "Some scrambling of indices");
while( idx != kRootParent )
{
if( !(fTree[idx].fFlags & f) )
{
return;
}
else
{
fTree[idx].fFlags &= ~f;
idx = fTree[idx].fParent;
}
}
}
inline void plSpaceTree::IEnableLeaf(Int16 idx, hsBitVector& cache) const
{
cache.SetBit(idx);
idx = fTree[idx].fParent;
while( idx != kRootParent )
{
if( cache.IsBitSet(idx) )
{
return;
}
else
{
cache.SetBit(idx);
idx = fTree[idx].fParent;
}
}
}
void plSpaceTree::EnableLeaf(Int16 idx, hsBitVector& cache) const
{
IEnableLeaf(idx, cache);
}
void plSpaceTree::EnableLeaves(const hsTArray<Int16>& list, hsBitVector& cache) const
{
if( IsEmpty() )
return;
int i;
for( i = 0; i < list.GetCount(); i++ )
{
IEnableLeaf(list[i], cache);
}
}
void plSpaceTree::IHarvestAndCullEnabledLeaves(Int16 subIdx, const hsBitVector& cache, hsTArray<Int16>& list) const
{
if( !cache.IsBitSet(subIdx) )
return;
const plSpaceTreeNode& subRoot = fTree[subIdx];
plVolumeCullResult res = fCullFunc->Test(subRoot.fWorldBounds);
if( res == kVolumeCulled )
return;
if( subRoot.fFlags & plSpaceTreeNode::kIsLeaf )
{
list.Append(subIdx);
}
else
{
if( res == kVolumeClear )
{
IHarvestEnabledLeaves(subRoot.fChildren[0], cache, list);
IHarvestEnabledLeaves(subRoot.fChildren[1], cache, list);
}
else
{
IHarvestAndCullEnabledLeaves(subRoot.fChildren[0], cache, list);
IHarvestAndCullEnabledLeaves(subRoot.fChildren[1], cache, list);
}
}
}
void plSpaceTree::IHarvestEnabledLeaves(Int16 subIdx, const hsBitVector& cache, hsTArray<Int16>& list) const
{
if( !cache.IsBitSet(subIdx) )
return;
const plSpaceTreeNode& subRoot = fTree[subIdx];
if( subRoot.fFlags & plSpaceTreeNode::kIsLeaf )
{
plProfile_Inc(HarvestLeaves);
list.Append(subIdx);
}
else
{
IHarvestEnabledLeaves(subRoot.fChildren[0], cache, list);
IHarvestEnabledLeaves(subRoot.fChildren[1], cache, list);
}
}
void plSpaceTree::HarvestEnabledLeaves(plVolumeIsect* cull, const hsBitVector& cache, hsTArray<Int16>& list) const
{
if( IsEmpty() )
return;
if( fCullFunc = cull )
IHarvestAndCullEnabledLeaves(fRoot, cache, list);
else
IHarvestEnabledLeaves(fRoot, cache, list);
}
void plSpaceTree::IHarvestEnabledLeaves(Int16 subIdx, const hsBitVector& cache, hsBitVector& totList, hsBitVector& list) const
{
if( IsDisabled(subIdx) )
return;
if( totList.IsBitSet(subIdx) )
return;
totList.SetBit(subIdx);
const plSpaceTreeNode& subRoot = fTree[subIdx];
if( subRoot.fFlags & plSpaceTreeNode::kIsLeaf )
{
plProfile_Inc(HarvestLeaves);
list.SetBit(subIdx);
}
else
{
IHarvestEnabledLeaves(subRoot.fChildren[0], cache, totList, list);
IHarvestEnabledLeaves(subRoot.fChildren[1], cache, totList, list);
}
}
void plSpaceTree::MoveLeaf(Int16 idx, const hsBounds3Ext& bnd)
{
hsAssert(idx == fTree[idx].fLeafIndex, "Some scrambling of indices");
fTree[idx].fWorldBounds = bnd;
while( idx != kRootParent )
{
if( fTree[idx].fFlags & plSpaceTreeNode::kDirty )
{
idx = kRootParent;
}
else
{
fTree[idx].fFlags |= plSpaceTreeNode::kDirty;
idx = fTree[idx].fParent;
}
}
}
void plSpaceTree::HarvestLeaves(Int16 subRoot, hsBitVector& totList, hsBitVector& list) const
{
if( !IsEmpty() )
{
if( fCache )
{
IHarvestEnabledLeaves(subRoot, *fCache, totList, list);
}
else
{
IHarvestLeaves(fTree[subRoot], totList, list);
}
}
}
void plSpaceTree::HarvestLeaves(hsBitVector& totList, hsBitVector& list) const
{
if( !IsEmpty() )
IHarvestLeaves(fTree[fRoot], totList, list);
}
void plSpaceTree::HarvestLeaves(hsBitVector& list) const
{
if( !IsEmpty() )
IHarvestLeaves(fTree[fRoot], scratchTotVec, list);
scratchTotVec.Clear();
}
void plSpaceTree::HarvestLeaves(plVolumeIsect* cull, hsBitVector& list) const
{
if( !IsEmpty() )
{
if( fCullFunc = cull )
IHarvestAndCullLeaves(fTree[fRoot], scratchTotVec, list);
else
IHarvestLeaves(fTree[fRoot], scratchTotVec, list);
}
scratchTotVec.Clear();
}
void plSpaceTree::HarvestLeaves(Int16 subRoot, hsBitVector& list) const
{
IHarvestLeaves(GetNode(subRoot), scratchTotVec, list);
scratchTotVec.Clear();
}
void plSpaceTree::HarvestLeaves(plVolumeIsect* cull, hsTArray<Int16>& list) const
{
if( !IsEmpty() )
{
scratchBitVec.Clear();
HarvestLeaves(cull, scratchBitVec);
BitVectorToList(list, scratchBitVec);
}
}
void plSpaceTree::HarvestLeaves(hsTArray<Int16>& list) const
{
if( !IsEmpty() )
{
scratchBitVec.Clear();
HarvestLeaves(scratchBitVec);
BitVectorToList(list, scratchBitVec);
}
}
void plSpaceTree::HarvestLeaves(Int16 subRoot, hsTArray<Int16>& list) const
{
if( !IsEmpty() )
{
scratchBitVec.Clear();
HarvestLeaves(subRoot, scratchBitVec);
BitVectorToList(list, scratchBitVec);
}
}
void plSpaceTree::BitVectorToList(hsTArray<Int16>& list, const hsBitVector& bitVec) const
{
#if 0 // added func to bitvector
int i;
for( i = 0; i < fNumLeaves; i++ )
{
if( bitVec.IsBitSet(i) )
list.Append(i);
}
#else // added func to bitvector
bitVec.Enumerate(list);
#endif // added func to bitvector
}
void plSpaceTree::IHarvestAndCullLeaves(const plSpaceTreeNode& subRoot, hsBitVector& totList, hsBitVector& list) const
{
if( subRoot.fFlags & plSpaceTreeNode::kDisabled )
return;
int idx = &subRoot - &fTree[0];
if( totList.IsBitSet(idx) )
return;
hsAssert(fCullFunc, "Oops");
plVolumeCullResult res = fCullFunc->Test(subRoot.fWorldBounds);
if( res == kVolumeCulled )
return;
if( subRoot.fFlags & plSpaceTreeNode::kIsLeaf )
{
totList.SetBit(idx);
plProfile_Inc(HarvestLeaves);
list.SetBit(subRoot.fLeafIndex);
}
else
{
if( res == kVolumeClear )
{
totList.SetBit(idx);
IHarvestLeaves(fTree[subRoot.fChildren[0]], totList, list);
IHarvestLeaves(fTree[subRoot.fChildren[1]], totList, list);
}
else
{
IHarvestAndCullLeaves(fTree[subRoot.fChildren[0]], totList, list);
IHarvestAndCullLeaves(fTree[subRoot.fChildren[1]], totList, list);
}
}
}
void plSpaceTree::IHarvestAndCullLeaves(const plSpaceTreeNode& subRoot, hsTArray<Int16>& list) const
{
if( subRoot.fFlags & plSpaceTreeNode::kDisabled )
return;
hsAssert(fCullFunc, "Oops");
plVolumeCullResult res = fCullFunc->Test(subRoot.fWorldBounds);
if( res == kVolumeCulled )
return;
if( subRoot.fFlags & plSpaceTreeNode::kIsLeaf )
{
plProfile_Inc(HarvestLeaves);
list.Append(subRoot.fLeafIndex);
}
else
{
if( res == kVolumeClear )
{
IHarvestLeaves(fTree[subRoot.fChildren[0]], list);
IHarvestLeaves(fTree[subRoot.fChildren[1]], list);
}
else
{
IHarvestAndCullLeaves(fTree[subRoot.fChildren[0]], list);
IHarvestAndCullLeaves(fTree[subRoot.fChildren[1]], list);
}
}
}
void plSpaceTree::IHarvestLeaves(const plSpaceTreeNode& subRoot, hsBitVector& totList, hsBitVector& list) const
{
if( subRoot.fFlags & plSpaceTreeNode::kDisabled )
return;
int idx = &subRoot - &fTree[0];
if( totList.IsBitSet(idx) )
return;
totList.SetBit(idx);
if( subRoot.fFlags & plSpaceTreeNode::kIsLeaf )
{
plProfile_Inc(HarvestLeaves);
list.SetBit(subRoot.fLeafIndex);
}
else
{
IHarvestLeaves(fTree[subRoot.fChildren[0]], totList, list);
IHarvestLeaves(fTree[subRoot.fChildren[1]], totList, list);
}
}
void plSpaceTree::IHarvestLeaves(const plSpaceTreeNode& subRoot, hsTArray<Int16>& list) const
{
if( subRoot.fFlags & plSpaceTreeNode::kDisabled )
return;
if( subRoot.fFlags & plSpaceTreeNode::kIsLeaf )
{
plProfile_Inc(HarvestLeaves);
list.Append(subRoot.fLeafIndex);
}
else
{
IHarvestLeaves(fTree[subRoot.fChildren[0]], list);
IHarvestLeaves(fTree[subRoot.fChildren[1]], list);
}
}
void plSpaceTree::Read(hsStream* s, hsResMgr* mgr)
{
plCreatable::Read(s, mgr);
fRoot = s->ReadSwap16();
fNumLeaves = UInt16(s->ReadSwap32());
UInt32 n = s->ReadSwap32();
fTree.SetCount(n);
int i;
for( i = 0; i < n; i++ )
fTree[i].Read(s);
}
void plSpaceTree::Write(hsStream* s, hsResMgr* mgr)
{
plCreatable::Write(s, mgr);
s->WriteSwap16(fRoot);
s->WriteSwap32(fNumLeaves);
s->WriteSwap32(fTree.GetCount());
int i;
for( i = 0; i < fTree.GetCount(); i++ )
{
fTree[i].Write(s);
}
}
// Some debug only stuff
void plSpaceTree::HarvestLevel(int level, hsTArray<Int16>& list) const
{
if( !IsEmpty() )
{
IHarvestLevel(fRoot, level, 0, list);
}
}
void plSpaceTree::IHarvestLevel(Int16 subRoot, int level, int currLevel, hsTArray<Int16>& list) const
{
if( level == currLevel )
{
list.Append(subRoot);
return;
}
if( IsLeaf(subRoot) )
return;
IHarvestLevel(GetNode(subRoot).GetChild(0), level, currLevel+1, list);
IHarvestLevel(GetNode(subRoot).GetChild(1), level, currLevel+1, list);
}

View File

@ -0,0 +1,191 @@
/*==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 plSpaceTree_inc
#define plSpaceTree_inc
#include "hsTemplates.h"
#include "hsBounds.h"
#include "../pnFactory/plCreatable.h"
#include "hsBitVector.h"
class hsStream;
class hsResMgr;
class plVolumeIsect;
class plSpaceTreeNode
{
public:
enum {
kNone = 0x0,
kIsLeaf = 0x1,
kDirty = 0x2,
kDisabled = 0x4,
kEmpty = 0x8,
kEnabledTemp = 0x10
};
hsBounds3Ext fWorldBounds;
UInt16 fFlags; // mostly for alignment;
Int16 fParent;
union {
Int16 fChildren[2]; // Children are actually in same array as parent
Int16 fLeafIndex;
};
Int16 GetChild(int w) const { hsAssert(!(fFlags & kIsLeaf), "Getting Child of leaf node"); return fChildren[w]; }
Int16 GetParent() const { return fParent; }
Int16 GetLeaf() const { hsAssert(fFlags & kIsLeaf, "Getting leaf idx off interior node"); return fLeafIndex; }
hsBool IsLeaf() const { return 0 != (fFlags & kIsLeaf); }
const hsBounds3Ext& GetWorldBounds() const { return fWorldBounds; }
// Kind of hate this. Would like to blast the whole thing in, but
// the bounds are a real class.
void Read(hsStream* s);
void Write(hsStream* s);
};
class plSpaceTree : public plCreatable
{
public:
enum plHarvestFlags {
kNone = 0x0,
kSortBackToFront = 0x1,
kSortFrontToBack = 0x2
};
enum {
kRootParent = -1
};
private:
hsTArray<plSpaceTreeNode> fTree;
const hsBitVector* fCache;
Int16 fRoot;
Int16 fNumLeaves;
UInt16 fHarvestFlags;
mutable plVolumeIsect* fCullFunc;
hsPoint3 fViewPos;
void IRefreshRecur(Int16 which);
void IHarvestAndCullLeaves(const plSpaceTreeNode& subRoot, hsTArray<Int16>& list) const;
void IHarvestLeaves(const plSpaceTreeNode& subRoot, hsTArray<Int16>& list) const;
void IHarvestAndCullLeaves(const plSpaceTreeNode& subRoot, hsBitVector& totList, hsBitVector& list) const;
void IHarvestLeaves(const plSpaceTreeNode& subRoot, hsBitVector& totList, hsBitVector& list) const;
void IHarvestLevel(Int16 subRoot, int level, int currLevel, hsTArray<Int16>& list) const;
void IHarvestAndCullEnabledLeaves(Int16 subRoot, const hsBitVector& cache, hsTArray<Int16>& list) const;
void IHarvestEnabledLeaves(Int16 subRoot, const hsBitVector& cache, hsTArray<Int16>& list) const;
void IHarvestEnabledLeaves(Int16 subIdx, const hsBitVector& cache, hsBitVector& totList, hsBitVector& list) const;
void IEnableLeaf(Int16 idx, hsBitVector& cache) const;
public:
plSpaceTree();
virtual ~plSpaceTree();
CLASSNAME_REGISTER( plSpaceTree );
GETINTERFACE_ANY( plSpaceTree, plCreatable );
void SetViewPos(const hsPoint3& p) { fViewPos = p; }
const hsPoint3& GetViewPos() const { return fViewPos; }
const plSpaceTreeNode& GetNode(Int16 w) const { return fTree[w]; }
Int16 GetRoot() const { return fRoot; }
hsBool IsRoot(Int16 w) const { return fRoot == w; }
hsBool IsLeaf(Int16 w) const { return GetNode(w).IsLeaf(); }
void HarvestLeaves(hsBitVector& totList, hsBitVector& list) const;
void HarvestLeaves(hsBitVector& list) const;
void HarvestLeaves(plVolumeIsect* cullFunc, hsBitVector& list) const;
void HarvestLeaves(Int16 subRoot, hsBitVector& list) const;
void HarvestLeaves(Int16 subRoot, hsBitVector& totList, hsBitVector& list) const;
void HarvestLeaves(hsTArray<Int16>& list) const;
void HarvestLeaves(plVolumeIsect* cullFunc, hsTArray<Int16>& list) const;
void HarvestLeaves(Int16 subRoot, hsTArray<Int16>& list) const;
void EnableLeaf(Int16 idx, hsBitVector& cache) const;
void EnableLeaves(const hsTArray<Int16>& list, hsBitVector& cache) const;
void HarvestEnabledLeaves(plVolumeIsect* cullFunc, const hsBitVector& cache, hsTArray<Int16>& list) const;
void SetCache(const hsBitVector* cache) { fCache = cache; }
void BitVectorToList(hsTArray<Int16>& list, const hsBitVector& bitVec) const;
void SetHarvestFlags(plHarvestFlags f) { fHarvestFlags = f; }
UInt16 GetHarvestFlags() const { return fHarvestFlags; }
UInt16 HasLeafFlag(Int16 w, UInt16 f) const { return GetNode(w).fFlags & f; }
void SetLeafFlag(Int16 w, UInt16 f, hsBool on=true);
void ClearLeafFlag(Int16 w, UInt16 f);
void ClearTreeFlag(UInt16 f);
void SetTreeFlag(UInt16 f, hsBool on=true);
hsBool IsDisabled(UInt16 w) const { return (GetNode(w).fFlags & plSpaceTreeNode::kDisabled) || (fCache && !fCache->IsBitSet(w)); }
// Should GetWorldBounds check and refresh if needed?
const hsBounds3Ext& GetWorldBounds() const { return GetNode(GetRoot()).fWorldBounds; }
void MoveLeaf(Int16 idx, const hsBounds3Ext& newWorldBnd);
void Refresh();
hsBool IsEmpty() const { return 0 != (GetNode(GetRoot()).fFlags & plSpaceTreeNode::kEmpty); }
hsBool IsDirty() const { return 0 != (GetNode(GetRoot()).fFlags & plSpaceTreeNode::kDirty); }
void MakeDirty() { fTree[GetRoot()].fFlags |= plSpaceTreeNode::kDirty; }
Int16 GetNumLeaves() const { return fNumLeaves; }
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
void HarvestLevel(int level, hsTArray<Int16>& list) const;
friend class plSpaceTreeMaker;
};
#endif // plSpaceTree_inc

View File

@ -0,0 +1,737 @@
/*==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 "plSpaceTreeMaker.h"
#include "../plMath/hsRadixSort.h"
#include "../plDrawable/plSpaceTree.h"
#include "hsUtils.h" // for testing, get hsRand()
#include "hsTimer.h"
#include "../plIntersect/plVolumeIsect.h"
//#define MF_DO_TIMES
enum mfTimeTypes
{
kMakeTree = 0,
kMakeFatTree,
kSortList,
kHarvest,
kMakeSpaceTree,
kMakeTreeAll,
kHarvestSphere,
kHarvestCone,
kHarvestCapped,
kNumTimes
};
#ifdef MF_DO_TIMES
double times[kNumTimes];
#define StartTimer(i) { times[(i)] -= hsTimer::GetSeconds(); }
#define StopTimer(i) { times[(i)] += hsTimer::GetSeconds(); }
#define InitTimers() { for( int i = 0; i < kNumTimes; i++ )times[i] = 0; }
#else // MF_DO_TIMES
#define StartTimer(i)
#define StopTimer(i)
#define InitTimers()
#endif // MF_DO_TIMES
// Create the tree
// more temp testing garbage
#if 0
plSpaceCullResult mySpaceCullFunction(const hsBounds3Ext& bnd)
{
const hsPoint3& maxs = bnd.GetMaxs();
const hsPoint3& mins = bnd.GetMins();
if( maxs.fX < 0.25f )
return kSpaceCulled;
if( maxs.fY < 0.25f )
return kSpaceCulled;
if( maxs.fZ < 0.25f )
return kSpaceCulled;
if( mins.fX > 0.75f )
return kSpaceCulled;
if( mins.fY > 0.75f )
return kSpaceCulled;
if( mins.fZ > 0.75f )
return kSpaceCulled;
if( maxs.fX > 0.75f )
return kSpaceSplit;
if( maxs.fY > 0.75f )
return kSpaceSplit;
if( maxs.fZ > 0.75f )
return kSpaceSplit;
if( mins.fX < 0.25f )
return kSpaceSplit;
if( mins.fY < 0.25f )
return kSpaceSplit;
if( mins.fZ < 0.25f )
return kSpaceSplit;
return kSpaceClear;
}
#endif
void plSpaceTreeMaker::ISortList(hsTArray<plSpacePrepNode*>& nodes, const hsVector3& axis)
{
StartTimer(kSortList);
hsRadixSort::Elem* list = fSortScratch;
hsRadixSort::Elem* listTrav = list;
Int32 n = nodes.GetCount();
while( n-- )
{
listTrav->fKey.fFloat = axis.InnerProduct(nodes[n]->fWorldBounds.GetCenter());
listTrav->fBody = (void*)nodes[n];
listTrav->fNext = listTrav+1;
listTrav++;
}
list[nodes.GetCount()-1].fNext = nil;
UInt32 sortFlags = 0;
hsRadixSort rad;
hsRadixSort::Elem* sortedList = rad.Sort(list, sortFlags);
listTrav = sortedList;
int i;
for( i = 0; i < nodes.GetCount(); i++ )
{
nodes[i] = (plSpacePrepNode*)(listTrav->fBody);
listTrav = listTrav->fNext;
}
StopTimer(kSortList);
return;
}
void plSpaceTreeMaker::ISplitList(hsTArray<plSpacePrepNode*>& nodes, const hsVector3& axis, hsTArray<plSpacePrepNode*>& lower, hsTArray<plSpacePrepNode*>& upper)
{
ISortList(nodes, axis);
int lowerCount = nodes.GetCount() / 2;
int upperCount = nodes.GetCount() - lowerCount;
lower.SetCount(lowerCount);
upper.SetCount(upperCount);
int i;
for( i = 0; i < lowerCount; i++ )
lower[i] = nodes[i];
for( i = 0; i < upperCount; i++ )
upper[i] = nodes[i + lowerCount];
}
hsBounds3Ext plSpaceTreeMaker::IFindDistToCenterAxis(hsTArray<plSpacePrepNode*>& nodes, hsScalar& length, hsVector3& axis)
{
hsBounds3Ext bnd;
bnd.MakeEmpty();
hsAssert(nodes.GetCount() > 1, "Degenerate case");
int i;
for( i = 0; i < nodes.GetCount(); i++ )
{
bnd.Union(&nodes[i]->fWorldBounds);
}
length = 0;
for( i = 0; i < nodes.GetCount(); i++ )
{
hsVector3 sep;
sep.Set(&bnd.GetCenter(), &nodes[i]->fWorldBounds.GetCenter());
hsScalar len = sep.MagnitudeSquared();
if( len > length )
{
axis = sep;
length = len;
}
}
length = hsSquareRoot(length);
if( length > 1.e-3f )
axis /= length;
else
return IFindSplitAxis(nodes, length, axis);
return bnd;
}
plSpacePrepNode* plSpaceTreeMaker::IMakeFatTreeRecur(hsTArray<plSpacePrepNode*>& nodes)
{
if( !nodes.GetCount() )
return nil;
StartTimer(kMakeFatTree);
plSpacePrepNode* subRoot = TRACKED_NEW plSpacePrepNode;
fTreeSize++;
if( nodes.GetCount() == 1 )
{
*subRoot = *nodes[0];
subRoot->fChildren[0] = nil;
subRoot->fChildren[1] = nil;
StopTimer(kMakeFatTree);
return subRoot;
}
// Find the overall bounds of the list.
// Find the maximum length vector from nodes[i] center to list center.
// If that length is zero, just use the maximum dimension of overall bounds.
hsScalar length;
hsVector3 axis;
hsBounds3Ext bnd = IFindDistToCenterAxis(nodes, length, axis);
hsTArray<plSpacePrepNode*> list0;
hsTArray<plSpacePrepNode*> list1;
ISplitList(nodes, axis, list0, list1);
subRoot->fChildren[0] = IMakeTreeRecur(list0);
subRoot->fChildren[1] = IMakeTreeRecur(list1);
subRoot->fWorldBounds = bnd;
StopTimer(kMakeFatTree);
return subRoot;
}
hsBounds3Ext plSpaceTreeMaker::IFindSplitAxis(hsTArray<plSpacePrepNode*>& nodes, hsScalar& length, hsVector3& axis)
{
hsBounds3Ext bnd;
bnd.MakeEmpty();
int i;
for( i = 0; i < nodes.GetCount(); i++ )
{
bnd.Union(&nodes[i]->fWorldBounds);
}
hsScalar maxLen = bnd.GetMaxs()[0] - bnd.GetMins()[0];
int maxAxis = 0;
if( bnd.GetMaxs()[1] - bnd.GetMins()[1] > maxLen )
{
maxLen = bnd.GetMaxs()[1] - bnd.GetMins()[1];
maxAxis = 1;
}
if( bnd.GetMaxs()[2] - bnd.GetMins()[2] > maxLen )
{
maxLen = bnd.GetMaxs()[2] - bnd.GetMins()[2];
maxAxis = 2;
}
length = maxLen;
switch( maxAxis )
{
case 0:
axis.Set(1.f, 0, 0);
break;
case 1:
axis.Set(0, 1.f, 0);
break;
case 2:
axis.Set(0, 0, 1.f);
break;
}
return bnd;
}
void plSpaceTreeMaker::IFindBigList(hsTArray<plSpacePrepNode*>& nodes, hsScalar length, const hsVector3& axis, hsTArray<plSpacePrepNode*>& giants, hsTArray<plSpacePrepNode*>& strimps)
{
const hsScalar kCutoffFrac = 0.5f;
giants.SetCount(0);
strimps.SetCount(0);
int i;
for( i = 0; i < nodes.GetCount(); i++ )
{
hsPoint2 depth;
nodes[i]->fWorldBounds.TestPlane(axis, depth);
if( depth.fY - depth.fX > length * kCutoffFrac )
giants.Append(nodes[i]);
else
strimps.Append(nodes[i]);
}
}
plSpacePrepNode* plSpaceTreeMaker::INewSubRoot(const hsBounds3Ext& bnd)
{
plSpacePrepNode* subRoot = TRACKED_NEW plSpacePrepNode;
subRoot->fDataIndex = Int16(-1);
fTreeSize++;
subRoot->fWorldBounds = bnd;
return subRoot;
}
plSpacePrepNode* plSpaceTreeMaker::IMakeTreeRecur(hsTArray<plSpacePrepNode*>& nodes)
{
if( !nodes.GetCount() )
return nil;
if( nodes.GetCount() == 1 )
{
return IMakeFatTreeRecur(nodes);
}
StartTimer(kMakeTree);
// Find the maximum bounds dimension
hsScalar length;
hsVector3 axis;
hsBounds3Ext bnd = IFindSplitAxis(nodes, length, axis);
// Find everyone with bounds over half that size in the same dimension as list0.
hsTArray<plSpacePrepNode*> list0;
hsTArray<plSpacePrepNode*> list1;
IFindBigList(nodes, length, axis, list0, list1);
plSpacePrepNode* subRoot = nil;
// If list0 not empty, put them in first child, recur on remainder,
if( list0.GetCount() && list1.GetCount() )
{
subRoot = INewSubRoot(bnd);
subRoot->fChildren[0] = IMakeFatTreeRecur(list0); // too big
subRoot->fChildren[1] = IMakeTreeRecur(list1); // remainder
}
else if( list0.GetCount() )
{
subRoot = IMakeFatTreeRecur(list0);
}
// Else sort along axis by bounds center, recur separately on lower and upper halves.
else
{
ISplitList(nodes, axis, list0, list1);
subRoot = INewSubRoot(bnd);
subRoot->fChildren[0] = IMakeTreeRecur(list0);
subRoot->fChildren[1] = IMakeTreeRecur(list1);
}
StopTimer(kMakeTree);
return subRoot;
}
void plSpaceTreeMaker::IMakeTree()
{
fSortScratch = TRACKED_NEW hsRadixSort::Elem[fLeaves.GetCount()];
fPrepTree = IMakeTreeRecur(fLeaves);
delete [] fSortScratch;
fSortScratch = nil;
}
void plSpaceTreeMaker::Reset()
{
fLeaves.Reset();
fPrepTree = nil;
fTreeSize = 0;
fSortScratch = nil;
}
void plSpaceTreeMaker::IDeleteTreeRecur(plSpacePrepNode* node)
{
if( node )
{
IDeleteTreeRecur(node->fChildren[0]);
IDeleteTreeRecur(node->fChildren[1]);
delete node;
}
}
void plSpaceTreeMaker::Cleanup()
{
IDeleteTreeRecur(fPrepTree);
fPrepTree = nil;
int i;
for( i = 0; i < fLeaves.GetCount(); i++ )
delete fLeaves[i];
fLeaves.Reset();
fDisabled.Reset();
}
Int32 plSpaceTreeMaker::AddLeaf(const hsBounds3Ext& worldBnd, hsBool disable)
{
plSpacePrepNode* leaf = TRACKED_NEW plSpacePrepNode;
fLeaves.Append(leaf);
leaf->fDataIndex = fLeaves.GetCount()-1;
leaf->fChildren[0] = nil;
leaf->fChildren[1] = nil;
leaf->fWorldBounds = worldBnd;
if( leaf->fWorldBounds.GetType() != kBoundsNormal )
{
static const hsPoint3 zero(0.f, 0.f, 0.f);
leaf->fWorldBounds.Reset(&zero);
}
fDisabled.SetBit(leaf->fDataIndex, disable);
return leaf->fDataIndex;
}
//#define MF_DO_RAND
#define MF_DO_3D
#ifdef MF_DO_RAND
#define MF_SETPOINT(pt,a,b,c) pt.Set(hsRand()/32767.f, hsRand()/32767.f, hsRand()/32767.f)
#else // MF_DO_RAND
#define MF_SETPOINT(pt,a,b,c) pt.Set(a,b,c)
#endif // MF_DO_RAND
void plSpaceTreeMaker::TestTree()
{
Reset();
const int kTestSize = 10;
int i;
for( i = 0; i < kTestSize; i++ )
{
int j;
for( j = 0; j < kTestSize; j++ )
{
int k;
#ifdef MF_DO_3D
for( k = 0; k < kTestSize; k++ )
#else // MF_DO_3D
k = 0;
#endif // MF_DO_3D
{
hsBounds3Ext bnd;
hsPoint3 pt;
MF_SETPOINT(pt, float(i-1)/kTestSize, float(j-1)/kTestSize, float(k-1)/kTestSize);
bnd.Reset(&pt);
MF_SETPOINT(pt, float(i)/kTestSize, float(j)/kTestSize, float(k)/kTestSize);
bnd.Union(&pt);
AddLeaf(bnd);
}
}
}
hsBitVector list;
plSpaceTree* tree = MakeTree();
#if 0 // HACK TESTING MOVE TO VOLUMECULL
hsMatrix44 liX;
hsMatrix44 invLiX;
liX.MakeTranslateMat(&hsVector3(0.5f, 0.5f, 0));
liX.GetInverse(&invLiX);
plSphereIsect sphere;
sphere.SetRadius(0.2);
sphere.SetTransform(liX, invLiX);
tree->SetViewPos(*hsPoint3().Set(0,0,0));
plConeIsect cone;
cone.SetAngle(hsScalarPI*0.25f);
cone.SetTransform(liX, invLiX);
StartTimer(kHarvestCone);
list.Clear();
tree->HarvestLeaves(&cone, list);
StopTimer(kHarvestCone);
plConeIsect capped;
capped.SetAngle(hsScalarPI*0.25f);
capped.SetLength(0.5f);
capped.SetTransform(liX, invLiX);
StartTimer(kHarvestCapped);
list.Clear();
tree->HarvestLeaves(&capped, list);
StopTimer(kHarvestCapped);
StartTimer(kHarvestSphere);
list.Clear();
tree->HarvestLeaves(&sphere, list);
StopTimer(kHarvestSphere);
#endif // HACK TESTING MOVE TO VOLUMECULL
delete tree;
}
plSpaceTree* plSpaceTreeMaker::MakeTree()
{
// DEBUG FISH
InitTimers();
// DEBUG FISH
StartTimer(kMakeTreeAll);
if( !fLeaves.GetCount() )
return IMakeEmptyTree();
if( fLeaves.GetCount() < 2 )
return IMakeDegenerateTree();
IMakeTree();
plSpaceTree* retVal = IMakeSpaceTree();
Cleanup();
StopTimer(kMakeTreeAll);
return retVal;
}
plSpaceTree* plSpaceTreeMaker::IMakeEmptyTree()
{
plSpaceTree* tree = TRACKED_NEW plSpaceTree;
tree->fTree.SetCount(1);
tree->fTree[0].fWorldBounds.Reset(&hsPoint3(0,0,0));
tree->fTree[0].fFlags = plSpaceTreeNode::kEmpty;
tree->fRoot = 0;
tree->fNumLeaves = 0;
Cleanup();
return tree;
}
plSpaceTree* plSpaceTreeMaker::IMakeDegenerateTree()
{
plSpaceTree* tree = TRACKED_NEW plSpaceTree;
tree->fTree.Push();
tree->fRoot = 0;
tree->fTree[0].fWorldBounds = fLeaves[0]->fWorldBounds;
tree->fTree[0].fFlags = plSpaceTreeNode::kIsLeaf;
tree->fTree[0].fLeafIndex = 0;
tree->fTree[0].fParent = plSpaceTree::kRootParent;
tree->fNumLeaves = 1;
if( fDisabled.IsBitSet(0) )
tree->SetLeafFlag(0, plSpaceTreeNode::kDisabled, true);
Cleanup();
return tree;
}
int plSpaceTreeMaker::ITreeDepth(plSpacePrepNode* subRoot)
{
if( !subRoot )
return 0;
int dep0 = ITreeDepth(subRoot->fChildren[0]);
int dep1 = ITreeDepth(subRoot->fChildren[1]);
int dep = hsMaximum(dep0, dep1);
return dep+1;
}
plSpaceTree* plSpaceTreeMaker::IMakeSpaceTree()
{
StartTimer(kMakeSpaceTree);
plSpaceTree* tree = TRACKED_NEW plSpaceTree;
plSpacePrepNode* head = fPrepTree;
tree->fTree.SetCount(fLeaves.GetCount());
IGatherLeavesRecur(head, tree);
int level = ITreeDepth(head);
while( level > 0 )
IMakeSpaceTreeRecur(head, tree, --level, 0);
tree->fRoot = tree->fTree.GetCount()-1;
tree->fTree[tree->fRoot].fParent = plSpaceTree::kRootParent;
tree->fNumLeaves = fLeaves.GetCount();
int i;
for( i = 0; i < fLeaves.GetCount(); i++ )
{
if( fDisabled.IsBitSet(i) )
tree->SetLeafFlag(i, plSpaceTreeNode::kDisabled, true);
}
StopTimer(kMakeSpaceTree);
return tree;
}
// The following goofy cache-friendly tree set up slows down the tree build by 10%, but speeds up the runtime by 9%.
// Sounds fair.
#if 0 // Leaves first
Int16 plSpaceTreeMaker::IMakeSpaceTreeRecur(plSpacePrepNode* sub, plSpaceTree* tree, const int targetLevel, int currLevel)
{
if( currLevel == targetLevel )
{
Int16 nodeIdx = tree->fTree.GetCount();
tree->fTree.Push();
tree->fTree[nodeIdx].fWorldBounds = sub->fWorldBounds;
sub->fIndex = nodeIdx;
if( !sub->fChildren[0] )
{
hsAssert(!sub->fChildren[1], "Unsupported unbalance of tree");
tree->fTree[nodeIdx].fFlags = plSpaceTreeNode::kIsLeaf;
tree->fTree[nodeIdx].fLeafIndex = sub->fDataIndex;
return nodeIdx;
}
hsAssert(sub->fChildren[1], "Unsupported unbalance of tree");
tree->fTree[nodeIdx].fFlags = plSpaceTreeNode::kNone;
return nodeIdx;
}
Int16 nodeIdx = sub->fIndex;
if( !sub->fChildren[0] )
{
hsAssert(!sub->fChildren[1] , "Unsupported unbalance of tree");
return nodeIdx;
}
hsAssert(sub->fChildren[1] , "Unsupported unbalance of tree");
tree->fTree[nodeIdx].fChildren[0] = IMakeSpaceTreeRecur(sub->fChildren[0], tree, targetLevel, currLevel+1);
tree->fTree[tree->fTree[nodeIdx].fChildren[0]].fParent = nodeIdx;
tree->fTree[nodeIdx].fChildren[1] = IMakeSpaceTreeRecur(sub->fChildren[1], tree, targetLevel, currLevel+1);
tree->fTree[tree->fTree[nodeIdx].fChildren[1]].fParent = nodeIdx;
return nodeIdx;
}
#else // Leaves first
void plSpaceTreeMaker::IGatherLeavesRecur(plSpacePrepNode* sub, plSpaceTree* tree)
{
// if it's a leaf, stuff it in the right slot, else recur
if( !sub->fChildren[0] )
{
hsAssert(!sub->fChildren[1], "Unsupported unbalance of tree");
plSpaceTreeNode& leaf = tree->fTree[sub->fDataIndex];
Int16 nodeIdx = sub->fDataIndex;
leaf.fWorldBounds = sub->fWorldBounds;
sub->fIndex = nodeIdx;
leaf.fFlags = plSpaceTreeNode::kIsLeaf;
leaf.fLeafIndex = nodeIdx;
return;
}
hsAssert(sub->fChildren[1], "Unsupported unbalance of tree");
IGatherLeavesRecur(sub->fChildren[0], tree);
IGatherLeavesRecur(sub->fChildren[1], tree);
}
void plSpaceTreeMaker::IMakeSpaceTreeRecur(plSpacePrepNode* sub, plSpaceTree* tree, const int targetLevel, int currLevel)
{
// If it's a leaf, we've already done it.
if( !sub->fChildren[0] )
{
hsAssert(!sub->fChildren[1], "Unsupported unbalance of tree");
return;
}
hsAssert(sub->fChildren[0] && sub->fChildren[1], "Shouldn't get this deep, already got the leaves");
if( currLevel == targetLevel )
{
Int16 nodeIdx = tree->fTree.GetCount();
tree->fTree.Push();
tree->fTree[nodeIdx].fWorldBounds = sub->fWorldBounds;
sub->fIndex = nodeIdx;
tree->fTree[nodeIdx].fFlags = plSpaceTreeNode::kNone;
tree->fTree[nodeIdx].fChildren[0] = sub->fChildren[0]->fIndex;
tree->fTree[sub->fChildren[0]->fIndex].fParent = nodeIdx;
tree->fTree[nodeIdx].fChildren[1] = sub->fChildren[1]->fIndex;
tree->fTree[sub->fChildren[1]->fIndex].fParent = nodeIdx;
return;
}
IMakeSpaceTreeRecur(sub->fChildren[0], tree, targetLevel, currLevel+1);
IMakeSpaceTreeRecur(sub->fChildren[1], tree, targetLevel, currLevel+1);
}
#endif // Leaves first

View File

@ -0,0 +1,107 @@
/*==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 plSpaceTreeMaker_inc
#define plSpaceTreeMaker_inc
#include "hsBounds.h"
#include "hsTemplates.h"
#include "hsBitVector.h"
class hsRadixSortElem;
class plSpaceTree;
class plSpacePrepNode
{
public:
hsBounds3Ext fWorldBounds;
Int16 fIndex;
Int16 fDataIndex;
plSpacePrepNode* fChildren[2];
};
class plSpaceTreeMaker
{
protected:
hsTArray<plSpacePrepNode*> fLeaves; // input
hsRadixSortElem* fSortScratch;
hsBitVector fDisabled;
plSpacePrepNode* fPrepTree;
Int16 fTreeSize;
plSpacePrepNode* INewSubRoot(const hsBounds3Ext& bnd);
void IFindBigList(hsTArray<plSpacePrepNode*>& nodes, hsScalar length, const hsVector3& axis, hsTArray<plSpacePrepNode*>& giants, hsTArray<plSpacePrepNode*>& strimp);
void ISortList(hsTArray<plSpacePrepNode*>& nodes, const hsVector3& axis);
void ISplitList(hsTArray<plSpacePrepNode*>& nodes, const hsVector3& axis, hsTArray<plSpacePrepNode*>& lower, hsTArray<plSpacePrepNode*>& upper);
hsBounds3Ext IFindDistToCenterAxis(hsTArray<plSpacePrepNode*>& nodes, hsScalar& length, hsVector3& axis);
plSpacePrepNode* IMakeFatTreeRecur(hsTArray<plSpacePrepNode*>& nodes);
hsBounds3Ext IFindSplitAxis(hsTArray<plSpacePrepNode*>& nodes, hsScalar& length, hsVector3& axis);
plSpacePrepNode* IMakeTreeRecur(hsTArray<plSpacePrepNode*>& nodes);
void IMakeTree();
plSpaceTree* IMakeEmptyTree();
plSpaceTree* IMakeDegenerateTree();
void IGatherLeavesRecur(plSpacePrepNode* sub, plSpaceTree* tree);
void IMakeSpaceTreeRecur(plSpacePrepNode* sub, plSpaceTree* tree, const int targetLevel, int currLevel);
plSpaceTree* IMakeSpaceTree();
int ITreeDepth(plSpacePrepNode* subRoot);
void IDeleteTreeRecur(plSpacePrepNode* node);
public:
void Cleanup();
void Reset();
Int32 AddLeaf(const hsBounds3Ext& worldBnd, hsBool disable=false);
plSpaceTree* MakeTree();
void TestTree(); // development only - NUKE ME mf horse
};
#endif // plSpaceTreeMaker_inc

View File

@ -0,0 +1,254 @@
/*==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 "plSpanInstance.h"
#include "hsGeometry3.h"
#include "hsStream.h"
void plSpanEncoding::Read(hsStream* s)
{
fCode = s->ReadByte();
fPosScale = s->ReadSwapScalar();
}
void plSpanEncoding::Write(hsStream* s) const
{
s->WriteByte((UInt8)fCode);
s->WriteSwapScalar(fPosScale);
}
plSpanInstance::plSpanInstance()
: fPosDelta(nil),
fCol(nil)
{
fL2W[0][1] = fL2W[0][2] = 0.f;
fL2W[1][0] = fL2W[1][2] = 0.f;
fL2W[2][0] = fL2W[2][1] = 0.f;
fL2W[0][0] = fL2W[1][1] = fL2W[2][2] = 1.f;
}
plSpanInstance::~plSpanInstance()
{
DeAlloc();
}
void plSpanInstance::DeAlloc()
{
delete [] fPosDelta;
fPosDelta = nil;
delete [] fCol;
fCol = nil;
}
void plSpanInstance::Alloc(const plSpanEncoding& encoding, UInt32 numVerts)
{
DeAlloc();
UInt32 posStride = PosStrideFromEncoding(encoding);
if( posStride )
fPosDelta = TRACKED_NEW UInt8[numVerts * posStride];
UInt32 colStride = ColStrideFromEncoding(encoding);
if( colStride )
fCol = TRACKED_NEW UInt8[numVerts * colStride];
}
void plSpanInstance::Read(hsStream* stream, const plSpanEncoding& encoding, UInt32 numVerts)
{
Alloc(encoding, numVerts);
stream->Read(12 * sizeof(hsScalar), fL2W[0]);
if( fPosDelta )
{
stream->Read(numVerts * PosStrideFromEncoding(encoding), fPosDelta);
}
if( fCol )
{
stream->Read(numVerts * ColStrideFromEncoding(encoding), fCol);
}
}
void plSpanInstance::Write(hsStream* stream, const plSpanEncoding& encoding, UInt32 numVerts) const
{
stream->Write(12 * sizeof(hsScalar), fL2W[0]);
if( fPosDelta )
{
stream->Write(numVerts * PosStrideFromEncoding(encoding), fPosDelta);
}
if( fCol )
{
stream->Write(numVerts * ColStrideFromEncoding(encoding), fCol);
}
}
hsMatrix44 plSpanInstance::LocalToWorld() const
{
hsMatrix44 retVal;
retVal.NotIdentity();
int i;
for( i = 0; i < 3; i++ )
{
int j;
for( j = 0; j < 4; j++ )
{
retVal.fMap[i][j] = fL2W[i][j];
}
}
retVal.fMap[3][0] =
retVal.fMap[3][1] =
retVal.fMap[3][2] = 0.f;
retVal.fMap[3][3] = 1.f;
return retVal;
}
hsMatrix44 plSpanInstance::WorldToLocal() const
{
hsMatrix44 l2w = LocalToWorld();
hsMatrix44 w2l;
l2w.GetInverse(&w2l);
return w2l;
}
void plSpanInstance::SetLocalToWorld(const hsMatrix44& l2w)
{
int i;
for( i = 0; i < 3; i++ )
{
int j;
for( j = 0; j < 4; j++ )
{
fL2W[i][j] = l2w.fMap[i][j];
}
}
}
void plSpanInstance::Encode(const plSpanEncoding& encoding, UInt32 numVerts, const hsVector3* delPos, const UInt32* color)
{
Alloc(encoding, numVerts);
hsAssert(!(encoding.fCode & plSpanEncoding::kPosMask) == !delPos, "Position encoding mismatch");
hsAssert(!(encoding.fCode & plSpanEncoding::kColMask) == !color, "Color encoding mismatch");
// Check that there's anything to encode.
if( !(fPosDelta || fCol) )
return;
Int8* pos888 = (Int8*)fPosDelta;
Int16* pos161616 = (Int16*)fPosDelta;
UInt32* pos101010 = (UInt32*)fPosDelta;
UInt8* col8 = (UInt8*)fCol;
UInt16* col16 = (UInt16*)fCol;
UInt32* col32 = (UInt32*)fCol;
int i;
for( i = 0; i < numVerts; i++ )
{
switch(encoding.fCode & plSpanEncoding::kPosMask)
{
case plSpanEncoding::kPos888:
pos888[0] = Int8(delPos->fX / encoding.fPosScale);
pos888[1] = Int8(delPos->fY / encoding.fPosScale);
pos888[2] = Int8(delPos->fZ / encoding.fPosScale);
pos888 += 3;
delPos++;
break;
case plSpanEncoding::kPos161616:
pos161616[0] = Int16(delPos->fX / encoding.fPosScale);
pos161616[1] = Int16(delPos->fY / encoding.fPosScale);
pos161616[2] = Int16(delPos->fZ / encoding.fPosScale);
pos161616 += 3;
delPos++;
break;
case plSpanEncoding::kPos101010:
*pos101010 =
((UInt32(delPos->fX / encoding.fPosScale) & 0x3f) << 0)
| ((UInt32(delPos->fY / encoding.fPosScale) & 0x3f) << 10)
| ((UInt32(delPos->fZ / encoding.fPosScale) & 0x3f) << 20);
pos101010++;
delPos++;
break;
case plSpanEncoding::kPos008:
*pos888 = Int8(delPos->fZ / encoding.fPosScale);
pos888++;
delPos++;
break;
case plSpanEncoding::kPosNone:
default:
break;
}
switch(encoding.fCode & plSpanEncoding::kColMask)
{
case plSpanEncoding::kColA8:
*col8 = (UInt8)((*color) >> 24);
col8++;
color++;
break;
case plSpanEncoding::kColI8:
*col8 = (UInt8)((*color) & 0xff);
col8++;
color++;
break;
case plSpanEncoding::kColAI88:
*col16 = (UInt16)(((*color) >> 16) & 0xffff);
col16++;
color++;
break;
case plSpanEncoding::kColRGB888:
*col8++ = (UInt8)((*color >> 16) & 0xff);
*col8++ = (UInt8)((*color >> 8) & 0xff);
*col8++ = (UInt8)((*color >> 0) & 0xff);
color++;
break;
case plSpanEncoding::kColARGB8888:
*col32++ = *color;
color++;
break;
case plSpanEncoding::kColNone:
default:
break;
}
}
}

View File

@ -0,0 +1,304 @@
/*==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 plSpanInstance_inc
#define plSpanInstance_inc
#include "hsGeometry3.h"
#include "hsMatrix44.h"
// plClusterGroup
// array of templates
// array of materials (indexed by templates)
// array of clusters
// array of LOD blend
// array of vis sets
// plCluster
// array of span instances that are combinable
// LOD blend start and end index
// vis set index
// Combinable means:
// same material
// same format
// same LOD blend
// same vis set
// same lights
// same encoding?
// plSpanInstance
// template idx
// 3x4 transform
// encoding flags
// (what components does it include, delPos? color?)
// (what's the encoding? 32bit RGBA? 16Bit/Chan? 10Bit/Chan? 8Bit/Chan?)
// (need an encoding per channel)
// plSpanTemplate
// numVerts
// Format (assume pos & norm?)
// kUVWMask
// kColMask
// kWeightMask
// fPos
// fNorm
// fCol
// fUVWs
// fWeights
class plSpanEncoding
{
public:
enum
{
kPosNone = 0x0,
kPos888 = 0x1,
kPos161616 = 0x2,
kPos101010 = 0x4,
kPos008 = 0x8,
kPosMask = kPos888 | kPos161616 | kPos101010 | kPos008,
kColNone = 0x0,
kColA8 = 0x10,
kColI8 = 0x20,
kColAI88 = 0x40,
kColRGB888 = 0x80,
kColARGB8888 = 0x100,
kColMask = kColNone
| kColA8
| kColI8
| kColAI88
| kColRGB888
| kColARGB8888,
};
UInt32 fCode;
hsScalar fPosScale;
plSpanEncoding() : fCode(kPosNone|kColNone), fPosScale(0) {}
plSpanEncoding(UInt32 c, hsScalar s) : fCode(c), fPosScale(s) {}
UInt32 Code() const { return fCode; }
hsScalar Scale() const { return fPosScale; }
void Read(hsStream* s);
void Write(hsStream* s) const;
};
class plSpanInstance
{
protected:
UInt8* fPosDelta;
UInt8* fCol;
hsScalar fL2W[3][4];
friend class plSpanInstanceIter;
public:
plSpanInstance();
~plSpanInstance();
void Read(hsStream* s, const plSpanEncoding& encoding, UInt32 numVerts);
void Write(hsStream* s, const plSpanEncoding& encoding, UInt32 numVerts) const;
void Encode(const plSpanEncoding& encoding, UInt32 numVerts, const hsVector3* delPos, const UInt32* color);
void Alloc(const plSpanEncoding& encoding, UInt32 numVerts);
void DeAlloc();
hsMatrix44 LocalToWorld() const;
hsMatrix44 WorldToLocal() const;
void SetLocalToWorld(const hsMatrix44& l2w);
hsBool HasPosDelta() const { return fPosDelta != nil; }
hsBool HasColor() const { return fCol != nil; }
static UInt16 PosStrideFromEncoding(const plSpanEncoding& encoding)
{
switch(encoding.fCode & plSpanEncoding::kPosMask)
{
case plSpanEncoding::kPos888:
return 3;
case plSpanEncoding::kPos161616:
return 6;
case plSpanEncoding::kPos101010:
return 4;
case plSpanEncoding::kPos008:
return 1;
}
return 0;
}
static UInt16 ColStrideFromEncoding(const plSpanEncoding& encoding)
{
switch(encoding.fCode & plSpanEncoding::kPosMask)
{
case plSpanEncoding::kColNone:
return 0;
case plSpanEncoding::kColA8:
return 1;
case plSpanEncoding::kColI8:
return 1;
case plSpanEncoding::kColAI88:
return 2;
case plSpanEncoding::kColRGB888:
return 3;
case plSpanEncoding::kColARGB8888:
return 4;
}
return 0;
}
};
class plSpanInstanceIter
{
protected:
plSpanInstance* fInst;
plSpanEncoding fEncoding;
UInt32 fNumVerts;
Int32 fNumVertsLeft;
UInt16 fPosStride;
UInt16 fColStride;
union {
Int8* fPos888;
Int16* fPos161616;
UInt32* fPos101010;
};
union {
UInt8* fA8;
UInt8* fI8;
UInt16* fAI88;
UInt8* fRGB888;
UInt32* fARGB8888;
};
public:
plSpanInstanceIter();
plSpanInstanceIter(plSpanInstance* inst, const plSpanEncoding& encoding, UInt32 numVerts) { Init(inst, encoding, numVerts); }
void Init(plSpanInstance* inst, const plSpanEncoding& encoding, UInt32 numVerts)
{
fInst = inst;
fEncoding = encoding;
fNumVerts = numVerts;
fPosStride = inst->PosStrideFromEncoding(fEncoding);
fColStride = inst->ColStrideFromEncoding(fEncoding);
fNumVertsLeft = 0;
}
void Begin()
{
fPos888 = (Int8*)fInst->fPosDelta;
fA8 = fInst->fCol;
fNumVertsLeft = fNumVerts;
}
void Advance()
{
fPos888 += fPosStride;
fA8 += fColStride;
fNumVertsLeft--;
}
hsBool More() const { return fNumVertsLeft > 0; }
hsVector3 DelPos() const
{
switch(fEncoding.fCode & plSpanEncoding::kPosMask)
{
case plSpanEncoding::kPos888:
return hsVector3(fPos888[0] * fEncoding.fPosScale,
fPos888[1] * fEncoding.fPosScale,
fPos888[2] * fEncoding.fPosScale);
case plSpanEncoding::kPos161616:
return hsVector3(fPos161616[0] * fEncoding.fPosScale,
fPos161616[1] * fEncoding.fPosScale,
fPos161616[2] * fEncoding.fPosScale);
case plSpanEncoding::kPos101010:
return hsVector3(int(*fPos101010 & 0x3f) * fEncoding.fPosScale,
int((*fPos101010 >> 10) & 0x3f) * fEncoding.fPosScale,
int((*fPos101010 >> 20) & 0x3f) * fEncoding.fPosScale);
case plSpanEncoding::kPos008:
return hsVector3(0,0, *fPos888 * fEncoding.fPosScale);
}
return hsVector3(0,0,0);
};
hsPoint3 Position(const hsPoint3& p) const
{
hsPoint3 pos(p);
pos += DelPos();
return pos;
};
UInt32 Color(UInt32 c) const
{
switch(fEncoding.fCode & plSpanEncoding::kColMask)
{
case plSpanEncoding::kColA8:
return (c & 0x00ffffff) | *fA8;
case plSpanEncoding::kColI8:
return (c & 0xff000000)
| (*fI8 << 16)
| (*fI8 << 8)
| (*fI8 << 0);
case plSpanEncoding::kColAI88:
{
const UInt32 col = *fAI88 & 0xff;
return ((*fAI88 & 0xff00) << 24)
| (col << 16)
| (col << 8)
| (col << 0);
}
case plSpanEncoding::kColRGB888:
return (c & 0xff000000)
| (fRGB888[0] << 16)
| (fRGB888[1] << 8)
| (fRGB888[2] << 0);
case plSpanEncoding::kColARGB8888:
return *fARGB8888;
}
return c;
};
};
#endif // plSpanInstance_inc

View File

@ -0,0 +1,153 @@
/*==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 "plSpanTemplate.h"
#include "plSpanInstance.h"
#include "hsStream.h"
#include "hsGeometry3.h"
plSpanTemplate::plSpanTemplate()
: fNumVerts(0),
fFormat(0),
fData(nil),
fNumTris(0),
fIndices(nil)
{
}
UInt32 plSpanTemplate::CalcStride()
{
fStride = 0;
if( NumPos() )
fStride += sizeof(hsPoint3);
if( NumNorm() )
fStride += sizeof(hsVector3);
if( NumColor() )
fStride += sizeof(UInt32);
if( NumColor2() )
fStride += sizeof(UInt32);
if( NumWgtIdx() )
fStride += sizeof(UInt32);
if( NumUVWs() )
fStride += (UInt8)(sizeof(hsPoint3) * NumUVWs());
if( NumWeights() )
fStride += (UInt8)(sizeof(hsScalar) * NumWeights());
return UInt32(fStride);
}
void plSpanTemplate::Alloc(UInt16 format, UInt32 numVerts, UInt32 numTris)
{
DeAlloc();
fNumVerts = (UInt16)numVerts;
fFormat = format;
CalcStride();
fNumTris = (UInt16)numTris;
fData = TRACKED_NEW UInt8[VertSize()];
fIndices = TRACKED_NEW UInt16[NumIndices()];
}
void plSpanTemplate::DeAlloc()
{
delete [] fData;
delete [] fIndices;
fNumTris = 0;
fNumVerts = 0;
fFormat = 0;
fData = nil;
fIndices = nil;
}
void plSpanTemplate::Read(hsStream* stream)
{
fNumVerts = stream->ReadSwap16();
fFormat = stream->ReadSwap16();
fNumTris = stream->ReadSwap16();
Alloc(fFormat, fNumVerts, fNumTris);
stream->Read(VertSize(), fData);
stream->Read(IndexSize(), fIndices);
}
void plSpanTemplate::Write(hsStream* stream) const
{
stream->WriteSwap16(fNumVerts);
stream->WriteSwap16(fFormat);
stream->WriteSwap16(fNumTris);
stream->Write(VertSize(), fData);
stream->Write(IndexSize(), fIndices);
}
void plSpanTemplateB::ComputeBounds()
{
fLocalBounds.MakeEmpty();
int i;
for( i = 0; i < NumVerts(); i++ )
fLocalBounds.Union(Position(i));
}
void plSpanTemplateB::AllocColors()
{
fMultColors = TRACKED_NEW hsColorRGBA[NumVerts()];
fAddColors = TRACKED_NEW hsColorRGBA[NumVerts()];
}
void plSpanTemplateB::DeAllocColors()
{
delete [] fMultColors;
delete [] fAddColors;
fMultColors = nil;
fAddColors = nil;
}

View File

@ -0,0 +1,280 @@
/*==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 plSpanTemplate_inc
#define plSpanTemplate_inc
#include "hsGeometry3.h"
#include "hsBounds.h"
#include "hsColorRGBA.h"
#include "plRenderLevel.h"
class hsStream;
class INode;
class hsGMaterial;
class plSpanTemplate
{
public:
// 99% of the time, the defaults are fine. Just tell me
// how many UVWs, and whether you've got color.
static UInt16 MakeFormat(hsBool hasColor, int numUVWs,
hsBool hasWgtIdx = false,
int numWgts = 0,
hsBool hasNorm = true,
hsBool hasPos = true,
hsBool hasColor2 = true)
{
return (hasPos ? kPosMask : 0)
| (hasNorm ? kNormMask : 0)
| (hasColor ? kColorMask : 0)
| (hasWgtIdx ? kWgtIdxMask : 0)
| ((numUVWs << 4) & kUVWMask)
| ((numWgts << 8) & kWeightMask)
| (hasColor2 ? kColor2Mask : 0); // Till we can get this out of here.
};
enum
{
kPosMask = 0x1,
kNormMask = 0x2,
kColorMask = 0x4,
kWgtIdxMask = 0x8,
kUVWMask = 0xf0,
kWeightMask = 0x300,
kColor2Mask = 0x400
};
enum Channel
{
kPosition,
kWeight,
kWgtIdx,
kNormal,
kColor,
kColor2,
kUVW
};
protected:
UInt16 fNumVerts;
UInt16 fFormat;
UInt8 fStride;
UInt16 fNumTris;
// Data stored interleaved. Any channels may be omitted, but
// existing channels are in exactly the following order:
// Position
// Weights
// Indices
// Normal
// Color
// Color2
// UVWs
UInt8* fData;
UInt16* fIndices;
friend class plClusterUtil;
public:
plSpanTemplate();
virtual ~plSpanTemplate() { DeAlloc(); }
const UInt8* VertData() const { return fData; }
const UInt16* IndexData() const { return fIndices; }
UInt32 NumVerts() const { return fNumVerts; }
UInt32 Stride() const { return UInt32(fStride); }
UInt32 CalcStride();
UInt32 VertSize() const { return NumVerts() * Stride(); }
UInt32 NumTris() const { return fNumTris; }
UInt32 NumIndices() const { return NumTris() * 3; }
UInt32 IndexSize() const { return NumIndices() * sizeof(UInt16); }
UInt8 PositionOffset() const { return UInt8(0); }
UInt8 WgtIdxOffset() const { return UInt8(PositionOffset() + NumPos() * sizeof(hsPoint3)); }
UInt8 WeightOffset() const { return UInt8(WgtIdxOffset() + NumWgtIdx() * sizeof(UInt32)); }
UInt8 NormalOffset() const { return UInt8(WeightOffset() + NumWeights() * sizeof(hsScalar)); }
UInt8 ColorOffset() const { return UInt8(NormalOffset() + NumNorm() * sizeof(hsVector3)); }
UInt8 Color2Offset() const { return UInt8(ColorOffset() + NumColor() * sizeof(UInt32)); }
UInt8 UVWOffset() const { return UInt8(Color2Offset() + NumColor2() * sizeof(UInt32)); }
UInt32 NumUVWs() const { return (fFormat & kUVWMask) >> 4; }
UInt32 NumWeights() const { return (fFormat & kWeightMask) >> 8; }
UInt32 NumPos() const { return (fFormat & kPosMask) >> 0; }
UInt32 NumNorm() const { return (fFormat & kNormMask) >> 1; }
UInt32 NumColor() const { return (fFormat & kColorMask) >> 2; }
UInt32 NumColor2() const { return (fFormat & kColor2Mask) >> 10; }
UInt32 NumWgtIdx() const { return (fFormat & kWgtIdxMask) >> 3; }
hsPoint3* Position(int i) const { return (hsPoint3*)GetData(kPosition, i); }
hsVector3* Normal(int i) const { return (hsVector3*)GetData(kNormal, i); }
UInt32* Color(int i) const { return (UInt32*)GetData(kColor, i); }
UInt32* Color2(int i) const { return (UInt32*)GetData(kColor2, i); }
UInt32* WgtIdx(int i) const { return (UInt32*)GetData(kWgtIdx, i); }
hsPoint3* UVWs(int iv, int iuv) const { return (hsPoint3*)GetData(kUVW, iv, iuv); }
hsScalar* Weight(int iv, int iw) const { return (hsScalar*)GetData(kWeight, iv, iw); }
UInt8* GetData(Channel chan, int i, int j=0) const
{
ValidateInput(chan, i, j);
UInt8* base = fData + i * fStride;
switch(chan)
{
case kPosition:
return base;
case kWeight:
return base
+ NumPos() * sizeof(hsPoint3)
+ j * sizeof(hsScalar);
case kWgtIdx:
return base
+ NumPos() * sizeof(hsPoint3)
+ NumWeights() * sizeof(hsScalar);
case kNormal:
return base
+ NumPos() * sizeof(hsPoint3)
+ NumWeights() * sizeof(hsScalar)
+ NumWgtIdx() * sizeof(UInt32);
case kColor:
return base
+ NumPos() * sizeof(hsPoint3)
+ NumWeights() * sizeof(hsScalar)
+ NumWgtIdx() * sizeof(UInt32)
+ NumNorm() * sizeof(hsVector3);
case kColor2:
return base
+ NumPos() * sizeof(hsPoint3)
+ NumWeights() * sizeof(hsScalar)
+ NumWgtIdx() * sizeof(UInt32)
+ NumNorm() * sizeof(hsVector3)
+ NumColor() * sizeof(UInt32);
case kUVW:
return base
+ NumPos() * sizeof(hsPoint3)
+ NumWeights() * sizeof(hsScalar)
+ NumWgtIdx() * sizeof(UInt32)
+ NumNorm() * sizeof(hsVector3)
+ NumColor() * sizeof(UInt32)
+ NumColor2() * sizeof(UInt32)
+ j * sizeof(hsPoint3);
}
hsAssert(false, "Unrecognized vertex channel");
return nil;
}
hsBool ValidateInput(Channel chan, int i, int j) const
{
switch(chan)
{
case kPosition:
hsAssert(NumPos(), "Invalid data request");
return NumPos() > 0;
case kWeight:
hsAssert(NumWeights(), "Invalid data request");
return NumWeights() > 0;
case kWgtIdx:
hsAssert(NumWgtIdx() > j, "Invalid data request");
return NumWgtIdx() > j;
case kNormal:
hsAssert(NumNorm(), "Invalid data request");
return NumNorm() > 0;
case kColor:
hsAssert(NumColor(), "Invalid data request");
return NumColor() > 0;
case kColor2:
hsAssert(NumColor2(), "Invalid data request");
return NumColor2() > 0;
case kUVW:
hsAssert(NumUVWs() > j, "Invalid data request");
return NumUVWs() > j;
}
hsAssert(false, "Unrecognized vertex channel");
return false;
}
void Alloc(UInt16 format, UInt32 numVerts, UInt32 numTris);
void DeAlloc();
void Read(hsStream* s);
void Write(hsStream* s) const;
};
// An export only version
class plSpanTemplateB : public plSpanTemplate
{
INode* fSrc;
hsBounds3Ext fLocalBounds;
hsColorRGBA* fMultColors;
hsColorRGBA* fAddColors;
public:
plSpanTemplateB(INode* src) : plSpanTemplate(), fSrc(src), fMaterial(nil) {}
virtual ~plSpanTemplateB() { DeAllocColors(); }
void ComputeBounds();
const hsBounds3Ext& GetLocalBounds() const { return fLocalBounds; }
INode* GetSrcNode() const { return fSrc; }
hsGMaterial* fMaterial;
plRenderLevel fRenderLevel;
hsColorRGBA* MultColor(int i) const { return &fMultColors[i]; }
hsColorRGBA* AddColor(int i) const { return &fAddColors[i]; }
void AllocColors();
void DeAllocColors();
};
#endif // plSpanTemplate_inc

View File

@ -0,0 +1,578 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plSpanTypes Class Functions //
// //
//// Version History /////////////////////////////////////////////////////////
// //
// 5.3.2001 mcn - Created. //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plSpanTypes.h"
#include "hsStream.h"
#include "../pnKeyedObject/plKey.h"
#include "../plPipeline/plGBufferGroup.h"
#include "../plPipeline/hsGDeviceRef.h"
#include "../plGLight/plLightInfo.h"
#include "plDrawable.h"
#include "plAuxSpan.h"
#include "plAccessSnapShot.h"
/////////////////////////////////////////////////////////////////////////////
//// plSpan Functions ////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Read ////////////////////////////////////////////////////////////////////
void plSpan::Read( hsStream *stream )
{
fSubType = (UInt16)(stream->ReadSwap32());
fFogEnvironment = nil;
fMaterialIdx = stream->ReadSwap32();
fLocalToWorld.Read( stream );
fWorldToLocal.Read( stream );
fProps = stream->ReadSwap32();
fLocalBounds.Read( stream );
fWorldBounds.Read( stream );
fNumMatrices = (UInt8)(stream->ReadSwap32());
fBaseMatrix = stream->ReadSwap32();
fLocalUVWChans = stream->ReadSwap16();
fMaxBoneIdx = stream->ReadSwap16();
fPenBoneIdx = stream->ReadSwap16();
fMinDist = stream->ReadSwapScalar();
fMaxDist = stream->ReadSwapScalar();
if( fProps & kWaterHeight )
fWaterHeight = stream->ReadSwapScalar();
#ifdef HS_DEBUGGING
fOwnerKey = nil;
#endif
}
//// Write ///////////////////////////////////////////////////////////////////
void plSpan::Write( hsStream *stream )
{
stream->WriteSwap32(fSubType);
stream->WriteSwap32( fMaterialIdx );
fLocalToWorld.Write( stream );
fWorldToLocal.Write( stream );
stream->WriteSwap32( fProps );
fLocalBounds.Write( stream );
fWorldBounds.Write( stream );
stream->WriteSwap32( fNumMatrices );
stream->WriteSwap32( fBaseMatrix );
stream->WriteSwap16( fLocalUVWChans );
stream->WriteSwap16( fMaxBoneIdx );
stream->WriteSwap16( fPenBoneIdx );
stream->WriteSwapScalar( fMinDist );
stream->WriteSwapScalar( fMaxDist );
if( fProps & kWaterHeight )
stream->WriteSwapScalar(fWaterHeight);
}
void plSpan::RemoveAuxSpan(plAuxSpan* aux)
{
int i = fAuxSpans.Find(aux);
int newCount = fAuxSpans.GetCount()-1;
if( i < newCount )
{
fAuxSpans[i] = fAuxSpans[fAuxSpans.GetCount()-1];
}
fAuxSpans.SetCount(newCount);
}
void plSpan::AddAuxSpan(plAuxSpan* aux)
{
fAuxSpans.Append(aux);
}
// AddPermaLight ////////////////////////////////////////////////////////////////
// PermaLights are permanently assigned to a set of spans. There's no checking
// for in range or anything, they are just on.
void plSpan::AddPermaLight(plLightInfo* li, hsBool proj)
{
if( li )
{
hsTArray<plLightInfo*>& lights = proj ? fPermaProjs : fPermaLights;
int idx = lights.Find(li);
if( lights.kMissingIndex == idx )
lights.Append(li);
if( lights.GetCount() )
fProps |= proj ? kPropHasPermaProjs : kPropHasPermaLights;
}
}
void plSpan::RemovePermaLight(plLightInfo* li, hsBool proj)
{
hsTArray<plLightInfo*>& lights = proj ? fPermaProjs : fPermaLights;
int idx = lights.Find(li);
if( lights.kMissingIndex != idx )
{
lights.Remove(idx);
if( !lights.GetCount() )
fProps &= ~(proj ? kPropHasPermaProjs : kPropHasPermaLights);
}
}
//// AddLight ////////////////////////////////////////////////////////////////
// Smart function for maintaining the sorted list of lights for a plSpan.
void plSpan::AddLight( plLightInfo *li, hsScalar strength, hsScalar scale, hsBool proj ) const
{
hsTArray<plLightInfo*>& lights = proj ? fProjectors : fLights;
hsTArray<hsScalar>& strengths = proj ? fProjStrengths : fLightStrengths;
hsTArray<hsScalar>& scales = proj ? fProjScales : fLightScales;
int i;
for( i = 0; i < lights.GetCount(); i++ )
{
if( strengths[ i ] < strength )
break;
}
lights.Insert(i, li);
strengths.Insert(i, strength);
scales.Insert(i, hsScalar(UInt32(scale * 127.9f)) / 127.f);
}
void plSpan::ClearLights() const
{
fLights.SetCount(0);
fLightStrengths.SetCount(0);
fLightScales.SetCount(0);
fProjectors.SetCount(0);
fProjStrengths.SetCount(0);
fProjScales.SetCount(0);
int i;
for( i = 0; i < fPermaLights.GetCount(); i++ )
{
if( !(fPermaLights[i]->IsIdle() || fPermaLights[i]->GetProperty(plLightInfo::kLPShadowOnly)) )
{
fLights.Append(fPermaLights[i]);
fLightStrengths.Append(2.f);
fLightScales.Append(1.f);
}
}
for( i = 0; i < fPermaProjs.GetCount(); i++ )
{
if( !(fPermaProjs[i]->IsIdle() || fPermaProjs[i]->GetProperty(plLightInfo::kLPShadowOnly)) )
{
fProjectors.Append(fPermaProjs[i]);
fProjStrengths.Append(2.f);
fProjScales.Append(1.f);
}
}
fShadowSlaveBits.Clear();
}
//// CanMergeInto ////////////////////////////////////////////////////////////
hsBool plSpan::CanMergeInto( plSpan *other )
{
if( fTypeMask ^ other->fTypeMask )
{
return false;
}
// Make sure lighting equations match
if( ( ( fProps ^ other->fProps ) & kLiteMask ) != 0 )
{
return false;
}
if( fNumMatrices != other->fNumMatrices )
return false;
if( fBaseMatrix != other->fBaseMatrix )
return false;
if( fMaterialIdx != other->fMaterialIdx )
{
return false;
}
if( fFogEnvironment != other->fFogEnvironment )
return false;
// Don't bother checking for having exactly the same matrix elements.
// Either they are both ident, or they are inequal.
if( fLocalToWorld != other->fLocalToWorld )
// if( !(fLocalToWorld.fFlags & other->fLocalToWorld.fFlags & hsMatrix44::kIsIdent) )
{
return false;
}
if( fLights.GetCount() != other->fLights.GetCount() )
return false;
if( fProjectors.GetCount() != other->fProjectors.GetCount() )
return false;
if( fLights.GetCount() )
{
if( !HSMemory::EqualBlocks(fLights.AcquireArray(), other->fLights.AcquireArray(), fLights.GetCount() * sizeof(plLightInfo*)) )
return false;
if( !HSMemory::EqualBlocks(fLightScales.AcquireArray(), other->fLightScales.AcquireArray(), fLights.GetCount() * sizeof(hsScalar)) )
return false;
}
if( fProjectors.GetCount() )
{
if( !HSMemory::EqualBlocks(fProjectors.AcquireArray(), other->fProjectors.AcquireArray(), fProjectors.GetCount() * sizeof(plLightInfo*)) )
return false;
if( !HSMemory::EqualBlocks(fProjScales.AcquireArray(), other->fProjScales.AcquireArray(), fProjectors.GetCount() * sizeof(hsScalar)) )
return false;
}
if( fShadowSlaveBits != other->fShadowSlaveBits )
return false;
if( fSubType ^ other->fSubType )
return false;
return true;
}
//// MergeInto ///////////////////////////////////////////////////////////////
void plSpan::MergeInto( plSpan *other )
{
int i;
for( i = 0; i < GetNumAuxSpans(); i++ )
other->fAuxSpans.Append(GetAuxSpan(i));
}
//// Constructor & Destructor ////////////////////////////////////////////////
plSpan::plSpan()
{
fTypeMask = kSpan;
fSubType = plDrawable::kSubNormal;
fMaterialIdx = (UInt32)-1;
fFogEnvironment = nil;
fProps = 0;
fSnapShot = nil;
ClearLights();
fVisSet.SetBit(0);
fNumMatrices = 0;
fBaseMatrix = 0;
fLocalUVWChans = 0;
fMaxBoneIdx = 0;
fPenBoneIdx = 0;
fMinDist = fMaxDist = -1.f;
fWaterHeight = 0;
#ifdef HS_DEBUGGING
fOwnerKey = nil;
#endif
}
void plSpan::Destroy()
{
if( fSnapShot )
{
fSnapShot->Destroy();
delete fSnapShot;
}
int i;
for( i = 0; i < fAuxSpans.GetCount(); i++ )
fAuxSpans[i]->fDrawable = nil;
}
//////////////////////////////////////////////////////////////////////////////
//// plVertexSpan Functions //////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
plVertexSpan::plVertexSpan()
{
fTypeMask |= kVertexSpan;
fGroupIdx = (UInt32)-1;
fVBufferIdx = (UInt32)-1;
fCellIdx = (UInt32)-1;
fCellOffset = (UInt32)-1;
}
void plVertexSpan::Read( hsStream* stream )
{
plSpan:: Read( stream );
fGroupIdx = stream->ReadSwap32();
fVBufferIdx = stream->ReadSwap32();
fCellIdx = stream->ReadSwap32();
fCellOffset = stream->ReadSwap32();
fVStartIdx = stream->ReadSwap32();
fVLength = stream->ReadSwap32();
}
void plVertexSpan::Write( hsStream* stream )
{
plSpan::Write( stream );
stream->WriteSwap32( fGroupIdx );
stream->WriteSwap32( fVBufferIdx );
stream->WriteSwap32( fCellIdx );
stream->WriteSwap32( fCellOffset );
stream->WriteSwap32( fVStartIdx );
stream->WriteSwap32( fVLength );
}
hsBool plVertexSpan::CanMergeInto( plSpan *other )
{
if( !plSpan::CanMergeInto( other ) )
return false;
plVertexSpan *otherSpan = (plVertexSpan*)other;
if( fGroupIdx != otherSpan->fGroupIdx ||
fVBufferIdx != otherSpan->fVBufferIdx ||
fCellIdx != otherSpan->fCellIdx )
{
return false;
}
return true;
}
void plVertexSpan::MergeInto( plSpan *other )
{
plSpan::MergeInto( other );
plVertexSpan* otherIce = (plVertexSpan*)other;
int min, max;
min = fVStartIdx;
max = min + fVLength - 1;
if( otherIce->fVStartIdx < min )
min = otherIce->fVStartIdx;
if( otherIce->fVStartIdx + otherIce->fVLength - 1 > max )
max = otherIce->fVStartIdx + otherIce->fVLength - 1;
otherIce->fVStartIdx = min;
otherIce->fVLength = max - min + 1;
}
//////////////////////////////////////////////////////////////////////////////
//// plIcicle Functions //////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Read ////////////////////////////////////////////////////////////////////
void plIcicle::Read( hsStream *stream )
{
plVertexSpan::Read( stream );
fIBufferIdx = stream->ReadSwap32();
fIPackedIdx = fIStartIdx = stream->ReadSwap32();
fILength = stream->ReadSwap32();
if( fProps & kPropFacesSortable )
{
/// Read in sorting data
int i;
fSortData = TRACKED_NEW plGBufferTriangle[ fILength / 3 ];
for( i = 0; i < fILength / 3; i++ )
fSortData[ i ].Read( stream );
}
else
fSortData = nil;
}
//// Write ///////////////////////////////////////////////////////////////////
void plIcicle::Write( hsStream *stream )
{
plVertexSpan::Write( stream );
stream->WriteSwap32( fIBufferIdx );
stream->WriteSwap32( fIStartIdx );
stream->WriteSwap32( fILength );
if( fProps & kPropFacesSortable )
{
/// Write out sorting data
int i;
for( i = 0; i < fILength / 3; i++ )
fSortData[ i ].Write( stream );
}
}
//// Destroy /////////////////////////////////////////////////////////////////
void plIcicle::Destroy( void )
{
plSpan::Destroy();
delete [] fSortData;
fSortData = nil;
}
//// CanMergeInto ////////////////////////////////////////////////////////////
hsBool plIcicle::CanMergeInto( plSpan *other )
{
if( !plVertexSpan::CanMergeInto( other ) )
return false;
plIcicle *otherIce = (plIcicle *)other;
if( fIBufferIdx != otherIce->fIBufferIdx )
return false;
if( (fNumMatrices != otherIce->fNumMatrices)
||(fBaseMatrix != otherIce->fBaseMatrix) )
return false;
if( fIPackedIdx != otherIce->fIPackedIdx + otherIce->fILength )
{
return false;
}
return true;
}
//// MergeInto ///////////////////////////////////////////////////////////////
void plIcicle::MergeInto( plSpan *other )
{
plVertexSpan::MergeInto( other );
plIcicle *otherIce = (plIcicle *)other;
otherIce->fILength += fILength;
}
//// Constructor/Destructor //////////////////////////////////////////////////
plIcicle::plIcicle()
{
fTypeMask |= kIcicleSpan;
fSortData = nil;
}
//////////////////////////////////////////////////////////////////////////////
//// plParticleSpan Functions ////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Constructor /////////////////////////////////////////////////////////////
plParticleSpan::plParticleSpan() : plIcicle()
{
fTypeMask |= kParticleSpan;
fProps |= kPropProjAsVtx;
fSource = nil;
fSortCount = 0;
}
//// CanMergeInto ////////////////////////////////////////////////////////////
hsBool plParticleSpan::CanMergeInto( plSpan *other )
{
return plIcicle::CanMergeInto( other );
}
//// MergeInto ///////////////////////////////////////////////////////////////
void plParticleSpan::MergeInto( plSpan *other )
{
plIcicle::MergeInto( other );
}
//// Destroy /////////////////////////////////////////////////////////////////
void plParticleSpan::Destroy( void )
{
plIcicle::Destroy();
fSource = nil;
if( fParentSet != nil )
{
fParentSet->fRefCount--;
if( fParentSet->fRefCount == 0 )
delete fParentSet;
}
}
//////////////////////////////////////////////////////////////////////////////
//// plParticleSet Functions /////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Constructor /////////////////////////////////////////////////////////////
plParticleSet::plParticleSet()
{
}
//// Destructor //////////////////////////////////////////////////////////////
plParticleSet::~plParticleSet()
{
fVLength = 0; // Flag as empty
}

View File

@ -0,0 +1,330 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plSpanTypes Header - Class Definitions for all the span types //
// //
//// Version History /////////////////////////////////////////////////////////
// //
// 5.3.2001 mcn - Created. //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plSpans_h
#define _plSpans_h
#include "hsBitVector.h"
#include "hsTemplates.h"
#include "hsBounds.h"
#include "hsMatrix44.h"
#include "../pnKeyedObject/plKey.h"
class hsGMaterial;
class plGeometrySpan;
class plFogEnvironment;
class plLightInfo;
class plGBufferTriangle;
class hsGDeviceRef;
class plShadowSlave;
class plAuxSpan;
class plAccessSnapShot;
class plDrawableSpans;
//// plSpan Class Definition /////////////////////////////////////////////////
// Represents the generic span for any kind of drawableMatter derivative.
class plSpan
{
public:
enum {
// Renumber these the next time we bump major version #s (no reason to do it now)
kPropNoDraw = 0x001,
kPropNoShadowCast = 0x002,
kPropFacesSortable = 0x004,
kPropVolatile = 0x008, // Means that the vertices for this span are volatile
kWaterHeight = 0x010, // Vtx Z value doesn't mean vtx pos, use fWaterHeight
kPropRunTimeLight = 0x020, // Enable dynamic lighting
kPropReverseSort = 0x040, // Sort front to back instead of back to front
kPropHasPermaLights = 0x080, // Has a list of permanently assigned lights.
kPropHasPermaProjs = 0x100, // Has a list of permanently assigned projectors.
// Lighting types
kLiteMaterial = 0x000, // Default
kLiteVtxPreshaded = 0x200, // For particle systems, gives us vtx alpha
kLiteVtxNonPreshaded = 0x400, // Runtime lit, gives us vtx alpha
kLiteProjection = 0x800,
kLiteShadowErase = 0x1000,
kLiteShadow = 0x2000,
kLiteMask = kLiteMaterial
| kLiteVtxPreshaded
| kLiteVtxNonPreshaded
| kLiteProjection
| kLiteShadowErase
| kLiteShadow, // Mask for all types
kPropMatHasSpecular = 0x10000, // Shortcut for efficiency; means the span's material has specular checked on it
kPropProjAsVtx = 0x20000, // Force projected lights to act as vertex lights
kPropSkipProjection = 0x40000, // Just skip projected lights entirely
kPropNoShadow = 0x80000, // Never cast a shadow on this.
kPropForceShadow = 0x100000, // Force casting a shadow, even if the pipeline thinks it'll look bad.
kPropDisableNormal = 0x200000, // Not a member of the normal vis-set
kPropCharacter = 0x400000, // Is a member of the character vis-set
kPartialSort = 0x800000,
kVisLOS = 0x1000000
};
enum plSpanType {
kSpan = 0x0,
kVertexSpan = 0x1,
kIcicleSpan = 0x2,
kParticleSpan = 0x8,
kParticleSet = 0x10
};
UInt16 fTypeMask; // For safe casting. Or it with the type you want to cast to, don't check equality
UInt16 fSubType; // Or'ed from plDrawable::plDrawableSubType
UInt32 fMaterialIdx; // Index into drawable's material array
hsMatrix44 fLocalToWorld;
hsMatrix44 fWorldToLocal;
UInt32 fBaseMatrix;
UInt8 fNumMatrices;
UInt16 fLocalUVWChans;
UInt16 fMaxBoneIdx;
UInt16 fPenBoneIdx;
UInt32 fProps;
hsBounds3Ext fLocalBounds;
hsBounds3Ext fWorldBounds;
plFogEnvironment *fFogEnvironment;
// Use setter/getters below.
hsScalar fMinDist;
hsScalar fMaxDist;
hsScalar fWaterHeight;
hsBitVector fVisSet;
hsBitVector fVisNot;
mutable plAccessSnapShot* fSnapShot;
// mutable hsBitVector fLightBits;
mutable hsTArray<plLightInfo*> fLights;
mutable hsTArray<hsScalar> fLightStrengths;
mutable hsTArray<hsScalar> fLightScales;
mutable hsTArray<plLightInfo*> fProjectors;
mutable hsTArray<hsScalar> fProjStrengths;
mutable hsTArray<hsScalar> fProjScales;
mutable hsBitVector fShadowBits;
mutable hsBitVector fShadowSlaveBits;
mutable hsTArray<plAuxSpan*> fAuxSpans;
hsTArray<plLightInfo*> fPermaLights;
hsTArray<plLightInfo*> fPermaProjs;
#ifdef HS_DEBUGGING
plKey fOwnerKey; // DEBUG ONLY--drawInterface owner key
#endif
plSpan();
const hsBitVector& GetShadowSlaves() const { return fShadowSlaveBits; }
void AddShadowSlave(int iSlave) const { fShadowSlaveBits.SetBit(iSlave); }
void SetShadowBit(UInt32 idx) const { fShadowBits.SetBit(idx); }
void ClearShadowBits() const { fShadowBits.Clear(); }
hsBool IsShadowBitSet(UInt32 idx) const { return fShadowBits.IsBitSet(idx); }
void ClearLights() const;
void AddLight( plLightInfo* li, hsScalar strength, hsScalar scale, hsBool proj ) const;
hsTArray<plLightInfo*>& GetLightList(hsBool proj) const { return proj ? fProjectors : fLights; }
UInt32 GetNumLights(hsBool proj) const { return proj ? fProjectors.GetCount() : fLights.GetCount(); }
plLightInfo* GetLight(int i, hsBool proj) const { return proj ? fProjectors[i] : fLights[i]; }
hsScalar GetLightStrength(int i, hsBool proj) const { return proj ? fProjStrengths[i] : fLightStrengths[i]; }
hsScalar GetLightScale(int i, hsBool proj) const { return proj ? fProjScales[i] : fLightScales[i]; }
void AddPermaLight(plLightInfo* li, hsBool proj);
void RemovePermaLight(plLightInfo* li, hsBool proj);
const hsBitVector& GetVisSet() const { return fVisSet; }
const hsBitVector& GetVisNot() const { return fVisNot; }
void SetVisBit(UInt32 w, hsBool on) { fVisSet.SetBit(w, on); }
void SetVisNot(UInt32 w, hsBool on) { fVisNot.SetBit(w, on); }
void RemoveAuxSpan(plAuxSpan* aux);
void AddAuxSpan(plAuxSpan* aux);
int GetNumAuxSpans() const { return fAuxSpans.GetCount(); }
plAuxSpan* GetAuxSpan(int i) const { return fAuxSpans[i]; }
virtual void Read( hsStream* stream );
virtual void Write( hsStream* stream );
virtual hsBool CanMergeInto( plSpan* other );
virtual void MergeInto( plSpan* other );
virtual void Destroy( void );
void SetMinDist(hsScalar minDist) { fMinDist = minDist; }
void SetMaxDist(hsScalar maxDist) { fMaxDist = maxDist; }
hsScalar GetMinDist() const { return fMinDist; }
hsScalar GetMaxDist() const { return fMaxDist; }
};
//// plVertexSpan Definition
// All span types which are based on vertices derive from this. That's
// currently all span types.
class plVertexSpan : public plSpan
{
public:
// Stuff internal
UInt32 fGroupIdx; // Which buffer group, i.e. which vertex format
UInt32 fVBufferIdx; // Which vertex buffer in group
UInt32 fCellIdx; // Cell index inside the vertex buffer
UInt32 fCellOffset; // Offset inside the cell
UInt32 fVStartIdx; // Start vertex # in the actual interlaced buffer
UInt32 fVLength; // Length of this span in the buffer
plVertexSpan();
virtual void Read( hsStream* stream );
virtual void Write( hsStream* stream );
virtual hsBool CanMergeInto( plSpan* other );
virtual void MergeInto( plSpan* other );
};
//// plIcicle Class Definition ///////////////////////////////////////////////
// Represents the generic span for a set of triangles to be drawn.
class plIcicle : public plVertexSpan
{
public:
UInt32 fIBufferIdx; // Which index buffer in group
UInt32 fIStartIdx; // Redundant, since all spans are contiguous. Here for debugging
UInt32 fILength; // Length of this span in the buffer
// The index into the indexbuffer ref. This can be different from fIStartIdx if spans get
// culled, then we pack the non-culled index spans into the beginning of the index buffer ref,
// so we can still put them all out with a single DIP call.
mutable UInt32 fIPackedIdx;
// Run-time-only stuff
plGBufferTriangle *fSortData; // Indices & center points for sorting tris in this span (optional)
plIcicle();
virtual void Read( hsStream* stream );
virtual void Write( hsStream* stream );
virtual hsBool CanMergeInto( plSpan* other );
virtual void MergeInto( plSpan* other );
virtual void Destroy( void );
};
//// plParticleSpan Class Definition /////////////////////////////////////////
// A single span that contains triangles for drawing particle-like things.
// Since we want to draw these just like icicles, we'll just derive from
// it...
class plParticleEmitter;
class plParticleSet;
class plParticleSpan : public plIcicle
{
public:
plParticleEmitter* fSource; // Source emitter, used to get array of plParticleCores
UInt32 fNumParticles;
UInt32 fSortCount;
UInt32 fSrcSpanIdx;
plParticleSet* fParentSet;
plParticleSpan();
virtual void Read( hsStream* stream ) { /*plParticleSpans don't read in!*/ }
virtual void Write( hsStream* stream ) { /*plParticleSpans don't write out!*/ }
virtual hsBool CanMergeInto( plSpan* other );
virtual void MergeInto( plSpan* other );
virtual void Destroy( void );
};
//// plParticleSet Class Definition //////////////////////////////////////////
// Represents a collection of dynamic plParticleSpans collected into one
// space, for rendering batches of particles.
class plParticleSet
{
public:
UInt32 fRefCount; // Delete if this gets to 0
UInt32 fDIEntry; // Our false DIIndices entry index
UInt32 fGroupIdx; // Which buffer group, i.e. which vertex format
UInt8 fFormat;
UInt32 fVBufferIdx;
UInt32 fCellIdx;
UInt32 fCellOffset;
UInt32 fVStartIdx;
UInt32 fVLength; // Total v.b. length that all the icicles can take up UInt32 fIBufferIdx;
UInt32 fIBufferIdx;
UInt32 fIStartIdx; // Start index buffer position
UInt32 fILength; // Total i.b. length that all the icicles can take up
UInt32 fNumSpans;
hsGMaterial* fMaterial;
UInt32 fNextVStartIdx;
UInt32 fNextCellOffset;
UInt32 fNextIStartIdx;
plParticleSet();
~plParticleSet();
};
#endif // _plSpans_h

View File

@ -0,0 +1,164 @@
/*==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 plTimedInterp_inc
#define plTimedInterp_inc
// There's no auto update on this, the owner is
// required to call update periodically.
//
// This isn't optimized in any way, and is still
// fairly general. Adding features would most likely
// be best implemented in a derived type.
// Notably lacking features are:
// ability to read and write,
// auto-eval on significant time change
//
//
// Requires class T to have the following members
// T& operator+=(const class T& t);
// T& operator-=(const class T& t);
// T& operator*=(hsScalar scale);
// T& operator=(const class T&); // unless builtin = is adequate.
//
template <class T> class plTimedInterp
{
protected:
T fInit;
T fCurr;
T fTarg;
double fDuration;
double fEnd;
const T& IEnd();
const T& IBegin();
const T& IEval(hsScalar parm);
public:
plTimedInterp();
plTimedInterp(const T& t);
const T& Set(const T& val) { return SetTarget(val, 0, 0); }
const T& SetTarget(const T& targ, double start, double duration);
const T& Update(double t);
operator T() const { return fCurr; }
const T& Value() const { return fCurr; }
};
template <class T>
plTimedInterp<T>::plTimedInterp()
: fDuration(0),
fEnd(0)
{
}
template <class T>
plTimedInterp<T>::plTimedInterp(const T& t)
: fInit(t),
fCurr(t),
fTarg(t),
fDuration(0),
fEnd(0)
{
}
template <class T>
const T&
plTimedInterp<T>::Update(double t)
{
if( fDuration <= 0 )
return IEnd();
hsScalar parm = hsScalar((fEnd - t) / fDuration);
if( parm <= 0 )
return IEnd();
else if( parm >= 1.f )
return IBegin();
return IEval(parm);
}
template <class T>
const T&
plTimedInterp<T>::SetTarget(const T& targ, double start, double dur)
{
fEnd = start + dur;
fDuration = dur;
fTarg = targ;
if( dur <= 0 )
fCurr = targ;
fInit = fCurr;
return fCurr;
}
template <class T>
const T&
plTimedInterp<T>::IEnd()
{
fDuration = 0;
fCurr = fTarg;
return fCurr;
}
template <class T>
const T&
plTimedInterp<T>::IBegin()
{
return fCurr;
}
template <class T>
const T&
plTimedInterp<T>::IEval(hsScalar parm)
{
fCurr = fInit;
fCurr -= fTarg;
fCurr *= parm;
fCurr += fTarg;
return fCurr;
}
#endif // plTimedInterp_inc

View File

@ -0,0 +1,463 @@
/*==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 "hsBounds.h"
#include "hsFastMath.h"
#include "plVisLOSMgr.h"
#include "plSpaceTree.h"
#include "plDrawableSpans.h"
#include "plAccessGeometry.h"
#include "plAccessSpan.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayerInterface.h"
#include "../plScene/plSceneNode.h"
#include "../plScene/plPageTreeMgr.h"
// Stuff for cursor los
#include "../plInputCore/plInputDevice.h"
#include "plPipeline.h"
#include "plTweak.h"
#include <algorithm>
#include <functional>
plVisLOSMgr* plVisLOSMgr::Instance()
{
static plVisLOSMgr inst;
return &inst;
}
hsBool plVisLOSMgr::ICheckSpaceTreeRecur(plSpaceTree* space, int which, hsTArray<plSpaceHit>& hits)
{
const plSpaceTreeNode& node = space->GetNode(which);
if( node.fFlags & plSpaceTreeNode::kDisabled )
return false;
hsScalar closest;
// If it's a hit
if( ICheckBound(node.fWorldBounds, closest) )
{
// If it's a leaf,
if( node.IsLeaf() )
{
// add it to the list with the closest intersection point,
plSpaceHit* hit = hits.Push();
hit->fIdx = which;
hit->fClosest = closest;
return true;
}
// else recurse on its children
else
{
hsBool retVal = false;
if( ICheckSpaceTreeRecur(space, node.GetChild(0), hits) )
retVal = true;
if( ICheckSpaceTreeRecur(space, node.GetChild(1), hits) )
retVal = true;
return retVal;
}
}
return false;
}
struct plCompSpaceHit : public std::binary_function<plSpaceHit, plSpaceHit, bool>
{
bool operator()( const plSpaceHit& lhs, const plSpaceHit& rhs) const
{
return lhs.fClosest < rhs.fClosest;
}
};
hsBool plVisLOSMgr::ICheckSpaceTree(plSpaceTree* space, hsTArray<plSpaceHit>& hits)
{
hits.SetCount(0);
if( space->IsEmpty() )
return false;
// Hierarchical search down the tree for bounds intersecting the current ray.
hsBool retVal = ICheckSpaceTreeRecur(space, space->GetRoot(), hits);
// Now sort them front to back.
plSpaceHit* begin = hits.AcquireArray();
plSpaceHit* end = begin + hits.GetCount();
std::sort(begin, end, plCompSpaceHit());
return retVal;
}
hsBool plVisLOSMgr::ISetup(const hsPoint3& pStart, const hsPoint3& pEnd)
{
fCurrFrom = pStart;
fCurrTarg = pEnd;
fMaxDist = hsVector3(&fCurrTarg, &fCurrFrom).Magnitude();
const hsScalar kMinMaxDist(0);
return fMaxDist > kMinMaxDist;
}
hsBool plVisLOSMgr::Check(const hsPoint3& pStart, const hsPoint3& pEnd, plVisHit& hit)
{
if( !fPageMgr )
return false;
// Setup any internals, like fMaxDist
if( !ISetup(pStart, pEnd) )
return false;
// Go through the nodes in the PageMgr and find the closest
// point of intersection for each scene node. If none are before
// pEnd, return false.
// Node come out sorted by closest point, front to back
static hsTArray<plSpaceHit> hits;
if( !ICheckSpaceTree(fPageMgr->GetSpaceTree(), hits) )
return false;
// In front to back order, check inside each node.
// Our max distance can be changing as we do this, because a
// face hit will limit how far we need to look. When we hit the
// first node with a closest distance < fMaxDist, we're done.
hsBool retVal = false;
int i;
for( i = 0; i < hits.GetCount(); i++ )
{
if( hits[i].fClosest > fMaxDist )
break;
if( ICheckSceneNode(fPageMgr->GetNodes()[hits[i].fIdx], hit) )
retVal = true;
}
return retVal;
}
hsBool plVisLOSMgr::ICheckSceneNode(plSceneNode* node, plVisHit& hit)
{
static hsTArray<plSpaceHit> hits;
if( !ICheckSpaceTree(node->GetSpaceTree(), hits) )
return false;
hsBool retVal = false;
int i;
for( i = 0; i < hits.GetCount(); i++ )
{
if( hits[i].fClosest > fMaxDist )
break;
if( (node->GetDrawPool()[hits[i].fIdx]->GetRenderLevel().Level() > 0)
&& !node->GetDrawPool()[hits[i].fIdx]->GetNativeProperty(plDrawable::kPropHasVisLOS) )
continue;
if( ICheckDrawable(node->GetDrawPool()[hits[i].fIdx], hit) )
retVal = true;
}
return retVal;
}
hsBool plVisLOSMgr::ICheckDrawable(plDrawable* d, plVisHit& hit)
{
plDrawableSpans* ds = plDrawableSpans::ConvertNoRef(d);
if( !ds )
return false;
static hsTArray<plSpaceHit> hits;
if( !ICheckSpaceTree(ds->GetSpaceTree(), hits) )
return false;
const hsBool isOpaque = !ds->GetRenderLevel().Level();
const hsTArray<plSpan *> spans = ds->GetSpanArray();
hsBool retVal = false;
int i;
for( i = 0; i < hits.GetCount(); i++ )
{
if( hits[i].fClosest > fMaxDist )
break;
if( isOpaque || (spans[hits[i].fIdx]->fProps & plSpan::kVisLOS) )
{
if( ICheckSpan(ds, hits[i].fIdx, hit) )
retVal = true;
}
}
return retVal;
}
hsBool plVisLOSMgr::ICheckSpan(plDrawableSpans* dr, UInt32 spanIdx, plVisHit& hit)
{
if( !(dr->GetSpan(spanIdx)->fTypeMask & plSpan::kIcicleSpan) )
return false;
plAccessSpan src;
plAccessGeometry::Instance()->OpenRO(dr, spanIdx, src);
const hsBool twoSided = !!(src.GetMaterial()->GetLayer(0)->GetMiscFlags() & hsGMatState::kMiscTwoSided);
hsBool retVal = false;
// We move into local space, look for hits, and convert the closest we find
// (if any) back into world space at the end.
hsPoint3 currFrom = src.GetWorldToLocal() * fCurrFrom;
hsPoint3 currTarg = src.GetWorldToLocal() * fCurrTarg;
hsVector3 currDir(&currTarg, &currFrom);
hsScalar maxDist = currDir.Magnitude();
currDir /= maxDist;
plAccTriIterator tri(&src.AccessTri());
for( tri.Begin(); tri.More(); tri.Advance() )
{
// Project the current ray onto the tri plane
hsVector3 norm = hsVector3(&tri.Position(1), &tri.Position(0)) % hsVector3(&tri.Position(2), &tri.Position(0));
hsScalar dotNorm = norm.InnerProduct(currDir);
const hsScalar kMinDotNorm = 1.e-3f;
if( dotNorm >= -kMinDotNorm )
{
if( !twoSided )
continue;
if( dotNorm <= kMinDotNorm )
continue;
}
hsScalar dist = hsVector3(&tri.Position(0), &currFrom).InnerProduct(norm);
if( dist > 0 )
continue;
dist /= dotNorm;
hsPoint3 projPt = currFrom;
projPt += currDir * dist;
// If the distance from source point to projected point is too long, skip
if( dist > maxDist )
continue;
// Find the 3 cross products (v[i+1]-v[i]) X (proj - v[i]) dotted with current ray
hsVector3 cross0 = hsVector3(&tri.Position(1), &tri.Position(0)) % hsVector3(&projPt, &tri.Position(0));
hsScalar dot0 = cross0.InnerProduct(currDir);
hsVector3 cross1 = hsVector3(&tri.Position(2), &tri.Position(1)) % hsVector3(&projPt, &tri.Position(1));
hsScalar dot1 = cross1.InnerProduct(currDir);
hsVector3 cross2 = hsVector3(&tri.Position(0), &tri.Position(2)) % hsVector3(&projPt, &tri.Position(2));
hsScalar dot2 = cross2.InnerProduct(currDir);
// If all 3 are negative, projPt is a hit
// If all 3 are positive and we're two sided, projPt is a hit
// We've already checked for back facing (when we checked for edge on in projection),
// so we'll accept either case here.
if( ((dot0 <= 0) && (dot1 <= 0) && (dot2 <= 0))
||((dot0 >= 0) && (dot1 >= 0) && (dot2 >= 0)) )
{
if( dist < maxDist )
{
maxDist = dist;
hit.fPos = projPt;
retVal = true;
}
}
}
plAccessGeometry::Instance()->Close(src);
if( retVal )
{
hit.fPos = src.GetLocalToWorld() * hit.fPos;
fCurrTarg = hit.fPos;
fMaxDist = hsVector3(&fCurrTarg, &fCurrFrom).Magnitude();
}
return retVal;
}
hsBool plVisLOSMgr::ICheckBound(const hsBounds3Ext& bnd, hsScalar& closest)
{
if( bnd.GetType() != kBoundsNormal )
return false;
if( bnd.IsInside(&fCurrFrom) || bnd.IsInside(&fCurrTarg) )
{
closest = 0;
return true;
}
const int face[6][4] =
{
{0,1,3,2},
{1,5,7,3},
{2,3,7,6},
{5,4,6,7},
{0,4,5,1},
{0,2,6,4}
};
hsPoint3 corn[8];
bnd.GetCorners(corn);
hsBool retVal = false;
const hsPoint3& currFrom = fCurrFrom;
const hsPoint3& currTarg = fCurrTarg;
hsVector3 currDir(&currTarg, &currFrom);
const hsScalar maxDistSq = currDir.MagnitudeSquared();
currDir *= hsFastMath::InvSqrt(maxDistSq);
int i;
for( i = 0; i < 6; i++ )
{
const hsPoint3& p0 = corn[face[i][0]];
const hsPoint3& p1 = corn[face[i][1]];
const hsPoint3& p2 = corn[face[i][2]];
const hsPoint3& p3 = corn[face[i][3]];
// Project the current ray onto the tri plane
hsVector3 norm = hsVector3(&p1, &p0) % hsVector3(&p2, &p0);
hsScalar dotNorm = norm.InnerProduct(currDir);
const hsScalar kMinDotNorm = 1.e-3f;
if( dotNorm >= -kMinDotNorm )
{
continue;
}
hsScalar dist = hsVector3(&p0, &currFrom).InnerProduct(norm);
if( dist >= 0 )
continue;
dist /= dotNorm;
// If the distance from source point to projected point is too long, skip
if( dist > fMaxDist )
continue;
hsPoint3 projPt = currFrom;
projPt += currDir * dist;
// Find the 3 cross products (v[i+1]-v[i]) X (proj - v[i]) dotted with current ray
hsVector3 cross0 = hsVector3(&p1, &p0) % hsVector3(&projPt, &p0);
hsScalar dot0 = cross0.InnerProduct(currDir);
hsVector3 cross1 = hsVector3(&p2, &p1) % hsVector3(&projPt, &p1);
hsScalar dot1 = cross1.InnerProduct(currDir);
hsVector3 cross2 = hsVector3(&p3, &p2) % hsVector3(&projPt, &p2);
hsScalar dot2 = cross2.InnerProduct(currDir);
hsVector3 cross3 = hsVector3(&p0, &p3) % hsVector3(&projPt, &p3);
hsScalar dot3 = cross3.InnerProduct(currDir);
// If all 4 are negative, projPt is a hit
if( (dot0 <= 0) && (dot1 <= 0) && (dot2 <= 0) && (dot3 <= 0) )
{
closest = dist;
return true;
}
}
return false;
}
hsBool plVisLOSMgr::CursorCheck(plVisHit& hit)
{
Int32 sx= Int32(plMouseDevice::Instance()->GetCursorX() * fPipe->Width());
Int32 sy= Int32(plMouseDevice::Instance()->GetCursorY() * fPipe->Height());
hsPoint3 from = fPipe->GetViewPositionWorld();
plConst(hsScalar) dist(1.e5f);
hsPoint3 targ;
fPipe->ScreenToWorldPoint(1, 0, &sx, &sy, dist, 0, &targ);
return Check(from, targ, hit);
}
/////////////////////////////////////////////////////////////////
#include "plPipeline.h"
#include "../pnSceneObject/plSceneObject.h"
static plSceneObject* marker = nil;
static plPipeline* pipe = nil;
void VisLOSHackBegin(plPipeline* p, plSceneObject* m)
{
marker = m;
pipe = p;
}
void VisLOSHackPulse()
{
if( !pipe )
return;
plVisHit hit;
if( plVisLOSMgr::Instance()->CursorCheck(hit) )
{
if( marker )
{
hsMatrix44 l2w = marker->GetLocalToWorld();
l2w.fMap[0][3] = hit.fPos.fX;
l2w.fMap[1][3] = hit.fPos.fY;
l2w.fMap[2][3] = hit.fPos.fZ;
l2w.NotIdentity();
hsMatrix44 w2l;
l2w.GetInverse(&w2l);
marker->SetTransform(l2w, w2l);
}
}
}

View File

@ -0,0 +1,100 @@
/*==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 plVisLOSMgr_inc
#define plVisLOSMgr_inc
#include "hsGeometry3.h"
#include "hsTemplates.h"
class plSpaceTreeNode;
class plSpaceTree;
class plDrawableSpans;
class plDrawable;
class plSceneNode;
class plPageTreeMgr;
class plPipeline;
class hsBounds3Ext;
class plVisHit
{
public:
hsPoint3 fPos;
};
class plSpaceHit
{
public:
int fIdx;
hsScalar fClosest;
};
class plVisLOSMgr
{
protected:
plPageTreeMgr* fPageMgr;
plPipeline* fPipe;
hsScalar fMaxDist;
hsPoint3 fCurrFrom;
hsPoint3 fCurrTarg;
hsBool ISetup(const hsPoint3& pStart, const hsPoint3& pEnd);
hsBool ICheckBound(const hsBounds3Ext& bnd, hsScalar& closest);
hsBool ICheckSpaceTreeRecur(plSpaceTree* space, int which, hsTArray<plSpaceHit>& hits);
hsBool ICheckSpaceTree(plSpaceTree* space, hsTArray<plSpaceHit>& hits);
hsBool ICheckSceneNode(plSceneNode* node, plVisHit& hit);
hsBool ICheckDrawable(plDrawable* d, plVisHit& hit);
hsBool ICheckSpan(plDrawableSpans* dr, UInt32 spanIdx, plVisHit& hit);
public:
hsBool Check(const hsPoint3& pStart, const hsPoint3& pEnd, plVisHit& hit);
hsBool CursorCheck(plVisHit& hit);
static plVisLOSMgr* Instance();
static void Init(plPipeline* pipe, plPageTreeMgr* mgr) { Instance()->fPipe = pipe; Instance()->fPageMgr = mgr; }
static void DeInit() { Instance()->fPipe = nil; Instance()->fPageMgr = nil; }
};
#endif // plVisLOSMgr_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,658 @@
/*==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 plWaveSet7_inc
#define plWaveSet7_inc
#include "hsGeometry3.h"
#include "hsTemplates.h"
#include "../plMath/plRandom.h"
#include "hsBounds.h"
#include "plFixedWaterState7.h"
#include "plWaveSetBase.h"
class hsStream;
class hsResMgr;
class plAccessVtxSpan;
class plMessage;
class hsGMaterial;
class plDrawableSpans;
class plRenderMsg;
class plArmatureUpdateMsg;
class plGenRefMsg;
class plAuxSpan;
class plDynaDecalMgr;
class plGBufferGroup;
class plBitmap;
class plMipmap;
class plLayer;
class plRenderRequest;
class plRenderRequestMsg;
class plRenderTarget;
class plShader;
class plPipeline;
class plRipVSConsts;
class plStatusLog;
class plGraphPlate;
class plWorldWaveData7
{
public:
hsPoint3 fDir;
hsScalar fLength;
hsScalar fFreq;
hsScalar fPhase;
hsScalar fAmplitude;
};
class plWorldWave7 : public plWorldWaveData7
{
public:
inline void Accumulate(hsPoint3& accumPos, hsVector3& accumNorm) const;
};
class plWaveSet7 : public plWaveSetBase
{
public:
// Props inc by 1 (bit shift in bitvector).
enum plDrawProperties {
kDisable = 0,
kNumProps // last in the list
};
// Flags, also in a bitvector, so far unused in the multimodifier
enum {
kHasRefObject = 16
};
enum {
kNumWaves = 4
};
enum {
kRefDynaDecalMgr,
kRefBuoy,
kRefBumpMat,
kRefBumpDraw,
kRefBumpVShader,
kRefBumpPShader,
kRefBiasVShader,
kRefBiasPShader,
kRefRipVShader,
kRefRipPShader,
kRefShoreVShader,
kRefShorePShader,
kRefFixedVShader,
kRefFixedPShader,
kRefGraphShoreTex,
kRefBubbleShoreTex,
kRefEdgeShoreTex,
kRefGraphShoreMat,
kRefGraphShoreDraw,
kRefGraphVShader,
kRefGraphPShader,
kRefGraphShoreRT,
kRefShore,
kRefDecal,
kRefDecVShader,
kRefDecPShader,
kRefEnvMap,
kRefCosineLUT,
kRefRefObj
};
enum {
kGraphShorePasses = 3
};
enum {
kNumWindDep = 5
};
enum {
kNumTexWaves = 16
};
enum {
kBumpPerPass = 4
};
enum {
kNumBumpShaders = kNumTexWaves / kBumpPerPass
};
enum {
kCompositeSize = 256
};
enum {
kUpdateWaveKs = 0x1,
kRemakeBubble = 0x2,
kRemakeEdge = 0x4,
kReRenderEnvMap = 0x8,
kReInitWaves = 0x10
};
protected:
double fCurrTime;
double fLastTime;
plStatusLog* fStatusLog;
plGraphPlate* fStatusGraph;
UInt32 fTrialUpdate;
plFixedWaterState7 fState;
hsScalar fScrunchLen;
hsScalar fScrunchScale;
hsVector3 fWindDir;
hsScalar fMinLen;
hsScalar fMaxLen;
hsScalar fFreqScale;
hsScalar fTransCountDown;
int fTransistor;
hsScalar fTransDel;
hsScalar fTexTransCountDown;
int fTexTrans;
hsScalar fTexTransDel;
hsScalar fTexWaveFade[kNumTexWaves];
plWorldWave7 fWorldWaves[kNumWaves];
hsScalar fFreqMod[kNumWaves];
plRandom fRand;
plKey fSceneNode;
hsTArray<plDynaDecalMgr*> fDecalMgrs;
hsTArray<plSceneObject*> fBuoys;
hsTArray<plSceneObject*> fShores;
hsTArray<plSceneObject*> fDecals;
plSceneObject* fRefObj;
hsTArray<hsBounds3Ext> fTargBnds;
plLayer* fBiasLayer[2];
plLayer* fBumpLayers[kNumTexWaves];
hsGMaterial* fBumpMat;
plDrawableSpans* fBumpDraw;
plRenderRequest* fBumpReq;
plRenderRequestMsg* fBumpReqMsg;
plMipmap* fCosineLUT;
plShader* fBumpVShader[kNumBumpShaders];
plShader* fBumpPShader[kNumBumpShaders];
plShader* fBiasVShader;
plShader* fBiasPShader;
plBitmap* fEnvMap;
UInt32 fEnvSize;
hsScalar fEnvRefresh;
plLayer* fFixedLayers[4];
plShader* fRipVShader;
plShader* fRipPShader;
plShader* fShoreVShader;
plShader* fShorePShader;
plShader* fFixedVShader;
plShader* fFixedPShader;
enum DecalVType {
kDecalV1Lay,
kDecalV2Lay11,
kDecalV2Lay12,
kDecalVEnv,
kNumDecalVShaders
};
enum DecalPType {
kDecalPBB,
kDecalPaB,
kDecalPaM,
kDecalPaA,
kDecalPAB,
kDecalPAM,
kDecalPAA,
kDecalPMB,
kDecalPMM,
kDecalPMA,
kDecalPEnv,
kNumDecalPShaders
};
plShader* fDecalVShaders[kNumDecalVShaders];
plShader* fDecalPShaders[kNumDecalPShaders];
// Graph shore stuff
plMipmap* fGraphShoreTex;
plMipmap* fBubbleShoreTex;
plMipmap* fEdgeShoreTex;
hsGMaterial* fGraphShoreMat[kGraphShorePasses];
plDrawableSpans* fGraphShoreDraw[kGraphShorePasses];
plRenderTarget* fGraphShoreRT[kGraphShorePasses];
plRenderRequest* fGraphReq[kGraphShorePasses];
plRenderRequestMsg* fGraphReqMsg[kGraphShorePasses];
plShader* fGraphVShader[kGraphShorePasses];
plShader* fGraphPShader[kGraphShorePasses];
class GraphState
{
public:
float fAge;
float fInvLife;
float fUOff;
float fFreq[4];
float fPhase[4];
float fAmp[4];
};
GraphState fGraphState[kGraphShorePasses];
class WaveK
{
public:
// fK is the number of times the sine wave repeats across the texture. Must be an integer
// fS/fK is the base X component of the direction of the wave, with Y = 1.f - X. Note that X^2 + Y^2 != 1.
// fD allows the wave to get more off the Y direction
// So the X component will be Int(fS + fD*dispersion) / fK, because it must be an integer ratio to
// preserve tiling. Also, (fS + fD) must be <= fK (for the Y normalization).
// See the notes.
float fS;
float fK;
float fD;
};
WaveK fWaveKs[kNumTexWaves];
class TexWaveDesc
{
public:
hsScalar fPhase;
hsScalar fAmp;
hsScalar fLen;
hsScalar fFreq;
hsScalar fDirX;
hsScalar fDirY;
hsScalar fRotScale00;
hsScalar fRotScale01;
};
TexWaveDesc fTexWaves[kNumTexWaves];
class TexWaveWindDep
{
public:
hsScalar fWindSpeed;
hsScalar fHeight;
hsScalar fSpecular;
};
TexWaveWindDep fWindDeps[kNumWindDep];
void IInitWaveConsts();
void IInitState();
inline void IScrunch(hsPoint3& pos, hsVector3& norm) const;
void ICalcWindow(hsScalar dt);
void ICalcScale();
void IUpdateWaves(hsScalar dt);
void IUpdateWave(hsScalar dt, int i);
hsBool IAnyBoundsVisible(plPipeline* pipe) const;
void IInitWave(int i);
void IReInitWaves();
void IUpdateRefObject();
void IUpdateWindDir(hsScalar dt);
void IShiftCenter(plSceneObject* so) const;
void IFloatBuoys(hsScalar dt);
void IFloatBuoy(hsScalar dt, plSceneObject* so);
// Bookkeeping
void IAddTarget(const plKey& key);
void IRemoveTarget(const plKey& key);
void ISetWindSpeed(hsScalar s);
hsBool IOnReceive(plGenRefMsg* refMsg);
hsBool IOnRemove(plGenRefMsg* refMsg);
hsBool ITransContinue(hsScalar dt);
void IStartTransition(hsScalar dt);
hsScalar ITransitionDelay() const;
void ITransition(hsScalar dt);
hsBool ITransTexContinue(hsScalar dt);
void IStartTexTransition(hsScalar dt);
void ITransTex(hsScalar dt);
void IInitTexWave(int i);
void ISetupTextureWaves();
void IUpdateLayers(hsScalar dt);
void IUpdateBumpLayers(hsScalar dt);
plRenderRequest* ICreateRenderRequest(plRenderTarget* rt, plDrawableSpans* draw, hsScalar pri);
void ISubmitRenderRequests();
plRenderTarget* ICreateTransferRenderTarget(const char* name, int size);
plDrawableSpans* ICreateClearDrawable(plDrawableSpans* drawable, hsGMaterial* mat);
void IAddBumpBiasShaders(plLayer* layer);
plMipmap* ICreateBiasNoiseMap();
void IAddBumpBiasLayer(hsGMaterial* mat);
plMipmap* ICreateBumpBitmapFFP(hsScalar amp, hsScalar dx, hsScalar dy) const;
hsGMaterial* ICreateBumpLayersFFP();
plMipmap* ICreateBumpMipmapPS();
plLayer* ICreateBumpLayerPS(plMipmap* mipMap, hsGMaterial* bumpMat, int which);
hsGMaterial* ICreateBumpLayersPS();
plDrawableSpans* ICreateBumpDrawable();
plLayer* ICreateTotalEnvLayer(plBitmap* envMap, hsGMaterial* mat, int which, const char* pref);
plLayer* ICreateTotalLayer(plBitmap* bm, hsGMaterial* mat, int which, const char* suff);
hsGMaterial* ICreateFixedMatPS(hsGMaterial* mat, const int numUVWs);
void ICreateFixedMat(hsGMaterial* mat, const int numUVWs);
void ICheckTargetMaterials();
plDrawableSpans* ICreateGraphDrawable(plDrawableSpans* drawable, hsGMaterial* mat, int nWid);
plDrawableSpans* ICreateEmptyGraphDrawable(const char* name, UInt32 ref, int wich);
hsGMaterial* ICreateEmptyMaterial(const char* name, UInt32 ref, int which);
plLayer* ICreateBlankLayer(const char* name, int suff);
plMipmap* ICreateBlankTex(const char* name, int width, int height, UInt32 ref);
plMipmap* ICreateGraphShoreTex(int width, int height);
plMipmap* ICreateBubbleShoreTex(int width, int height);
void IRefillBubbleShoreTex();
plMipmap* ICreateEdgeShoreTex(int width, int height);
void IRefillEdgeShoreTex();
void ISetAsTexture(plLayer* lay, plBitmap* tex);
void ICreateGraphShoreLayer(hsGMaterial* mat, int iPass);
void ICreateGraphBubbleLayer(hsGMaterial* mat, int iPass);
void ICreateGraphEdgeLayer(hsGMaterial* mat, int iPass);
void ICreateGraphShoreMaterials();
plRenderTarget* ISetupGraphShoreRenderReq(int which);
void IMakeShoreLayer(hsGMaterial* mat, int which);
void ISetupShoreLayers(hsGMaterial* mat);
void ISetupGraphShore(hsGMaterial* mat);
void ICheckShoreMaterial(plSceneObject* so);
void ICheckShoreMaterials();
void ICheckDecalMaterial(plSceneObject* so);
void ICheckDecalMaterials();
void ISetupDecal(hsGMaterial* mat);
void ICheckDecalEnvLayers(hsGMaterial* mat);
void IAddGraphPShader(hsGMaterial* mat, int iPass);
void IAddGraphVShader(hsGMaterial* mat, int iPass);
void IUpdateGraphShader(hsScalar dt, int iPass);
void IInitGraph(int iPass);
void IShuffleDownGraphs(int iPass);
// type is either plLayRefMsg::kVertexShader or plLayRefMsg::kPixelShader.
void IAddShaderToLayers(hsGMaterial* mat, int iFirst, int iLast, UInt8 type, plShader* shader);
void IAddBumpPixelShader(hsGMaterial* mat, int iShader, int iFirst, int iLast);
void IAddBumpVertexShader(hsGMaterial* mat, int iShader, int iFirst, int iLast);
void IAddRipVertexShader(hsGMaterial* mat, const plRipVSConsts& ripConsts);
void IAddRipPixelShader(hsGMaterial* mat, const plRipVSConsts& ripConsts);
void IAddShoreVertexShader(hsGMaterial* mat);
void IAddShorePixelShader(hsGMaterial* mat);
void IAddFixedVertexShader(hsGMaterial* mat, const int numUVWs);
void IAddFixedPixelShader(hsGMaterial* mat);
plShader* IGetDecalPShader(hsGMaterial* mat);
plShader* ICreateDecalPShader(DecalPType t);
plShader* IGetDecalVShader(hsGMaterial* mat);
plShader* ICreateDecalVShader(DecalVType t);
void IUpdateShaders(plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l);
void IUpdateBiasVShader();
void IUpdateBumpPShader(plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l);
void IUpdateBumpVShader(plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l);
void IUpdateRipPShader(plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l);
void IUpdateRipVShader(plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l);
void IUpdateShoreVShader(plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l);
void IUpdateFixedVShader(plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l);
void IUpdateFixedPShader(plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l);
void IUpdateGraphShaders(plPipeline* pipe, hsScalar dt);
void IUpdateDecVShader(int t, plPipeline* pipe);
void IUpdateDecVShaders(plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual int IShoreRef() const { return kRefShore; }
virtual int IDecalRef() const { return kRefDecal; }
inline void LogF(const char *format, ...) const;
inline void LogF(UInt32 color, const char *format, ...) const;
inline void IRestartLog() const;
inline void GraphLen(hsScalar len) const;
inline void IRestartGraph() const;
public:
plWaveSet7();
virtual ~plWaveSet7();
CLASSNAME_REGISTER( plWaveSet7 );
GETINTERFACE_ANY( plWaveSet7, plWaveSetBase );
virtual hsBool MsgReceive(plMessage* msg);
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return false; }
Int32 GetNumProperties() const { return kNumProps; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
hsScalar EvalPoint(hsPoint3& pos, hsVector3& norm);
// Getters and Setters for Python twiddling
//
// First a way to set new values. The secs parameter says how long to take
// blending to the new value from the current value.
//
// Geometric wave parameters. These are all safe to twiddle at any time or speed.
// The new settings take effect as new waves are spawned.
void SetGeoMaxLength(hsScalar s, hsScalar secs=0) { fState.fGeoState.fMaxLength.Set(s, secs); }
void SetGeoMinLength(hsScalar s, hsScalar secs=0) { fState.fGeoState.fMinLength.Set(s, secs); }
void SetGeoAmpOverLen(hsScalar s, hsScalar secs=0) { fState.fGeoState.fAmpOverLen.Set(s, secs); }
void SetGeoChop(hsScalar s, hsScalar secs=0) { fState.fGeoState.fChop.Set(s, secs); }
void SetGeoAngleDev(hsScalar s, hsScalar secs=0) { fState.fGeoState.fAngleDev.Set(s, secs); }
// Texture wave parameters. Safe to twiddle any time or speed.
// The new settings take effect as new waves are spawned.
void SetTexMaxLength(hsScalar s, hsScalar secs=0) { fState.fTexState.fMaxLength.Set(s, secs); }
void SetTexMinLength(hsScalar s, hsScalar secs=0) { fState.fTexState.fMinLength.Set(s, secs); }
void SetTexAmpOverLen(hsScalar s, hsScalar secs=0) { fState.fTexState.fAmpOverLen.Set(s, secs); }
void SetTexChop(hsScalar s, hsScalar secs=0) { fState.fTexState.fChop.Set(s, secs); }
void SetTexAngleDev(hsScalar s, hsScalar secs=0) { fState.fTexState.fAngleDev.Set(s, secs); }
// The size in feet of one tile of the ripple texture. If you change this (I don't
// recommend it), you need to change it very slowly or it will look very stupid.
void SetRippleScale(hsScalar s, hsScalar secs=0) { fState.fRippleScale.Set(s, secs); }
// The direction the wind is blowing (waves will be more or less perpindicular to wind dir).
// Change somewhat slowly, like over 30 seconds.
void SetWindDir(const hsVector3& s, hsScalar secs=0) { fState.fWindDir.Set(s, secs); }
// Change these gently, effect is immediate.
void SetSpecularNoise(hsScalar s, hsScalar secs=0) { hsVector3 spec = fState.fSpecVec; spec[plFixedWaterState7::kNoise] = s; fState.fSpecVec.Set(spec, secs); }
void SetSpecularStart(hsScalar s, hsScalar secs=0) { hsVector3 spec = fState.fSpecVec; spec[plFixedWaterState7::kSpecStart] = s; fState.fSpecVec.Set(spec, secs); }
void SetSpecularEnd(hsScalar s, hsScalar secs=0) { hsVector3 spec = fState.fSpecVec; spec[plFixedWaterState7::kSpecEnd] = s; fState.fSpecVec.Set(spec, secs); }
// Water Height is overriden if the ref object is animated.
void SetWaterHeight(hsScalar s, hsScalar secs=0) { fState.fWaterHeight.Set(s, secs); }
// Water Offset and DepthFalloff are complicated, and not immediately interesting to animate.
void SetWaterOffset(const hsVector3& s, hsScalar secs=0) { fState.fWaterOffset.Set(s, secs); }
void SetOpacOffset(hsScalar s, hsScalar secs=0) { hsVector3 off = fState.fWaterOffset; off.fX = s; fState.fWaterOffset.Set(off, secs); }
void SetReflOffset(hsScalar s, hsScalar secs=0) { hsVector3 off = fState.fWaterOffset; off.fY = s; fState.fWaterOffset.Set(off, secs); }
void SetWaveOffset(hsScalar s, hsScalar secs=0) { hsVector3 off = fState.fWaterOffset; off.fZ = s; fState.fWaterOffset.Set(off, secs); }
void SetDepthFalloff(const hsVector3& s, hsScalar secs=0) { fState.fDepthFalloff.Set(s, secs); }
void SetOpacFalloff(hsScalar s, hsScalar secs=0) { hsVector3 off = fState.fDepthFalloff; off.fX = s; fState.fDepthFalloff.Set(off, secs); }
void SetReflFalloff(hsScalar s, hsScalar secs=0) { hsVector3 off = fState.fDepthFalloff; off.fY = s; fState.fDepthFalloff.Set(off, secs); }
void SetWaveFalloff(hsScalar s, hsScalar secs=0) { hsVector3 off = fState.fDepthFalloff; off.fZ = s; fState.fDepthFalloff.Set(off, secs); }
// Max and Min Atten aren't very interesting, and will probably go away.
void SetMaxAtten(const hsVector3& s, hsScalar secs=0) { fState.fMaxAtten.Set(s, secs); }
void SetMinAtten(const hsVector3& s, hsScalar secs=0) { fState.fMinAtten.Set(s, secs); }
// Skipping the shore parameters, because they are never used.
// Water colors, adjust slowly, effect is immediate.
void SetWaterTint(const hsColorRGBA& s, hsScalar secs=0) { fState.fWaterTint.Set(s, secs); }
void SetWaterRGB(const hsVector3& col, hsScalar secs=0) { hsColorRGBA rgb; rgb.Set(col.fX, col.fY, col.fZ, GetWaterOpacity()); SetWaterTint(rgb, secs); }
void SetWaterOpacity(hsScalar s, hsScalar secs=0) { hsColorRGBA col = GetWaterTint(); col.a = s; SetWaterTint(col, secs); }
void SetSpecularTint(const hsColorRGBA& s, hsScalar secs=0) { fState.fSpecularTint.Set(s, secs); }
void SetSpecularRGB(const hsVector3& col, hsScalar secs=0) { hsColorRGBA rgb; rgb.Set(col.fX, col.fY, col.fZ, GetSpecularMute()); SetSpecularTint(rgb, secs); }
void SetSpecularMute(hsScalar s, hsScalar secs=0) { hsColorRGBA col = GetSpecularTint(); col.a = s; SetSpecularTint(col, secs); }
// The environment map is essentially projected onto a sphere. Moving the center of
// the sphere north will move the reflections north, changing the radius of the
// sphere effects parallax in the obvious way.
void SetEnvCenter(const hsPoint3& s, hsScalar secs=0) { fState.fEnvCenter.Set(s, secs); }
void SetEnvRadius(hsScalar s, hsScalar secs=0) { fState.fEnvRadius.Set(s, secs); }
// Now a way to get current values. See the accompanying Setter for notes on
// what the parameter means.
//
hsScalar GetGeoMaxLength() const { return fState.fGeoState.fMaxLength; }
hsScalar GetGeoMinLength() const { return fState.fGeoState.fMinLength; }
hsScalar GetGeoAmpOverLen() const { return fState.fGeoState.fAmpOverLen; }
hsScalar GetGeoChop() const { return fState.fGeoState.fChop; }
hsScalar GetGeoAngleDev() const { return fState.fGeoState.fAngleDev; }
hsScalar GetTexMaxLength() const { return fState.fTexState.fMaxLength; }
hsScalar GetTexMinLength() const { return fState.fTexState.fMinLength; }
hsScalar GetTexAmpOverLen() const { return fState.fTexState.fAmpOverLen; }
hsScalar GetTexChop() const { return fState.fTexState.fChop; }
hsScalar GetTexAngleDev() const { return fState.fTexState.fAngleDev; }
hsScalar GetRippleScale() const { return fState.fRippleScale; }
hsVector3 GetWindDir() const { return fState.fWindDir; }
hsScalar GetSpecularNoise() const { hsVector3 spec = fState.fSpecVec; return spec[plFixedWaterState7::kNoise]; }
hsScalar GetSpecularStart() const { hsVector3 spec = fState.fSpecVec; return spec[plFixedWaterState7::kSpecStart]; }
hsScalar GetSpecularEnd() const { hsVector3 spec = fState.fSpecVec; return spec[plFixedWaterState7::kSpecEnd]; }
hsScalar GetWaterHeight() const { return fState.fWaterHeight; }
hsVector3 GetWaterOffset() const { return fState.fWaterOffset; }
hsScalar GetOpacOffset() const { hsVector3 off = fState.fWaterOffset; return off.fX; }
hsScalar GetReflOffset() const { hsVector3 off = fState.fWaterOffset; return off.fY; }
hsScalar GetWaveOffset() const { hsVector3 off = fState.fWaterOffset; return off.fZ; }
hsVector3 GetDepthFalloff() const { return fState.fDepthFalloff; }
hsScalar GetOpacFalloff() const { hsVector3 off = fState.fDepthFalloff; return off.fX; }
hsScalar GetReflFalloff() const { hsVector3 off = fState.fDepthFalloff; return off.fY; }
hsScalar GetWaveFalloff() const { hsVector3 off = fState.fDepthFalloff; return off.fZ; }
hsVector3 GetMaxAtten() const { return fState.fMaxAtten; }
hsVector3 GetMinAtten() const { return fState.fMinAtten; }
hsColorRGBA GetWaterTint() const { return fState.fWaterTint; }
hsVector3 GetWaterRGB() const { hsColorRGBA col = GetWaterTint(); return hsVector3(col.r, col.g, col.b); }
hsScalar GetWaterOpacity() const { return GetWaterTint().a; }
hsColorRGBA GetSpecularTint() const { return fState.fSpecularTint; }
hsVector3 GetSpecularRGB() const { hsColorRGBA col = GetSpecularTint(); return hsVector3(col.r, col.g, col.b); }
hsScalar GetSpecularMute() const { return GetSpecularTint().a; }
hsPoint3 GetEnvCenter() const { return fState.fEnvCenter; }
hsScalar GetEnvRadius() const { return fState.fEnvRadius; }
// Export/debugging functions. For runtime, use message interface (plGenRefMsg, plWaveMsg).
void AddTarget(const plKey& key);
void RemoveTarget(const plKey& key);
void AddShoreTest(plKey& key);
void SetRefObject(plSceneObject* refObj);
void SetSceneNode(const plKey& key);
plKey GetSceneNode() const { return fSceneNode; }
void AddDynaDecalMgr(plKey& key);
void RemoveDynaDecalMgr(plKey& key);
void AddBuoy(plKey soKey);
void RemoveBuoy(plKey soKey);
virtual hsBool SetupRippleMat(hsGMaterial* mat, const plRipVSConsts& ripConsts);
virtual hsScalar GetHeight() const { return State().fWaterHeight; }
const plFixedWaterState7::WaveState& GeoState() const { return State().fGeoState; }
const plFixedWaterState7::WaveState& TexState() const { return State().fTexState; }
const plFixedWaterState7& State() const { return fState; }
void SetState(const plFixedWaterState7& state, hsScalar dur);
void SetEnvSize(UInt32 s) { fEnvSize = s; }
UInt32 GetEnvSize() const { return fEnvSize; }
void StopLog();
void StartLog();
hsBool Logging() const { return fStatusLog != nil; }
void StartGraph();
void StopGraph();
hsBool Graphing() const { return fStatusGraph != nil; }
};
#endif // plWaveSet7_inc

View File

@ -0,0 +1,66 @@
/*==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 "plWaveSetBase.h"
#include "hsResMgr.h"
#include "../pnMessage/plRefMsg.h"
plWaveSetBase::plWaveSetBase()
{
}
plWaveSetBase::~plWaveSetBase()
{
}
void plWaveSetBase::AddShore(plKey key)
{
hsgResMgr::ResMgr()->SendRef(key, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, IShoreRef()), plRefFlags::kPassiveRef);
}
void plWaveSetBase::AddDecal(plKey key)
{
hsgResMgr::ResMgr()->SendRef(key, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, IDecalRef()), plRefFlags::kPassiveRef);
}

View File

@ -0,0 +1,78 @@
/*==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 plWaveSetBase_inc
#define plWaveSetBase_inc
#include "../pnModifier/plMultiModifier.h"
#include "hsGeometry3.h"
class hsGMaterial;
class plRipVSConsts;
class plWaveSetBase : public plMultiModifier
{
virtual int IShoreRef() const = 0;
virtual int IDecalRef() const = 0;
public:
plWaveSetBase();
virtual ~plWaveSetBase();
CLASSNAME_REGISTER( plWaveSetBase );
GETINTERFACE_ANY( plWaveSetBase, plMultiModifier );
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return false; }
Int32 GetNumProperties() const { return 0; }
virtual hsBool SetupRippleMat(hsGMaterial* mat, const plRipVSConsts& ripConsts) = 0;
virtual hsScalar GetHeight() const = 0;
virtual hsVector3 GetWindDir() const = 0;
void AddShore(plKey soKey);
void AddDecal(plKey key);
};
#endif // plWaveSetBase_inc

View File

@ -0,0 +1,426 @@
/*==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 plWaveSetShaderConsts_inc
#define plWaveSetShaderConsts_inc
// Notice there can be skips for multi-vector consts (e.g. matrices).
namespace plGridVS
{
enum {
kLocalToNDC = 0,
kProjRow0 = 0,
kProjRow1 = 1,
kProjRow2 = 2,
kProjRow3 = 3,
kWaterTint = 4,
kFrequency = 5,
kPhase = 6,
kAmplitude = 7,
kDirectionX = 8,
kDirectionY = 9,
kUTransform = 10,
kVTransform = 11,
kScrunch = 12,
kSinConsts = 13,
kCosConsts = 14,
kPiConsts = 15,
kNumericConsts = 16,
kCameraPos = 17,
kWindRot = 18,
kEnvAdjust = 19,
kEnvTint = 20,
kNumConsts
};
};
namespace plFixedVS
{
enum {
kWorldToNDC = 0,
kProjRow0 = 0,
kProjRow1 = 1,
kProjRow2 = 2,
kProjRow3 = 3,
kWaterTint = 4,
kFrequency = 5,
kPhase = 6,
kAmplitude = 7,
kDirectionX = 8,
kDirectionY = 9,
kUTransform = 10,
kVTransform = 11,
kScrunch = 12,
kSinConsts = 13,
kCosConsts = 14,
kPiConsts = 15,
kNumericConsts = 16,
kCameraPos = 17,
kWindRot = 18,
kEnvAdjust = 19,
kEnvTint = 20,
kLocalToWorld = 21,
kL2WRow0 = 21,
kL2WRow1 = 22,
kL2WRow2 = 23,
kLengths = 24,
kWaterLevel = 25,
kDepthFalloff = 26,
kMinAtten = 27,
kFogSet = 28,
kNumConsts
};
};
namespace plFixedVS7
{
enum {
kWorldToNDC = 0,
kProjRow0 = 0,
kProjRow1 = 1,
kProjRow2 = 2,
kProjRow3 = 3,
kWaterTint = 4,
kFrequency = 5,
kPhase = 6,
kAmplitude = 7,
kDirectionX = 8,
kDirectionY = 9,
kUVScale = 10,
kSpecAtten = 11,
kScrunch = 12, // UNUSED
kSinConsts = 13,
kCosConsts = 14,
kPiConsts = 15,
kNumericConsts = 16,
kCameraPos = 17,
kWindRot = 18,
kEnvAdjust = 19,
kEnvTint = 20,
kLocalToWorld = 21,
kL2WRow0 = 21,
kL2WRow1 = 22,
kL2WRow2 = 23,
kLengths = 24,
kWaterLevel = 25,
kDepthFalloff = 26,
kMinAtten = 27,
kFogSet = 28,
kDirXK = 29,
kDirYK = 30,
kDirXW = 31,
kDirYW = 32,
kWK = 33,
kDirXSqKW = 34,
kDirXDirYKW = 35,
kDirYSqKW = 36,
kNumConsts
};
};
namespace plShoreVS
{
enum {
kWorldToNDC = 0,
kProjRow0 = 0,
kProjRow1 = 1,
kProjRow2 = 2,
kProjRow3 = 3,
kShoreTint = 4,
kFrequency = 5,
kPhase = 6,
kAmplitude = 7,
kDirectionX = 8,
kDirectionY = 9,
kIncline = 10,
kFogSet = 11,
kScrunch = 12, // UNUSED
kSinConsts = 13,
kCosConsts = 14,
kPiConsts = 15,
kNumericConsts = 16,
kQADirX = 17, // Q * Dir.x * A
kQADirY = 18, // Q * Dir.y * A
kTex0Transform = 19,
kTex0_Row0 = 19,
kTex0_Row1 = 20,
kTex0_Row2 = 21,
kTex1Transform = 22, // UNUSED
kTex1_Row0 = 22,
kTex1_Row1 = 23,
kTex1_Row2 = 24,
kLocalToWorld = 25,
kL2WRow0 = 26,
kL2WRow1 = 27,
kL2WRow2 = 28,
kLengths = 29,
kWaterLevel = 30,
kDepthFalloff = 31,
kMinAtten = 32,
kNumConsts
};
};
namespace plGraphVS
{
enum {
kNumericConsts = 0,
kFrequency = 1,
kPhase = 2,
kAmplitude = 3,
kPiConsts = 4,
kCosConsts = 5,
kUVWConsts = 6,
kColor = 7,
kNumConsts
};
};
namespace plGraphPS
{
enum {
kNumConsts
};
};
namespace plFixedPS
{
enum {
kDir0 = 0,
kDir1 = 1,
kDir2 = 2,
kDir3 = 3,
kNumConsts
};
};
namespace plBumpPS
{
enum {
kWave0 = 0,
kWave1 = 1,
kWave2 = 2,
kWave3 = 3,
kHalfOne = 4,
kBias = 5,
kNumConsts
};
};
namespace plBumpVS
{
enum {
kUXform0 = 0,
kUXform1 = 1,
kUXform2 = 2,
kUXform3 = 3,
kNumbers = 4,
kNumConsts
};
};
namespace plBiasPS
{
enum {
kNumConsts
};
};
namespace plBiasVS
{
enum {
kTexU0 = 0,
kTexV0 = 1,
kTexU1 = 2,
kTexV1 = 3,
kNumbers = 4,
kScaleBias = 5,
kNumConsts
};
};
namespace plCompPS
{
enum {
kNumConsts
};
};
namespace plCompVS
{
enum {
kTex0Transform = 0,
kTex0_Row0 = 0,
kTex0_Row1 = 1,
kTex1Transform = 2,
kTex1_Row0 = 2,
kTex1_Row1 = 3,
kTex2Transform = 4,
kTex2_Row0 = 4,
kTex2_Row1 = 5,
kTex3Transform = 6,
kTex3_Row0 = 6,
kTex3_Row1 = 7,
kNumbers = 8,
kNumConsts
};
};
namespace plRipVS // closely related to plFixedVS and plShoreVS
{
enum {
kWorldToNDC = 0,
kProjRow0 = 0,
kProjRow1 = 1,
kProjRow2 = 2,
kProjRow3 = 3,
kFogSet = 4,
kFrequency = 5,
kPhase = 6,
kAmplitude = 7,
kDirectionX = 8,
kDirectionY = 9,
kQADirX = 10,
kQADirY = 11,
kScrunch = 12, // UNUSED
kSinConsts = 13,
kCosConsts = 14,
kPiConsts = 15,
kNumericConsts = 16,
kCameraPos = 17,
kWindRot = 18, // UNUSED
kTex0Transform = 19, // UNUSED
kTex0_Row0 = 19,
kTex0_Row1 = 20,
kTex0_Row2 = 21,
kTex1Transform = 22, // UNUSED
kTex1_Row0 = 22,
kTex1_Row1 = 23,
kTex1_Row2 = 24,
kLocalToWorld = 25,
kL2WRow0 = 26,
kL2WRow1 = 27,
kL2WRow2 = 28,
kLengths = 29,
kWaterLevel = 30,
kDepthFalloff = 31,
kMinAtten = 32,
kTexConsts = 33,
kLifeConsts = 34,
kRampBias = 35,
kNumConsts
};
};
namespace plWaveDecVS // closely related to plFixedVS and plShoreVS
{
enum {
kWorldToNDC = 0,
kProjRow0 = 0,
kProjRow1 = 1,
kProjRow2 = 2,
kProjRow3 = 3,
kFrequency = 4,
kPhase = 5,
kAmplitude = 6,
kDirectionX = 7,
kDirectionY = 8,
kScrunch = 9, // UNUSED
kSinConsts = 10,
kCosConsts = 11,
kPiConsts = 12,
kNumericConsts = 13,
kTex0Transform = 14,
kTex0_Row0 = 14,
kTex0_Row1 = 15,
kTex1Transform = 16,
kTex1_Row0 = 16,
kTex1_Row1 = 17,
kLocalToWorld = 18,
kL2WRow0 = 18,
kL2WRow1 = 19,
kL2WRow2 = 20,
kLengths = 21,
kWaterLevel = 22,
kDepthFalloff = 23,
kMinAtten = 24,
kBias = 25, // Only using one slot
kMatColor = 26,
kCameraPos = 27, // Only used by DecalEnv
kEnvAdjust = 28, // Only used by DecalEnv
kFogSet = 29,
kQADirX = 30,
kQADirY = 31,
kDirXW = 32, // Only used by DecalEnv
kDirYW = 33, // Only used by DecalEnv
kWK = 34, // Only used by DecalEnv
kDirXSqKW = 35, // Only used by DecalEnv
kDirXDirYKW = 36, // Only used by DecalEnv
kDirYSqKW = 37, // Only used by DecalEnv
kNumConsts
};
};
#endif // plWaveSetShaderConsts_inc