Torque3D Documentation / _generateds / renderMeshExample.cpp

renderMeshExample.cpp

Engine/source/T3D/examples/renderMeshExample.cpp

More...

Public Functions

ConsoleDocClass(RenderMeshExample , "@brief An example scene object which renders <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mesh.\n\n</a>" "This class implements <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> basic <a href="/coding/class/classsceneobject/">SceneObject</a> that can exist in the world at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "3D position and <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> itself. There are several valid ways <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> an " "object in Torque. This class implements the preferred rendering method which " "is <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> submit <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/structmeshrenderinst/">MeshRenderInst</a> along with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> Material, vertex buffer, " "primitive buffer, and transform and allow the <a href="/coding/class/classrendermeshmgr/">RenderMeshMgr</a> handle the " "actual setup and rendering <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">you.\n\n</a>" "See the C++code <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> implementation <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">details.\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Examples\n</a>" )
DefineEngineMethod(RenderMeshExample , postApply , void , () , "A utility method <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> forcing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> network <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">update.\n</a>" )

Detailed Description

Public Functions

ConsoleDocClass(RenderMeshExample , "@brief An example scene object which renders <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mesh.\n\n</a>" "This class implements <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> basic <a href="/coding/class/classsceneobject/">SceneObject</a> that can exist in the world at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "3D position and <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> itself. There are several valid ways <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> an " "object in Torque. This class implements the preferred rendering method which " "is <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> submit <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/structmeshrenderinst/">MeshRenderInst</a> along with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> Material, vertex buffer, " "primitive buffer, and transform and allow the <a href="/coding/class/classrendermeshmgr/">RenderMeshMgr</a> handle the " "actual setup and rendering <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">you.\n\n</a>" "See the C++code <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> implementation <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">details.\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Examples\n</a>" )

DefineEngineMethod(RenderMeshExample , postApply , void , () , "A utility method <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> forcing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> network <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">update.\n</a>" )

IMPLEMENT_CO_NETOBJECT_V1(RenderMeshExample )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "T3D/examples/renderMeshExample.h"
 26
 27#include "math/mathIO.h"
 28#include "scene/sceneRenderState.h"
 29#include "console/consoleTypes.h"
 30#include "core/stream/bitStream.h"
 31#include "materials/materialManager.h"
 32#include "materials/baseMatInstance.h"
 33#include "renderInstance/renderPassManager.h"
 34#include "lighting/lightQuery.h"
 35#include "console/engineAPI.h"
 36
 37IMPLEMENT_CO_NETOBJECT_V1(RenderMeshExample);
 38
 39ConsoleDocClass( RenderMeshExample, 
 40   "@brief An example scene object which renders a mesh.\n\n"
 41   "This class implements a basic SceneObject that can exist in the world at a "
 42   "3D position and render itself. There are several valid ways to render an "
 43   "object in Torque. This class implements the preferred rendering method which "
 44   "is to submit a MeshRenderInst along with a Material, vertex buffer, "
 45   "primitive buffer, and transform and allow the RenderMeshMgr handle the "
 46   "actual setup and rendering for you.\n\n"
 47   "See the C++ code for implementation details.\n\n"
 48   "@ingroup Examples\n" );
 49
 50
 51//-----------------------------------------------------------------------------
 52// Object setup and teardown
 53//-----------------------------------------------------------------------------
 54RenderMeshExample::RenderMeshExample()
 55{
 56   // Flag this object so that it will always
 57   // be sent across the network to clients
 58   mNetFlags.set( Ghostable | ScopeAlways );
 59
 60   // Set it as a "static" object that casts shadows
 61   mTypeMask |= StaticObjectType | StaticShapeObjectType;
 62
 63   // Make sure we the Material instance to NULL
 64   // so we don't try to access it incorrectly
 65   mMaterialInst = NULL;
 66
 67   initMaterialAsset(Material);
 68}
 69
 70RenderMeshExample::~RenderMeshExample()
 71{
 72   if ( mMaterialInst )
 73      SAFE_DELETE( mMaterialInst );
 74}
 75
 76//-----------------------------------------------------------------------------
 77// Object Editing
 78//-----------------------------------------------------------------------------
 79void RenderMeshExample::initPersistFields()
 80{
 81   addGroup( "Rendering" );
 82   scriptBindMaterialAsset(Material, RenderMeshExample, "The material used to render the mesh.");
 83   endGroup( "Rendering" );
 84
 85   // SceneObject already handles exposing the transform
 86   Parent::initPersistFields();
 87}
 88
 89void RenderMeshExample::inspectPostApply()
 90{
 91   Parent::inspectPostApply();
 92
 93   // Flag the network mask to send the updates
 94   // to the client object
 95   setMaskBits( UpdateMask );
 96}
 97
 98bool RenderMeshExample::onAdd()
 99{
100   if ( !Parent::onAdd() )
101      return false;
102
103   // Set up a 1x1x1 bounding box
104   mObjBox.set( Point3F( -0.5f, -0.5f, -0.5f ),
105                Point3F(  0.5f,  0.5f,  0.5f ) );
106
107   resetWorldBox();
108
109   // Add this object to the scene
110   addToScene();
111
112   // Refresh this object's material (if any)
113   updateMaterial();
114
115   return true;
116}
117
118void RenderMeshExample::onRemove()
119{
120   // Remove this object from the scene
121   removeFromScene();
122
123   Parent::onRemove();
124}
125
126void RenderMeshExample::setTransform(const MatrixF & mat)
127{
128   // Let SceneObject handle all of the matrix manipulation
129   Parent::setTransform( mat );
130
131   // Dirty our network mask so that the new transform gets
132   // transmitted to the client object
133   setMaskBits( TransformMask );
134}
135
136U32 RenderMeshExample::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
137{
138   // Allow the Parent to get a crack at writing its info
139   U32 retMask = Parent::packUpdate( conn, mask, stream );
140
141   // Write our transform information
142   if ( stream->writeFlag( mask & TransformMask ) )
143   {
144      mathWrite(*stream, getTransform());
145      mathWrite(*stream, getScale());
146   }
147
148   // Write out any of the updated editable properties
149   if (stream->writeFlag(mask & UpdateMask))
150   {
151      packMaterialAsset(conn, Material);
152   }
153
154   return retMask;
155}
156
157void RenderMeshExample::unpackUpdate(NetConnection *conn, BitStream *stream)
158{
159   // Let the Parent read any info it sent
160   Parent::unpackUpdate(conn, stream);
161
162   if ( stream->readFlag() )  // TransformMask
163   {
164      mathRead(*stream, &mObjToWorld);
165      mathRead(*stream, &mObjScale);
166
167      setTransform( mObjToWorld );
168   }
169
170   if ( stream->readFlag() )  // UpdateMask
171   {
172      unpackMaterialAsset(conn, Material);
173
174      if ( isProperlyAdded() )
175         updateMaterial();
176   }
177}
178
179//-----------------------------------------------------------------------------
180// Object Rendering
181//-----------------------------------------------------------------------------
182void RenderMeshExample::createGeometry()
183{
184   static const Point3F cubePoints[8] = 
185   {
186      Point3F( 1, -1, -1), Point3F( 1, -1,  1), Point3F( 1,  1, -1), Point3F( 1,  1,  1),
187      Point3F(-1, -1, -1), Point3F(-1,  1, -1), Point3F(-1, -1,  1), Point3F(-1,  1,  1)
188   };
189
190   static const Point3F cubeNormals[6] = 
191   {
192      Point3F( 1,  0,  0), Point3F(-1,  0,  0), Point3F( 0,  1,  0),
193      Point3F( 0, -1,  0), Point3F( 0,  0,  1), Point3F( 0,  0, -1)
194   };
195
196   static const Point2F cubeTexCoords[4] = 
197   {
198      Point2F( 0,  0), Point2F( 0, -1),
199      Point2F( 1,  0), Point2F( 1, -1)
200   };
201
202   static const U32 cubeFaces[36][3] = 
203   {
204      { 3, 0, 3 }, { 0, 0, 0 }, { 1, 0, 1 },
205      { 2, 0, 2 }, { 0, 0, 0 }, { 3, 0, 3 },
206      { 7, 1, 1 }, { 4, 1, 2 }, { 5, 1, 0 },
207      { 6, 1, 3 }, { 4, 1, 2 }, { 7, 1, 1 },
208      { 3, 2, 1 }, { 5, 2, 2 }, { 2, 2, 0 },
209      { 7, 2, 3 }, { 5, 2, 2 }, { 3, 2, 1 },
210      { 1, 3, 3 }, { 4, 3, 0 }, { 6, 3, 1 },
211      { 0, 3, 2 }, { 4, 3, 0 }, { 1, 3, 3 },
212      { 3, 4, 3 }, { 6, 4, 0 }, { 7, 4, 1 },
213      { 1, 4, 2 }, { 6, 4, 0 }, { 3, 4, 3 },
214      { 2, 5, 1 }, { 4, 5, 2 }, { 0, 5, 0 },
215      { 5, 5, 3 }, { 4, 5, 2 }, { 2, 5, 1 }
216   };
217
218   // Fill the vertex buffer
219   VertexType *pVert = NULL;
220
221   mVertexBuffer.set( GFX, 36, GFXBufferTypeStatic );
222   pVert = mVertexBuffer.lock();
223
224   Point3F halfSize = getObjBox().getExtents() * 0.5f;
225
226   for (U32 i = 0; i < 36; i++)
227   {
228      const U32& vdx = cubeFaces[i][0];
229      const U32& ndx = cubeFaces[i][1];
230      const U32& tdx = cubeFaces[i][2];
231
232      pVert[i].point    = cubePoints[vdx] * halfSize;
233      pVert[i].normal   = cubeNormals[ndx];
234      pVert[i].texCoord = cubeTexCoords[tdx];
235   }
236
237   mVertexBuffer.unlock();
238
239   // Fill the primitive buffer
240   U16 *pIdx = NULL;
241
242   mPrimitiveBuffer.set( GFX, 36, 12, GFXBufferTypeStatic );
243
244   mPrimitiveBuffer.lock(&pIdx);     
245   
246   for (U16 i = 0; i < 36; i++)
247      pIdx[i] = i;
248
249   mPrimitiveBuffer.unlock();
250}
251
252void RenderMeshExample::updateMaterial()
253{
254   if (mMaterialAsset.notNull())
255   {
256      if (mMaterialInst && String(mMaterialAsset->getMaterialDefinitionName()).equal(mMaterialInst->getMaterial()->getName(), String::NoCase))
257         return;
258
259      SAFE_DELETE(mMaterialInst);
260
261      mMaterialInst = MATMGR->createMatInstance(mMaterialAsset->getMaterialDefinitionName(), getGFXVertexFormat< VertexType >());
262
263      if (!mMaterialInst)
264         Con::errorf("RenderMeshExample::updateMaterial - no Material called '%s'", mMaterialAsset->getMaterialDefinitionName());
265   }
266}
267
268void RenderMeshExample::prepRenderImage( SceneRenderState *state )
269{
270   // Do a little prep work if needed
271   if ( mVertexBuffer.isNull() )
272      createGeometry();
273
274   // If we have no material then skip out.
275   if ( !mMaterialInst || !state)
276      return;
277
278   // If we don't have a material instance after the override then 
279   // we can skip rendering all together.
280   BaseMatInstance *matInst = state->getOverrideMaterial( mMaterialInst );
281   if ( !matInst )
282      return;
283
284   // Get a handy pointer to our RenderPassmanager
285   RenderPassManager *renderPass = state->getRenderPass();
286
287   // Allocate an MeshRenderInst so that we can submit it to the RenderPassManager
288   MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();
289
290   // Set our RenderInst as a standard mesh render
291   ri->type = RenderPassManager::RIT_Mesh;
292
293   //If our material has transparency set on this will redirect it to proper render bin
294   if ( matInst->getMaterial()->isTranslucent() )
295   {
296      ri->type = RenderPassManager::RIT_Translucent;
297      ri->translucentSort = true;
298   }
299
300   // Calculate our sorting point
301   if ( state )
302   {
303      // Calculate our sort point manually.
304      const Box3F& rBox = getRenderWorldBox();
305      ri->sortDistSq = rBox.getSqDistanceToPoint( state->getCameraPosition() );      
306   } 
307   else 
308      ri->sortDistSq = 0.0f;
309
310   // Set up our transforms
311   MatrixF objectToWorld = getRenderTransform();
312   objectToWorld.scale( getScale() );
313
314   ri->objectToWorld = renderPass->allocUniqueXform( objectToWorld );
315   ri->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
316   ri->projection    = renderPass->allocSharedXform(RenderPassManager::Projection);
317
318   // If our material needs lights then fill the RIs 
319   // light vector with the best lights.
320   if ( matInst->isForwardLit() )
321   {
322      LightQuery query;
323      query.init( getWorldSphere() );
324      query.getLights( ri->lights, 8 );
325   }
326
327   // Make sure we have an up-to-date backbuffer in case
328   // our Material would like to make use of it
329   // NOTICE: SFXBB is removed and refraction is disabled!
330   //ri->backBuffTex = GFX->getSfxBackBuffer();
331
332   // Set our Material
333   ri->matInst = matInst;
334
335   // Set up our vertex buffer and primitive buffer
336   ri->vertBuff = &mVertexBuffer;
337   ri->primBuff = &mPrimitiveBuffer;
338
339   ri->prim = renderPass->allocPrim();
340   ri->prim->type = GFXTriangleList;
341   ri->prim->minIndex = 0;
342   ri->prim->startIndex = 0;
343   ri->prim->numPrimitives = 12;
344   ri->prim->startVertex = 0;
345   ri->prim->numVertices = 36;
346
347   // We sort by the material then vertex buffer
348   ri->defaultKey = matInst->getStateHint();
349   ri->defaultKey2 = (uintptr_t)ri->vertBuff; // Not 64bit safe!
350
351   // Submit our RenderInst to the RenderPassManager
352   state->getRenderPass()->addInst( ri );
353}
354
355DefineEngineMethod( RenderMeshExample, postApply, void, (),,
356   "A utility method for forcing a network update.\n")
357{
358   object->inspectPostApply();
359}
360