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