mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
Fixes mapping of imposter images to be packed as part of the shape asset, and fixes paths to be formatted more sanely.
This commit is contained in:
parent
bd876e427a
commit
a8b3d874a1
|
|
@ -129,6 +129,13 @@ ShapeAsset::ShapeAsset()
|
|||
mConstructorFileName = StringTable->EmptyString();
|
||||
mFilePath = StringTable->EmptyString();
|
||||
mConstructorFilePath = StringTable->EmptyString();
|
||||
|
||||
mDiffuseImposterFileName = StringTable->EmptyString();
|
||||
mDiffuseImposterPath = StringTable->EmptyString();
|
||||
mNormalImposterFileName = StringTable->EmptyString();
|
||||
mNormalImposterPath = StringTable->EmptyString();
|
||||
|
||||
|
||||
mLoadedState = AssetErrCode::NotLoaded;
|
||||
}
|
||||
|
||||
|
|
@ -162,6 +169,12 @@ void ShapeAsset::initPersistFields()
|
|||
&setShapeFile, &getShapeFile, "Path to the shape file we want to render");
|
||||
addProtectedField("constuctorFileName", TypeAssetLooseFilePath, Offset(mConstructorFileName, ShapeAsset),
|
||||
&setShapeConstructorFile, &getShapeConstructorFile, "Path to the shape file we want to render");
|
||||
|
||||
addProtectedField("diffuseImposterFileName", TypeAssetLooseFilePath, Offset(mDiffuseImposterFileName, ShapeAsset),
|
||||
&setDiffuseImposterFile, &getDiffuseImposterFile, "Path to the diffuse imposter file we want to render");
|
||||
addProtectedField("normalImposterFileName", TypeAssetLooseFilePath, Offset(mNormalImposterFileName, ShapeAsset),
|
||||
&setNormalImposterFile, &getNormalImposterFile, "Path to the normal imposter file we want to render");
|
||||
|
||||
}
|
||||
|
||||
void ShapeAsset::setDataField(StringTableEntry slotName, StringTableEntry array, StringTableEntry value)
|
||||
|
|
@ -193,6 +206,20 @@ void ShapeAsset::initializeAsset()
|
|||
|
||||
mConstructorFilePath = getOwned() ? expandAssetFilePath(mConstructorFilePath) : mConstructorFilePath;
|
||||
|
||||
mDiffuseImposterPath = getOwned() ? expandAssetFilePath(mDiffuseImposterFileName) : mDiffuseImposterFileName;
|
||||
if (mDiffuseImposterPath == StringTable->EmptyString())
|
||||
{
|
||||
String diffusePath = String(mFilePath) + "_imposter.dds";
|
||||
mDiffuseImposterPath = StringTable->insert(diffusePath.c_str());
|
||||
}
|
||||
|
||||
mNormalImposterPath = getOwned() ? expandAssetFilePath(mNormalImposterFileName) : mNormalImposterFileName;
|
||||
if (mNormalImposterPath == StringTable->EmptyString())
|
||||
{
|
||||
String normalPath = String(mFilePath) + "_imposter_normals.dds";
|
||||
mNormalImposterPath = StringTable->insert(normalPath.c_str());
|
||||
}
|
||||
|
||||
loadShape();
|
||||
}
|
||||
|
||||
|
|
@ -232,6 +259,42 @@ void ShapeAsset::setShapeConstructorFile(const char* pShapeConstructorFile)
|
|||
refreshAsset();
|
||||
}
|
||||
|
||||
void ShapeAsset::setDiffuseImposterFile(const char* pImageFile)
|
||||
{
|
||||
// Sanity!
|
||||
AssertFatal(pImageFile != NULL, "Cannot use a NULL image file.");
|
||||
|
||||
// Fetch image file.
|
||||
pImageFile = StringTable->insert(pImageFile, true);
|
||||
|
||||
// Ignore no change,
|
||||
if (pImageFile == mDiffuseImposterFileName)
|
||||
return;
|
||||
|
||||
mDiffuseImposterFileName = getOwned() ? expandAssetFilePath(pImageFile) : pImageFile;
|
||||
|
||||
// Refresh the asset.
|
||||
refreshAsset();
|
||||
}
|
||||
|
||||
void ShapeAsset::setNormalImposterFile(const char* pImageFile)
|
||||
{
|
||||
// Sanity!
|
||||
AssertFatal(pImageFile != NULL, "Cannot use a NULL image file.");
|
||||
|
||||
// Fetch image file.
|
||||
pImageFile = StringTable->insert(pImageFile, true);
|
||||
|
||||
// Ignore no change,
|
||||
if (pImageFile == mNormalImposterFileName)
|
||||
return;
|
||||
|
||||
mNormalImposterFileName = getOwned() ? expandAssetFilePath(pImageFile) : pImageFile;
|
||||
|
||||
// Refresh the asset.
|
||||
refreshAsset();
|
||||
}
|
||||
|
||||
void ShapeAsset::_onResourceChanged(const Torque::Path &path)
|
||||
{
|
||||
if (path != Torque::Path(mFilePath) )
|
||||
|
|
@ -292,6 +355,10 @@ bool ShapeAsset::loadShape()
|
|||
return false; //if it failed to load, bail out
|
||||
}
|
||||
|
||||
mShape->setupBillboardDetails(mFilePath, mDiffuseImposterPath, mNormalImposterPath);
|
||||
|
||||
//If they exist, grab our imposters here and bind them to our shapeAsset
|
||||
|
||||
bool hasBlends = false;
|
||||
|
||||
//Now that we've successfully loaded our shape and have any materials and animations loaded
|
||||
|
|
|
|||
|
|
@ -73,6 +73,12 @@ protected:
|
|||
StringTableEntry mConstructorFilePath;
|
||||
Resource<TSShape> mShape;
|
||||
|
||||
StringTableEntry mDiffuseImposterFileName;
|
||||
StringTableEntry mDiffuseImposterPath;
|
||||
|
||||
StringTableEntry mNormalImposterFileName;
|
||||
StringTableEntry mNormalImposterPath;
|
||||
|
||||
//Material assets we're dependent on and use
|
||||
Vector<StringTableEntry> mMaterialAssetIds;
|
||||
Vector<AssetPtr<MaterialAsset>> mMaterialAssets;
|
||||
|
|
@ -170,6 +176,15 @@ public:
|
|||
inline StringTableEntry getShapeFilePath(void) const { return mFilePath; };
|
||||
inline StringTableEntry getShapeConstructorFilePath(void) const { return mConstructorFilePath; };
|
||||
|
||||
//Imposter images
|
||||
void setDiffuseImposterFile(const char* pImageFile);
|
||||
inline StringTableEntry getDiffuseImposterFile(void) const { return mDiffuseImposterFileName; };
|
||||
inline StringTableEntry getDiffuseImposterFilePath(void) const { return mDiffuseImposterPath; };
|
||||
|
||||
void setNormalImposterFile(const char* pImageFile);
|
||||
inline StringTableEntry getNormalImposterFile(void) const { return mNormalImposterFileName; };
|
||||
inline StringTableEntry getNormalImposterFilePath(void) const { return mNormalImposterPath; };
|
||||
|
||||
static U32 getAssetByFilename(StringTableEntry fileName, AssetPtr<ShapeAsset>* shapeAsset);
|
||||
|
||||
static StringTableEntry getAssetIdByFilename(StringTableEntry fileName);
|
||||
|
|
@ -188,6 +203,10 @@ protected:
|
|||
static bool setShapeConstructorFile(void* obj, const char* index, const char* data) { static_cast<ShapeAsset*>(obj)->setShapeConstructorFile(data); return false; }
|
||||
static const char* getShapeConstructorFile(void* obj, const char* data) { return static_cast<ShapeAsset*>(obj)->getShapeConstructorFile(); }
|
||||
|
||||
static bool setDiffuseImposterFile(void* obj, StringTableEntry index, StringTableEntry data) { static_cast<ShapeAsset*>(obj)->setDiffuseImposterFile(data); return false; }
|
||||
static const char* getDiffuseImposterFile(void* obj, const char* data) { return static_cast<ShapeAsset*>(obj)->getDiffuseImposterFile(); }
|
||||
static bool setNormalImposterFile(void* obj, StringTableEntry index, StringTableEntry data) { static_cast<ShapeAsset*>(obj)->setNormalImposterFile(data); return false; }
|
||||
static const char* getNormalImposterFile(void* obj, const char* data) { return static_cast<ShapeAsset*>(obj)->getNormalImposterFile(); }
|
||||
};
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
|
|
|
|||
|
|
@ -3062,6 +3062,15 @@ Torque::Path AssetImporter::importShapeAsset(AssetImportObject* assetItem)
|
|||
}
|
||||
}
|
||||
|
||||
if (Con::getBoolVariable("$TSLastDetail::dumpImposters", false))
|
||||
{
|
||||
String imposterPath = assetItem->assetName + "_imposter.png";
|
||||
String normalsPath = assetItem->assetName + "_imposter_normals.png";
|
||||
|
||||
newAsset->setDiffuseImposterFile(imposterPath.c_str());
|
||||
newAsset->setNormalImposterFile(normalsPath.c_str());
|
||||
}
|
||||
|
||||
Taml tamlWriter;
|
||||
bool importSuccessful = tamlWriter.write(newAsset, tamlPath.c_str());
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ TSLastDetail::TSLastDetail( TSShape *shape,
|
|||
mCenter = mShape->center;
|
||||
|
||||
mCachePath = cachePath;
|
||||
mDiffusePath = mCachePath + "_imposter.dds";
|
||||
mNormalPath = mCachePath + "_imposter_normals.dds";
|
||||
|
||||
mMaterial = NULL;
|
||||
mMatInstance = NULL;
|
||||
|
|
@ -94,6 +96,38 @@ TSLastDetail::TSLastDetail( TSShape *shape,
|
|||
smLastDetails.push_back( this );
|
||||
}
|
||||
|
||||
TSLastDetail::TSLastDetail(TSShape* shape,
|
||||
const String& cachePath,
|
||||
const String& diffusePath,
|
||||
const String& normalPath,
|
||||
U32 numEquatorSteps,
|
||||
U32 numPolarSteps,
|
||||
F32 polarAngle,
|
||||
bool includePoles,
|
||||
S32 dl, S32 dim)
|
||||
{
|
||||
mNumEquatorSteps = getMax(numEquatorSteps, (U32)1);
|
||||
mNumPolarSteps = numPolarSteps;
|
||||
mPolarAngle = polarAngle;
|
||||
mIncludePoles = includePoles;
|
||||
mShape = shape;
|
||||
mDl = dl;
|
||||
mDim = getMax(dim, (S32)32);
|
||||
|
||||
mRadius = mShape->mRadius;
|
||||
mCenter = mShape->center;
|
||||
|
||||
mCachePath = cachePath;
|
||||
mDiffusePath = diffusePath;
|
||||
mNormalPath = normalPath;
|
||||
|
||||
mMaterial = NULL;
|
||||
mMatInstance = NULL;
|
||||
|
||||
// Store this in the static list.
|
||||
smLastDetails.push_back(this);
|
||||
}
|
||||
|
||||
TSLastDetail::~TSLastDetail()
|
||||
{
|
||||
SAFE_DELETE( mMatInstance );
|
||||
|
|
@ -189,7 +223,8 @@ void TSLastDetail::update( bool forceUpdate )
|
|||
|
||||
// Do we need to update the imposter?
|
||||
const String diffuseMapPath = _getDiffuseMapPath();
|
||||
if ( forceUpdate ||
|
||||
bool isFile = Platform::isFile(diffuseMapPath.c_str());
|
||||
if ( forceUpdate || !Platform::isFile(diffuseMapPath.c_str()) ||
|
||||
Platform::compareModifiedTimes( diffuseMapPath, shapeFile ) <= 0 )
|
||||
_update();
|
||||
|
||||
|
|
@ -218,8 +253,9 @@ void TSLastDetail::update( bool forceUpdate )
|
|||
// Setup the material for this imposter.
|
||||
mMaterial = MATMGR->allocateAndRegister( String::EmptyString );
|
||||
mMaterial->mAutoGenerated = true;
|
||||
mMaterial->_setDiffuseMap(diffuseMapPath,0);
|
||||
mMaterial->_setNormalMap(_getNormalMapPath(), 0);
|
||||
mMaterial->setDiffuseMapFile(diffuseMapPath, 0);
|
||||
mMaterial->setNormalMapFile(_getNormalMapPath(), 0);
|
||||
|
||||
mMaterial->mImposterLimits.set( (mNumPolarSteps * 2) + 1, mNumEquatorSteps, mPolarAngle, mIncludePoles );
|
||||
mMaterial->mTranslucent = true;
|
||||
mMaterial->mTranslucentBlendOp = Material::None;
|
||||
|
|
@ -466,8 +502,8 @@ void TSLastDetail::_update()
|
|||
// Should we dump the images?
|
||||
if ( Con::getBoolVariable( "$TSLastDetail::dumpImposters", false ) )
|
||||
{
|
||||
String imposterPath = mCachePath + ".imposter.png";
|
||||
String normalsPath = mCachePath + ".imposter_normals.png";
|
||||
String imposterPath = _getDiffuseMapPath();
|
||||
String normalsPath = _getNormalMapPath();
|
||||
|
||||
FileStream stream;
|
||||
if ( stream.open( imposterPath, Torque::FS::File::Write ) )
|
||||
|
|
|
|||
|
|
@ -92,6 +92,9 @@ protected:
|
|||
/// where we'll be storing our cache for rendered imposters.
|
||||
String mCachePath;
|
||||
|
||||
String mDiffusePath;
|
||||
String mNormalPath;
|
||||
|
||||
/// The shape detail level to capture into
|
||||
/// the imposters.
|
||||
S32 mDl;
|
||||
|
|
@ -148,10 +151,10 @@ protected:
|
|||
void _validateDim();
|
||||
|
||||
/// Helper which returns the imposter diffuse map path.
|
||||
String _getDiffuseMapPath() const { return mCachePath + ".imposter.dds"; }
|
||||
String _getDiffuseMapPath() const { return mDiffusePath; }
|
||||
|
||||
/// Helper which returns the imposter normal map path.
|
||||
String _getNormalMapPath() const { return mCachePath + ".imposter_normals.dds"; }
|
||||
String _getNormalMapPath() const { return mNormalPath; }
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -164,6 +167,16 @@ public:
|
|||
S32 dl,
|
||||
S32 dim );
|
||||
|
||||
TSLastDetail(TSShape* shape,
|
||||
const String& cachePath,
|
||||
const String& diffusePath,
|
||||
const String& normalPath,
|
||||
U32 numEquatorSteps,
|
||||
U32 numPolarSteps,
|
||||
F32 polarAngle,
|
||||
bool includePoles,
|
||||
S32 dl, S32 dim);
|
||||
|
||||
~TSLastDetail();
|
||||
|
||||
/// Global preference for rendering imposters to shadows.
|
||||
|
|
|
|||
|
|
@ -969,6 +969,39 @@ void TSShape::setupBillboardDetails( const String &cachePath )
|
|||
}
|
||||
}
|
||||
|
||||
void TSShape::setupBillboardDetails(const String& cachePath, const String& diffsePath, const String& normalPath)
|
||||
{
|
||||
// set up billboard details -- only do this once, meaning that
|
||||
// if we add a sequence to the shape we don't redo the billboard
|
||||
// details...
|
||||
if (!billboardDetails.empty())
|
||||
return;
|
||||
|
||||
for (U32 i = 0; i < details.size(); i++)
|
||||
{
|
||||
const Detail& det = details[i];
|
||||
|
||||
if (det.subShapeNum >= 0)
|
||||
continue; // not a billboard detail
|
||||
|
||||
while (billboardDetails.size() <= i)
|
||||
billboardDetails.push_back(NULL);
|
||||
|
||||
billboardDetails[i] = new TSLastDetail(this,
|
||||
cachePath,
|
||||
diffsePath,
|
||||
normalPath,
|
||||
det.bbEquatorSteps,
|
||||
det.bbPolarSteps,
|
||||
det.bbPolarAngle,
|
||||
det.bbIncludePoles,
|
||||
det.bbDetailLevel,
|
||||
det.bbDimension);
|
||||
|
||||
billboardDetails[i]->update();
|
||||
}
|
||||
}
|
||||
|
||||
void TSShape::initMaterialList()
|
||||
{
|
||||
S32 numSubShapes = subShapeFirstObject.size();
|
||||
|
|
|
|||
|
|
@ -429,6 +429,8 @@ class TSShape
|
|||
|
||||
void setupBillboardDetails( const String &cachePath );
|
||||
|
||||
void setupBillboardDetails(const String& cachePath, const String& diffsePath, const String& normalPath);
|
||||
|
||||
/// Inits object list (no geometry buffers)
|
||||
void initObjects();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue