You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
6.9 KiB
232 lines
6.9 KiB
14 years ago
|
/*==LICENSE==*
|
||
|
|
||
|
CyanWorlds.com Engine - MMOG client, server and tools
|
||
|
Copyright (C) 2011 Cyan Worlds, Inc.
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||
|
or by snail mail at:
|
||
|
Cyan Worlds, Inc.
|
||
|
14617 N Newport Hwy
|
||
|
Mead, WA 99021
|
||
|
|
||
|
*==LICENSE==*/
|
||
|
#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;
|
||
|
}
|