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
This commit is contained in:
JeffR 2021-12-24 17:26:45 -06:00
parent d9bedbe31c
commit b70faae38f
10 changed files with 206 additions and 172 deletions

View file

@ -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();
dt->update();
// We need to create our own instance to render with.
TSShapeInstance* shape = new TSShapeInstance(mShape, true);
delete dt;
if(overrideMaterial.isNotEmpty())
shape->reSkin(overrideMaterial, mShape->materialList->getMaterialName(0));
return mFilePath;
// 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();
}
delete ddsDest;
delete imposter;
delete imposterNrml;
// If we did a begin then end it now.
if (!sceneBegun)
GFX->endScene();
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), (""),

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because one or more lines are too long

View file

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

View file

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

File diff suppressed because one or more lines are too long