Browse Source

Updates the handling of the baking of shape asset previews to generate them with support for view angle control to improve visibility, as well as supporting overriding of a material in the preview bake
Also utilizes the updated bake handling to have material asset previews render as a sphere shape asset, overriding with the material asset's material, improving distinction of what is a material asset vs image asset
Also updates the sphere preview mesh to be more generic and not only for reflection probes

JeffR 3 years ago
parent
commit
b70faae38f

+ 89 - 14
Engine/source/T3D/assets/ShapeAsset.cpp

@@ -51,6 +51,9 @@
 #endif
 #include "util/imposterCapture.h"
 
+#include "ts/tsShapeInstance.h"
+#include "gfx/bitmap/imageUtils.h"
+
 StringTableEntry ShapeAsset::smNoShapeAssetFallback = NULL;
 
 //-----------------------------------------------------------------------------
@@ -560,25 +563,94 @@ ShapeAnimationAsset* ShapeAsset::getAnimation(S32 index)
 }
 
 #ifdef TORQUE_TOOLS
-const char* ShapeAsset::generateCachedPreviewImage(S32 resolution)
+const char* ShapeAsset::generateCachedPreviewImage(S32 resolution, String overrideMaterial)
 {
    if (!mShape)
       return "";
 
-   TSLastDetail* dt = new TSLastDetail(mShape,
-      mFilePath,
-      1,
-      0,
-      0,
-      false,
-      0,
-      resolution);
+   // We're gonna render... make sure we can.
+   bool sceneBegun = GFX->canCurrentlyRender();
+   if (!sceneBegun)
+      GFX->beginScene();
+
+   // We need to create our own instance to render with.
+   TSShapeInstance* shape = new TSShapeInstance(mShape, true);
+
+   if(overrideMaterial.isNotEmpty())
+      shape->reSkin(overrideMaterial, mShape->materialList->getMaterialName(0));
+
+   // Animate the shape once.
+   shape->animate(0);
+
+   // So we don't have to change it everywhere.
+   const GFXFormat format = GFXFormatR8G8B8A8;
+
+   GBitmap* imposter = NULL;
+   GBitmap* imposterNrml = NULL;
+
+   ImposterCapture* imposterCap = new ImposterCapture();
+
+   static const MatrixF topXfm(EulerF(-M_PI_F / 2.0f, 0, 0));
+   static const MatrixF bottomXfm(EulerF(M_PI_F / 2.0f, 0, 0));
+
+   MatrixF angMat;
+
+   S32 mip = 0;
+
+   PROFILE_START(ShapeAsset_generateCachedPreviewImage);
+
+   //dMemset(destBmp.getWritableBits(mip), 0, destBmp.getWidth(mip) * destBmp.getHeight(mip) * GFXFormat_getByteSize(format));
+
+   F32 rotX = -(mDegToRad(60.0) - 0.5f * M_PI_F);
+   F32 rotZ = -(mDegToRad(45.0) - 0.5f * M_PI_F);
+
+   // We capture the images in a particular order which must
+   // match the order expected by the imposter renderer.
+
+   imposterCap->begin(shape, 0, resolution, mShape->mRadius, mShape->center);
+
+   angMat.mul(MatrixF(EulerF(rotX, 0, 0)),
+      MatrixF(EulerF(0, 0, rotZ)));
+
+   imposterCap->capture(angMat, &imposter, &imposterNrml);
+
+   imposterCap->end();
+
+   PROFILE_END(); // ShapeAsset_generateCachedPreviewImage
+
+   delete imposterCap;
+   delete shape;
+
+   String dumpPath = String(mFilePath) + "_Preview.dds";
+
+   char* returnBuffer = Con::getReturnBuffer(dumpPath.length());
+   dSprintf(returnBuffer, dumpPath.length(), "%s", dumpPath.c_str());
+
+   /*FileStream stream;
+   if (stream.open(dumpPath, Torque::FS::File::Write))
+      destBmp.writeBitmap("png", stream);
+   stream.close();*/
+   
+   DDSFile* ddsDest = DDSFile::createDDSFileFromGBitmap(imposter);
+   ImageUtil::ddsCompress(ddsDest, GFXFormatBC2);
+
+   // Finally save the imposters to disk.
+   FileStream fs;
+   if (fs.open(returnBuffer, Torque::FS::File::Write))
+   {
+      ddsDest->write(fs);
+      fs.close();
+   }
 
-   dt->update();
+   delete ddsDest;
+   delete imposter;
+   delete imposterNrml;
 
-   delete dt;
+   // If we did a begin then end it now.
+   if (!sceneBegun)
+      GFX->endScene();
 
-   return mFilePath;
+   return returnBuffer;
 }
 #endif
 
