mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
Processed core, tools and default modules to utilize assets Converted all console types that were string based, such as TypeImageFilename to utilize const char*/the string table, which avoids a lot of type swapping shenanigans and avoids string corruption Removed unneeded MainEditor mockup module Removed some unused/duplicate image assets from the tools
408 lines
12 KiB
C++
408 lines
12 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "platform/platform.h"
|
|
#include "decalDataFile.h"
|
|
|
|
#include "math/mathIO.h"
|
|
#include "core/tAlgorithm.h"
|
|
#include "core/stream/fileStream.h"
|
|
|
|
#include "T3D/decal/decalManager.h"
|
|
#include "T3D/decal/decalData.h"
|
|
|
|
|
|
template<>
|
|
void* Resource<DecalDataFile>::create( const Torque::Path &path )
|
|
{
|
|
FileStream stream;
|
|
stream.open( path.getFullPath(), Torque::FS::File::Read );
|
|
if ( stream.getStatus() != Stream::Ok )
|
|
return NULL;
|
|
|
|
DecalDataFile *file = new DecalDataFile();
|
|
if ( !file->read( stream ) )
|
|
{
|
|
delete file;
|
|
return NULL;
|
|
}
|
|
|
|
return file;
|
|
}
|
|
|
|
template<>
|
|
ResourceBase::Signature Resource<DecalDataFile>::signature()
|
|
{
|
|
return MakeFourCC('d','e','c','f');
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DecalDataFile::DecalDataFile()
|
|
: mIsDirty( false ),
|
|
mSphereWithLastInsertion( NULL )
|
|
{
|
|
VECTOR_SET_ASSOCIATION( mSphereList );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DecalDataFile::~DecalDataFile()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DecalDataFile::clear()
|
|
{
|
|
for ( U32 i=0; i < mSphereList.size(); i++ )
|
|
delete mSphereList[i];
|
|
|
|
mSphereList.clear();
|
|
mSphereWithLastInsertion = NULL;
|
|
mChunker.freeBlocks();
|
|
|
|
mIsDirty = true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool DecalDataFile::write( Stream& stream )
|
|
{
|
|
// Write our identifier... so we have a better
|
|
// idea if we're reading pure garbage.
|
|
// This identifier stands for "Torque Decal Data File".
|
|
stream.write( 4, "TDDF" );
|
|
|
|
// Now the version number.
|
|
stream.write( (U8)FILE_VERSION );
|
|
|
|
Vector<DecalInstance*> allDecals;
|
|
|
|
// Gather all DecalInstances that should be saved.
|
|
for ( U32 i = 0; i < mSphereList.size(); i++ )
|
|
{
|
|
Vector<DecalInstance*>::const_iterator item = mSphereList[i]->mItems.begin();
|
|
for ( ; item != mSphereList[i]->mItems.end(); item++ )
|
|
{
|
|
if ( (*item)->mFlags & SaveDecal )
|
|
allDecals.push_back( (*item) );
|
|
}
|
|
}
|
|
|
|
// Gather all the DecalData datablocks used.
|
|
Vector<const DecalData*> allDatablocks;
|
|
for ( U32 i = 0; i < allDecals.size(); i++ )
|
|
allDatablocks.push_back_unique( allDecals[i]->mDataBlock );
|
|
|
|
// Write out datablock lookupNames.
|
|
U32 count = allDatablocks.size();
|
|
stream.write( count );
|
|
for ( U32 i = 0; i < count; i++ )
|
|
stream.write( allDatablocks[i]->lookupName );
|
|
|
|
Vector<const DecalData*>::iterator dataIter;
|
|
|
|
// Write out the DecalInstance list.
|
|
count = allDecals.size();
|
|
stream.write( count );
|
|
for ( U32 i = 0; i < count; i++ )
|
|
{
|
|
DecalInstance *inst = allDecals[i];
|
|
|
|
dataIter = T3D::find( allDatablocks.begin(), allDatablocks.end(), inst->mDataBlock );
|
|
U8 dataIndex = dataIter - allDatablocks.begin();
|
|
|
|
stream.write( dataIndex );
|
|
mathWrite( stream, inst->mPosition );
|
|
mathWrite( stream, inst->mNormal );
|
|
mathWrite( stream, inst->mTangent );
|
|
stream.write( inst->mTextureRectIdx );
|
|
stream.write( inst->mSize );
|
|
stream.write( inst->mRenderPriority );
|
|
}
|
|
|
|
// Clear the dirty flag.
|
|
mIsDirty = false;
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool DecalDataFile::read( Stream &stream )
|
|
{
|
|
// NOTE: we are shortcutting by just saving out the DecalInst and
|
|
// using regular addDecal methods to add them, which will end up
|
|
// generating the DecalSphere(s) in the process.
|
|
// It would be more efficient however to just save out all the data
|
|
// and read it all in with no calculation required.
|
|
|
|
// Read our identifier... so we know we're
|
|
// not reading in pure garbage.
|
|
char id[4] = { 0 };
|
|
stream.read( 4, id );
|
|
if ( dMemcmp( id, "TDDF", 4 ) != 0 )
|
|
{
|
|
Con::errorf( "DecalDataFile::read() - This is not a Decal file!" );
|
|
return false;
|
|
}
|
|
|
|
// Empty ourselves before we really begin reading.
|
|
clear();
|
|
|
|
// Now the version number.
|
|
U8 version;
|
|
stream.read( &version );
|
|
if ( version != (U8)FILE_VERSION )
|
|
{
|
|
Con::errorf( "DecalDataFile::read() - file versions do not match!" );
|
|
Con::errorf( "You must manually delete the old .decals file before continuing!" );
|
|
return false;
|
|
}
|
|
|
|
// Read in the lookupNames of the DecalData datablocks and recover the datablock.
|
|
Vector<DecalData*> allDatablocks;
|
|
U32 count;
|
|
stream.read( &count );
|
|
allDatablocks.setSize( count );
|
|
for ( U32 i = 0; i < count; i++ )
|
|
{
|
|
String lookupName;
|
|
stream.read( &lookupName );
|
|
|
|
DecalData *data = DecalData::findDatablock( lookupName );
|
|
|
|
if ( !data )
|
|
{
|
|
char name[512];
|
|
dSprintf(name, 512, "%s_missing", lookupName.c_str());
|
|
|
|
DecalData *stubCheck = DecalData::findDatablock( name );
|
|
if( !stubCheck )
|
|
{
|
|
data = new DecalData;
|
|
data->lookupName = name;
|
|
data->registerObject(name);
|
|
Sim::getRootGroup()->addObject( data );
|
|
data->mMaterialName = "WarningMaterial";
|
|
data->mMaterial = dynamic_cast<Material*>(Sim::findObject("WarningMaterial"));
|
|
|
|
Con::errorf( "DecalDataFile::read() - DecalData %s does not exist! Temporarily created %s_missing.", lookupName.c_str(), lookupName.c_str());
|
|
}
|
|
}
|
|
|
|
allDatablocks[ i ] = data;
|
|
}
|
|
|
|
U8 dataIndex;
|
|
DecalData *data;
|
|
|
|
// Now read all the DecalInstance(s).
|
|
stream.read( &count );
|
|
for ( U32 i = 0; i < count; i++ )
|
|
{
|
|
DecalInstance *inst = _allocateInstance();
|
|
|
|
stream.read( &dataIndex );
|
|
mathRead( stream, &inst->mPosition );
|
|
mathRead( stream, &inst->mNormal );
|
|
mathRead( stream, &inst->mTangent );
|
|
stream.read( &inst->mTextureRectIdx );
|
|
stream.read( &inst->mSize );
|
|
stream.read( &inst->mRenderPriority );
|
|
|
|
inst->mVisibility = 1.0f;
|
|
inst->mFlags = PermanentDecal | SaveDecal | ClipDecal;
|
|
inst->mCreateTime = Sim::getCurrentTime();
|
|
inst->mVerts = NULL;
|
|
inst->mIndices = NULL;
|
|
inst->mVertCount = 0;
|
|
inst->mIndxCount = 0;
|
|
|
|
data = allDatablocks[ dataIndex ];
|
|
|
|
if ( data )
|
|
{
|
|
inst->mDataBlock = data;
|
|
|
|
_addDecalToSpheres( inst );
|
|
|
|
// onload set instances should get added to the appropriate vec
|
|
inst->mId = gDecalManager->mDecalInstanceVec.size();
|
|
gDecalManager->mDecalInstanceVec.push_back(inst);
|
|
}
|
|
else
|
|
{
|
|
_freeInstance( inst );
|
|
Con::errorf( "DecalDataFile::read - cannot find DecalData for DecalInstance read from disk." );
|
|
}
|
|
}
|
|
|
|
// Clear the dirty flag.
|
|
mIsDirty = false;
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DecalInstance* DecalDataFile::addDecal( const Point3F& pos, const Point3F& normal, const Point3F& tangent,
|
|
DecalData* decalData, F32 decalScale, S32 decalTexIndex, U8 flags )
|
|
{
|
|
DecalInstance* newDecal = _allocateInstance();
|
|
|
|
newDecal->mRenderPriority = 0;
|
|
newDecal->mCustomTex = NULL;
|
|
newDecal->mId = -1;
|
|
|
|
newDecal->mPosition = pos;
|
|
newDecal->mNormal = normal;
|
|
newDecal->mTangent = tangent;
|
|
|
|
newDecal->mSize = decalData->size * decalScale;
|
|
|
|
newDecal->mDataBlock = decalData;
|
|
|
|
S32 frame = newDecal->mDataBlock->frame;
|
|
// randomize the frame if the flag is set. this number is used directly below us
|
|
// when calculating render coords
|
|
if ( decalData->randomize )
|
|
frame = gRandGen.randI();
|
|
|
|
frame %= getMax( decalData->texCoordCount, 0 ) + 1;
|
|
|
|
newDecal->mTextureRectIdx = frame;
|
|
|
|
newDecal->mVisibility = 1.0f;
|
|
|
|
newDecal->mLastAlpha = -1.0f;
|
|
|
|
newDecal->mCreateTime = Sim::getCurrentTime();
|
|
|
|
newDecal->mVerts = NULL;
|
|
newDecal->mIndices = NULL;
|
|
newDecal->mVertCount = 0;
|
|
newDecal->mIndxCount = 0;
|
|
|
|
newDecal->mFlags = flags;
|
|
newDecal->mFlags |= ClipDecal;
|
|
|
|
_addDecalToSpheres( newDecal );
|
|
|
|
return newDecal;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DecalDataFile::_addDecalToSpheres( DecalInstance* inst )
|
|
{
|
|
// First try the sphere we have last inserted an item into, if there is one.
|
|
// Given a good spatial locality of insertions, this is a reasonable first
|
|
// guess as a good candidate.
|
|
|
|
if( mSphereWithLastInsertion && mSphereWithLastInsertion->tryAddItem( inst ) )
|
|
return;
|
|
|
|
// Otherwise, go through the list and try to find an existing sphere that meets
|
|
// our tolerances.
|
|
|
|
for( U32 i = 0; i < mSphereList.size(); i++ )
|
|
{
|
|
DecalSphere* sphere = mSphereList[i];
|
|
|
|
if( sphere == mSphereWithLastInsertion )
|
|
continue;
|
|
|
|
if( sphere->tryAddItem( inst ) )
|
|
{
|
|
mSphereWithLastInsertion = sphere;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Didn't find a suitable existing sphere, so create a new one.
|
|
|
|
DecalSphere* sphere = new DecalSphere( inst->mPosition, inst->mSize / 2.f );
|
|
|
|
mSphereList.push_back( sphere );
|
|
mSphereWithLastInsertion = sphere;
|
|
|
|
sphere->mItems.push_back( inst );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DecalDataFile::removeDecal( DecalInstance *inst )
|
|
{
|
|
if( !_removeDecalFromSpheres( inst ) )
|
|
return;
|
|
|
|
_freeInstance( inst );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool DecalDataFile::_removeDecalFromSpheres( DecalInstance *inst )
|
|
{
|
|
for( U32 i = 0; i < mSphereList.size(); i++ )
|
|
{
|
|
DecalSphere* sphere = mSphereList[ i ];
|
|
Vector< DecalInstance* > &items = sphere->mItems;
|
|
|
|
// Try to remove the instance from the list of this sphere.
|
|
// If that fails, the instance doesn't belong to this sphere
|
|
// so continue.
|
|
|
|
if( !items.remove( inst ) )
|
|
continue;
|
|
|
|
// If the sphere is now empty, remove it. Otherwise, update
|
|
// it's bounds.
|
|
|
|
if( items.empty() )
|
|
{
|
|
if( mSphereWithLastInsertion == sphere )
|
|
mSphereWithLastInsertion = NULL;
|
|
|
|
delete sphere;
|
|
mSphereList.erase( i );
|
|
}
|
|
else
|
|
sphere->updateWorldSphere();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DecalDataFile::notifyDecalModified( DecalInstance *inst )
|
|
{
|
|
_removeDecalFromSpheres( inst );
|
|
_addDecalToSpheres( inst );
|
|
}
|