convexShape.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749
  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 "T3D/convexShape.h"
  24. #include "math/mathIO.h"
  25. #include "math/mathUtils.h"
  26. #include "scene/sceneRenderState.h"
  27. #include "console/consoleTypes.h"
  28. #include "core/stream/bitStream.h"
  29. #include "materials/materialManager.h"
  30. #include "lighting/lightQuery.h"
  31. #include "renderInstance/renderPassManager.h"
  32. #include "gfx/gfxTransformSaver.h"
  33. #include "gfx/primBuilder.h"
  34. #include "gfx/gfxDrawUtil.h"
  35. #include "core/bitVector.h"
  36. #include "materials/materialFeatureTypes.h"
  37. #include "materials/baseMatInstance.h"
  38. #include "collision/optimizedPolyList.h"
  39. #include "T3D/physics/physicsPlugin.h"
  40. #include "T3D/physics/physicsBody.h"
  41. #include "T3D/physics/physicsCollision.h"
  42. #include "console/engineAPI.h"
  43. IMPLEMENT_CO_NETOBJECT_V1( ConvexShape );
  44. ConsoleDocClass( ConvexShape,
  45. "@brief A renderable, collidable convex shape defined by a collection of surface planes.\n\n"
  46. "%ConvexShape is intended to be used as a temporary asset for quickly "
  47. "blocking out a scene or filling in approximate shapes to be later replaced "
  48. "with final assets. This is most easily done by using the WorldEditor's "
  49. "Sketch Tool.\n\n"
  50. "@ingroup enviroMisc"
  51. );
  52. Point3F ConvexShapeCollisionConvex::support( const VectorF &vec ) const
  53. {
  54. const Vector< Point3F > &pointList = pShape->mGeometry.points;
  55. if ( pointList.empty() )
  56. return pShape->getObjBox().getCenter();
  57. // This doesn't deal with the case that the farthest plane along vec is also
  58. // perpendicular to it, but in that case maybe it doesn't matter which point we return
  59. // anyway.
  60. F32 bestDot = mDot( pointList[0], vec );
  61. const Point3F *bestP = &pointList[0];
  62. for ( S32 i = 1; i < pointList.size(); i++ )
  63. {
  64. F32 newD = mDot( pointList[i], vec );
  65. if ( newD > bestDot )
  66. {
  67. bestDot = newD;
  68. bestP = &pointList[i];
  69. }
  70. }
  71. return *bestP;
  72. }
  73. void ConvexShapeCollisionConvex::getFeatures( const MatrixF &mat, const VectorF &n, ConvexFeature *cf )
  74. {
  75. if ( pShape->mGeometry.points.empty() )
  76. {
  77. cf->material = 0;
  78. cf->object = NULL;
  79. return;
  80. }
  81. cf->material = 0;
  82. cf->object = mObject;
  83. // Simple implementation... Add all Points, Edges and Faces.
  84. // Points...
  85. S32 firstVert = cf->mVertexList.size();
  86. const Vector< Point3F > &pointList = pShape->mGeometry.points;
  87. const U32 pointListCount = pointList.size();
  88. cf->mVertexList.increment( pointListCount );
  89. for ( S32 i = 0; i < pointListCount; i++ )
  90. mat.mulP( pointList[i], &(cf->mVertexList[ firstVert + i ]) );
  91. // Edges and Triangles for each face...
  92. const Vector< ConvexShape::Face > &faceList = pShape->mGeometry.faces;
  93. for ( S32 i = 0; i < faceList.size(); i++ )
  94. {
  95. // Add this Face's Edges.
  96. const Vector< ConvexShape::Edge > &edgeList = faceList[i].edges;
  97. const U32 edgeCount = edgeList.size();
  98. const S32 firstEdge = cf->mEdgeList.size();
  99. cf->mEdgeList.increment( edgeCount );
  100. for ( S32 j = 0; j < edgeCount; j++ )
  101. {
  102. cf->mEdgeList[ firstEdge + j ].vertex[0] = faceList[i].points[ edgeList[j].p0 ];
  103. cf->mEdgeList[ firstEdge + j ].vertex[1] = faceList[i].points[ edgeList[j].p1 ];
  104. }
  105. // Add this face's Triangles.
  106. // Note that ConvexFeature calls triangles 'faces' but a ConvexShape 'Face' is not
  107. // necessarily a single triangle.
  108. const Vector< ConvexShape::Triangle > &triangleList = faceList[i].triangles;
  109. const U32 triangleCount = triangleList.size();
  110. S32 firstTriangle = cf->mFaceList.size();
  111. cf->mFaceList.increment( triangleCount );
  112. for ( S32 j = 0; j < triangleCount; j++ )
  113. {
  114. ConvexFeature::Face &cft = cf->mFaceList[ firstTriangle + j ];
  115. cft.normal = faceList[i].normal;
  116. cft.vertex[0] = triangleList[j].p0;
  117. cft.vertex[1] = triangleList[j].p1;
  118. cft.vertex[2] = triangleList[j].p2;
  119. }
  120. }
  121. }
  122. void ConvexShapeCollisionConvex::getPolyList( AbstractPolyList* list )
  123. {
  124. SphereF sphere( Point3F::Zero, 0.0f );
  125. pShape->buildPolyList( PLC_Collision, list, Box3F::Invalid, sphere );
  126. }
  127. GFXImplementVertexFormat( ConvexVert )
  128. {
  129. addElement( "POSITION", GFXDeclType_Float3 );
  130. addElement( "COLOR", GFXDeclType_Color );
  131. addElement( "NORMAL", GFXDeclType_Float3 );
  132. addElement( "TANGENT", GFXDeclType_Float3 );
  133. addElement( "TEXCOORD", GFXDeclType_Float2, 0 );
  134. };
  135. static const U32 sgConvexFaceColorCount = 16;
  136. static const ColorI sgConvexFaceColors[ sgConvexFaceColorCount ] =
  137. {
  138. ColorI( 239, 131, 201 ),
  139. ColorI( 124, 255, 69 ),
  140. ColorI( 255, 65, 77 ),
  141. ColorI( 33, 118, 235 ),
  142. ColorI( 114, 227, 110 ),
  143. ColorI( 197, 50, 237 ),
  144. ColorI( 236, 255, 255 ),
  145. ColorI( 139, 225, 192 ),
  146. ColorI( 215, 9, 65 ),
  147. ColorI( 249, 114, 93 ),
  148. ColorI( 255, 255, 90 ),
  149. ColorI( 93, 104, 97 ),
  150. ColorI( 255, 214, 192 ),
  151. ColorI( 122, 44, 198 ),
  152. ColorI( 137, 141, 194 ),
  153. ColorI( 164, 114, 43 )
  154. };
  155. bool ConvexShape::smRenderEdges = false;
  156. bool ConvexShape::protectedSetSurface( void *object, const char *index, const char *data )
  157. {
  158. ConvexShape *shape = static_cast< ConvexShape* >( object );
  159. QuatF quat;
  160. Point3F pos;
  161. //MatrixF mat;
  162. /*
  163. dSscanf( data, "%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g",
  164. &mat[0], &mat[1], &mat[2], &mat[3],
  165. &mat[4], &mat[5], &mat[6], &mat[7],
  166. &mat[8], &mat[9], &mat[10], &mat[11],
  167. &mat[12], &mat[13], &mat[14], &mat[15] );
  168. */
  169. dSscanf( data, "%g %g %g %g %g %g %g", &quat.x, &quat.y, &quat.z, &quat.w, &pos.x, &pos.y, &pos.z );
  170. MatrixF surface;
  171. quat.setMatrix( &surface );
  172. surface.setPosition( pos );
  173. shape->mSurfaces.push_back( surface );
  174. return false;
  175. }
  176. ConvexShape::ConvexShape()
  177. : mMaterialName( "Grid512_OrangeLines_Mat" ),
  178. mMaterialInst( NULL ),
  179. mVertCount( 0 ),
  180. mPrimCount( 0 ),
  181. mPhysicsRep( NULL ),
  182. mNormalLength( 0.3f )
  183. {
  184. mNetFlags.set( Ghostable | ScopeAlways );
  185. mTypeMask |= StaticObjectType |
  186. StaticShapeObjectType;
  187. mConvexList = new Convex;
  188. }
  189. ConvexShape::~ConvexShape()
  190. {
  191. if ( mMaterialInst )
  192. SAFE_DELETE( mMaterialInst );
  193. delete mConvexList;
  194. mConvexList = NULL;
  195. }
  196. void ConvexShape::initPersistFields()
  197. {
  198. addGroup( "Rendering" );
  199. addField( "material", TypeMaterialName, Offset( mMaterialName, ConvexShape ), "Material used to render the ConvexShape surface." );
  200. endGroup( "Rendering" );
  201. addGroup( "Internal" );
  202. addProtectedField( "surface", TypeRealString, NULL, &protectedSetSurface, &defaultProtectedGetFn,
  203. "Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors );
  204. endGroup( "Internal" );
  205. Parent::initPersistFields();
  206. }
  207. void ConvexShape::inspectPostApply()
  208. {
  209. Parent::inspectPostApply();
  210. _updateGeometry( true );
  211. setMaskBits( UpdateMask );
  212. }
  213. bool ConvexShape::onAdd()
  214. {
  215. if ( !Parent::onAdd() )
  216. return false;
  217. //mObjBox.set( -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f );
  218. //resetWorldBox();
  219. // Face Order:
  220. // Top, Bottom, Front, Back, Left, Right
  221. // X Axis
  222. static const Point3F cubeTangents[6] =
  223. {
  224. Point3F( 1, 0, 0 ),
  225. Point3F(-1, 0, 0 ),
  226. Point3F( 1, 0, 0 ),
  227. Point3F(-1, 0, 0 ),
  228. Point3F( 0, 1, 0 ),
  229. Point3F( 0, -1, 0 )
  230. };
  231. // Y Axis
  232. static const Point3F cubeBinormals[6] =
  233. {
  234. Point3F( 0, 1, 0 ),
  235. Point3F( 0, 1, 0 ),
  236. Point3F( 0, 0, -1 ),
  237. Point3F( 0, 0, -1 ),
  238. Point3F( 0, 0, -1 ),
  239. Point3F( 0, 0, -1 )
  240. };
  241. // Z Axis
  242. static const Point3F cubeNormals[6] =
  243. {
  244. Point3F( 0, 0, 1),
  245. Point3F( 0, 0, -1),
  246. Point3F( 0, 1, 0),
  247. Point3F( 0, -1, 0),
  248. Point3F(-1, 0, 0),
  249. Point3F( 1, 0, 0),
  250. };
  251. if ( mSurfaces.empty() )
  252. {
  253. for ( S32 i = 0; i < 6; i++ )
  254. {
  255. mSurfaces.increment();
  256. MatrixF &surf = mSurfaces.last();
  257. surf.identity();
  258. surf.setColumn( 0, cubeTangents[i] );
  259. surf.setColumn( 1, cubeBinormals[i] );
  260. surf.setColumn( 2, cubeNormals[i] );
  261. surf.setPosition( cubeNormals[i] * 0.5f );
  262. }
  263. }
  264. if ( isClientObject() )
  265. _updateMaterial();
  266. _updateGeometry( true );
  267. addToScene();
  268. return true;
  269. }
  270. void ConvexShape::onRemove()
  271. {
  272. removeFromScene();
  273. mConvexList->nukeList();
  274. SAFE_DELETE( mPhysicsRep );
  275. Parent::onRemove();
  276. }
  277. void ConvexShape::writeFields( Stream &stream, U32 tabStop )
  278. {
  279. Parent::writeFields( stream, tabStop );
  280. // Now write all planes.
  281. stream.write(2, "\r\n");
  282. S32 count = mSurfaces.size();
  283. if ( count > smMaxSurfaces )
  284. {
  285. Con::errorf( "ConvexShape has too many surfaces to save! Truncated value %d to maximum value of %d", count, smMaxSurfaces );
  286. count = smMaxSurfaces;
  287. }
  288. for ( U32 i = 0; i < count; i++ )
  289. {
  290. const MatrixF &mat = mSurfaces[i];
  291. QuatF quat( mat );
  292. Point3F pos( mat.getPosition() );
  293. stream.writeTabs(tabStop);
  294. char buffer[1024];
  295. dMemset( buffer, 0, 1024 );
  296. dSprintf( buffer, 1024, "surface = \"%g %g %g %g %g %g %g\";",
  297. quat.x, quat.y, quat.z, quat.w, pos.x, pos.y, pos.z );
  298. stream.writeLine( (const U8*)buffer );
  299. }
  300. }
  301. bool ConvexShape::writeField( StringTableEntry fieldname, const char *value )
  302. {
  303. if ( fieldname == StringTable->insert("surface") )
  304. return false;
  305. return Parent::writeField( fieldname, value );
  306. }
  307. void ConvexShape::onScaleChanged()
  308. {
  309. if ( isProperlyAdded() )
  310. _updateCollision();
  311. }
  312. void ConvexShape::setTransform( const MatrixF &mat )
  313. {
  314. Parent::setTransform( mat );
  315. if ( mPhysicsRep )
  316. mPhysicsRep->setTransform( mat );
  317. setMaskBits( TransformMask );
  318. }
  319. U32 ConvexShape::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
  320. {
  321. U32 retMask = Parent::packUpdate( conn, mask, stream );
  322. if ( stream->writeFlag( mask & TransformMask ) )
  323. {
  324. mathWrite(*stream, getTransform());
  325. mathWrite(*stream, getScale());
  326. }
  327. if ( stream->writeFlag( mask & UpdateMask ) )
  328. {
  329. stream->write( mMaterialName );
  330. U32 surfCount = mSurfaces.size();
  331. stream->writeInt( surfCount, 32 );
  332. for ( S32 i = 0; i < surfCount; i++ )
  333. {
  334. QuatF quat( mSurfaces[i] );
  335. Point3F pos( mSurfaces[i].getPosition() );
  336. mathWrite( *stream, quat );
  337. mathWrite( *stream, pos );
  338. }
  339. }
  340. return retMask;
  341. }
  342. void ConvexShape::unpackUpdate( NetConnection *conn, BitStream *stream )
  343. {
  344. Parent::unpackUpdate( conn, stream );
  345. if ( stream->readFlag() ) // TransformMask
  346. {
  347. mathRead(*stream, &mObjToWorld);
  348. mathRead(*stream, &mObjScale);
  349. setTransform( mObjToWorld );
  350. setScale( mObjScale );
  351. }
  352. if ( stream->readFlag() ) // UpdateMask
  353. {
  354. stream->read( &mMaterialName );
  355. if ( isProperlyAdded() )
  356. _updateMaterial();
  357. mSurfaces.clear();
  358. const U32 surfCount = stream->readInt( 32 );
  359. for ( S32 i = 0; i < surfCount; i++ )
  360. {
  361. mSurfaces.increment();
  362. MatrixF &mat = mSurfaces.last();
  363. QuatF quat;
  364. Point3F pos;
  365. mathRead( *stream, &quat );
  366. mathRead( *stream, &pos );
  367. quat.setMatrix( &mat );
  368. mat.setPosition( pos );
  369. }
  370. if ( isProperlyAdded() )
  371. _updateGeometry( true );
  372. }
  373. }
  374. void ConvexShape::prepRenderImage( SceneRenderState *state )
  375. {
  376. /*
  377. if ( state->isDiffusePass() )
  378. {
  379. ObjectRenderInst *ri2 = state->getRenderPass()->allocInst<ObjectRenderInst>();
  380. ri2->renderDelegate.bind( this, &ConvexShape::_renderDebug );
  381. ri2->type = RenderPassManager::RIT_Editor;
  382. state->getRenderPass()->addInst( ri2 );
  383. }
  384. */
  385. if ( mVertexBuffer.isNull() || !state)
  386. return;
  387. // If we don't have a material instance after the override then
  388. // we can skip rendering all together.
  389. BaseMatInstance *matInst = state->getOverrideMaterial( mMaterialInst ? mMaterialInst : MATMGR->getWarningMatInstance() );
  390. if ( !matInst )
  391. return;
  392. // Get a handy pointer to our RenderPassmanager
  393. RenderPassManager *renderPass = state->getRenderPass();
  394. // Allocate an MeshRenderInst so that we can submit it to the RenderPassManager
  395. MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();
  396. // Set our RenderInst as a standard mesh render
  397. ri->type = RenderPassManager::RIT_Mesh;
  398. // Calculate our sorting point
  399. if ( state )
  400. {
  401. // Calculate our sort point manually.
  402. const Box3F& rBox = getRenderWorldBox();
  403. ri->sortDistSq = rBox.getSqDistanceToPoint( state->getCameraPosition() );
  404. }
  405. else
  406. ri->sortDistSq = 0.0f;
  407. // Set up our transforms
  408. MatrixF objectToWorld = getRenderTransform();
  409. objectToWorld.scale( getScale() );
  410. ri->objectToWorld = renderPass->allocUniqueXform( objectToWorld );
  411. ri->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
  412. ri->projection = renderPass->allocSharedXform(RenderPassManager::Projection);
  413. // If we need lights then set them up.
  414. if ( matInst->isForwardLit() )
  415. {
  416. LightQuery query;
  417. query.init( getWorldSphere() );
  418. query.getLights( ri->lights, 8 );
  419. }
  420. // Make sure we have an up-to-date backbuffer in case
  421. // our Material would like to make use of it
  422. // NOTICE: SFXBB is removed and refraction is disabled!
  423. //ri->backBuffTex = GFX->getSfxBackBuffer();
  424. // Set our Material
  425. ri->matInst = matInst;
  426. if ( matInst->getMaterial()->isTranslucent() )
  427. {
  428. ri->translucentSort = true;
  429. ri->type = RenderPassManager::RIT_Translucent;
  430. }
  431. // Set up our vertex buffer and primitive buffer
  432. ri->vertBuff = &mVertexBuffer;
  433. ri->primBuff = &mPrimitiveBuffer;
  434. ri->prim = renderPass->allocPrim();
  435. ri->prim->type = GFXTriangleList;
  436. ri->prim->minIndex = 0;
  437. ri->prim->startIndex = 0;
  438. ri->prim->numPrimitives = mPrimCount;
  439. ri->prim->startVertex = 0;
  440. ri->prim->numVertices = mVertCount;
  441. // We sort by the material then vertex buffer.
  442. ri->defaultKey = matInst->getStateHint();
  443. ri->defaultKey2 = (uintptr_t)ri->vertBuff; // Not 64bit safe!
  444. // Submit our RenderInst to the RenderPassManager
  445. state->getRenderPass()->addInst( ri );
  446. }
  447. void ConvexShape::buildConvex( const Box3F &box, Convex *convex )
  448. {
  449. if ( mGeometry.faces.empty() )
  450. return;
  451. mConvexList->collectGarbage();
  452. Box3F realBox = box;
  453. mWorldToObj.mul( realBox );
  454. realBox.minExtents.convolveInverse( mObjScale );
  455. realBox.maxExtents.convolveInverse( mObjScale );
  456. if ( realBox.isOverlapped( getObjBox() ) == false )
  457. return;
  458. // See if this convex exists in the working set already...
  459. Convex *cc = 0;
  460. CollisionWorkingList &wl = convex->getWorkingList();
  461. for ( CollisionWorkingList* itr = wl.wLink.mNext; itr != &wl; itr = itr->wLink.mNext )
  462. {
  463. if ( itr->mConvex->getType() == ConvexShapeCollisionConvexType )
  464. {
  465. ConvexShapeCollisionConvex *pConvex = static_cast<ConvexShapeCollisionConvex*>(itr->mConvex);
  466. if ( pConvex->pShape == this )
  467. {
  468. cc = itr->mConvex;
  469. return;
  470. }
  471. }
  472. }
  473. // Set up the convex...
  474. ConvexShapeCollisionConvex *cp = new ConvexShapeCollisionConvex();
  475. mConvexList->registerObject( cp );
  476. convex->addToWorkingList( cp );
  477. cp->mObject = this;
  478. cp->pShape = this;
  479. }
  480. bool ConvexShape::buildPolyList( PolyListContext context, AbstractPolyList *plist, const Box3F &box, const SphereF &sphere )
  481. {
  482. if ( mGeometry.points.empty() )
  483. return false;
  484. // If we're exporting deal with that first.
  485. if ( context == PLC_Export )
  486. {
  487. AssertFatal( dynamic_cast<OptimizedPolyList*>( plist ), "ConvexShape::buildPolyList - Bad polylist for export!" );
  488. _export( (OptimizedPolyList*)plist, box, sphere );
  489. return true;
  490. }
  491. plist->setTransform( &mObjToWorld, mObjScale );
  492. plist->setObject( this );
  493. // Add points...
  494. const Vector< Point3F > pointList = mGeometry.points;
  495. S32 base = plist->addPoint( pointList[0] );
  496. for ( S32 i = 1; i < pointList.size(); i++ )
  497. plist->addPoint( pointList[i] );
  498. // Add Surfaces...
  499. const Vector< ConvexShape::Face > faceList = mGeometry.faces;
  500. if(context == PLC_Navigation)
  501. {
  502. for(S32 i = 0; i < faceList.size(); i++)
  503. {
  504. const ConvexShape::Face &face = faceList[i];
  505. S32 s = face.triangles.size();
  506. for(S32 j = 0; j < s; j++)
  507. {
  508. plist->begin(0, s*i + j);
  509. plist->plane(PlaneF(face.centroid, face.normal));
  510. plist->vertex(base + face.points[face.triangles[j].p0]);
  511. plist->vertex(base + face.points[face.triangles[j].p1]);
  512. plist->vertex(base + face.points[face.triangles[j].p2]);
  513. plist->end();
  514. }
  515. }
  516. return true;
  517. }
  518. for ( S32 i = 0; i < faceList.size(); i++ )
  519. {
  520. const ConvexShape::Face &face = faceList[i];
  521. plist->begin( 0, i );
  522. plist->plane( PlaneF( face.centroid, face.normal ) );
  523. for ( S32 j = 0; j < face.triangles.size(); j++ )
  524. {
  525. plist->vertex( base + face.points[ face.triangles[j].p0 ] );
  526. plist->vertex( base + face.points[ face.triangles[j].p1 ] );
  527. plist->vertex( base + face.points[ face.triangles[j].p2 ] );
  528. }
  529. plist->end();
  530. }
  531. return true;
  532. }
  533. void ConvexShape::_export( OptimizedPolyList *plist, const Box3F &box, const SphereF &sphere )
  534. {
  535. BaseMatInstance *matInst = mMaterialInst;
  536. if ( isServerObject() && getClientObject() )
  537. matInst = dynamic_cast<ConvexShape*>(getClientObject())->mMaterialInst;
  538. MatrixF saveMat;
  539. Point3F saveScale;
  540. plist->getTransform( &saveMat, &saveScale );
  541. plist->setTransform( &mObjToWorld, mObjScale );
  542. plist->setObject( this );
  543. const Vector< ConvexShape::Face > faceList = mGeometry.faces;
  544. const Vector< Point3F > &pointList = mGeometry.points;
  545. for ( S32 i = 0; i < faceList.size(); i++ )
  546. {
  547. const ConvexShape::Face &face = faceList[i];
  548. plist->begin( matInst, i, OptimizedPolyList::TriangleList );
  549. plist->plane( PlaneF( face.centroid, face.normal ) );
  550. for ( S32 j = 0; j < face.triangles.size(); j++ )
  551. {
  552. for ( S32 k = 0; k < 3; k++ )
  553. {
  554. U32 vertId = face.triangles[j][k];
  555. plist->vertex( pointList[ face.points[ vertId ] ], face.normal, face.texcoords[ vertId ] );
  556. }
  557. }
  558. plist->end();
  559. }
  560. plist->setTransform( &saveMat, saveScale );
  561. }
  562. bool ConvexShape::castRay( const Point3F &start, const Point3F &end, RayInfo *info )
  563. {
  564. if ( mPlanes.empty() )
  565. return false;
  566. const Vector< PlaneF > &planeList = mPlanes;
  567. const U32 planeCount = planeList.size();
  568. F32 t;
  569. F32 tmin = F32_MAX;
  570. S32 hitFace = -1;
  571. Point3F hitPnt, pnt;
  572. VectorF rayDir( end - start );
  573. rayDir.normalizeSafe();
  574. if ( false )
  575. {
  576. PlaneF plane( Point3F(0,0,0), Point3F(0,0,1) );
  577. Point3F sp( 0,0,-1 );
  578. Point3F ep( 0,0,1 );
  579. F32 t = plane.intersect( sp, ep );
  580. Point3F hitPnt;
  581. hitPnt.interpolate( sp, ep, t );
  582. }
  583. for ( S32 i = 0; i < planeCount; i++ )
  584. {
  585. // Don't hit the back-side of planes.
  586. if ( mDot( rayDir, planeList[i] ) >= 0.0f )
  587. continue;
  588. t = planeList[i].intersect( start, end );
  589. if ( t >= 0.0f && t <= 1.0f && t < tmin )
  590. {
  591. pnt.interpolate( start, end, t );
  592. S32 j = 0;
  593. for ( ; j < planeCount; j++ )
  594. {
  595. if ( i == j )
  596. continue;
  597. F32 dist = planeList[j].distToPlane( pnt );
  598. if ( dist > 1.0e-004f )
  599. break;
  600. }
  601. if ( j == planeCount )
  602. {
  603. tmin = t;
  604. hitFace = i;
  605. }
  606. }
  607. }
  608. if ( hitFace == -1 )
  609. return false;
  610. info->face = hitFace;
  611. info->material = mMaterialInst;
  612. info->normal = planeList[ hitFace ];
  613. info->object = this;
  614. info->t = tmin;
  615. //mObjToWorld.mulV( info->normal );
  616. return true;
  617. }
  618. bool ConvexShape::collideBox( const Point3F &start, const Point3F &end, RayInfo *info )
  619. {
  620. return Parent::collideBox( start, end, info );
  621. }
  622. void ConvexShape::updateBounds( bool recenter )
  623. {
  624. if ( mGeometry.points.size() == 0 )
  625. return;
  626. Vector<Point3F> &pointListOS = mGeometry.points;
  627. U32 pointCount = pointListOS.size();
  628. Point3F volumnCenter( 0,0,0 );
  629. F32 areaSum = 0.0f;
  630. F32 faceCount = mGeometry.faces.size();
  631. for ( S32 i = 0; i < faceCount; i++ )
  632. {
  633. volumnCenter += mGeometry.faces[i].centroid * mGeometry.faces[i].area;
  634. areaSum += mGeometry.faces[i].area;
  635. }
  636. if ( areaSum == 0.0f )
  637. return;
  638. volumnCenter /= areaSum;
  639. mObjBox.minExtents = mObjBox.maxExtents = Point3F::Zero;
  640. mObjBox.setCenter( volumnCenter );
  641. for ( S32 i = 0; i < pointCount; i++ )
  642. mObjBox.extend( pointListOS[i] );
  643. resetWorldBox();
  644. }
  645. void ConvexShape::recenter()
  646. {
  647. if ( mGeometry.points.size() == 0 )
  648. return;
  649. Point3F volCenterOS( 0,0,0 );
  650. F32 areaSum = 0.0f;
  651. F32 faceCount = mGeometry.faces.size();
  652. for ( S32 i = 0; i < faceCount; i++ )
  653. {
  654. volCenterOS += mGeometry.faces[i].centroid * mGeometry.faces[i].area;
  655. areaSum += mGeometry.faces[i].area;
  656. }
  657. volCenterOS /= areaSum;
  658. for ( S32 i = 0; i < mSurfaces.size(); i++ )
  659. mSurfaces[i].setPosition( mSurfaces[i].getPosition() - volCenterOS );
  660. Point3F volCenterWS;
  661. MatrixF objToWorld( mObjToWorld );
  662. objToWorld.scale( mObjScale );
  663. objToWorld.mulP( volCenterOS, &volCenterWS );
  664. setPosition( volCenterWS );
  665. _updateGeometry(true);
  666. }
  667. MatrixF ConvexShape::getSurfaceWorldMat( S32 surfId, bool scaled ) const
  668. {
  669. if ( surfId < 0 || surfId >= mSurfaces.size() )
  670. return MatrixF::Identity;
  671. MatrixF objToWorld( mObjToWorld );
  672. if ( scaled )
  673. objToWorld.scale( mObjScale );
  674. MatrixF surfMat;
  675. surfMat.mul( objToWorld, mSurfaces[surfId] );
  676. return surfMat;
  677. }
  678. // Used in cullEmptyPlanes.
  679. S32 QSORT_CALLBACK sortDescendingU32( const void *a, const void *b )
  680. {
  681. U32 *aa = (U32*)(a);
  682. U32 *bb = (U32*)(b);
  683. return (S32)(*bb) - (S32)(*aa);
  684. }
  685. void ConvexShape::cullEmptyPlanes( Vector< U32 > *removedPlanes )
  686. {
  687. //if ( mPlanes.size() == mGeometry.faces.size() )
  688. // return;
  689. removedPlanes->clear();
  690. const U32 startPlaneCount = mPlanes.size();
  691. const Vector< ConvexShape::Face > &faceList = mGeometry.faces;
  692. const U32 faceCount = faceList.size();
  693. S32 *used = new S32[ startPlaneCount ];
  694. for ( S32 i = 0; i < startPlaneCount; i++ )
  695. used[i] = i;
  696. for ( S32 i = 0; i < faceCount; i++ )
  697. {
  698. if ( faceList[i].area > 0.001f )
  699. used[ faceList[i].id ] = -1;
  700. }
  701. for ( S32 i = 0; i < startPlaneCount; i++ )
  702. {
  703. if ( used[i] != -1 )
  704. removedPlanes->push_back( used[i] );
  705. }
  706. dQsort( removedPlanes->address(), removedPlanes->size(), sizeof( U32 ), sortDescendingU32 );
  707. for ( S32 i = 0; i < removedPlanes->size(); i++ )
  708. {
  709. mPlanes.erase( (*removedPlanes)[i] );
  710. mSurfaces.erase( (*removedPlanes)[i] );
  711. }
  712. delete [] used;
  713. }
  714. void ConvexShape::exportToCollada()
  715. {
  716. if ( mSurfaces.size() == 0 )
  717. {
  718. Con::errorf( "ConvexShape::exportToCollada() - has no surfaces to export!" );
  719. return;
  720. }
  721. }
  722. void ConvexShape::resizePlanes( const Point3F &size )
  723. {
  724. //Point3F nSize;
  725. //mWorldToObj.mulV( nSize );
  726. for ( S32 i = 0; i < mSurfaces.size(); i++ )
  727. {
  728. MatrixF objToPlane( mSurfaces[i] );
  729. objToPlane.inverse();
  730. Point3F lim;
  731. objToPlane.mulV( size, &lim );
  732. F32 sign = ( mPlanes[i].d > 0.0f ) ? 1.0f : -1.0f;
  733. mPlanes[i].d = mFabs(lim.z) * 0.5f * sign;
  734. //mPlanes[i].d = -lim.z * 0.5f;
  735. mSurfaces[i].setPosition( mPlanes[i].getPosition() );
  736. }
  737. }
  738. void ConvexShape::getSurfaceLineList( S32 surfId, Vector< Point3F > &lineList )
  739. {
  740. if ( surfId < 0 || surfId > mSurfaces.size() - 1 )
  741. return;
  742. S32 faceId = -1;
  743. for ( S32 i = 0; i < mGeometry.faces.size(); i++ )
  744. {
  745. if ( mGeometry.faces[i].id == surfId )
  746. {
  747. faceId = i;
  748. break;
  749. }
  750. }
  751. if ( faceId == -1 )
  752. return;
  753. ConvexShape::Face &face = mGeometry.faces[faceId];
  754. const Vector< Point3F > &pointList = mGeometry.points;
  755. if ( pointList.size() == 0 )
  756. return;
  757. for ( S32 i = 0; i < face.winding.size(); i++ )
  758. lineList.push_back( pointList[ face.points[ face.winding[i] ] ] );
  759. lineList.push_back( pointList[ face.points[ face.winding.first() ] ] );
  760. }
  761. void ConvexShape::_updateMaterial()
  762. {
  763. // If the material name matches then don't bother updating it.
  764. if ( mMaterialInst && mMaterialName.equal( mMaterialInst->getMaterial()->getName(), String::NoCase ) )
  765. return;
  766. SAFE_DELETE( mMaterialInst );
  767. Material *material;
  768. if ( !Sim::findObject( mMaterialName, material ) )
  769. Sim::findObject( "WarningMaterial", material );
  770. mMaterialInst = material->createMatInstance();
  771. //GFXStateBlockDesc desc;
  772. //desc.setCullMode( GFXCullNone );
  773. //desc.setBlend( false );
  774. //mMaterialInst->addStateBlockDesc( desc );
  775. FeatureSet features = MATMGR->getDefaultFeatures();
  776. //features.addFeature( MFT_DiffuseVertColor );
  777. mMaterialInst->init( features, getGFXVertexFormat<VertexType>() );
  778. if ( !mMaterialInst->isValid() )
  779. {
  780. SAFE_DELETE( mMaterialInst );
  781. }
  782. }
  783. void ConvexShape::_updateGeometry( bool updateCollision )
  784. {
  785. mPlanes.clear();
  786. for ( S32 i = 0; i < mSurfaces.size(); i++ )
  787. mPlanes.push_back( PlaneF( mSurfaces[i].getPosition(), mSurfaces[i].getUpVector() ) );
  788. Vector< Point3F > tangents;
  789. for ( S32 i = 0; i < mSurfaces.size(); i++ )
  790. tangents.push_back( mSurfaces[i].getRightVector() );
  791. mGeometry.generate( mPlanes, tangents );
  792. AssertFatal( mGeometry.faces.size() <= mSurfaces.size(), "Got more faces than planes?" );
  793. const Vector< ConvexShape::Face > &faceList = mGeometry.faces;
  794. const Vector< Point3F > &pointList = mGeometry.points;
  795. // Reset our surface center points.
  796. for ( S32 i = 0; i < faceList.size(); i++ )
  797. mSurfaces[ faceList[i].id ].setPosition( faceList[i].centroid );
  798. mPlanes.clear();
  799. for ( S32 i = 0; i < mSurfaces.size(); i++ )
  800. mPlanes.push_back( PlaneF( mSurfaces[i].getPosition(), mSurfaces[i].getUpVector() ) );
  801. // Update bounding box.
  802. updateBounds( false );
  803. mVertexBuffer = NULL;
  804. mPrimitiveBuffer = NULL;
  805. mVertCount = 0;
  806. mPrimCount = 0;
  807. if ( updateCollision )
  808. _updateCollision();
  809. // Server does not need to generate vertex/prim buffers.
  810. if ( isServerObject() )
  811. return;
  812. if ( faceList.empty() )
  813. return;
  814. // Get total vert and prim count.
  815. for ( S32 i = 0; i < faceList.size(); i++ )
  816. {
  817. U32 count = faceList[i].triangles.size();
  818. mPrimCount += count;
  819. mVertCount += count * 3;
  820. }
  821. // Allocate VB and copy in data.
  822. mVertexBuffer.set( GFX, mVertCount, GFXBufferTypeStatic );
  823. VertexType *pVert = mVertexBuffer.lock();
  824. for ( S32 i = 0; i < faceList.size(); i++ )
  825. {
  826. const ConvexShape::Face &face = faceList[i];
  827. const Vector< U32 > &facePntMap = face.points;
  828. const Vector< ConvexShape::Triangle > &triangles = face.triangles;
  829. const ColorI &faceColor = sgConvexFaceColors[ i % sgConvexFaceColorCount ];
  830. for ( S32 j = 0; j < triangles.size(); j++ )
  831. {
  832. for ( S32 k = 0; k < 3; k++ )
  833. {
  834. pVert->normal = face.normal;
  835. pVert->tangent = face.tangent;
  836. pVert->color = faceColor;
  837. pVert->point = pointList[ facePntMap[ triangles[j][k] ] ];
  838. pVert->texCoord = face.texcoords[ triangles[j][k] ];
  839. pVert++;
  840. }
  841. }
  842. }
  843. mVertexBuffer.unlock();
  844. // Allocate PB
  845. mPrimitiveBuffer.set( GFX, mPrimCount * 3, mPrimCount, GFXBufferTypeStatic );
  846. U16 *pIndex;
  847. mPrimitiveBuffer.lock( &pIndex );
  848. for ( U16 i = 0; i < mPrimCount * 3; i++ )
  849. {
  850. *pIndex = i;
  851. pIndex++;
  852. }
  853. mPrimitiveBuffer.unlock();
  854. }
  855. void ConvexShape::_updateCollision()
  856. {
  857. SAFE_DELETE( mPhysicsRep );
  858. if ( !PHYSICSMGR )
  859. return;
  860. PhysicsCollision *colShape = PHYSICSMGR->createCollision();
  861. // We need the points untransformed!
  862. Vector<Point3F> rawPoints;
  863. MatrixF xfm( getWorldTransform() );
  864. xfm.setPosition( Point3F::Zero );
  865. for ( U32 i=0; i < mGeometry.points.size(); i++ )
  866. {
  867. Point3F p = mGeometry.points[i];
  868. xfm.mulP( p );
  869. rawPoints.push_back( p );
  870. }
  871. // The convex generation from a point cloud
  872. // can fail at times... give up in that case.
  873. if ( !colShape->addConvex( mGeometry.points.address(),
  874. mGeometry.points.size(),
  875. MatrixF::Identity ) )
  876. {
  877. delete colShape;
  878. return;
  879. }
  880. PhysicsWorld *world = PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" );
  881. mPhysicsRep = PHYSICSMGR->createBody();
  882. mPhysicsRep->init( colShape, 0, 0, this, world );
  883. mPhysicsRep->setTransform( getTransform() );
  884. }
  885. void ConvexShape::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *mat )
  886. {
  887. GFXDrawUtil *drawer = GFX->getDrawUtil();
  888. GFX->setTexture( 0, NULL );
  889. // Render world box.
  890. if ( false )
  891. {
  892. Box3F wbox( mWorldBox );
  893. //if ( getServerObject() )
  894. // Box3F wbox = static_cast<ConvexShape*>( getServerObject() )->mWorldBox;
  895. GFXStateBlockDesc desc;
  896. desc.setCullMode( GFXCullNone );
  897. desc.setFillModeWireframe();
  898. drawer->drawCube( desc, wbox, ColorI::RED );
  899. }
  900. const Vector< Point3F > &pointList = mGeometry.points;
  901. const Vector< ConvexShape::Face > &faceList = mGeometry.faces;
  902. // Render Edges.
  903. if ( false )
  904. {
  905. GFXTransformSaver saver;
  906. //GFXFrustumSaver fsaver;
  907. MatrixF xfm( getRenderTransform() );
  908. xfm.scale( getScale() );
  909. GFX->multWorld( xfm );
  910. GFXStateBlockDesc desc;
  911. desc.setZReadWrite( true, false );
  912. desc.setBlend( true );
  913. GFX->setStateBlockByDesc( desc );
  914. //MathUtils::getZBiasProjectionMatrix( 0.01f, state->getFrustum(), )
  915. const Point3F &camFvec = state->getCameraTransform().getForwardVector();
  916. for ( S32 i = 0; i < faceList.size(); i++ )
  917. {
  918. const ConvexShape::Face &face = faceList[i];
  919. const Vector< ConvexShape::Edge > &edgeList = face.edges;
  920. const Vector< U32 > &facePntList = face.points;
  921. PrimBuild::begin( GFXLineList, edgeList.size() * 2 );
  922. PrimBuild::color( ColorI::WHITE * 0.8f );
  923. for ( S32 j = 0; j < edgeList.size(); j++ )
  924. {
  925. PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p0 ] ] - camFvec * 0.001f );
  926. PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p1 ] ] - camFvec * 0.001f );
  927. }
  928. PrimBuild::end();
  929. }
  930. }
  931. ColorI faceColorsx[4] =
  932. {
  933. ColorI( 255, 0, 0 ),
  934. ColorI( 0, 255, 0 ),
  935. ColorI( 0, 0, 255 ),
  936. ColorI( 255, 0, 255 )
  937. };
  938. MatrixF objToWorld( mObjToWorld );
  939. objToWorld.scale( mObjScale );
  940. // Render faces centers/colors.
  941. if ( false )
  942. {
  943. GFXStateBlockDesc desc;
  944. desc.setCullMode( GFXCullNone );
  945. Point3F size( 0.1f );
  946. for ( S32 i = 0; i < faceList.size(); i++ )
  947. {
  948. ColorI color = faceColorsx[ i % 4 ];
  949. S32 div = ( i / 4 ) * 4;
  950. if ( div > 0 )
  951. color /= div;
  952. color.alpha = 255;
  953. Point3F pnt;
  954. objToWorld.mulP( faceList[i].centroid, &pnt );
  955. drawer->drawCube( desc, size, pnt, color, NULL );
  956. }
  957. }
  958. // Render winding order.
  959. if ( false )
  960. {
  961. GFXStateBlockDesc desc;
  962. desc.setCullMode( GFXCullNone );
  963. desc.setZReadWrite( true, false );
  964. GFX->setStateBlockByDesc( desc );
  965. U32 pointCount = 0;
  966. for ( S32 i = 0; i < faceList.size(); i++ )
  967. pointCount += faceList[i].winding.size();
  968. PrimBuild::begin( GFXLineList, pointCount * 2 );
  969. for ( S32 i = 0; i < faceList.size(); i++ )
  970. {
  971. for ( S32 j = 0; j < faceList[i].winding.size(); j++ )
  972. {
  973. Point3F p0 = pointList[ faceList[i].points[ faceList[i].winding[j] ] ];
  974. Point3F p1 = p0 + mSurfaces[ faceList[i].id ].getUpVector() * 0.75f * ( Point3F::One / mObjScale );
  975. objToWorld.mulP( p0 );
  976. objToWorld.mulP( p1 );
  977. ColorI color = faceColorsx[ j % 4 ];
  978. S32 div = ( j / 4 ) * 4;
  979. if ( div > 0 )
  980. color /= div;
  981. color.alpha = 255;
  982. PrimBuild::color( color );
  983. PrimBuild::vertex3fv( p0 );
  984. PrimBuild::color( color );
  985. PrimBuild::vertex3fv( p1 );
  986. }
  987. }
  988. PrimBuild::end();
  989. }
  990. // Render Points.
  991. if ( false )
  992. {
  993. /*
  994. GFXTransformSaver saver;
  995. MatrixF xfm( getRenderTransform() );
  996. xfm.scale( getScale() );
  997. GFX->multWorld( xfm );
  998. GFXStateBlockDesc desc;
  999. Point3F size( 0.05f );
  1000. */
  1001. }
  1002. // Render surface transforms.
  1003. if ( false )
  1004. {
  1005. GFXStateBlockDesc desc;
  1006. desc.setBlend( false );
  1007. desc.setZReadWrite( true, true );
  1008. Point3F scale(mNormalLength);
  1009. for ( S32 i = 0; i < mSurfaces.size(); i++ )
  1010. {
  1011. MatrixF objToWorld( mObjToWorld );
  1012. objToWorld.scale( mObjScale );
  1013. MatrixF renderMat;
  1014. renderMat.mul( objToWorld, mSurfaces[i] );
  1015. renderMat.setPosition( renderMat.getPosition() + renderMat.getUpVector() * 0.001f );
  1016. drawer->drawTransform( desc, renderMat, &scale, NULL );
  1017. }
  1018. }
  1019. }
  1020. void ConvexShape::renderFaceEdges( S32 faceid, const ColorI &color /*= ColorI::WHITE*/, F32 lineWidth /*= 1.0f */ )
  1021. {
  1022. const Vector< ConvexShape::Face > &faceList = mGeometry.faces;
  1023. if ( faceid >= faceList.size() )
  1024. return;
  1025. GFXTransformSaver saver;
  1026. MatrixF xfm( mObjToWorld );
  1027. xfm.scale( mObjScale );
  1028. GFX->multWorld( xfm );
  1029. GFXStateBlockDesc desc;
  1030. desc.setBlend( true );
  1031. GFX->setStateBlockByDesc( desc );
  1032. MatrixF projBias(true);
  1033. const Frustum& frustum = GFX->getFrustum();
  1034. MathUtils::getZBiasProjectionMatrix( 0.001f, frustum, &projBias );
  1035. GFX->setProjectionMatrix( projBias );
  1036. S32 s = faceid;
  1037. S32 e = faceid + 1;
  1038. if ( faceid == -1 )
  1039. {
  1040. s = 0;
  1041. e = faceList.size();
  1042. }
  1043. for ( S32 i = s; i < e; i++ )
  1044. {
  1045. const ConvexShape::Face &face = faceList[i];
  1046. const Vector< ConvexShape::Edge > &edgeList = face.edges;
  1047. const Vector< U32 > &facePntList = face.points;
  1048. const Vector< Point3F > &pointList = mGeometry.points;
  1049. PrimBuild::begin( GFXLineList, edgeList.size() * 2 );
  1050. PrimBuild::color( color );
  1051. for ( S32 j = 0; j < edgeList.size(); j++ )
  1052. {
  1053. PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p0 ] ] );
  1054. PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p1 ] ] );
  1055. }
  1056. PrimBuild::end();
  1057. }
  1058. }
  1059. void ConvexShape::getSurfaceTriangles( S32 surfId, Vector< Point3F > *outPoints, Vector< Point2F > *outCoords, bool worldSpace )
  1060. {
  1061. S32 faceId = -1;
  1062. for ( S32 i = 0; i < mGeometry.faces.size(); i++ )
  1063. {
  1064. if ( mGeometry.faces[i].id == surfId )
  1065. {
  1066. faceId = i;
  1067. break;
  1068. }
  1069. }
  1070. if ( faceId == -1 )
  1071. return;
  1072. const ConvexShape::Face &face = mGeometry.faces[ faceId ];
  1073. const Vector< Point3F > &pointList = mGeometry.points;
  1074. const MatrixF &surfToObj = mSurfaces[ faceId ];
  1075. MatrixF objToSurf( surfToObj );
  1076. objToSurf.inverse();
  1077. Point3F surfScale( 1.5f, 1.5f, 1.0f );
  1078. for ( S32 i = 0; i < face.triangles.size(); i++ )
  1079. {
  1080. for ( S32 j = 0; j < 3; j++ )
  1081. {
  1082. Point3F pnt( pointList[ face.points[ face.triangles[i][j] ] ] );
  1083. objToSurf.mulP( pnt );
  1084. pnt *= surfScale;
  1085. surfToObj.mulP( pnt );
  1086. outPoints->push_back( pnt );
  1087. if ( outCoords )
  1088. outCoords->push_back( face.texcoords[ face.triangles[i][j] ] );
  1089. }
  1090. }
  1091. if ( worldSpace )
  1092. {
  1093. MatrixF objToWorld( mObjToWorld );
  1094. objToWorld.scale( mObjScale );
  1095. for ( S32 i = 0; i < outPoints->size(); i++ )
  1096. objToWorld.mulP( (*outPoints)[i] );
  1097. }
  1098. }
  1099. void ConvexShape::Geometry::generate( const Vector< PlaneF > &planes, const Vector< Point3F > &tangents )
  1100. {
  1101. PROFILE_SCOPE( Geometry_generate );
  1102. points.clear();
  1103. faces.clear();
  1104. AssertFatal( planes.size() == tangents.size(), "ConvexShape - incorrect plane/tangent count." );
  1105. #ifdef TORQUE_ENABLE_ASSERTS
  1106. for ( S32 i = 0; i < planes.size(); i++ )
  1107. {
  1108. F32 dt = mDot( planes[i], tangents[i] );
  1109. AssertFatal( mIsZero( dt, 0.0001f ), "ConvexShape - non perpendicular input vectors." );
  1110. AssertFatal( planes[i].isUnitLength() && tangents[i].isUnitLength(), "ConvexShape - non unit length input vector." );
  1111. }
  1112. #endif
  1113. const U32 planeCount = planes.size();
  1114. Point3F linePt, lineDir;
  1115. for ( S32 i = 0; i < planeCount; i++ )
  1116. {
  1117. Vector< MathUtils::Line > collideLines;
  1118. // Find the lines defined by the intersection of this plane with all others.
  1119. for ( S32 j = 0; j < planeCount; j++ )
  1120. {
  1121. if ( i == j )
  1122. continue;
  1123. if ( planes[i].intersect( planes[j], linePt, lineDir ) )
  1124. {
  1125. collideLines.increment();
  1126. MathUtils::Line &line = collideLines.last();
  1127. line.origin = linePt;
  1128. line.direction = lineDir;
  1129. }
  1130. }
  1131. if ( collideLines.empty() )
  1132. continue;
  1133. // Find edges and points defined by the intersection of these lines.
  1134. // As we find them we fill them into our working ConvexShape::Face
  1135. // structure.
  1136. Face newFace;
  1137. for ( S32 j = 0; j < collideLines.size(); j++ )
  1138. {
  1139. Vector< Point3F > collidePoints;
  1140. for ( S32 k = 0; k < collideLines.size(); k++ )
  1141. {
  1142. if ( j == k )
  1143. continue;
  1144. MathUtils::LineSegment segment;
  1145. MathUtils::mShortestSegmentBetweenLines( collideLines[j], collideLines[k], &segment );
  1146. F32 dist = ( segment.p0 - segment.p1 ).len();
  1147. if ( dist < 0.0005f )
  1148. {
  1149. S32 l = 0;
  1150. for ( ; l < planeCount; l++ )
  1151. {
  1152. if ( planes[l].whichSide( segment.p0 ) == PlaneF::Front )
  1153. break;
  1154. }
  1155. if ( l == planeCount )
  1156. collidePoints.push_back( segment.p0 );
  1157. }
  1158. }
  1159. //AssertFatal( collidePoints.size() <= 2, "A line can't collide with more than 2 other lines in a convex shape..." );
  1160. if ( collidePoints.size() != 2 )
  1161. continue;
  1162. // Push back collision points into our points vector
  1163. // if they are not duplicates and determine the id
  1164. // index for those points to be used by Edge(s).
  1165. const Point3F &pnt0 = collidePoints[0];
  1166. const Point3F &pnt1 = collidePoints[1];
  1167. S32 idx0 = -1;
  1168. S32 idx1 = -1;
  1169. for ( S32 k = 0; k < points.size(); k++ )
  1170. {
  1171. if ( pnt0.equal( points[k] ) )
  1172. {
  1173. idx0 = k;
  1174. break;
  1175. }
  1176. }
  1177. for ( S32 k = 0; k < points.size(); k++ )
  1178. {
  1179. if ( pnt1.equal( points[k] ) )
  1180. {
  1181. idx1 = k;
  1182. break;
  1183. }
  1184. }
  1185. if ( idx0 == -1 )
  1186. {
  1187. points.push_back( pnt0 );
  1188. idx0 = points.size() - 1;
  1189. }
  1190. if ( idx1 == -1 )
  1191. {
  1192. points.push_back( pnt1 );
  1193. idx1 = points.size() - 1;
  1194. }
  1195. // Construct the Face::Edge defined by this collision.
  1196. S32 localIdx0 = newFace.points.push_back_unique( idx0 );
  1197. S32 localIdx1 = newFace.points.push_back_unique( idx1 );
  1198. newFace.edges.increment();
  1199. ConvexShape::Edge &newEdge = newFace.edges.last();
  1200. newEdge.p0 = localIdx0;
  1201. newEdge.p1 = localIdx1;
  1202. }
  1203. if ( newFace.points.size() < 3 )
  1204. continue;
  1205. //AssertFatal( newFace.points.size() == newFace.edges.size(), "ConvexShape - face point count does not equal edge count." );
  1206. // Fill in some basic Face information.
  1207. newFace.id = i;
  1208. newFace.normal = planes[i];
  1209. newFace.tangent = tangents[i];
  1210. // Make a working array of Point3Fs on this face.
  1211. U32 pntCount = newFace.points.size();
  1212. Point3F *workPoints = new Point3F[ pntCount ];
  1213. for ( S32 j = 0; j < pntCount; j++ )
  1214. workPoints[j] = points[ newFace.points[j] ];
  1215. // Calculate the average point for calculating winding order.
  1216. Point3F averagePnt = Point3F::Zero;
  1217. for ( S32 j = 0; j < pntCount; j++ )
  1218. averagePnt += workPoints[j];
  1219. averagePnt /= pntCount;
  1220. // Sort points in correct winding order.
  1221. U32 *vertMap = new U32[pntCount];
  1222. MatrixF quadMat( true );
  1223. quadMat.setPosition( averagePnt );
  1224. quadMat.setColumn( 0, newFace.tangent );
  1225. quadMat.setColumn( 1, mCross( newFace.normal, newFace.tangent ) );
  1226. quadMat.setColumn( 2, newFace.normal );
  1227. quadMat.inverse();
  1228. // Transform working points into quad space
  1229. // so we can work with them as 2D points.
  1230. for ( S32 j = 0; j < pntCount; j++ )
  1231. quadMat.mulP( workPoints[j] );
  1232. MathUtils::sortQuadWindingOrder( true, workPoints, vertMap, pntCount );
  1233. // Save points in winding order.
  1234. for ( S32 j = 0; j < pntCount; j++ )
  1235. newFace.winding.push_back( vertMap[j] );
  1236. // Calculate the area and centroid of the face.
  1237. newFace.area = 0.0f;
  1238. for ( S32 j = 0; j < pntCount; j++ )
  1239. {
  1240. S32 k = ( j + 1 ) % pntCount;
  1241. const Point3F &p0 = workPoints[ vertMap[j] ];
  1242. const Point3F &p1 = workPoints[ vertMap[k] ];
  1243. // Note that this calculation returns positive area for clockwise winding
  1244. // and negative area for counterclockwise winding.
  1245. newFace.area += p0.y * p1.x;
  1246. newFace.area -= p0.x * p1.y;
  1247. }
  1248. //AssertFatal( newFace.area > 0.0f, "ConvexShape - face area was not positive." );
  1249. if ( newFace.area > 0.0f )
  1250. newFace.area /= 2.0f;
  1251. F32 factor;
  1252. F32 cx = 0.0f, cy = 0.0f;
  1253. for ( S32 j = 0; j < pntCount; j++ )
  1254. {
  1255. S32 k = ( j + 1 ) % pntCount;
  1256. const Point3F &p0 = workPoints[ vertMap[j] ];
  1257. const Point3F &p1 = workPoints[ vertMap[k] ];
  1258. factor = p0.x * p1.y - p1.x * p0.y;
  1259. cx += ( p0.x + p1.x ) * factor;
  1260. cy += ( p0.y + p1.y ) * factor;
  1261. }
  1262. factor = 1.0f / ( newFace.area * 6.0f );
  1263. newFace.centroid.set( cx * factor, cy * factor, 0.0f );
  1264. quadMat.inverse();
  1265. quadMat.mulP( newFace.centroid );
  1266. delete [] workPoints;
  1267. workPoints = NULL;
  1268. // Make polygons / triangles for this face.
  1269. const U32 polyCount = pntCount - 2;
  1270. newFace.triangles.setSize( polyCount );
  1271. for ( S32 j = 0; j < polyCount; j++ )
  1272. {
  1273. ConvexShape::Triangle &poly = newFace.triangles[j];
  1274. poly.p0 = vertMap[0];
  1275. if ( j == 0 )
  1276. {
  1277. poly.p1 = vertMap[ 1 ];
  1278. poly.p2 = vertMap[ 2 ];
  1279. }
  1280. else
  1281. {
  1282. poly.p1 = vertMap[ 1 + j ];
  1283. poly.p2 = vertMap[ 2 + j ];
  1284. }
  1285. }
  1286. delete [] vertMap;
  1287. // Calculate texture coordinates for each point in this face.
  1288. const Point3F binormal = mCross( newFace.normal, newFace.tangent );
  1289. PlaneF planey( newFace.centroid - 0.5f * binormal, binormal );
  1290. PlaneF planex( newFace.centroid - 0.5f * newFace.tangent, newFace.tangent );
  1291. newFace.texcoords.setSize( newFace.points.size() );
  1292. for ( S32 j = 0; j < newFace.points.size(); j++ )
  1293. {
  1294. F32 x = planex.distToPlane( points[ newFace.points[ j ] ] );
  1295. F32 y = planey.distToPlane( points[ newFace.points[ j ] ] );
  1296. newFace.texcoords[j].set( -x, -y );
  1297. }
  1298. // Data verification tests.
  1299. #ifdef TORQUE_ENABLE_ASSERTS
  1300. //S32 triCount = newFace.triangles.size();
  1301. //S32 edgeCount = newFace.edges.size();
  1302. //AssertFatal( triCount == edgeCount - 2, "ConvexShape - triangle/edge count do not match." );
  1303. /*
  1304. for ( S32 j = 0; j < triCount; j++ )
  1305. {
  1306. F32 area = MathUtils::mTriangleArea( points[ newFace.points[ newFace.triangles[j][0] ] ],
  1307. points[ newFace.points[ newFace.triangles[j][1] ] ],
  1308. points[ newFace.points[ newFace.triangles[j][2] ] ] );
  1309. AssertFatal( area > 0.0f, "ConvexShape - triangle winding bad." );
  1310. }*/
  1311. #endif
  1312. // Done with this Face.
  1313. faces.push_back( newFace );
  1314. }
  1315. }