Torque3D/Engine/source/T3D/examples/renderShapeExample.cpp

259 lines
7.8 KiB
C++
Raw Normal View History

2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// 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
mShapeInstance = NULL;
}
RenderShapeExample::~RenderShapeExample()
{
}
//-----------------------------------------------------------------------------
// Object Editing
//-----------------------------------------------------------------------------
void RenderShapeExample::initPersistFields()
{
docsURL;
Parent::initPersistFields();
addGroup( "Shapes" );
INITPERSISTFIELD_SHAPEASSET_REFACTOR(Shape, RenderShapeExample, "The path to the shape file.")
endGroup( "Shapes" );
2012-09-19 15:15:01 +00:00
// SceneObject already handles exposing the transform
}
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_REFACTOR(conn, Shape);
2012-09-19 15:15:01 +00:00
// 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_REFACTOR(conn, Shape);
2012-09-19 15:15:01 +00:00
if ( isProperlyAdded() )
createShape();
}
}
//-----------------------------------------------------------------------------
// Object Rendering
//-----------------------------------------------------------------------------
void RenderShapeExample::createShape()
{
if ( mShapeAsset.isNull() )
2012-09-19 15:15:01 +00:00
return;
// Clean up our previous shape
if ( mShapeInstance )
SAFE_DELETE( mShapeInstance );
// Attempt to preload the Materials for this shape
if ( isClientObject() &&
!getShape()->preloadMaterialList(getShape().getPath() ) &&
2012-09-19 15:15:01 +00:00
NetConnection::filesWereDownloaded() )
{
return;
}
// Update the bounding box
mObjBox = getShape()->mBounds;
2012-09-19 15:15:01 +00:00
resetWorldBox();
setRenderTransform(mObjToWorld);
// Create the TSShapeInstance
mShapeInstance = new TSShapeInstance(getShape(), isClientObject() );
2012-09-19 15:15:01 +00:00
}
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 );
}