ShapeVector.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 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 "graphics/dgl.h"
  23. #include "console/consoleTypes.h"
  24. #include "2d/core/Utility.h"
  25. #include "ShapeVector.h"
  26. // Script bindings.
  27. #include "ShapeVector_ScriptBinding.h"
  28. //----------------------------------------------------------------------------
  29. IMPLEMENT_CONOBJECT(ShapeVector);
  30. //----------------------------------------------------------------------------
  31. ShapeVector::ShapeVector() :
  32. mLineColor(ColorF(1.0f,1.0f,1.0f,1.0f)),
  33. mFillColor(ColorF(0.5f,0.5f,0.5f,1.0f)),
  34. mFillMode(false),
  35. mPolygonScale( 1.0f, 1.0f ),
  36. mIsCircle(false),
  37. mCircleRadius(1.0f),
  38. mFlipX(false),
  39. mFlipY(false)
  40. {
  41. // Set Vector Associations.
  42. VECTOR_SET_ASSOCIATION( mPolygonBasisList );
  43. VECTOR_SET_ASSOCIATION( mPolygonLocalList );
  44. // Use a static body by default.
  45. mBodyDefinition.type = b2_staticBody;
  46. }
  47. //----------------------------------------------------------------------------
  48. ShapeVector::~ShapeVector()
  49. {
  50. }
  51. //----------------------------------------------------------------------------
  52. void ShapeVector::initPersistFields()
  53. {
  54. addProtectedField("PolyList", TypePoint2FVector, Offset(mPolygonBasisList, ShapeVector), &setPolyList, &defaultProtectedGetFn, &writePolyList, "");
  55. addField("LineColor", TypeColorF, Offset(mLineColor, ShapeVector), &writeLineColor, "");
  56. addField("FillColor", TypeColorF, Offset(mFillColor, ShapeVector), &writeFillColor, "");
  57. addField("FillMode", TypeBool, Offset(mFillMode, ShapeVector), &writeFillMode, "");
  58. addField("IsCircle", TypeBool, Offset(mIsCircle, ShapeVector), &writeIsCircle, "");
  59. addField("CircleRadius", TypeF32, Offset(mCircleRadius, ShapeVector), &writeCircleRadius, "");
  60. Parent::initPersistFields();
  61. }
  62. //----------------------------------------------------------------------------
  63. void ShapeVector::copyTo(SimObject* obj)
  64. {
  65. Parent::copyTo(obj);
  66. AssertFatal(dynamic_cast<ShapeVector*>(obj), "ShapeVector::copyTo() - Object is not the correct type.");
  67. ShapeVector* object = static_cast<ShapeVector*>(obj);
  68. // Copy fields
  69. object->mFillMode = mFillMode;
  70. object->mFillColor = mFillColor;
  71. object->mLineColor = mLineColor;
  72. object->mIsCircle = mIsCircle;
  73. object->mCircleRadius = mCircleRadius;
  74. object->mFlipX = mFlipX;
  75. object->mFlipY = mFlipY;
  76. if (getPolyVertexCount() > 0)
  77. object->setPolyCustom(mPolygonBasisList.size(), getPoly());
  78. }
  79. //----------------------------------------------------------------------------
  80. bool ShapeVector::onAdd()
  81. {
  82. // Call Parent.
  83. if(!Parent::onAdd())
  84. return false;
  85. // Return Okay.
  86. return true;
  87. }
  88. //----------------------------------------------------------------------------
  89. void ShapeVector::onRemove()
  90. {
  91. // Call Parent.
  92. Parent::onRemove();
  93. }
  94. //----------------------------------------------------------------------------
  95. void ShapeVector::sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer )
  96. {
  97. // Fetch Vertex Count.
  98. const U32 vertexCount = mPolygonLocalList.size();
  99. // Finish if not vertices.
  100. if ( vertexCount == 0 && !mIsCircle)
  101. return;
  102. // Disable Texturing.
  103. glDisable ( GL_TEXTURE_2D );
  104. // Save Model-view.
  105. glMatrixMode(GL_MODELVIEW);
  106. glPushMatrix();
  107. // Fetch Position/Rotation.
  108. const Vector2 position = getRenderPosition();
  109. // Set Blend Options.
  110. setBlendOptions();
  111. if (mIsCircle)
  112. {
  113. glRotatef( mRadToDeg(getRenderAngle()), 0.0f, 0.0f, 1.0f );
  114. renderCircleShape(position, mCircleRadius);
  115. }
  116. else
  117. {
  118. // Move into Vector-Space.
  119. glTranslatef( position.x, position.y, 0.0f );
  120. glRotatef( mRadToDeg(getRenderAngle()), 0.0f, 0.0f, 1.0f );
  121. renderPolygonShape(vertexCount);
  122. }
  123. // Restore color.
  124. glColor4f( 1,1,1,1 );
  125. // Restore Matrix.
  126. glPopMatrix();
  127. }
  128. void ShapeVector::renderCircleShape(Vector2 position, F32 radius)
  129. {
  130. if (mFillMode)
  131. {
  132. const float32 k_segments = 32.0f;
  133. const float32 k_increment = 2.0f * b2_pi / k_segments;
  134. float32 theta = 0.0f;
  135. glEnable(GL_BLEND);
  136. glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  137. glColor4f(mFillColor.red, mFillColor.green, mFillColor.blue, mFillColor.alpha);
  138. glBegin(GL_TRIANGLE_FAN);
  139. for (int32 i = 0; i < k_segments; ++i)
  140. {
  141. Vector2 v = position + radius * Vector2(cosf(theta), sinf(theta));
  142. glVertex2f(v.x, v.y);
  143. theta += k_increment;
  144. }
  145. glEnd();
  146. glDisable(GL_BLEND);
  147. theta = 0.0f;
  148. glColor4f(mLineColor.red, mLineColor.green, mLineColor.blue, 1.0f);
  149. glBegin(GL_LINE_LOOP);
  150. for (int32 i = 0; i < k_segments; ++i)
  151. {
  152. Vector2 v = position + radius * Vector2(cosf(theta), sinf(theta));
  153. glVertex2f(v.x, v.y);
  154. theta += k_increment;
  155. }
  156. glEnd();
  157. }
  158. else
  159. {
  160. const float32 k_segments = 36.0f;
  161. const float32 k_increment = 2.0f * b2_pi / k_segments;
  162. float32 theta = 0.0f;
  163. glColor4f(mLineColor.red, mLineColor.green, mLineColor.blue, mLineColor.alpha);
  164. glBegin(GL_LINE_LOOP);
  165. for (int32 i = 0; i < k_segments; ++i)
  166. {
  167. Vector2 v = position + radius * Vector2(cosf(theta), sinf(theta));
  168. glVertex2f(v.x, v.y);
  169. theta += k_increment;
  170. }
  171. glEnd();
  172. }
  173. }
  174. void ShapeVector::renderPolygonShape(U32 vertexCount)
  175. {
  176. #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_ANDROID) || defined(TORQUE_OS_EMSCRIPTEN)
  177. // Fill Mode?
  178. if ( mFillMode )
  179. {
  180. // Yes, so set polygon mode to FILL.
  181. //glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  182. // Set Fill color.
  183. glColor4f( (GLfloat)mFillColor.red, (GLfloat)mFillColor.green, (GLfloat)mFillColor.blue, (GLfloat)mFillColor.alpha );
  184. GLfloat vert1[] = {//get first vert and make triangles based off of this one
  185. (GLfloat)(mPolygonLocalList[0].x),
  186. (GLfloat)(mPolygonLocalList[0].y),
  187. };
  188. GLfloat prevVert[] = {
  189. (GLfloat)(mPolygonLocalList[1].x),
  190. (GLfloat)(mPolygonLocalList[1].y),
  191. };
  192. // Draw Object.
  193. for ( U32 n = 2; n < vertexCount; n++ )
  194. {
  195. //glVertex2fv ( (GLfloat*)&(mPolygonLocalList[n]) );
  196. GLfloat vertex[] = {
  197. vert1[0], vert1[1],
  198. (GLfloat)(mPolygonLocalList[n].x), (GLfloat)(mPolygonLocalList[n].y),
  199. prevVert[0], prevVert[1],
  200. };
  201. glVertexPointer(2, GL_FLOAT, 0, vertex );
  202. glDrawArrays(GL_TRIANGLES, 0, 3 );
  203. prevVert[0] = (GLfloat)(mPolygonLocalList[n].x);//save the current one's for nxt time
  204. prevVert[1] = (GLfloat)(mPolygonLocalList[n].y);
  205. }
  206. //glDrawArrays(GL_TRIANGLES, 0, vertexCount);
  207. //glEnd();
  208. }
  209. // Set Line color.
  210. glColor4f(mLineColor.red, mLineColor.green, mLineColor.blue, mLineColor.alpha );
  211. for ( U32 n = 1; n <= vertexCount; n++ )
  212. {
  213. GLfloat verts[] = {
  214. (GLfloat)(mPolygonLocalList[n - 1].x),
  215. (GLfloat)(mPolygonLocalList[n - 1].y),
  216. (GLfloat)(mPolygonLocalList[n == vertexCount ? 0 : n].x),
  217. (GLfloat)(mPolygonLocalList[n == vertexCount ? 0 : n].y),
  218. };
  219. glVertexPointer(2, GL_FLOAT, 0, verts );
  220. glDrawArrays(GL_LINE_LOOP, 0, 2);//draw last two
  221. }
  222. #else
  223. // Fill Mode?
  224. if ( mFillMode )
  225. {
  226. // Yes, so set polygon mode to FILL.
  227. glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  228. // Set Fill color.
  229. glColor4fv( (GLfloat*)&mFillColor );
  230. // Draw Object.
  231. glBegin( GL_POLYGON );
  232. for ( U32 n = 0; n < vertexCount; n++ )
  233. {
  234. glVertex2fv ( (GLfloat*)&(mPolygonLocalList[n]) );
  235. }
  236. glEnd();
  237. }
  238. // Set Line color.
  239. glColor4fv( (GLfloat*)&mLineColor );
  240. // Draw Object.
  241. glBegin(GL_LINES);
  242. for ( U32 n = 1; n <= vertexCount; n++ )
  243. {
  244. glVertex2fv ( (GLfloat*)&(mPolygonLocalList[n - 1]) );
  245. glVertex2fv ( (GLfloat*)&(mPolygonLocalList[n == vertexCount ? 0 : n]) );
  246. }
  247. glEnd();
  248. #endif
  249. }
  250. //----------------------------------------------------------------------------
  251. void ShapeVector::setSize( const Vector2& size )
  252. {
  253. F32 xDifference = mSize.x / size.x;
  254. // Call Parent.
  255. Parent::setSize( size );
  256. if (mIsCircle)
  257. {
  258. mCircleRadius /= xDifference;
  259. }
  260. else
  261. {
  262. // Generate Local Polygon.
  263. generateLocalPoly();
  264. }
  265. }
  266. //----------------------------------------------------------------------------
  267. void ShapeVector::setPolyScale( const Vector2& scale )
  268. {
  269. // Check Scales.
  270. if ( scale.x <= 0.0f || scale.y <= 0.0f )
  271. {
  272. Con::warnf("ShapeVector::setPolyScale() - Polygon Scales must be greater than zero! '%g,%g'.", scale.x, scale.y);
  273. return;
  274. }
  275. // Check Scales.
  276. if ( scale.x > 1.0f || scale.y > 1.0f )
  277. {
  278. Con::warnf("ShapeVector::setPolyScale() - Polygon Scales cannot be greater than one! '%g,%g'.", scale.x, scale.y);
  279. return;
  280. }
  281. // Set Polygon Scale.
  282. mPolygonScale = scale;
  283. // Generation Local Poly.
  284. generateLocalPoly();
  285. }
  286. //----------------------------------------------------------------------------
  287. void ShapeVector::setPolyPrimitive( const U32 polyVertexCount )
  288. {
  289. // Check it's not zero!
  290. if ( polyVertexCount == 0 )
  291. {
  292. // Warn.
  293. Con::warnf("ShapeVector::setPolyPrimitive() - Vertex count must be greater than zero!");
  294. // Finish Here.
  295. return;
  296. }
  297. // Clear Polygon List.
  298. mPolygonBasisList.clear();
  299. mPolygonBasisList.setSize( polyVertexCount );
  300. // Point?
  301. if ( polyVertexCount == 1 )
  302. {
  303. // Set Polygon Point.
  304. mPolygonBasisList[0].Set(0.0f, 0.0f);
  305. }
  306. // Special-Case Quad?
  307. else if ( polyVertexCount == 4 )
  308. {
  309. // Yes, so set Quad.
  310. mPolygonBasisList[0].Set(-0.5f, -0.5f);
  311. mPolygonBasisList[1].Set(+0.5f, -0.5f);
  312. mPolygonBasisList[2].Set(+0.5f, +0.5f);
  313. mPolygonBasisList[3].Set(-0.5f, +0.5f);
  314. }
  315. else
  316. {
  317. // No, so calculate Regular (Primitive) Polygon Stepping.
  318. //
  319. // NOTE:- The polygon sits on an circle that subscribes the interior
  320. // of the collision box.
  321. F32 angle = M_PI_F / polyVertexCount;
  322. const F32 angleStep = M_2PI_F / polyVertexCount;
  323. // Calculate Polygon.
  324. for ( U32 n = 0; n < polyVertexCount; n++ )
  325. {
  326. // Calculate Angle.
  327. angle += angleStep;
  328. // Store Polygon Vertex.
  329. mPolygonBasisList[n].Set(mCos(angle), mSin(angle));
  330. }
  331. }
  332. // Generation Local Poly.
  333. generateLocalPoly();
  334. }
  335. //----------------------------------------------------------------------------
  336. void ShapeVector::setPolyCustom( const U32 polyVertexCount, const char* pCustomPolygon )
  337. {
  338. // Validate Polygon.
  339. if ( polyVertexCount < 1 )
  340. {
  341. // Warn.
  342. Con::warnf("ShapeVector::setPolyCustom() - Vertex count must be greater than zero!");
  343. return;
  344. }
  345. // Fetch Custom Polygon Value Count.
  346. const U32 customCount = Utility::mGetStringElementCount(pCustomPolygon);
  347. // Validate Polygon Custom Length.
  348. if ( customCount != polyVertexCount*2 )
  349. {
  350. // Warn.
  351. Con::warnf("ShapeVector::setPolyCustom() - Invalid Custom Polygon Items '%d'; expected '%d'!", customCount, polyVertexCount*2 );
  352. return;
  353. }
  354. //// Validate Polygon Vertices.
  355. //for ( U32 n = 0; n < customCount; n+=2 )
  356. //{
  357. // // Fetch Coordinate.
  358. // const Vector2 coord = Utility::mGetStringElementVector(pCustomPolygon, n);
  359. // // Check Range.
  360. // if ( coord.x < -1.0f || coord.x > 1.0f || coord.y < -1.0f || coord.y > 1.0f )
  361. // {
  362. // // Warn.
  363. // Con::warnf("ShapeVector::setPolyCustom() - Invalid Polygon Coordinate range; Must be -1 to +1! '(%g,%g)'", coord.x, coord.y );
  364. // return;
  365. // }
  366. //}
  367. // Clear Polygon Basis List.
  368. mPolygonBasisList.clear();
  369. mPolygonBasisList.setSize( polyVertexCount );
  370. // Validate Polygon Vertices.
  371. for ( U32 n = 0; n < polyVertexCount; n++ )
  372. {
  373. // Fetch Coordinate.
  374. const F32 x = dAtof(Utility::mGetStringElement(pCustomPolygon, n*2));
  375. const F32 y = dAtof(Utility::mGetStringElement(pCustomPolygon, n*2+1));
  376. // Store Polygon Vertex.
  377. mPolygonBasisList[n].Set(x, y);
  378. }
  379. // Generation Local Poly.
  380. generateLocalPoly();
  381. }
  382. //----------------------------------------------------------------------------
  383. const char* ShapeVector::getPoly( void )
  384. {
  385. // Get Collision Polygon.
  386. const Vector2* pPoly = (getPolyVertexCount() > 0) ? getPolyBasis() : NULL;
  387. // Set Max Buffer Size.
  388. const U32 maxBufferSize = getPolyVertexCount() * 18 + 1;
  389. // Get Return Buffer.
  390. char* pReturnBuffer = Con::getReturnBuffer( maxBufferSize );
  391. // Check Buffer.
  392. if( !pReturnBuffer )
  393. {
  394. // Warn.
  395. Con::printf("ShapeVector::getPoly() - Unable to allocate buffer!");
  396. // Exit.
  397. return NULL;
  398. }
  399. // Set Buffer Counter.
  400. U32 bufferCount = 0;
  401. // Add Polygon Edges.
  402. for ( U32 n = 0; n < getPolyVertexCount(); n++ )
  403. {
  404. // Output Object ID.
  405. bufferCount += dSprintf( pReturnBuffer + bufferCount, maxBufferSize-bufferCount, "%0.5f %0.5f ", pPoly[n].x, pPoly[n].y );
  406. // Finish early if we run out of buffer space.
  407. if ( bufferCount >= maxBufferSize )
  408. {
  409. // Warn.
  410. Con::warnf("ShapeVector::getPoly() - Error writing to buffer!");
  411. break;
  412. }
  413. }
  414. // Return Buffer.
  415. return pReturnBuffer;
  416. }
  417. //----------------------------------------------------------------------------
  418. const char* ShapeVector::getWorldPoly( void )
  419. {
  420. // Get the object space polygon
  421. //const Vector2* pPoly = (getPolyVertexCount() > 0) ? getPolyBasis() : NULL;
  422. // Set the max buffer size
  423. const U32 maxBufferSize = getPolyVertexCount() * 18 + 1;
  424. // Get the return buffer.
  425. char* pReturnBuffer = Con::getReturnBuffer( maxBufferSize );
  426. // Check the buffer.
  427. if( !pReturnBuffer )
  428. {
  429. // Warn.
  430. Con::printf("ShapeVector::getWorldPoly() - Unable to allocate buffer!");
  431. // Exit.
  432. return NULL;
  433. }
  434. // Set Buffer Counter.
  435. U32 bufferCount = 0;
  436. // Add Polygon Edges.
  437. for ( U32 n = 0; n < getPolyVertexCount(); n++ )
  438. {
  439. // Convert the poly point to a world coordinate
  440. Vector2 worldPoint = getWorldPoint(mPolygonLocalList[n]);
  441. // Output the point
  442. bufferCount += dSprintf( pReturnBuffer + bufferCount, maxBufferSize-bufferCount, "%0.5f %0.5f ", worldPoint.x, worldPoint.y );
  443. // Finish early if we run out of buffer space.
  444. if ( bufferCount >= maxBufferSize )
  445. {
  446. // Warn.
  447. Con::warnf("ShapeVector::getWorldPoly() - Error writing to buffer!");
  448. break;
  449. }
  450. }
  451. // Return Buffer.
  452. return pReturnBuffer;
  453. }
  454. //----------------------------------------------------------------------------
  455. void ShapeVector::generateLocalPoly( void )
  456. {
  457. // Fetch Polygon Vertex Count.
  458. const U32 polyVertexCount = mPolygonBasisList.size();
  459. // Process Collision Polygon (if we've got one).
  460. if ( polyVertexCount > 0 )
  461. {
  462. // Clear Polygon List.
  463. mPolygonLocalList.clear();
  464. mPolygonLocalList.setSize( polyVertexCount );
  465. // Fetch Half Size.
  466. const Vector2 halfSize = getHalfSize();
  467. // Calculate Polygon Half-Size.
  468. const Vector2 polyHalfSize( halfSize.x * mPolygonScale.x, halfSize.y * mPolygonScale.y );
  469. // Scale/Orientate Polygon.
  470. for ( U32 n = 0; n < polyVertexCount; n++ )
  471. {
  472. // Fetch Polygon Basis.
  473. Vector2 polyVertex = mPolygonBasisList[n];
  474. // Scale.
  475. polyVertex.Set( polyVertex.x * mSize.x * (mFlipX ? -1.0f : 1.0f),
  476. polyVertex.y * mSize.y * (mFlipY ? -1.0f : 1.0f));
  477. // Set Vertex.
  478. mPolygonLocalList[n] = polyVertex;
  479. }
  480. }
  481. }
  482. //----------------------------------------------------------------------------
  483. Vector2 ShapeVector::getBoxFromPoints()
  484. {
  485. Vector2 box(1.0f, 1.0f);
  486. // Fetch Polygon Vertex Count.
  487. const U32 polyVertexCount = mPolygonBasisList.size();
  488. F32 minX = 0;
  489. F32 minY = 0;
  490. F32 maxX = 0;
  491. F32 maxY = 0;
  492. // Process Collision Polygon (if we've got one).
  493. if ( polyVertexCount > 0 )
  494. {
  495. // Scale/Orientate Polygon.
  496. for ( U32 n = 0; n < polyVertexCount; n++ )
  497. {
  498. // Fetch Polygon Basis.
  499. Vector2 polyVertex = mPolygonBasisList[n];
  500. if (polyVertex.x > maxX)
  501. maxX = polyVertex.x;
  502. else if (polyVertex.x < minX)
  503. minX = polyVertex.x;
  504. if (polyVertex.y > maxY)
  505. maxY = polyVertex.y;
  506. else if (polyVertex.y < minY)
  507. minY = polyVertex.y;
  508. }
  509. }
  510. box.x = maxX - minX;
  511. box.y = maxY - minY;
  512. return box;
  513. }