scenePolyhedralObject.impl.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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 "platform/platform.h"
  23. #include "scene/mixin/scenePolyhedralObject.h"
  24. #include "console/consoleTypes.h"
  25. #include "gfx/gfxDrawUtil.h"
  26. #include "gfx/gfxTransformSaver.h"
  27. #include "core/stream/bitStream.h"
  28. #include "math/mathIO.h"
  29. #if 0 // Enable when enabling debug rendering below.
  30. #include "scene/sceneRenderState.h"
  31. #include "gfx/sim/debugDraw.h"
  32. #endif
  33. //-----------------------------------------------------------------------------
  34. template< typename Base, typename P >
  35. void ScenePolyhedralObject< Base, P >::initPersistFields()
  36. {
  37. Parent::addGroup( "Internal" );
  38. Parent::addProtectedField( "plane", TypeRealString, NULL,
  39. &_setPlane, &defaultProtectedGetFn,
  40. "For internal use only.",
  41. AbstractClassRep::FIELD_HideInInspectors );
  42. Parent::addProtectedField( "point", TypeRealString, NULL,
  43. &_setPoint, &defaultProtectedGetFn,
  44. "For internal use only.",
  45. AbstractClassRep::FIELD_HideInInspectors );
  46. Parent::addProtectedField( "edge", TypeRealString, NULL,
  47. &_setEdge, &defaultProtectedGetFn,
  48. "For internal use only.",
  49. AbstractClassRep::FIELD_HideInInspectors );
  50. Parent::endGroup( "Internal" );
  51. Parent::initPersistFields();
  52. }
  53. //-----------------------------------------------------------------------------
  54. template< typename Base, typename P >
  55. bool ScenePolyhedralObject< Base, P >::onAdd()
  56. {
  57. // If no polyhedron has been initialized for the zone, default
  58. // to object box. Do this before calling the parent's onAdd()
  59. // so that we set the object box correctly.
  60. if( mPolyhedron.getNumPlanes() == 0 )
  61. {
  62. mPolyhedron.buildBox( MatrixF::Identity, this->getObjBox() );
  63. mIsBox = true;
  64. }
  65. else
  66. {
  67. mIsBox = false;
  68. // Compute object-space bounds from polyhedron.
  69. this->mObjBox = mPolyhedron.getBounds();
  70. }
  71. if( !Parent::onAdd() )
  72. return false;
  73. return true;
  74. }
  75. //-----------------------------------------------------------------------------
  76. template< typename Base, typename P >
  77. bool ScenePolyhedralObject< Base, P >::containsPoint( const Point3F& point )
  78. {
  79. // If our shape is the OBB, use the default implementation
  80. // inherited from SceneObject.
  81. if( this->mIsBox )
  82. return Parent::containsPoint( point );
  83. // Take the point into our local object space.
  84. Point3F p = point;
  85. this->getWorldTransform().mulP( p );
  86. p.convolveInverse( this->getScale() );
  87. // See if the polyhedron contains the point.
  88. return mPolyhedron.isContained( p );
  89. }
  90. //-----------------------------------------------------------------------------
  91. template< typename Base, typename P >
  92. void ScenePolyhedralObject< Base, P >::_renderObject( ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* overrideMat )
  93. {
  94. if( overrideMat )
  95. return;
  96. if( this->mIsBox )
  97. Parent::_renderObject( ri, state, overrideMat );
  98. else if( !this->mEditorRenderMaterial )
  99. {
  100. GFXTransformSaver saver;
  101. MatrixF mat = this->getRenderTransform();
  102. mat.scale( this->getScale() );
  103. GFX->multWorld( mat );
  104. GFXStateBlockDesc desc;
  105. desc.setZReadWrite( true, false );
  106. desc.setBlend( true );
  107. desc.setCullMode( GFXCullNone );
  108. GFX->getDrawUtil()->drawPolyhedron( desc, mPolyhedron, this->_getDefaultEditorSolidColor() );
  109. // Render black wireframe.
  110. desc.setFillModeWireframe();
  111. GFX->getDrawUtil()->drawPolyhedron( desc, mPolyhedron, this->_getDefaultEditorWireframeColor() );
  112. }
  113. else
  114. {
  115. //TODO: render polyhedron with material
  116. }
  117. // Debug rendering.
  118. #if 0
  119. if( state->isDiffusePass() )
  120. DebugDrawer::get()->drawPolyhedronDebugInfo( mPolyhedron, this->getTransform(), this->getScale() );
  121. #endif
  122. }
  123. //-----------------------------------------------------------------------------
  124. template< typename Base, typename P >
  125. U32 ScenePolyhedralObject< Base, P >::packUpdate( NetConnection* connection, U32 mask, BitStream* stream )
  126. {
  127. U32 retMask = Parent::packUpdate( connection, mask, stream );
  128. if( stream->writeFlag( !mIsBox && ( mask & PolyMask ) ) )
  129. {
  130. // Write planes.
  131. const U32 numPlanes = mPolyhedron.getNumPlanes();
  132. const typename PolyhedronType::PlaneType* planes = mPolyhedron.getPlanes();
  133. stream->writeInt( numPlanes, 8 );
  134. for( U32 i = 0; i < numPlanes; ++ i )
  135. mathWrite( *stream, planes[ i ] );
  136. // Write points.
  137. const U32 numPoints = mPolyhedron.getNumPoints();
  138. const typename PolyhedronType::PointType* points = mPolyhedron.getPoints();
  139. stream->writeInt( numPoints, 8 );
  140. for( U32 i = 0; i < numPoints; ++ i )
  141. mathWrite( *stream, points[ i ] );
  142. // Write edges.
  143. const U32 numEdges = mPolyhedron.getNumEdges();
  144. const typename PolyhedronType::EdgeType* edges = mPolyhedron.getEdges();
  145. stream->writeInt( numEdges, 8 );
  146. for( U32 i = 0; i < numEdges; ++ i )
  147. {
  148. const typename PolyhedronType::EdgeType& edge = edges[ i ];
  149. stream->writeInt( edge.face[ 0 ], 8 );
  150. stream->writeInt( edge.face[ 1 ], 8 );
  151. stream->writeInt( edge.vertex[ 0 ], 8 );
  152. stream->writeInt( edge.vertex[ 1 ], 8 );
  153. }
  154. }
  155. return retMask;
  156. }
  157. //-----------------------------------------------------------------------------
  158. template< typename Base, typename P >
  159. void ScenePolyhedralObject< Base, P >::unpackUpdate( NetConnection* connection, BitStream* stream )
  160. {
  161. Parent::unpackUpdate( connection, stream );
  162. if( stream->readFlag() ) // PolyMask
  163. {
  164. // Read planes.
  165. const U32 numPlanes = stream->readInt( 8 );
  166. mPolyhedron.planeList.setSize( numPlanes );
  167. for( U32 i = 0; i < numPlanes; ++ i )
  168. mathRead( *stream, &mPolyhedron.planeList[ i ] );
  169. // Read points.
  170. const U32 numPoints = stream->readInt( 8 );
  171. mPolyhedron.pointList.setSize( numPoints );
  172. for( U32 i = 0; i < numPoints; ++ i )
  173. mathRead( *stream, &mPolyhedron.pointList[ i ] );
  174. // Read edges.
  175. const U32 numEdges = stream->readInt( 8 );
  176. mPolyhedron.edgeList.setSize( numEdges );
  177. for( U32 i = 0; i < numEdges; ++ i )
  178. {
  179. typename PolyhedronType::EdgeType& edge = mPolyhedron.edgeList[ i ];
  180. edge.face[ 0 ] = stream->readInt( 8 );
  181. edge.face[ 1 ] = stream->readInt( 8 );
  182. edge.vertex[ 0 ] = stream->readInt( 8 );
  183. edge.vertex[ 1 ] = stream->readInt( 8 );
  184. }
  185. }
  186. }
  187. //-----------------------------------------------------------------------------
  188. template< typename Base, typename P >
  189. bool ScenePolyhedralObject< Base, P >::writeField( StringTableEntry name, const char* value )
  190. {
  191. StringTableEntry sPlane = StringTable->insert( "plane" );
  192. StringTableEntry sPoint = StringTable->insert( "point" );
  193. StringTableEntry sEdge = StringTable->insert( "edge" );
  194. if( name == sPlane || name == sPoint || name == sEdge )
  195. return false;
  196. return Parent::writeField( name, value );
  197. }
  198. //-----------------------------------------------------------------------------
  199. template< typename Base, typename P >
  200. void ScenePolyhedralObject< Base, P >::writeFields( Stream& stream, U32 tabStop )
  201. {
  202. Parent::writeFields( stream, tabStop );
  203. // If the polyhedron is the same as our object box,
  204. // don't bother writing out the planes and points.
  205. if( mIsBox )
  206. return;
  207. stream.write( 2, "\r\n" );
  208. // Write all planes.
  209. const U32 numPlanes = mPolyhedron.getNumPlanes();
  210. for( U32 i = 0; i < numPlanes; ++ i )
  211. {
  212. const PlaneF& plane = mPolyhedron.getPlanes()[ i ];
  213. stream.writeTabs( tabStop );
  214. char buffer[ 1024 ];
  215. dSprintf( buffer, sizeof( buffer ), "plane = \"%g %g %g %g\";",
  216. plane.x, plane.y, plane.z, plane.d
  217. );
  218. stream.writeLine( reinterpret_cast< const U8* >( buffer ) );
  219. }
  220. // Write all points.
  221. const U32 numPoints = mPolyhedron.getNumPoints();
  222. for( U32 i = 0; i < numPoints; ++ i )
  223. {
  224. const Point3F& point = mPolyhedron.getPoints()[ i ];
  225. stream.writeTabs( tabStop );
  226. char buffer[ 1024 ];
  227. dSprintf( buffer, sizeof( buffer ), "point = \"%g %g %g\";",
  228. point.x, point.y, point.z
  229. );
  230. stream.writeLine( reinterpret_cast< const U8* >( buffer ) );
  231. }
  232. // Write all edges.
  233. const U32 numEdges = mPolyhedron.getNumEdges();
  234. for( U32 i = 0; i < numEdges; ++ i )
  235. {
  236. const PolyhedronData::Edge& edge = mPolyhedron.getEdges()[ i ];
  237. stream.writeTabs( tabStop );
  238. char buffer[ 1024 ];
  239. dSprintf( buffer, sizeof( buffer ), "edge = \"%i %i %i %i\";",
  240. edge.face[ 0 ], edge.face[ 1 ],
  241. edge.vertex[ 0 ], edge.vertex[ 1 ]
  242. );
  243. stream.writeLine( reinterpret_cast< const U8* >( buffer ) );
  244. }
  245. }
  246. //-----------------------------------------------------------------------------
  247. template< typename Base, typename P >
  248. bool ScenePolyhedralObject< Base, P >::_setPlane( void* object, const char* index, const char* data )
  249. {
  250. ScenePolyhedralObject* obj = reinterpret_cast< ScenePolyhedralObject* >( object );
  251. PlaneF plane;
  252. dSscanf( data, "%g %g %g %g",
  253. &plane.x,
  254. &plane.y,
  255. &plane.z,
  256. &plane.d
  257. );
  258. obj->mPolyhedron.planeList.push_back( plane );
  259. obj->setMaskBits( PolyMask );
  260. obj->mIsBox = false;
  261. return false;
  262. }
  263. //-----------------------------------------------------------------------------
  264. template< typename Base, typename P >
  265. bool ScenePolyhedralObject< Base, P >::_setPoint( void* object, const char* index, const char* data )
  266. {
  267. ScenePolyhedralObject* obj = reinterpret_cast< ScenePolyhedralObject* >( object );
  268. Point3F point;
  269. dSscanf( data, "%g %g %g %g",
  270. &point[ 0 ],
  271. &point[ 1 ],
  272. &point[ 2 ]
  273. );
  274. obj->mPolyhedron.pointList.push_back( point );
  275. obj->setMaskBits( PolyMask );
  276. obj->mIsBox = false;
  277. return false;
  278. }
  279. //-----------------------------------------------------------------------------
  280. template< typename Base, typename P >
  281. bool ScenePolyhedralObject< Base, P >::_setEdge( void* object, const char* index, const char* data )
  282. {
  283. ScenePolyhedralObject* obj = reinterpret_cast< ScenePolyhedralObject* >( object );
  284. PolyhedronData::Edge edge;
  285. dSscanf( data, "%i %i %i %i",
  286. &edge.face[ 0 ],
  287. &edge.face[ 1 ],
  288. &edge.vertex[ 0 ],
  289. &edge.vertex[ 1 ]
  290. );
  291. obj->mPolyhedron.edgeList.push_back( edge );
  292. obj->setMaskBits( PolyMask );
  293. obj->mIsBox = false;
  294. return false;
  295. }