renderObjectExample.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "T3D/examples/renderObjectExample.h"
  23. #include "math/mathIO.h"
  24. #include "scene/sceneRenderState.h"
  25. #include "core/stream/bitStream.h"
  26. #include "materials/sceneData.h"
  27. #include "gfx/gfxDebugEvent.h"
  28. #include "gfx/gfxTransformSaver.h"
  29. #include "renderInstance/renderPassManager.h"
  30. IMPLEMENT_CO_NETOBJECT_V1(RenderObjectExample);
  31. ConsoleDocClass( RenderObjectExample,
  32. "@brief An example scene object which renders using a callback.\n\n"
  33. "This class implements a basic SceneObject that can exist in the world at a "
  34. "3D position and render itself. Note that RenderObjectExample handles its own "
  35. "rendering by submitting itself as an ObjectRenderInst (see "
  36. "renderInstance\renderPassmanager.h) along with a delegate for its render() "
  37. "function. However, the preffered rendering method in the engine is to submit "
  38. "a MeshRenderInst along with a Material, vertex buffer, primitive buffer, and "
  39. "transform and allow the RenderMeshMgr handle the actual rendering. You can "
  40. "see this implemented in RenderMeshExample.\n\n"
  41. "See the C++ code for implementation details.\n\n"
  42. "@ingroup Examples\n" );
  43. //-----------------------------------------------------------------------------
  44. // Object setup and teardown
  45. //-----------------------------------------------------------------------------
  46. RenderObjectExample::RenderObjectExample()
  47. {
  48. // Flag this object so that it will always
  49. // be sent across the network to clients
  50. mNetFlags.set( Ghostable | ScopeAlways );
  51. // Set it as a "static" object
  52. mTypeMask |= StaticObjectType | StaticShapeObjectType;
  53. }
  54. RenderObjectExample::~RenderObjectExample()
  55. {
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Object Editing
  59. //-----------------------------------------------------------------------------
  60. void RenderObjectExample::initPersistFields()
  61. {
  62. // SceneObject already handles exposing the transform
  63. Parent::initPersistFields();
  64. }
  65. bool RenderObjectExample::onAdd()
  66. {
  67. if ( !Parent::onAdd() )
  68. return false;
  69. // Set up a 1x1x1 bounding box
  70. mObjBox.set( Point3F( -0.5f, -0.5f, -0.5f ),
  71. Point3F( 0.5f, 0.5f, 0.5f ) );
  72. resetWorldBox();
  73. // Add this object to the scene
  74. addToScene();
  75. return true;
  76. }
  77. void RenderObjectExample::onRemove()
  78. {
  79. // Remove this object from the scene
  80. removeFromScene();
  81. Parent::onRemove();
  82. }
  83. void RenderObjectExample::setTransform(const MatrixF & mat)
  84. {
  85. // Let SceneObject handle all of the matrix manipulation
  86. Parent::setTransform( mat );
  87. // Dirty our network mask so that the new transform gets
  88. // transmitted to the client object
  89. setMaskBits( TransformMask );
  90. }
  91. U32 RenderObjectExample::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
  92. {
  93. // Allow the Parent to get a crack at writing its info
  94. U32 retMask = Parent::packUpdate( conn, mask, stream );
  95. // Write our transform information
  96. if ( stream->writeFlag( mask & TransformMask ) )
  97. {
  98. mathWrite(*stream, getTransform());
  99. mathWrite(*stream, getScale());
  100. }
  101. return retMask;
  102. }
  103. void RenderObjectExample::unpackUpdate(NetConnection *conn, BitStream *stream)
  104. {
  105. // Let the Parent read any info it sent
  106. Parent::unpackUpdate(conn, stream);
  107. if ( stream->readFlag() ) // TransformMask
  108. {
  109. mathRead(*stream, &mObjToWorld);
  110. mathRead(*stream, &mObjScale);
  111. setTransform( mObjToWorld );
  112. }
  113. }
  114. //-----------------------------------------------------------------------------
  115. // Object Rendering
  116. //-----------------------------------------------------------------------------
  117. void RenderObjectExample::createGeometry()
  118. {
  119. static const Point3F cubePoints[8] =
  120. {
  121. Point3F( 1.0f, -1.0f, -1.0f), Point3F( 1.0f, -1.0f, 1.0f),
  122. Point3F( 1.0f, 1.0f, -1.0f), Point3F( 1.0f, 1.0f, 1.0f),
  123. Point3F(-1.0f, -1.0f, -1.0f), Point3F(-1.0f, 1.0f, -1.0f),
  124. Point3F(-1.0f, -1.0f, 1.0f), Point3F(-1.0f, 1.0f, 1.0f)
  125. };
  126. static const Point3F cubeNormals[6] =
  127. {
  128. Point3F( 1.0f, 0.0f, 0.0f), Point3F(-1.0f, 0.0f, 0.0f),
  129. Point3F( 0.0f, 1.0f, 0.0f), Point3F( 0.0f, -1.0f, 0.0f),
  130. Point3F( 0.0f, 0.0f, 1.0f), Point3F( 0.0f, 0.0f, -1.0f)
  131. };
  132. static const ColorI cubeColors[3] =
  133. {
  134. ColorI( 255, 0, 0, 255 ),
  135. ColorI( 0, 255, 0, 255 ),
  136. ColorI( 0, 0, 255, 255 )
  137. };
  138. static const U32 cubeFaces[36][3] =
  139. {
  140. { 3, 0, 0 }, { 0, 0, 0 }, { 1, 0, 0 },
  141. { 2, 0, 0 }, { 0, 0, 0 }, { 3, 0, 0 },
  142. { 7, 1, 0 }, { 4, 1, 0 }, { 5, 1, 0 },
  143. { 6, 1, 0 }, { 4, 1, 0 }, { 7, 1, 0 },
  144. { 3, 2, 1 }, { 5, 2, 1 }, { 2, 2, 1 },
  145. { 7, 2, 1 }, { 5, 2, 1 }, { 3, 2, 1 },
  146. { 1, 3, 1 }, { 4, 3, 1 }, { 6, 3, 1 },
  147. { 0, 3, 1 }, { 4, 3, 1 }, { 1, 3, 1 },
  148. { 3, 4, 2 }, { 6, 4, 2 }, { 7, 4, 2 },
  149. { 1, 4, 2 }, { 6, 4, 2 }, { 3, 4, 2 },
  150. { 2, 5, 2 }, { 4, 5, 2 }, { 0, 5, 2 },
  151. { 5, 5, 2 }, { 4, 5, 2 }, { 2, 5, 2 }
  152. };
  153. // Fill the vertex buffer
  154. VertexType *pVert = NULL;
  155. mVertexBuffer.set( GFX, 36, GFXBufferTypeStatic );
  156. pVert = mVertexBuffer.lock();
  157. Point3F halfSize = getObjBox().getExtents() * 0.5f;
  158. for (U32 i = 0; i < 36; i++)
  159. {
  160. const U32& vdx = cubeFaces[i][0];
  161. const U32& ndx = cubeFaces[i][1];
  162. const U32& cdx = cubeFaces[i][2];
  163. pVert[i].point = cubePoints[vdx] * halfSize;
  164. pVert[i].normal = cubeNormals[ndx];
  165. pVert[i].color = cubeColors[cdx];
  166. }
  167. mVertexBuffer.unlock();
  168. // Set up our normal and reflection StateBlocks
  169. GFXStateBlockDesc desc;
  170. // The normal StateBlock only needs a default StateBlock
  171. mNormalSB = GFX->createStateBlock( desc );
  172. // The reflection needs its culling reversed
  173. desc.cullDefined = true;
  174. desc.cullMode = GFXCullCW;
  175. mReflectSB = GFX->createStateBlock( desc );
  176. }
  177. void RenderObjectExample::prepRenderImage( SceneRenderState *state )
  178. {
  179. // Do a little prep work if needed
  180. if ( mVertexBuffer.isNull() )
  181. createGeometry();
  182. // Allocate an ObjectRenderInst so that we can submit it to the RenderPassManager
  183. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  184. // Now bind our rendering function so that it will get called
  185. ri->renderDelegate.bind( this, &RenderObjectExample::render );
  186. // Set our RenderInst as a standard object render
  187. ri->type = RenderPassManager::RIT_Object;
  188. // Set our sorting keys to a default value
  189. ri->defaultKey = 0;
  190. ri->defaultKey2 = 0;
  191. // Submit our RenderInst to the RenderPassManager
  192. state->getRenderPass()->addInst( ri );
  193. }
  194. void RenderObjectExample::render( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
  195. {
  196. if ( overrideMat )
  197. return;
  198. if ( mVertexBuffer.isNull() )
  199. return;
  200. PROFILE_SCOPE(RenderObjectExample_Render);
  201. // Set up a GFX debug event (this helps with debugging rendering events in external tools)
  202. GFXDEBUGEVENT_SCOPE( RenderObjectExample_Render, ColorI::RED );
  203. // GFXTransformSaver is a handy helper class that restores
  204. // the current GFX matrices to their original values when
  205. // it goes out of scope at the end of the function
  206. GFXTransformSaver saver;
  207. // Calculate our object to world transform matrix
  208. MatrixF objectToWorld = getRenderTransform();
  209. objectToWorld.scale( getScale() );
  210. // Apply our object transform
  211. GFX->multWorld( objectToWorld );
  212. // Deal with reflect pass otherwise
  213. // set the normal StateBlock
  214. if ( state->isReflectPass() )
  215. GFX->setStateBlock( mReflectSB );
  216. else
  217. GFX->setStateBlock( mNormalSB );
  218. // Set up the "generic" shaders
  219. // These handle rendering on GFX layers that don't support
  220. // fixed function. Otherwise they disable shaders.
  221. GFX->setupGenericShaders( GFXDevice::GSModColorTexture );
  222. // Set the vertex buffer
  223. GFX->setVertexBuffer( mVertexBuffer );
  224. // Draw our triangles
  225. GFX->drawPrimitive( GFXTriangleList, 0, 12 );
  226. }