gfxDrawUtil.cpp 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583
  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 "gfx/gfxDrawUtil.h"
  24. #include "core/frameAllocator.h"
  25. #include "core/strings/stringFunctions.h"
  26. #include "core/strings/unicode.h"
  27. #include "math/util/frustum.h"
  28. #include "math/util/sphereMesh.h"
  29. #include "math/mathUtils.h"
  30. #include "gfx/gfxFontRenderBatcher.h"
  31. #include "gfx/gfxTransformSaver.h"
  32. #include "gfx/gfxPrimitiveBuffer.h"
  33. #include "gfx/primBuilder.h"
  34. #include "gfx/gfxDebugEvent.h"
  35. #include "math/mPolyhedron.impl.h"
  36. GFXDrawUtil::GFXDrawUtil( GFXDevice * d)
  37. {
  38. mDevice = d;
  39. mBitmapModulation.set(0xFF, 0xFF, 0xFF, 0xFF);
  40. mTextAnchorColor.set(0xFF, 0xFF, 0xFF, 0xFF);
  41. mFontRenderBatcher = new FontRenderBatcher();
  42. _setupStateBlocks();
  43. }
  44. GFXDrawUtil::~GFXDrawUtil()
  45. {
  46. delete mFontRenderBatcher;
  47. }
  48. void GFXDrawUtil::_setupStateBlocks()
  49. {
  50. // DrawBitmapStretchSR
  51. GFXStateBlockDesc bitmapStretchSR;
  52. bitmapStretchSR.setCullMode(GFXCullNone);
  53. bitmapStretchSR.setZReadWrite(false);
  54. bitmapStretchSR.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
  55. bitmapStretchSR.samplersDefined = true;
  56. // Linear: Create wrap SB
  57. bitmapStretchSR.samplers[0] = GFXSamplerStateDesc::getWrapLinear();
  58. mBitmapStretchWrapLinearSB = mDevice->createStateBlock(bitmapStretchSR);
  59. // Linear: Create clamp SB
  60. bitmapStretchSR.samplers[0] = GFXSamplerStateDesc::getClampLinear();
  61. mBitmapStretchLinearSB = mDevice->createStateBlock(bitmapStretchSR);
  62. // Point:
  63. bitmapStretchSR.samplers[0].minFilter = GFXTextureFilterPoint;
  64. bitmapStretchSR.samplers[0].mipFilter = GFXTextureFilterPoint;
  65. bitmapStretchSR.samplers[0].magFilter = GFXTextureFilterPoint;
  66. // Point: Create clamp SB, last created clamped so no work required here
  67. mBitmapStretchSB = mDevice->createStateBlock(bitmapStretchSR);
  68. // Point: Create wrap SB, have to do this manually because getWrapLinear doesn't
  69. bitmapStretchSR.samplers[0].addressModeU = GFXAddressWrap;
  70. bitmapStretchSR.samplers[0].addressModeV = GFXAddressWrap;
  71. bitmapStretchSR.samplers[0].addressModeW = GFXAddressWrap;
  72. mBitmapStretchWrapSB = mDevice->createStateBlock(bitmapStretchSR);
  73. GFXStateBlockDesc rectFill;
  74. rectFill.setCullMode(GFXCullNone);
  75. rectFill.setZReadWrite(false);
  76. rectFill.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
  77. mRectFillSB = mDevice->createStateBlock(rectFill);
  78. }
  79. //-----------------------------------------------------------------------------
  80. // Color Modulation
  81. //-----------------------------------------------------------------------------
  82. void GFXDrawUtil::setBitmapModulation( const ColorI &modColor )
  83. {
  84. mBitmapModulation = modColor;
  85. }
  86. void GFXDrawUtil::clearBitmapModulation()
  87. {
  88. mBitmapModulation.set( 255, 255, 255, 255 );
  89. }
  90. void GFXDrawUtil::getBitmapModulation( ColorI *color )
  91. {
  92. mBitmapModulation.getColor( color );
  93. }
  94. void GFXDrawUtil::setTextAnchorColor( const ColorI &ancColor )
  95. {
  96. mTextAnchorColor = ancColor;
  97. }
  98. //-----------------------------------------------------------------------------
  99. // Draw Text
  100. //-----------------------------------------------------------------------------
  101. U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF16 *in_string,
  102. const ColorI *colorTable, const U32 maxColorIndex, F32 rot )
  103. {
  104. return drawTextN( font, ptDraw, in_string, dStrlen(in_string), colorTable, maxColorIndex, rot );
  105. }
  106. U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF8 *in_string,
  107. const ColorI *colorTable, const U32 maxColorIndex, F32 rot )
  108. {
  109. return drawTextN( font, ptDraw, in_string, dStrlen(in_string), colorTable, maxColorIndex, rot );
  110. }
  111. U32 GFXDrawUtil::drawText( GFont *font, const Point2F &ptDraw, const UTF8 *in_string, const ColorI *colorTable /*= NULL*/, const U32 maxColorIndex /*= 9*/, F32 rot /*= 0.f */ )
  112. {
  113. return drawText(font,Point2I((S32)ptDraw.x,(S32)ptDraw.y),in_string,colorTable,maxColorIndex,rot);
  114. }
  115. U32 GFXDrawUtil::drawText( GFont *font, const Point2F &ptDraw, const UTF16 *in_string, const ColorI *colorTable /*= NULL*/, const U32 maxColorIndex /*= 9*/, F32 rot /*= 0.f */ )
  116. {
  117. return drawText(font,Point2I((S32)ptDraw.x,(S32)ptDraw.y),in_string,colorTable,maxColorIndex,rot);
  118. }
  119. U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF8 *in_string, U32 n,
  120. const ColorI *colorTable, const U32 maxColorIndex, F32 rot )
  121. {
  122. // return on zero length strings
  123. if( n == 0 )
  124. return ptDraw.x;
  125. // Convert to UTF16 temporarily.
  126. n++; // space for null terminator
  127. FrameTemp<UTF16> ubuf( n );
  128. convertUTF8toUTF16N(in_string, ubuf, n);
  129. return drawTextN( font, ptDraw, ubuf, n, colorTable, maxColorIndex, rot );
  130. }
  131. U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_string,
  132. U32 n, const ColorI *colorTable, const U32 maxColorIndex, F32 rot )
  133. {
  134. // return on zero length strings
  135. if( n == 0 )
  136. return ptDraw.x;
  137. // If it's over about 4000 verts we want to break it up
  138. if( n > 666 )
  139. {
  140. U32 left = drawTextN(font, ptDraw, in_string, 666, colorTable, maxColorIndex, rot);
  141. Point2I newDrawPt(left, ptDraw.y);
  142. const UTF16* str = (const UTF16*)in_string;
  143. return drawTextN(font, newDrawPt, &(str[666]), n - 666, colorTable, maxColorIndex, rot);
  144. }
  145. PROFILE_START(GFXDevice_drawTextN);
  146. const PlatformFont::CharInfo *tabci = NULL;
  147. S32 ptX = 0;
  148. // Queue everything for render.
  149. mFontRenderBatcher->init(font, n);
  150. U32 i;
  151. UTF16 c;
  152. for (i = 0, c = in_string[i]; i < n && in_string[i]; i++, c = in_string[i])
  153. {
  154. switch(c)
  155. {
  156. // We have to do a little dance here since \t = 0x9, \n = 0xa, and \r = 0xd
  157. case 1: case 2: case 3: case 4: case 5: case 6: case 7:
  158. case 11: case 12:
  159. case 14:
  160. {
  161. // Color code
  162. if (colorTable)
  163. {
  164. static U8 remap[15] =
  165. {
  166. 0x0, // 0 special null terminator
  167. 0x0, // 1 ascii start-of-heading??
  168. 0x1,
  169. 0x2,
  170. 0x3,
  171. 0x4,
  172. 0x5,
  173. 0x6,
  174. 0x0, // 8 special backspace
  175. 0x0, // 9 special tab
  176. 0x0, // a special \n
  177. 0x7,
  178. 0x8,
  179. 0x0, // a special \r
  180. 0x9
  181. };
  182. U8 remapped = remap[c];
  183. // Ignore if the color is greater than the specified max index:
  184. if ( remapped <= maxColorIndex )
  185. {
  186. const ColorI &clr = colorTable[remapped];
  187. mBitmapModulation = clr;
  188. }
  189. }
  190. // And skip rendering this character.
  191. continue;
  192. }
  193. // reset color?
  194. case 15:
  195. {
  196. mBitmapModulation = mTextAnchorColor;
  197. // And skip rendering this character.
  198. continue;
  199. }
  200. // push color:
  201. case 16:
  202. {
  203. mTextAnchorColor = mBitmapModulation;
  204. // And skip rendering this character.
  205. continue;
  206. }
  207. // pop color:
  208. case 17:
  209. {
  210. mBitmapModulation = mTextAnchorColor;
  211. // And skip rendering this character.
  212. continue;
  213. }
  214. // Tab character
  215. case dT('\t'):
  216. {
  217. if ( tabci == NULL )
  218. tabci = &(font->getCharInfo( dT(' ') ));
  219. const U32 fontTabIncrement = tabci->xIncrement * GFont::TabWidthInSpaces;
  220. ptX += fontTabIncrement;
  221. // And skip rendering this character.
  222. continue;
  223. }
  224. // Don't draw invalid characters.
  225. default:
  226. {
  227. if( !font->isValidChar( c ) )
  228. continue;
  229. }
  230. }
  231. // Queue char for rendering..
  232. mFontRenderBatcher->queueChar(c, ptX, mBitmapModulation);
  233. }
  234. mFontRenderBatcher->render(rot, Point2F((F32)ptDraw.x, (F32)ptDraw.y));
  235. PROFILE_END();
  236. return ptX + ptDraw.x;
  237. }
  238. U32 GFXDrawUtil::drawTextN( GFont *font, const Point2F &ptDraw, const UTF8 *in_string, U32 n, const ColorI *colorTable /*= NULL*/, const U32 maxColorIndex /*= 9*/, F32 rot /*= 0.f */ )
  239. {
  240. return drawTextN(font,Point2I((S32)ptDraw.x,(S32)ptDraw.y),in_string,n,colorTable,maxColorIndex,rot);
  241. }
  242. U32 GFXDrawUtil::drawTextN( GFont *font, const Point2F &ptDraw, const UTF16 *in_string, U32 n, const ColorI *colorTable /*= NULL*/, const U32 maxColorIndex /*= 9*/, F32 rot /*= 0.f */ )
  243. {
  244. return drawTextN(font,Point2I((S32)ptDraw.x,(S32)ptDraw.y),in_string,n,colorTable,maxColorIndex,rot);
  245. }
  246. //-----------------------------------------------------------------------------
  247. // Draw Bitmaps
  248. //-----------------------------------------------------------------------------
  249. void GFXDrawUtil::drawBitmap( GFXTextureObject* texture, const Point2I &in_rAt, const GFXBitmapFlip in_flip, const GFXTextureFilterType filter , bool in_wrap /*= true*/ )
  250. {
  251. drawBitmap(texture,Point2F((F32)in_rAt.x,(F32)in_rAt.y),in_flip,filter,in_wrap);
  252. }
  253. void GFXDrawUtil::drawBitmapStretch( GFXTextureObject* texture, const RectI &dstRect, const GFXBitmapFlip in_flip, const GFXTextureFilterType filter , bool in_wrap /*= true*/ )
  254. {
  255. drawBitmapStretch(texture,RectF((F32)dstRect.point.x,(F32)dstRect.point.y,(F32)dstRect.extent.x,(F32)dstRect.extent.y),in_flip,filter,in_wrap);
  256. }
  257. void GFXDrawUtil::drawBitmapSR( GFXTextureObject* texture, const Point2I &in_rAt, const RectI &srcRect, const GFXBitmapFlip in_flip, const GFXTextureFilterType filter , bool in_wrap /*= true*/ )
  258. {
  259. drawBitmapSR(texture,Point2F((F32)in_rAt.x,(F32)in_rAt.y),RectF((F32)srcRect.point.x,(F32)srcRect.point.y,(F32)srcRect.extent.x,(F32)srcRect.extent.y),in_flip,filter,in_wrap);
  260. }
  261. void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject *texture, const RectI &dstRect, const RectI &srcRect, const GFXBitmapFlip in_flip, const GFXTextureFilterType filter , bool in_wrap /*= true*/ )
  262. {
  263. RectF dstRectF = RectF((F32)dstRect.point.x,(F32)dstRect.point.y,(F32)dstRect.extent.x,(F32)dstRect.extent.y);
  264. RectF srcRectF = RectF((F32)srcRect.point.x,(F32)srcRect.point.y,(F32)srcRect.extent.x,(F32)srcRect.extent.y);
  265. drawBitmapStretchSR(texture,dstRectF,srcRectF,in_flip,filter,in_wrap);
  266. }
  267. void GFXDrawUtil::drawBitmap( GFXTextureObject*texture, const Point2F &in_rAt, const GFXBitmapFlip in_flip /*= GFXBitmapFlip_None*/, const GFXTextureFilterType filter /*= GFXTextureFilterPoint */ , bool in_wrap /*= true*/ )
  268. {
  269. AssertFatal( texture != 0, "No texture specified for drawBitmap()" );
  270. RectI subRegion( 0, 0, texture->mBitmapSize.x, texture->mBitmapSize.y );
  271. RectI stretch( in_rAt.x, in_rAt.y, texture->mBitmapSize.x, texture->mBitmapSize.y );
  272. drawBitmapStretchSR( texture, stretch, subRegion, in_flip, filter, in_wrap );
  273. }
  274. void GFXDrawUtil::drawBitmapStretch( GFXTextureObject*texture, const RectF &dstRect, const GFXBitmapFlip in_flip /*= GFXBitmapFlip_None*/, const GFXTextureFilterType filter /*= GFXTextureFilterPoint */ , bool in_wrap /*= true*/ )
  275. {
  276. AssertFatal( texture != 0, "No texture specified for drawBitmapStretch()" );
  277. RectF subRegion( 0.f, 0.f, (F32)texture->mBitmapSize.x, (F32)texture->mBitmapSize.y );
  278. drawBitmapStretchSR( texture, dstRect, subRegion, in_flip, filter, in_wrap );
  279. }
  280. void GFXDrawUtil::drawBitmapSR( GFXTextureObject*texture, const Point2F &in_rAt, const RectF &srcRect, const GFXBitmapFlip in_flip /*= GFXBitmapFlip_None*/, const GFXTextureFilterType filter /*= GFXTextureFilterPoint */ , bool in_wrap /*= true*/ )
  281. {
  282. AssertFatal( texture != 0, "No texture specified for drawBitmapSR()" );
  283. RectF stretch( in_rAt.x, in_rAt.y, srcRect.len_x(), srcRect.len_y() );
  284. drawBitmapStretchSR( texture, stretch, srcRect, in_flip, filter, in_wrap );
  285. }
  286. void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &dstRect, const RectF &srcRect, const GFXBitmapFlip in_flip /*= GFXBitmapFlip_None*/, const GFXTextureFilterType filter /*= GFXTextureFilterPoint */ , bool in_wrap /*= true*/ )
  287. {
  288. // Sanity if no texture is specified.
  289. if(!texture)
  290. return;
  291. GFXVertexBufferHandle<GFXVertexPCT> verts(mDevice, 4, GFXBufferTypeVolatile );
  292. verts.lock();
  293. F32 texLeft = (srcRect.point.x) / (texture->mTextureSize.x);
  294. F32 texRight = (srcRect.point.x + srcRect.extent.x) / (texture->mTextureSize.x);
  295. F32 texTop = (srcRect.point.y) / (texture->mTextureSize.y);
  296. F32 texBottom = (srcRect.point.y + srcRect.extent.y) / (texture->mTextureSize.y);
  297. F32 screenLeft = dstRect.point.x;
  298. F32 screenRight = (dstRect.point.x + dstRect.extent.x);
  299. F32 screenTop = dstRect.point.y;
  300. F32 screenBottom = (dstRect.point.y + dstRect.extent.y);
  301. if( in_flip & GFXBitmapFlip_X )
  302. {
  303. F32 temp = texLeft;
  304. texLeft = texRight;
  305. texRight = temp;
  306. }
  307. if( in_flip & GFXBitmapFlip_Y )
  308. {
  309. F32 temp = texTop;
  310. texTop = texBottom;
  311. texBottom = temp;
  312. }
  313. const F32 fillConv = mDevice->getFillConventionOffset();
  314. verts[0].point.set( screenLeft - fillConv, screenTop - fillConv, 0.f );
  315. verts[1].point.set( screenRight - fillConv, screenTop - fillConv, 0.f );
  316. verts[2].point.set( screenLeft - fillConv, screenBottom - fillConv, 0.f );
  317. verts[3].point.set( screenRight - fillConv, screenBottom - fillConv, 0.f );
  318. verts[0].color = verts[1].color = verts[2].color = verts[3].color = mBitmapModulation;
  319. verts[0].texCoord.set( texLeft, texTop );
  320. verts[1].texCoord.set( texRight, texTop );
  321. verts[2].texCoord.set( texLeft, texBottom );
  322. verts[3].texCoord.set( texRight, texBottom );
  323. verts.unlock();
  324. mDevice->setVertexBuffer( verts );
  325. switch (filter)
  326. {
  327. case GFXTextureFilterPoint :
  328. mDevice->setStateBlock(in_wrap ? mBitmapStretchWrapSB : mBitmapStretchSB);
  329. break;
  330. case GFXTextureFilterLinear :
  331. mDevice->setStateBlock(in_wrap ? mBitmapStretchWrapLinearSB : mBitmapStretchLinearSB);
  332. break;
  333. default:
  334. AssertFatal(false, "No GFXDrawUtil state block defined for this filter type!");
  335. mDevice->setStateBlock(mBitmapStretchSB);
  336. break;
  337. }
  338. mDevice->setTexture( 0, texture );
  339. mDevice->setupGenericShaders( GFXDevice::GSModColorTexture );
  340. mDevice->drawPrimitive( GFXTriangleStrip, 0, 2 );
  341. }
  342. //-----------------------------------------------------------------------------
  343. // Draw Rectangle
  344. //-----------------------------------------------------------------------------
  345. void GFXDrawUtil::drawRect( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color )
  346. {
  347. drawRect( Point2F((F32)upperLeft.x,(F32)upperLeft.y),Point2F((F32)lowerRight.x,(F32)lowerRight.y),color);
  348. }
  349. void GFXDrawUtil::drawRect( const RectI &rect, const ColorI &color )
  350. {
  351. drawRect( rect.point, Point2I(rect.point.x + rect.extent.x - 1, rect.point.y + rect.extent.y - 1), color );
  352. }
  353. void GFXDrawUtil::drawRect( const RectF &rect, const ColorI &color )
  354. {
  355. drawRect( rect.point, Point2F(rect.point.x + rect.extent.x - 1, rect.point.y + rect.extent.y - 1), color );
  356. }
  357. void GFXDrawUtil::drawRect( const Point2F &upperLeft, const Point2F &lowerRight, const ColorI &color )
  358. {
  359. //
  360. // Convert Box a----------x
  361. // | |
  362. // x----------b
  363. //
  364. // Into Triangle-Strip Outline
  365. // v0-----------v2
  366. // | a x |
  367. // | v1-----v3 |
  368. // | | | |
  369. // | v7-----v5 |
  370. // | x b |
  371. // v6-----------v4
  372. //
  373. // NorthWest and NorthEast facing offset vectors
  374. // These adjust the thickness of the line, it'd be neat if one day
  375. // they were passed in as arguments.
  376. Point2F nw(-0.5f,-0.5f); /* \ */
  377. Point2F ne(0.5f,-0.5f); /* / */
  378. GFXVertexBufferHandle<GFXVertexPC> verts (mDevice, 10, GFXBufferTypeVolatile );
  379. verts.lock();
  380. F32 ulOffset = 0.5f - mDevice->getFillConventionOffset();
  381. verts[0].point.set( upperLeft.x + ulOffset + nw.x, upperLeft.y + ulOffset + nw.y, 0.0f );
  382. verts[1].point.set( upperLeft.x + ulOffset - nw.x, upperLeft.y + ulOffset - nw.y, 0.0f );
  383. verts[2].point.set( lowerRight.x + ne.x, upperLeft.y + ulOffset + ne.y, 0.0f );
  384. verts[3].point.set( lowerRight.x - ne.x, upperLeft.y + ulOffset - ne.y, 0.0f );
  385. verts[4].point.set( lowerRight.x - nw.x, lowerRight.y - nw.y, 0.0f );
  386. verts[5].point.set( lowerRight.x + nw.x, lowerRight.y + nw.y, 0.0f );
  387. verts[6].point.set( upperLeft.x + ulOffset - ne.x, lowerRight.y - ne.y, 0.0f );
  388. verts[7].point.set( upperLeft.x + ulOffset + ne.x, lowerRight.y + ne.y, 0.0f );
  389. verts[8].point.set( upperLeft.x + ulOffset + nw.x, upperLeft.y + ulOffset + nw.y, 0.0f ); // same as 0
  390. verts[9].point.set( upperLeft.x + ulOffset - nw.x, upperLeft.y + ulOffset - nw.y, 0.0f ); // same as 1
  391. for (S32 i=0; i<10; i++)
  392. verts[i].color = color;
  393. verts.unlock();
  394. mDevice->setVertexBuffer( verts );
  395. mDevice->setStateBlock(mRectFillSB);
  396. mDevice->setupGenericShaders();
  397. mDevice->drawPrimitive( GFXTriangleStrip, 0, 8 );
  398. }
  399. //-----------------------------------------------------------------------------
  400. // Draw Rectangle Fill
  401. //-----------------------------------------------------------------------------
  402. void GFXDrawUtil::drawRectFill( const RectF &rect, const ColorI &color )
  403. {
  404. drawRectFill(rect.point, Point2F(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color );
  405. }
  406. void GFXDrawUtil::drawRectFill( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color )
  407. {
  408. drawRectFill(Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color);
  409. }
  410. void GFXDrawUtil::drawRectFill( const RectI &rect, const ColorI &color )
  411. {
  412. drawRectFill(rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color );
  413. }
  414. void GFXDrawUtil::drawRectFill( const Point2F &upperLeft, const Point2F &lowerRight, const ColorI &color )
  415. {
  416. //
  417. // Convert Box a----------x
  418. // | |
  419. // x----------b
  420. // Into Quad
  421. // v0---------v1
  422. // | a x |
  423. // | |
  424. // | x b |
  425. // v2---------v3
  426. //
  427. // NorthWest and NorthEast facing offset vectors
  428. Point2F nw(-0.5,-0.5); /* \ */
  429. Point2F ne(0.5,-0.5); /* / */
  430. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, 4, GFXBufferTypeVolatile);
  431. verts.lock();
  432. F32 ulOffset = 0.5f - mDevice->getFillConventionOffset();
  433. verts[0].point.set( upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset, 0.0f);
  434. verts[1].point.set( lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f);
  435. verts[2].point.set( upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f);
  436. verts[3].point.set( lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f);
  437. for (S32 i=0; i<4; i++)
  438. verts[i].color = color;
  439. verts.unlock();
  440. mDevice->setStateBlock(mRectFillSB);
  441. mDevice->setVertexBuffer( verts );
  442. mDevice->setupGenericShaders();
  443. mDevice->drawPrimitive( GFXTriangleStrip, 0, 2 );
  444. }
  445. void GFXDrawUtil::draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle )
  446. {
  447. width *= 0.5;
  448. Point3F offset( screenPoint.x, screenPoint.y, 0.0 );
  449. GFXVertexBufferHandle<GFXVertexPC> verts( mDevice, 4, GFXBufferTypeVolatile );
  450. verts.lock();
  451. verts[0].point.set( -width, -width, 0.0f );
  452. verts[1].point.set( -width, width, 0.0f );
  453. verts[2].point.set( width, -width, 0.0f );
  454. verts[3].point.set( width, width, 0.0f );
  455. verts[0].color = verts[1].color = verts[2].color = verts[3].color = mBitmapModulation;
  456. if (spinAngle == 0.0f)
  457. {
  458. for( S32 i = 0; i < 4; i++ )
  459. verts[i].point += offset;
  460. }
  461. else
  462. {
  463. MatrixF rotMatrix( EulerF( 0.0, 0.0, spinAngle ) );
  464. for( S32 i = 0; i < 4; i++ )
  465. {
  466. rotMatrix.mulP( verts[i].point );
  467. verts[i].point += offset;
  468. }
  469. }
  470. verts.unlock();
  471. mDevice->setVertexBuffer( verts );
  472. mDevice->setStateBlock(mRectFillSB);
  473. mDevice->setupGenericShaders();
  474. mDevice->drawPrimitive( GFXTriangleStrip, 0, 2 );
  475. }
  476. //-----------------------------------------------------------------------------
  477. // Draw Line
  478. //-----------------------------------------------------------------------------
  479. void GFXDrawUtil::drawLine( const Point3F &startPt, const Point3F &endPt, const ColorI &color )
  480. {
  481. drawLine( startPt.x, startPt.y, startPt.z, endPt.x, endPt.y, endPt.z, color );
  482. }
  483. void GFXDrawUtil::drawLine( const Point2F &startPt, const Point2F &endPt, const ColorI &color )
  484. {
  485. drawLine( startPt.x, startPt.y, 0.0f, endPt.x, endPt.y, 0.0f, color );
  486. }
  487. void GFXDrawUtil::drawLine( const Point2I &startPt, const Point2I &endPt, const ColorI &color )
  488. {
  489. drawLine( startPt.x, startPt.y, 0.0f, endPt.x, endPt.y, 0.0f, color );
  490. }
  491. void GFXDrawUtil::drawLine( F32 x1, F32 y1, F32 x2, F32 y2, const ColorI &color )
  492. {
  493. drawLine( x1, y1, 0.0f, x2, y2, 0.0f, color );
  494. }
  495. void GFXDrawUtil::drawLine( F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI &color )
  496. {
  497. GFXVertexBufferHandle<GFXVertexPC> verts( mDevice, 2, GFXBufferTypeVolatile );
  498. verts.lock();
  499. verts[0].point.set( x1, y1, z1 );
  500. verts[1].point.set( x2, y2, z2 );
  501. verts[0].color = color;
  502. verts[1].color = color;
  503. verts.unlock();
  504. mDevice->setVertexBuffer( verts );
  505. mDevice->setStateBlock( mRectFillSB );
  506. mDevice->setupGenericShaders();
  507. mDevice->drawPrimitive( GFXLineList, 0, 1 );
  508. }
  509. //-----------------------------------------------------------------------------
  510. // 3D World Draw Misc
  511. //-----------------------------------------------------------------------------
  512. static SphereMesh gSphere;
  513. void GFXDrawUtil::drawSphere( const GFXStateBlockDesc &desc, F32 radius, const Point3F &pos, const ColorI &color, bool drawTop, bool drawBottom, const MatrixF *xfm )
  514. {
  515. MatrixF mat;
  516. if ( xfm )
  517. mat = *xfm;
  518. else
  519. mat = MatrixF::Identity;
  520. mat.scale(Point3F(radius,radius,radius));
  521. mat.setPosition(pos);
  522. GFX->pushWorldMatrix();
  523. GFX->multWorld(mat);
  524. const SphereMesh::TriangleMesh * sphereMesh = gSphere.getMesh(2);
  525. S32 numPoly = sphereMesh->numPoly;
  526. S32 totalPoly = 0;
  527. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, numPoly*3, GFXBufferTypeVolatile);
  528. verts.lock();
  529. S32 vertexIndex = 0;
  530. for (S32 i=0; i<numPoly; i++)
  531. {
  532. if (!drawBottom)
  533. {
  534. if (sphereMesh->poly[i].pnt[0].z < -0.01f || sphereMesh->poly[i].pnt[1].z < -0.01f || sphereMesh->poly[i].pnt[2].z < -0.01f)
  535. continue;
  536. }
  537. if (!drawTop)
  538. {
  539. if (sphereMesh->poly[i].pnt[0].z > 0.01f || sphereMesh->poly[i].pnt[1].z > 0.01f || sphereMesh->poly[i].pnt[2].z > 0.01f)
  540. continue;
  541. }
  542. totalPoly++;
  543. verts[vertexIndex].point = sphereMesh->poly[i].pnt[0];
  544. verts[vertexIndex].color = color;
  545. vertexIndex++;
  546. verts[vertexIndex].point = sphereMesh->poly[i].pnt[1];
  547. verts[vertexIndex].color = color;
  548. vertexIndex++;
  549. verts[vertexIndex].point = sphereMesh->poly[i].pnt[2];
  550. verts[vertexIndex].color = color;
  551. vertexIndex++;
  552. }
  553. verts.unlock();
  554. mDevice->setStateBlockByDesc( desc );
  555. mDevice->setVertexBuffer( verts );
  556. mDevice->setupGenericShaders();
  557. mDevice->drawPrimitive( GFXTriangleList, 0, totalPoly );
  558. GFX->popWorldMatrix();
  559. }
  560. //-----------------------------------------------------------------------------
  561. static const Point3F cubePoints[8] =
  562. {
  563. Point3F(-1, -1, -1), Point3F(-1, -1, 1), Point3F(-1, 1, -1), Point3F(-1, 1, 1),
  564. Point3F( 1, -1, -1), Point3F( 1, -1, 1), Point3F( 1, 1, -1), Point3F( 1, 1, 1)
  565. };
  566. static const U32 cubeFaces[6][4] =
  567. {
  568. { 0, 4, 6, 2 }, { 0, 2, 3, 1 }, { 0, 1, 5, 4 },
  569. { 3, 2, 6, 7 }, { 7, 6, 4, 5 }, { 3, 7, 5, 1 }
  570. };
  571. void GFXDrawUtil::drawTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm )
  572. {
  573. if ( desc.fillMode == GFXFillWireframe )
  574. _drawWireTriangle( desc, p0, p1, p2, color, xfm );
  575. else
  576. _drawSolidTriangle( desc, p0, p1, p2, color, xfm );
  577. }
  578. void GFXDrawUtil::_drawWireTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm )
  579. {
  580. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, 4, GFXBufferTypeVolatile);
  581. verts.lock();
  582. // Set up the line strip
  583. verts[0].point = p0;
  584. verts[0].color = color;
  585. verts[1].point = p1;
  586. verts[1].color = color;
  587. verts[2].point = p2;
  588. verts[2].color = color;
  589. verts[3].point = p0;
  590. verts[3].color = color;
  591. // Apply xfm if we were passed one.
  592. if ( xfm != NULL )
  593. {
  594. for ( U32 i = 0; i < 4; i++ )
  595. xfm->mulP( verts[i].point );
  596. }
  597. verts.unlock();
  598. GFXStateBlockRef sb = mDevice->createStateBlock( desc );
  599. mDevice->setStateBlock( sb );
  600. mDevice->setVertexBuffer( verts );
  601. mDevice->setupGenericShaders();
  602. mDevice->drawPrimitive( GFXLineStrip, 0, 3 );
  603. }
  604. void GFXDrawUtil::_drawSolidTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm )
  605. {
  606. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, 3, GFXBufferTypeVolatile);
  607. verts.lock();
  608. // Set up the line strip
  609. verts[0].point = p0;
  610. verts[0].color = color;
  611. verts[1].point = p1;
  612. verts[1].color = color;
  613. verts[2].point = p2;
  614. verts[2].color = color;
  615. // Apply xfm if we were passed one.
  616. if ( xfm != NULL )
  617. {
  618. for ( U32 i = 0; i < 3; i++ )
  619. xfm->mulP( verts[i].point );
  620. }
  621. verts.unlock();
  622. GFXStateBlockRef sb = mDevice->createStateBlock( desc );
  623. mDevice->setStateBlock( sb );
  624. mDevice->setVertexBuffer( verts );
  625. mDevice->setupGenericShaders();
  626. mDevice->drawPrimitive( GFXTriangleList, 0, 1 );
  627. }
  628. void GFXDrawUtil::drawPolygon( const GFXStateBlockDesc& desc, const Point3F* points, U32 numPoints, const ColorI& color, const MatrixF* xfm /* = NULL */ )
  629. {
  630. const bool isWireframe = ( desc.fillMode == GFXFillWireframe );
  631. const U32 numVerts = isWireframe ? numPoints + 1 : numPoints;
  632. GFXVertexBufferHandle< GFXVertexPC > verts( mDevice, numVerts, GFXBufferTypeVolatile );
  633. verts.lock();
  634. for( U32 i = 0; i < numPoints; ++ i )
  635. {
  636. verts[ i ].point = points[ i ];
  637. verts[ i ].color = color;
  638. }
  639. if( xfm )
  640. {
  641. for( U32 i = 0; i < numPoints; ++ i )
  642. xfm->mulP( verts[ i ].point );
  643. }
  644. if( isWireframe )
  645. {
  646. verts[ numVerts - 1 ].point = verts[ 0 ].point;
  647. verts[ numVerts - 1 ].color = color;
  648. }
  649. verts.unlock();
  650. mDevice->setStateBlockByDesc( desc );
  651. mDevice->setVertexBuffer( verts );
  652. mDevice->setupGenericShaders();
  653. if( desc.fillMode == GFXFillWireframe )
  654. mDevice->drawPrimitive( GFXLineStrip, 0, numPoints );
  655. else
  656. mDevice->drawPrimitive( GFXTriangleFan, 0, numPoints - 2 );
  657. }
  658. void GFXDrawUtil::drawCube( const GFXStateBlockDesc &desc, const Box3F &box, const ColorI &color, const MatrixF *xfm )
  659. {
  660. drawCube( desc, box.getExtents(), box.getCenter(), color, xfm );
  661. }
  662. void GFXDrawUtil::drawCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm )
  663. {
  664. if ( desc.fillMode == GFXFillWireframe )
  665. _drawWireCube( desc, size, pos, color, xfm );
  666. else
  667. _drawSolidCube( desc, size, pos, color, xfm );
  668. }
  669. void GFXDrawUtil::_drawWireCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm )
  670. {
  671. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, 30, GFXBufferTypeVolatile);
  672. verts.lock();
  673. Point3F halfSize = size * 0.5f;
  674. // setup 6 line loops
  675. U32 vertexIndex = 0;
  676. for(S32 i = 0; i < 6; i++)
  677. {
  678. for(S32 j = 0; j < 5; j++)
  679. {
  680. S32 idx = cubeFaces[i][j%4];
  681. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  682. verts[vertexIndex].color = color;
  683. vertexIndex++;
  684. }
  685. }
  686. // Apply xfm if we were passed one.
  687. if ( xfm != NULL )
  688. {
  689. for ( U32 i = 0; i < 30; i++ )
  690. xfm->mulP( verts[i].point );
  691. }
  692. // Apply position offset
  693. for ( U32 i = 0; i < 30; i++ )
  694. verts[i].point += pos;
  695. verts.unlock();
  696. mDevice->setStateBlockByDesc( desc );
  697. mDevice->setVertexBuffer( verts );
  698. mDevice->setupGenericShaders();
  699. for( U32 i=0; i<6; i++ )
  700. mDevice->drawPrimitive( GFXLineStrip, i*5, 4 );
  701. }
  702. void GFXDrawUtil::_drawSolidCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm )
  703. {
  704. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, 36, GFXBufferTypeVolatile);
  705. verts.lock();
  706. Point3F halfSize = size * 0.5f;
  707. // setup 6 line loops
  708. U32 vertexIndex = 0;
  709. U32 idx;
  710. for(S32 i = 0; i < 6; i++)
  711. {
  712. idx = cubeFaces[i][0];
  713. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  714. verts[vertexIndex].color = color;
  715. vertexIndex++;
  716. idx = cubeFaces[i][1];
  717. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  718. verts[vertexIndex].color = color;
  719. vertexIndex++;
  720. idx = cubeFaces[i][3];
  721. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  722. verts[vertexIndex].color = color;
  723. vertexIndex++;
  724. idx = cubeFaces[i][1];
  725. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  726. verts[vertexIndex].color = color;
  727. vertexIndex++;
  728. idx = cubeFaces[i][2];
  729. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  730. verts[vertexIndex].color = color;
  731. vertexIndex++;
  732. idx = cubeFaces[i][3];
  733. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  734. verts[vertexIndex].color = color;
  735. vertexIndex++;
  736. }
  737. // Apply xfm if we were passed one.
  738. if ( xfm != NULL )
  739. {
  740. for ( U32 i = 0; i < 36; i++ )
  741. xfm->mulV( verts[i].point );
  742. }
  743. // Apply position offset
  744. for ( U32 i = 0; i < 36; i++ )
  745. verts[i].point += pos;
  746. verts.unlock();
  747. mDevice->setStateBlockByDesc( desc );
  748. mDevice->setVertexBuffer( verts );
  749. mDevice->setupGenericShaders();
  750. mDevice->drawPrimitive( GFXTriangleList, 0, 12 );
  751. }
  752. void GFXDrawUtil::drawPolyhedron( const GFXStateBlockDesc &desc, const AnyPolyhedron &poly, const ColorI &color, const MatrixF *xfm )
  753. {
  754. if ( desc.fillMode == GFXFillWireframe )
  755. _drawWirePolyhedron( desc, poly, color, xfm );
  756. else
  757. _drawSolidPolyhedron( desc, poly, color, xfm );
  758. }
  759. void GFXDrawUtil::_drawWirePolyhedron( const GFXStateBlockDesc &desc, const AnyPolyhedron &poly, const ColorI &color, const MatrixF *xfm )
  760. {
  761. GFXDEBUGEVENT_SCOPE( GFXDrawUtil_DrawWirePolyhedron, ColorI::GREEN );
  762. const U32 numEdges = poly.getNumEdges();
  763. const Point3F* points = poly.getPoints();
  764. const Polyhedron::Edge* edges = poly.getEdges();
  765. // Allocate a temporary vertex buffer.
  766. GFXVertexBufferHandle< GFXVertexPC > verts( mDevice, numEdges * 2, GFXBufferTypeVolatile);
  767. // Fill it with the vertices for the edges.
  768. verts.lock();
  769. for( U32 i = 0; i < numEdges; ++ i )
  770. {
  771. const U32 nvert = i * 2;
  772. verts[ nvert + 0 ].point = points[ edges[ i ].vertex[ 0 ] ];
  773. verts[ nvert + 0 ].color = color;
  774. verts[ nvert + 1 ].point = points[ edges[ i ].vertex[ 1 ] ];
  775. verts[ nvert + 1 ].color = color;
  776. }
  777. if( xfm )
  778. {
  779. for( U32 i = 0; i < numEdges; ++ i )
  780. {
  781. xfm->mulP( verts[ i + 0 ].point );
  782. xfm->mulP( verts[ i + 1 ].point );
  783. }
  784. }
  785. verts.unlock();
  786. // Render the line list.
  787. mDevice->setStateBlockByDesc( desc );
  788. mDevice->setVertexBuffer( verts );
  789. mDevice->setupGenericShaders();
  790. mDevice->drawPrimitive( GFXLineList, 0, numEdges );
  791. }
  792. void GFXDrawUtil::_drawSolidPolyhedron( const GFXStateBlockDesc &desc, const AnyPolyhedron &poly, const ColorI &color, const MatrixF *xfm )
  793. {
  794. GFXDEBUGEVENT_SCOPE( GFXDrawUtil_DrawSolidPolyhedron, ColorI::GREEN );
  795. const U32 numPoints = poly.getNumPoints();
  796. const Point3F* points = poly.getPoints();
  797. const PlaneF* planes = poly.getPlanes();
  798. const Point3F viewDir = GFX->getViewMatrix().getForwardVector();
  799. // Create a temp buffer for the vertices and
  800. // put all the polyhedron's points in there.
  801. GFXVertexBufferHandle< GFXVertexPC > verts( mDevice, numPoints, GFXBufferTypeVolatile );
  802. verts.lock();
  803. for( U32 i = 0; i < numPoints; ++ i )
  804. {
  805. verts[ i ].point = points[ i ];
  806. verts[ i ].color = color;
  807. }
  808. if( xfm )
  809. {
  810. for( U32 i = 0; i < numPoints; ++ i )
  811. xfm->mulP( verts[ i ].point );
  812. }
  813. verts.unlock();
  814. // Allocate a temp buffer for the face indices.
  815. const U32 numIndices = poly.getNumEdges() * 2;
  816. const U32 numPlanes = poly.getNumPlanes();
  817. GFXPrimitiveBufferHandle prims( mDevice, numIndices, 0, GFXBufferTypeVolatile );
  818. // Unfortunately, since polygons may have varying numbers of
  819. // vertices, we also need to retain that information.
  820. FrameTemp< U32 > numIndicesForPoly( numPlanes );
  821. U32 numPolys = 0;
  822. // Create all the polygon indices.
  823. U16* indices;
  824. prims.lock( &indices );
  825. U32 idx = 0;
  826. for( U32 i = 0; i < numPlanes; ++ i )
  827. {
  828. // Since face extraction is somewhat costly, don't bother doing it for
  829. // backfacing polygons if culling is enabled.
  830. if( !desc.cullDefined || desc.cullMode != GFXCullNone )
  831. {
  832. F32 dot = mDot( planes[ i ], viewDir );
  833. // See if it faces *the same way* as the view direction. This would
  834. // normally mean that the face is *not* backfacing but since we expect
  835. // planes on the polyhedron to be facing *inwards*, we need to reverse
  836. // the logic here.
  837. if( dot > 0.f )
  838. continue;
  839. }
  840. U32 numPoints = poly.extractFace( i, &indices[ idx ], numIndices - idx );
  841. numIndicesForPoly[ numPolys ] = numPoints;
  842. idx += numPoints;
  843. numPolys ++;
  844. }
  845. prims.unlock();
  846. // Set up state.
  847. mDevice->setStateBlockByDesc( desc );
  848. mDevice->setupGenericShaders();
  849. mDevice->setVertexBuffer( verts );
  850. mDevice->setPrimitiveBuffer( prims );
  851. // Render one triangle fan for each polygon.
  852. U32 startIndex = 0;
  853. for( U32 i = 0; i < numPolys; ++ i )
  854. {
  855. U32 numVerts = numIndicesForPoly[ i ];
  856. mDevice->drawIndexedPrimitive( GFXTriangleFan, 0, 0, numPoints, startIndex, numVerts - 2 );
  857. startIndex += numVerts;
  858. }
  859. }
  860. void GFXDrawUtil::drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const MatrixF &objMat, const ColorI &color )
  861. {
  862. GFXTransformSaver saver;
  863. mDevice->setStateBlockByDesc( desc );
  864. MatrixF scaledObjMat( true );
  865. scaledObjMat = objMat;
  866. scaledObjMat.scale( size );
  867. scaledObjMat.setPosition( pos );
  868. PrimBuild::color( color );
  869. PrimBuild::begin( GFXLineList, 48 );
  870. static const Point3F cubePoints[8] =
  871. {
  872. Point3F(-0.5, -0.5, -0.5), Point3F(-0.5, -0.5, 0.5), Point3F(-0.5, 0.5, -0.5), Point3F(-0.5, 0.5, 0.5),
  873. Point3F( 0.5, -0.5, -0.5), Point3F( 0.5, -0.5, 0.5), Point3F( 0.5, 0.5, -0.5), Point3F( 0.5, 0.5, 0.5)
  874. };
  875. // 8 corner points of the box
  876. for ( U32 i = 0; i < 8; i++ )
  877. {
  878. //const Point3F &start = cubePoints[i];
  879. // 3 lines per corner point
  880. for ( U32 j = 0; j < 3; j++ )
  881. {
  882. Point3F start = cubePoints[i];
  883. Point3F end = start;
  884. end[j] *= 0.8f;
  885. scaledObjMat.mulP(start);
  886. PrimBuild::vertex3fv(start);
  887. scaledObjMat.mulP(end);
  888. PrimBuild::vertex3fv(end);
  889. }
  890. }
  891. PrimBuild::end();
  892. }
  893. static const Point2F circlePoints[] =
  894. {
  895. Point2F(0.707107f, 0.707107f),
  896. Point2F(0.923880f, 0.382683f),
  897. Point2F(1.000000f, 0.000000f),
  898. Point2F(0.923880f, -0.382684f),
  899. Point2F(0.707107f, -0.707107f),
  900. Point2F(0.382683f, -0.923880f),
  901. Point2F(0.000000f, -1.000000f),
  902. Point2F(-0.382683f, -0.923880f),
  903. Point2F(-0.707107f, -0.707107f),
  904. Point2F(-0.923880f, -0.382684f),
  905. Point2F(-1.000000f, 0.000000f),
  906. Point2F(-0.923879f, 0.382684f),
  907. Point2F(-0.707107f, 0.707107f),
  908. Point2F(-0.382683f, 0.923880f),
  909. Point2F(0.000000f, 1.000000f),
  910. Point2F(0.382684f, 0.923879f)
  911. };
  912. void GFXDrawUtil::drawCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm )
  913. {
  914. if ( desc.fillMode == GFXFillWireframe )
  915. _drawWireCapsule( desc, center, radius, height, color, xfm );
  916. else
  917. _drawSolidCapsule( desc, center, radius, height, color, xfm );
  918. }
  919. void GFXDrawUtil::_drawSolidCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm )
  920. {
  921. MatrixF mat;
  922. if ( xfm )
  923. mat = *xfm;
  924. else
  925. mat = MatrixF::Identity;
  926. S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
  927. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, numPoints * 2 + 2, GFXBufferTypeVolatile);
  928. verts.lock();
  929. for (S32 i=0; i<numPoints + 1; i++)
  930. {
  931. S32 imod = i % numPoints;
  932. verts[2 * i].point = Point3F( circlePoints[imod].x * radius, circlePoints[imod].y * radius, height );
  933. verts[2 * i].color = color;
  934. verts[2 * i + 1].point = Point3F( circlePoints[imod].x * radius, circlePoints[imod].y * radius, -height );
  935. verts[2 * i + 1].color = color;
  936. }
  937. S32 totalNumPnts = numPoints * 2 + 2;
  938. // Apply xfm if we were passed one.
  939. for ( U32 i = 0; i < totalNumPnts; i++ )
  940. mat.mulP( verts[i].point );
  941. // Apply position offset
  942. for ( U32 i = 0; i < totalNumPnts; i++ )
  943. verts[i].point += center;
  944. verts.unlock();
  945. mDevice->setStateBlockByDesc( desc );
  946. mDevice->setVertexBuffer( verts );
  947. mDevice->setupGenericShaders();
  948. mDevice->drawPrimitive( GFXTriangleStrip, 0, 2 * numPoints );
  949. Point3F sphereCenter;
  950. MatrixF sphereMat;
  951. if ( xfm )
  952. sphereMat = *xfm;
  953. else
  954. sphereMat = MatrixF::Identity;
  955. sphereCenter.set( 0, 0, 0.5f * height );
  956. mat.mulV( sphereCenter );
  957. sphereCenter += center;
  958. drawSphere( desc, radius, sphereCenter, color, true, false, &sphereMat );
  959. sphereCenter.set( 0, 0, -0.5f * height );
  960. mat.mulV( sphereCenter );
  961. sphereCenter += center;
  962. drawSphere( desc, radius, sphereCenter, color, false, true, &sphereMat );
  963. }
  964. void GFXDrawUtil::_drawWireCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm )
  965. {
  966. MatrixF mat;
  967. if ( xfm )
  968. mat = *xfm;
  969. else
  970. mat = MatrixF::Identity;
  971. mat.scale( Point3F(radius,radius,height*0.5f) );
  972. mat.setPosition(center);
  973. mDevice->pushWorldMatrix();
  974. mDevice->multWorld(mat);
  975. S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
  976. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, numPoints, GFXBufferTypeVolatile);
  977. verts.lock();
  978. for (S32 i=0; i< numPoints; i++)
  979. {
  980. S32 idx = i & (~1); // just draw the even ones
  981. F32 z = i & 1 ? 1.0f : -1.0f;
  982. verts[i].point = Point3F(circlePoints[idx].x,circlePoints[idx].y, z);
  983. verts[i].color = color;
  984. }
  985. verts.unlock();
  986. mDevice->setStateBlockByDesc( desc );
  987. mDevice->setVertexBuffer( verts );
  988. mDevice->setupGenericShaders();
  989. for (S32 i=0; i<numPoints; i += 2)
  990. mDevice->drawPrimitive(GFXLineStrip, i, 1);
  991. mDevice->popWorldMatrix();
  992. Point3F sphereCenter;
  993. sphereCenter.z = center.z + 0.5f * height;
  994. drawSphere( desc, radius,sphereCenter,color,true,false);
  995. sphereCenter.z = center.z - 0.5f * height;
  996. drawSphere( desc, radius,sphereCenter,color,false,true);
  997. }
  998. void GFXDrawUtil::drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color )
  999. {
  1000. VectorF uvec = tipPnt - basePnt;
  1001. F32 height = uvec.len();
  1002. uvec.normalize();
  1003. MatrixF mat( true );
  1004. MathUtils::getMatrixFromUpVector( uvec, &mat );
  1005. mat.setPosition(basePnt);
  1006. Point3F scale( baseRadius, baseRadius, height );
  1007. mat.scale(scale);
  1008. GFXTransformSaver saver;
  1009. mDevice->pushWorldMatrix();
  1010. mDevice->multWorld(mat);
  1011. S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
  1012. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, numPoints + 2, GFXBufferTypeVolatile);
  1013. verts.lock();
  1014. verts[0].point = Point3F(0.0f,0.0f,1.0f);
  1015. verts[0].color = color;
  1016. for (S32 i=0; i<numPoints + 1; i++)
  1017. {
  1018. S32 imod = i % numPoints;
  1019. verts[i + 1].point = Point3F(circlePoints[imod].x,circlePoints[imod].y, 0.0f);
  1020. verts[i + 1].color = color;
  1021. }
  1022. verts.unlock();
  1023. mDevice->setStateBlockByDesc( desc );
  1024. mDevice->setVertexBuffer( verts );
  1025. mDevice->setupGenericShaders( GFXDevice::GSModColorTexture );
  1026. mDevice->drawPrimitive( GFXTriangleFan, 0, numPoints );
  1027. mDevice->drawPrimitive( GFXTriangleFan, 1, numPoints-1 );
  1028. mDevice->popWorldMatrix();
  1029. }
  1030. void GFXDrawUtil::drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 radius, const ColorI &color )
  1031. {
  1032. VectorF uvec = tipPnt - basePnt;
  1033. F32 height = uvec.len();
  1034. uvec.normalize();
  1035. MatrixF mat( true );
  1036. MathUtils::getMatrixFromUpVector( uvec, &mat );
  1037. mat.setPosition(basePnt);
  1038. Point3F scale( radius, radius, height * 2 );
  1039. mat.scale(scale);
  1040. GFXTransformSaver saver;
  1041. mDevice->pushWorldMatrix();
  1042. mDevice->multWorld(mat);
  1043. S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
  1044. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, numPoints * 4 + 4, GFXBufferTypeVolatile);
  1045. verts.lock();
  1046. for (S32 i=0; i<numPoints + 1; i++)
  1047. {
  1048. S32 imod = i % numPoints;
  1049. verts[i].point = Point3F(circlePoints[imod].x,circlePoints[imod].y, 0.5f);
  1050. verts[i].color = color;
  1051. verts[i + numPoints + 1].point = Point3F(circlePoints[imod].x,circlePoints[imod].y, 0);
  1052. verts[i + numPoints + 1].color = color;
  1053. verts[2*numPoints + 2 + 2 * i].point = Point3F(circlePoints[imod].x,circlePoints[imod].y, 0.5f);
  1054. verts[2*numPoints + 2 + 2 * i].color = color;
  1055. verts[2*numPoints + 2 + 2 * i + 1].point = Point3F(circlePoints[imod].x,circlePoints[imod].y, 0);
  1056. verts[2*numPoints + 2 + 2 * i + 1].color = color;
  1057. }
  1058. verts.unlock();
  1059. mDevice->setStateBlockByDesc( desc );
  1060. mDevice->setVertexBuffer( verts );
  1061. mDevice->setupGenericShaders( GFXDevice::GSModColorTexture );
  1062. mDevice->drawPrimitive( GFXTriangleFan, 0, numPoints );
  1063. mDevice->drawPrimitive( GFXTriangleFan, numPoints + 1, numPoints );
  1064. mDevice->drawPrimitive( GFXTriangleStrip, 2 * numPoints + 2, 2 * numPoints);
  1065. mDevice->popWorldMatrix();
  1066. }
  1067. void GFXDrawUtil::drawArrow( const GFXStateBlockDesc &desc, const Point3F &start, const Point3F &end, const ColorI &color )
  1068. {
  1069. GFXTransformSaver saver;
  1070. // Direction and length of the arrow.
  1071. VectorF dir = end - start;
  1072. F32 len = dir.len();
  1073. dir.normalize();
  1074. len *= 0.2f;
  1075. // Base of the cone will be a distance back from the end of the arrow
  1076. // proportional to the total distance of the arrow... 0.3f looks about right.
  1077. Point3F coneBase = end - dir * len * 0.3f;
  1078. // Calculate the radius of the cone given that we want the cone to have
  1079. // an angle of 25 degrees (just because it looks good).
  1080. F32 coneLen = ( end - coneBase ).len();
  1081. F32 coneDiameter = mTan( mDegToRad(25.0f) ) * coneLen;
  1082. // Draw the cone on at the arrow's tip.
  1083. drawCone( desc, coneBase, end, coneDiameter / 2.0f, color );
  1084. // Get the difference in length from
  1085. // the start of the cone to the end
  1086. // of the cylinder so we can put the
  1087. // end of the cylinder right against where
  1088. // the cone starts.
  1089. Point3F coneDiff = end - coneBase;
  1090. // Draw the cylinder.
  1091. F32 stickRadius = len * 0.025f;
  1092. drawCylinder( desc, start, end - coneDiff, stickRadius, color );
  1093. }
  1094. void GFXDrawUtil::drawFrustum( const Frustum &f, const ColorI &color )
  1095. {
  1096. const Point3F *points = f.getPoints();
  1097. // Draw near and far planes.
  1098. for (U32 offset = 0; offset < 8; offset+=4)
  1099. {
  1100. drawLine(points[offset+0], points[offset+1], color);
  1101. drawLine(points[offset+2], points[offset+3], color);
  1102. drawLine(points[offset+0], points[offset+2], color);
  1103. drawLine(points[offset+1], points[offset+3], color);
  1104. }
  1105. // connect the near and far planes
  1106. drawLine(points[Frustum::NearTopLeft], points[Frustum::FarTopLeft], color);
  1107. drawLine(points[Frustum::NearTopRight], points[Frustum::FarTopRight], color);
  1108. drawLine(points[Frustum::NearBottomLeft], points[Frustum::FarBottomLeft], color);
  1109. drawLine(points[Frustum::NearBottomRight], points[Frustum::FarBottomRight], color);
  1110. }
  1111. void GFXDrawUtil::drawSolidPlane( const GFXStateBlockDesc &desc, const Point3F &pos, const Point2F &size, const ColorI &color )
  1112. {
  1113. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, 4, GFXBufferTypeVolatile);
  1114. verts.lock();
  1115. verts[0].point = pos + Point3F( -size.x / 2.0f, -size.y / 2.0f, 0 );
  1116. verts[0].color = color;
  1117. verts[1].point = pos + Point3F( -size.x / 2.0f, size.y / 2.0f, 0 );
  1118. verts[1].color = color;
  1119. verts[2].point = pos + Point3F( size.x / 2.0f, size.y / 2.0f, 0 );
  1120. verts[2].color = color;
  1121. verts[3].point = pos + Point3F( size.x / 2.0f, -size.y / 2.0f, 0 );
  1122. verts[3].color = color;
  1123. verts.unlock();
  1124. mDevice->setStateBlockByDesc( desc );
  1125. mDevice->setVertexBuffer( verts );
  1126. mDevice->setupGenericShaders();
  1127. mDevice->drawPrimitive( GFXTriangleFan, 0, 2 );
  1128. }
  1129. void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &pos, const Point2F &size, const Point2F &step, const ColorI &color, Plane plane )
  1130. {
  1131. // Note that when calculating the number of steps, we +0.5 to round up,
  1132. // and +1 for the last line (ie. 4 steps needs 5 lines to be rendered)
  1133. U32 uSteps = 0;
  1134. if( step.x > 0 )
  1135. uSteps = size.x / step.x + 0.5 + 1;
  1136. U32 vSteps = 0;
  1137. if( step.y > 0 )
  1138. vSteps = size.y / step.y + 0.5 + 1;
  1139. if( uSteps <= 1 || vSteps <= 1 )
  1140. return;
  1141. const U32 numVertices = uSteps * 2 + vSteps * 2;
  1142. const U32 numLines = uSteps + vSteps;
  1143. Point3F origin;
  1144. switch( plane )
  1145. {
  1146. case PlaneXY:
  1147. origin = Point3F( pos.x - ( size.x / 2.0f ), pos.y - ( size.y / 2.0f ), pos.z );
  1148. break;
  1149. case PlaneXZ:
  1150. origin = Point3F( pos.x - ( size.x / 2.0f ), pos.y, pos.z - ( size.y / 2.0f ) );
  1151. break;
  1152. case PlaneYZ:
  1153. origin = Point3F( pos.x, pos.y - ( size.x / 2.0f ), pos.z - ( size.y / 2.0f ) );
  1154. break;
  1155. }
  1156. GFXVertexBufferHandle<GFXVertexPC> verts( mDevice, numVertices, GFXBufferTypeVolatile );
  1157. verts.lock();
  1158. U32 vertCount = 0;
  1159. if( plane == PlaneXY || plane == PlaneXZ )
  1160. {
  1161. F32 start = mFloor( origin.x / step.x + 0.5f ) * step.x;
  1162. for ( U32 i = 0; i < uSteps; i++ )
  1163. {
  1164. verts[vertCount].point = Point3F( start + step.x * i, origin.y, origin.z );
  1165. verts[vertCount].color = color;
  1166. ++vertCount;
  1167. if( plane == PlaneXY )
  1168. verts[vertCount].point = Point3F( start + step.x * i, origin.y + size.y, origin.z );
  1169. else
  1170. verts[vertCount].point = Point3F( start + step.x * i, origin.y, origin.z + size.y );
  1171. verts[vertCount].color = color;
  1172. ++vertCount;
  1173. }
  1174. }
  1175. if( plane == PlaneXY || plane == PlaneYZ )
  1176. {
  1177. U32 num;
  1178. F32 stp;
  1179. if( plane == PlaneXY )
  1180. {
  1181. num = vSteps;
  1182. stp = step.y;
  1183. }
  1184. else
  1185. {
  1186. num = uSteps;
  1187. stp = step.x;
  1188. }
  1189. F32 start = mFloor( origin.y / stp + 0.5f ) * stp;
  1190. for ( U32 i = 0; i < num; i++ )
  1191. {
  1192. verts[vertCount].point = Point3F( origin.x, start + stp * i, origin.z );
  1193. verts[vertCount].color = color;
  1194. ++vertCount;
  1195. if( plane == PlaneXY )
  1196. verts[vertCount].point = Point3F( origin.x + size.x, start + stp * i, origin.z );
  1197. else
  1198. verts[vertCount].point = Point3F( origin.x, start + stp * i, origin.z + size.x );
  1199. verts[vertCount].color = color;
  1200. ++vertCount;
  1201. }
  1202. }
  1203. if( plane == PlaneXZ || plane == PlaneYZ )
  1204. {
  1205. F32 start = mFloor( origin.z / step.y + 0.5f ) * step.y;
  1206. for ( U32 i = 0; i < vSteps; i++ )
  1207. {
  1208. verts[vertCount].point = Point3F( origin.x, origin.y, start + step.y * i );
  1209. verts[vertCount].color = color;
  1210. ++vertCount;
  1211. if( plane == PlaneXZ )
  1212. verts[vertCount].point = Point3F( origin.x + size.x, origin.y, start + step.y * i );
  1213. else
  1214. verts[vertCount].point = Point3F( origin.x, origin.y + size.x, start + step.y * i );
  1215. verts[vertCount].color = color;
  1216. ++vertCount;
  1217. }
  1218. }
  1219. verts.unlock();
  1220. mDevice->setStateBlockByDesc( desc );
  1221. mDevice->setVertexBuffer( verts );
  1222. mDevice->setupGenericShaders();
  1223. mDevice->drawPrimitive( GFXLineList, 0, numLines );
  1224. }
  1225. void GFXDrawUtil::drawTransform( const GFXStateBlockDesc &desc, const MatrixF &mat, const Point3F *scale, const ColorI colors[3] )
  1226. {
  1227. GFXTransformSaver saver;
  1228. GFX->multWorld( mat );
  1229. GFXVertexBufferHandle<GFXVertexPC> verts( mDevice, 6, GFXBufferTypeVolatile );
  1230. verts.lock();
  1231. const static ColorI defColors[3] =
  1232. {
  1233. ColorI::RED,
  1234. ColorI::GREEN,
  1235. ColorI::BLUE
  1236. };
  1237. const ColorI *colArray = ( colors != NULL ) ? colors : defColors;
  1238. verts[0].point = Point3F::Zero;
  1239. verts[0].color = colArray[0];
  1240. verts[1].point = Point3F( 1, 0, 0 );
  1241. verts[1].color = colArray[0];
  1242. verts[2].point = Point3F::Zero;
  1243. verts[2].color = colArray[1];
  1244. verts[3].point = Point3F( 0, 1, 0 );
  1245. verts[3].color = colArray[1];
  1246. verts[4].point = Point3F::Zero;
  1247. verts[4].color = colArray[2];
  1248. verts[5].point = Point3F( 0, 0, 1 );
  1249. verts[5].color = colArray[2];
  1250. if ( scale )
  1251. {
  1252. verts[1].point *= *scale;
  1253. verts[3].point *= *scale;
  1254. verts[5].point *= *scale;
  1255. }
  1256. verts.unlock();
  1257. mDevice->setStateBlockByDesc( desc );
  1258. mDevice->setVertexBuffer( verts );
  1259. mDevice->setupGenericShaders();
  1260. mDevice->drawPrimitive( GFXLineList, 0, 3 );
  1261. }