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.
578 lines
15 KiB
578 lines
15 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
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 |
|
} |
|
|
|
|
|
|
|
|