Procházet zdrojové kódy

Fixes mapping of imposter images to be packed as part of the shape asset, and fixes paths to be formatted more sanely.

JeffR před 3 roky
rodič
revize
a8b3d874a1

+ 67 - 0
Engine/source/T3D/assets/ShapeAsset.cpp

@@ -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

+ 19 - 0
Engine/source/T3D/assets/ShapeAsset.h

@@ -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

+ 9 - 0
Engine/source/T3D/assets/assetImporter.cpp

@@ -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());
 

+ 41 - 5
Engine/source/ts/tsLastDetail.cpp

@@ -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  ) )

+ 15 - 2
Engine/source/ts/tsLastDetail.h

@@ -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.

+ 33 - 0
Engine/source/ts/tsShape.cpp

@@ -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();

+ 2 - 0
Engine/source/ts/tsShape.h

@@ -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();