@@ -625,9 +697,12 @@ DefineEngineMethod(ShapeAsset, getStatusString, String, (), , "get status string
 
 
 #ifdef TORQUE_TOOLS
-DefineEngineMethod(ShapeAsset, generateCachedPreviewImage, const char*, (S32 resolution), (256), "")
+DefineEngineMethod(ShapeAsset, generateCachedPreviewImage, const char*, (S32 resolution, const char* overrideMaterialName), (256, ""),
+   "Generates a baked preview image of the given shapeAsset. Only really used for generating Asset Browser icons.\n"
+   "@param resolution Optional field for what resolution to bake the preview image at. Must be pow2\n"
+   "@param overrideMaterialName Optional field for overriding the material used when rendering the shape for the bake.")
 {
-   return object->generateCachedPreviewImage(resolution);
+   return object->generateCachedPreviewImage(resolution, overrideMaterialName);
 }
 
 DefineEngineStaticMethod(ShapeAsset, getAssetIdByFilename, const char*, (const char* filePath), (""),

+ 1 - 1
Engine/source/T3D/assets/ShapeAsset.h

@@ -191,7 +191,7 @@ public:
    static U32 getAssetById(StringTableEntry assetId, AssetPtr<ShapeAsset>* shapeAsset);
 
 #ifdef TORQUE_TOOLS
-   const char* generateCachedPreviewImage(S32 resolution);
+   const char* generateCachedPreviewImage(S32 resolution, String overrideMaterial = "");
 #endif
 
 protected:

+ 1 - 1
Engine/source/T3D/lighting/reflectionProbe.cpp

@@ -798,7 +798,7 @@ void ReflectionProbe::createEditorResources()
 
    mEditorShape = NULL;
 
-   String shapeFile = "tools/resources/ReflectProbeSphere.dae";
+   String shapeFile = "tools/resources/previewSphereShape.dae";
 
    // Attempt to get the resource from the ResourceManager
    mEditorShape = ResourceManager::get().load(shapeFile);

+ 5 - 11
Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.tscript

@@ -433,7 +433,7 @@ function AssetBrowser::buildMaterialAssetPreview(%this, %assetDef, %previewData)
 
    %generatePreview = false;
 
-   %previewFilePath = %previewPath @ %assetDef.assetName @ "_Preview.png";
+   %previewFilePath = %previewPath @ %assetDef.assetName @ "_Preview.dds";
    if(!isFile(%previewFilePath))
    {
       %generatePreview = true;
@@ -457,17 +457,11 @@ function AssetBrowser::buildMaterialAssetPreview(%this, %assetDef, %previewData)
    
    if(isObject(%assetDef.materialDefinitionName))
    {
-      	if(isFile(%assetDef.materialDefinitionName.getDiffuseMap(0)))
-         {
-            %difMap = %assetDef.materialDefinitionName.getDiffuseMap(0);
-         }
-      	else if(%assetDef.materialDefinitionName.getDiffuseMapAsset(0) !$= "")
-      	{
-         %imgAsset = AssetDatabase.acquireAsset(%assetDef.materialDefinitionName.getDiffuseMapAsset(0));
-            %difMap = %imgAsset.getImagePath();
-   		}
+         %previewShapeDef = AssetDatabase.acquireAsset("ToolsModule:previewSphereShape");
+         %generatedFilePath = %previewShapeDef.generateCachedPreviewImage(256, %assetDef.materialDefinitionName);
       
-         %success = saveScaledImage(%difMap, %previewFilePath);
+         pathCopy(%generatedFilePath, %previewFilePath);
+         fileDelete(%generatedFilePath);
 
          %previewAsset = new ImageAsset()
          {

+ 3 - 13
Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.tscript

@@ -258,7 +258,7 @@ function AssetBrowser::buildShapeAssetPreview(%this, %assetDef, %previewData)
    
    %generatePreview = false;
    
-   %previewFilePath = %previewPath @ %assetDef.assetName @ "_Preview.png";
+   %previewFilePath = %previewPath @ %assetDef.assetName @ "_Preview.dds";
    if(!isFile(%previewFilePath) || (compareFileTimes(%assetDef.getShapeFile(), %previewFilePath) == 1))
    {
       %generatePreview = true;
@@ -272,21 +272,11 @@ function AssetBrowser::buildShapeAssetPreview(%this, %assetDef, %previewData)
       
       //This is slightly hacky, but we're going to utilize the imposter/last detail system
       //to generate our previews for us and then clean up the unneeded bits
-      %oldImposterSetting = $TSLastDetail::dumpImposters;
-      $TSLastDetail::dumpImposters = true;
       
       %filePath = %assetDef.generateCachedPreviewImage();
       
-      %imposterPath = %filePath @ ".imposter.png";
-      pathCopy(%imposterPath, %previewFilePath);
-      
-      //cleanup
-      fileDelete(%imposterPath);
-      fileDelete(%filePath @ ".imposter.dds");
-      fileDelete(%filePath @ ".imposter_normals.png");
-      fileDelete(%filePath @ ".imposter_normals.dds");
-      
-      $TSLastDetail::dumpImposters = %oldImposterSetting;
+      pathCopy(%filePath, %previewFilePath);
+      fileDelete(%filePath); //cleanup
       
       %previewAsset = new ImageAsset()
       {

+ 0 - 6
Templates/BaseGame/game/tools/resources/ReflectProbeSphere.asset.taml

@@ -1,6 +0,0 @@
-<ShapeAsset
-    canSave="true"
-    canSaveDynamicFields="true"
-    AssetName="ReflectProbeSphere"
-    fileName="@assetFile=ReflectProbeSphere.dae"
-    constuctorFileName="@assetFile=ReflectProbeSphere.tscript" />

File diff suppressed because it is too large
+ 0 - 61
Templates/BaseGame/game/tools/resources/ReflectProbeSphere.dae


+ 0 - 11
Templates/BaseGame/game/tools/resources/ReflectProbeSphere.tscript

@@ -1,11 +0,0 @@
-
-singleton TSShapeConstructor(ReflectProbeSpheredae)
-{
-   baseShapeAsset = "ToolsModule:ReflectProbeSphere";
-   singleDetailSize = "0";
-   flipUVCoords = "0";
-   JoinIdenticalVerts = "0";
-   reverseWindingOrder = "0";
-   removeRedundantMats = "0";
-   animFPS = "2";
-};

+ 6 - 0
Templates/BaseGame/game/tools/resources/previewSphereShape.asset.taml

@@ -0,0 +1,6 @@
+<ShapeAsset
+    canSave="true"
+    canSaveDynamicFields="true"
+    AssetName="previewSphereShape"
+    fileName="@assetFile=previewSphereShape.dae"
+    constuctorFileName="@assetFile=previewSphereShape.tscript" />

File diff suppressed because it is too large
+ 41 - 0
Templates/BaseGame/game/tools/resources/previewSphereShape.dae


Some files were not shown because too many files changed in this diff