Torque3D/Engine/source/T3D/examples/renderShapeExample.cpp
JeffR 976c0bca79 Fixed uninitialized values for renderMeshExample and renderShapeExample which would cause a crash on creation
Added utility method to prefab to be able to get the internal simGroup that contains it's children
Adjusted logic for mounting items in GuiShapeEdPreview to utilize assetIds for the shapes
Moved the Asset and AssetBrowser editor settings populate functions to the AssetBrowser script to better organize things
Fixed command usage for General, Player and Observer spawn point creator entries to use the correct callback commands
Fixed logic for creator callback commands that don't just route through the class name based structure
Added RMB context menu actions for opening asset file or folder locations in OS file explorer
Fixed lookup of animation assets when editing a shape's animations in the shape editor so it provides the assetId of the anim if it exists
Fixes handling of mounting in the shape editor so it utilizes assets and the asset browser like everything else
2022-04-06 01:08:20 -05:00

263 lines
7.9 KiB
C++

//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "T3D/examples/renderShapeExample.h"
#include "math/mathIO.h"
#include "sim/netConnection.h"
#include "scene/sceneRenderState.h"
#include "console/consoleTypes.h"
#include "core/resourceManager.h"
#include "core/stream/bitStream.h"
#include "gfx/gfxTransformSaver.h"
#include "renderInstance/renderPassManager.h"
#include "lighting/lightQuery.h"
IMPLEMENT_CO_NETOBJECT_V1(RenderShapeExample);
ConsoleDocClass( RenderShapeExample,
"@brief An example scene object which renders a DTS.\n\n"
"This class implements a basic SceneObject that can exist in the world at a "
"3D position and render itself. There are several valid ways to render an "
"object in Torque. This class makes use of the 'TS' (three space) shape "
"system. TS manages loading the various mesh formats supported by Torque as "
"well was rendering those meshes (including LOD and animation...though this "
"example doesn't include any animation over time).\n\n"
"See the C++ code for implementation details.\n\n"
"@ingroup Examples\n" );
//-----------------------------------------------------------------------------
// Object setup and teardown
//-----------------------------------------------------------------------------
RenderShapeExample::RenderShapeExample()
{
// Flag this object so that it will always
// be sent across the network to clients
mNetFlags.set( Ghostable | ScopeAlways );
// Set it as a "static" object.
mTypeMask |= StaticObjectType | StaticShapeObjectType;
// Make sure to initialize our TSShapeInstance to NULL
INIT_ASSET(Shape);
mShapeInstance = NULL;
}
RenderShapeExample::~RenderShapeExample()
{
}
//-----------------------------------------------------------------------------
// Object Editing
//-----------------------------------------------------------------------------
void RenderShapeExample::initPersistFields()
{
addGroup( "Rendering" );
INITPERSISTFIELD_SHAPEASSET(Shape, RenderShapeExample, "The path to the shape file.")
endGroup( "Rendering" );
// SceneObject already handles exposing the transform
Parent::initPersistFields();
}
void RenderShapeExample::inspectPostApply()
{
Parent::inspectPostApply();
// Flag the network mask to send the updates
// to the client object
setMaskBits( UpdateMask );
}
bool RenderShapeExample::onAdd()
{
if ( !Parent::onAdd() )
return false;
// Set up a 1x1x1 bounding box
mObjBox.set( Point3F( -0.5f, -0.5f, -0.5f ),
Point3F( 0.5f, 0.5f, 0.5f ) );
resetWorldBox();
// Add this object to the scene
addToScene();
// Setup the shape.
createShape();
return true;
}
void RenderShapeExample::onRemove()
{
// Remove this object from the scene
removeFromScene();
// Remove our TSShapeInstance
if ( mShapeInstance )
SAFE_DELETE( mShapeInstance );
Parent::onRemove();
}
void RenderShapeExample::setTransform(const MatrixF & mat)
{
// Let SceneObject handle all of the matrix manipulation
Parent::setTransform( mat );
// Dirty our network mask so that the new transform gets
// transmitted to the client object
setMaskBits( TransformMask );
}
U32 RenderShapeExample::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
{
// Allow the Parent to get a crack at writing its info
U32 retMask = Parent::packUpdate( conn, mask, stream );
// Write our transform information
if ( stream->writeFlag( mask & TransformMask ) )
{
mathWrite(*stream, getTransform());
mathWrite(*stream, getScale());
}
// Write out any of the updated editable properties
if ( stream->writeFlag( mask & UpdateMask ) )
{
PACK_ASSET(conn, Shape);
// Allow the server object a chance to handle a new shape
createShape();
}
return retMask;
}
void RenderShapeExample::unpackUpdate(NetConnection *conn, BitStream *stream)
{
// Let the Parent read any info it sent
Parent::unpackUpdate(conn, stream);
if ( stream->readFlag() ) // TransformMask
{
mathRead(*stream, &mObjToWorld);
mathRead(*stream, &mObjScale);
setTransform( mObjToWorld );
}
if ( stream->readFlag() ) // UpdateMask
{
UNPACK_ASSET(conn, Shape);
if ( isProperlyAdded() )
createShape();
}
}
//-----------------------------------------------------------------------------
// Object Rendering
//-----------------------------------------------------------------------------
void RenderShapeExample::createShape()
{
if ( getShape() == StringTable->EmptyString() )
return;
// If this is the same shape then no reason to update it
if ( mShapeInstance && getShape() == StringTable->insert(mShape.getPath().getFullPath().c_str()) )
return;
// Clean up our previous shape
if ( mShapeInstance )
SAFE_DELETE( mShapeInstance );
// Attempt to preload the Materials for this shape
if ( isClientObject() &&
!mShape->preloadMaterialList( mShape.getPath() ) &&
NetConnection::filesWereDownloaded() )
{
return;
}
// Update the bounding box
mObjBox = mShape->mBounds;
resetWorldBox();
setRenderTransform(mObjToWorld);
// Create the TSShapeInstance
mShapeInstance = new TSShapeInstance( mShape, isClientObject() );
}
void RenderShapeExample::prepRenderImage( SceneRenderState *state )
{
// Make sure we have a TSShapeInstance
if ( !mShapeInstance )
return;
// Calculate the distance of this object from the camera
Point3F cameraOffset;
getRenderTransform().getColumn( 3, &cameraOffset );
cameraOffset -= state->getDiffuseCameraPosition();
F32 dist = cameraOffset.len();
if ( dist < 0.01f )
dist = 0.01f;
// Set up the LOD for the shape
F32 invScale = ( 1.0f / getMax( getMax( mObjScale.x, mObjScale.y ), mObjScale.z ) );
mShapeInstance->setDetailFromDistance( state, dist * invScale );
// Make sure we have a valid level of detail
if ( mShapeInstance->getCurrentDetail() < 0 )
return;
// GFXTransformSaver is a handy helper class that restores
// the current GFX matrices to their original values when
// it goes out of scope at the end of the function
GFXTransformSaver saver;
// Set up our TS render state
TSRenderState rdata;
rdata.setSceneState( state );
rdata.setFadeOverride( 1.0f );
// We might have some forward lit materials
// so pass down a query to gather lights.
LightQuery query;
query.init( getWorldSphere() );
rdata.setLightQuery( &query );
// Set the world matrix to the objects render transform
MatrixF mat = getRenderTransform();
mat.scale( mObjScale );
GFX->setWorldMatrix( mat );
// Animate the the shape
mShapeInstance->animate();
// Allow the shape to submit the RenderInst(s) for itself
mShapeInstance->render( rdata );
}