mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
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:
parent
d9bedbe31c
commit
b70faae38f
|
|
@ -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), (""),
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -1,11 +0,0 @@
|
|||
|
||||
singleton TSShapeConstructor(ReflectProbeSpheredae)
|
||||
{
|
||||
baseShapeAsset = "ToolsModule:ReflectProbeSphere";
|
||||
singleDetailSize = "0";
|
||||
flipUVCoords = "0";
|
||||
JoinIdenticalVerts = "0";
|
||||
reverseWindingOrder = "0";
|
||||
removeRedundantMats = "0";
|
||||
animFPS = "2";
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<ShapeAsset
|
||||
canSave="true"
|
||||
canSaveDynamicFields="true"
|
||||
AssetName="previewSphereShape"
|
||||
fileName="@assetFile=previewSphereShape.dae"
|
||||
constuctorFileName="@assetFile=previewSphereShape.tscript" />
|
||||
101
Templates/BaseGame/game/tools/resources/previewSphereShape.dae
Normal file
101
Templates/BaseGame/game/tools/resources/previewSphereShape.dae
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue