gfxDrawUtil.cpp 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577
  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 * sizeof(UTF16) );
  128. convertUTF8toUTF16(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, upperLeft.y+ne.y+ulOffset, 0.0f );
  435. verts[2].point.set( upperLeft.x-ne.x+ulOffset, lowerRight.y-ne.y, 0.0f );
  436. verts[3].point.set( lowerRight.x-nw.x, lowerRight.y-nw.y, 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.f)
  457. {
  458. MatrixF rotMatrix( EulerF( 0.0, 0.0, spinAngle ) );
  459. for( S32 i = 0; i < 4; i++ )
  460. {
  461. rotMatrix.mulP( verts[i].point );
  462. verts[i].point += offset;
  463. }
  464. }
  465. verts.unlock();
  466. mDevice->setVertexBuffer( verts );
  467. mDevice->setStateBlock(mRectFillSB);
  468. mDevice->setupGenericShaders();
  469. mDevice->drawPrimitive( GFXTriangleStrip, 0, 2 );
  470. }
  471. //-----------------------------------------------------------------------------
  472. // Draw Line
  473. //-----------------------------------------------------------------------------
  474. void GFXDrawUtil::drawLine( const Point3F &startPt, const Point3F &endPt, const ColorI &color )
  475. {
  476. drawLine( startPt.x, startPt.y, startPt.z, endPt.x, endPt.y, endPt.z, color );
  477. }
  478. void GFXDrawUtil::drawLine( const Point2F &startPt, const Point2F &endPt, const ColorI &color )
  479. {
  480. drawLine( startPt.x, startPt.y, 0.0f, endPt.x, endPt.y, 0.0f, color );
  481. }
  482. void GFXDrawUtil::drawLine( const Point2I &startPt, const Point2I &endPt, const ColorI &color )
  483. {
  484. drawLine( startPt.x, startPt.y, 0.0f, endPt.x, endPt.y, 0.0f, color );
  485. }
  486. void GFXDrawUtil::drawLine( F32 x1, F32 y1, F32 x2, F32 y2, const ColorI &color )
  487. {
  488. drawLine( x1, y1, 0.0f, x2, y2, 0.0f, color );
  489. }
  490. void GFXDrawUtil::drawLine( F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI &color )
  491. {
  492. GFXVertexBufferHandle<GFXVertexPC> verts( mDevice, 2, GFXBufferTypeVolatile );
  493. verts.lock();
  494. verts[0].point.set( x1, y1, z1 );
  495. verts[1].point.set( x2, y2, z2 );
  496. verts[0].color = color;
  497. verts[1].color = color;
  498. verts.unlock();
  499. mDevice->setVertexBuffer( verts );
  500. mDevice->setStateBlock( mRectFillSB );
  501. mDevice->drawPrimitive( GFXLineList, 0, 1 );
  502. }
  503. //-----------------------------------------------------------------------------
  504. // 3D World Draw Misc
  505. //-----------------------------------------------------------------------------
  506. static SphereMesh gSphere;
  507. void GFXDrawUtil::drawSphere( const GFXStateBlockDesc &desc, F32 radius, const Point3F &pos, const ColorI &color, bool drawTop, bool drawBottom, const MatrixF *xfm )
  508. {
  509. MatrixF mat;
  510. if ( xfm )
  511. mat = *xfm;
  512. else
  513. mat = MatrixF::Identity;
  514. mat.scale(Point3F(radius,radius,radius));
  515. mat.setPosition(pos);
  516. GFX->pushWorldMatrix();
  517. GFX->multWorld(mat);
  518. const SphereMesh::TriangleMesh * sphereMesh = gSphere.getMesh(2);
  519. S32 numPoly = sphereMesh->numPoly;
  520. S32 totalPoly = 0;
  521. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, numPoly*3, GFXBufferTypeVolatile);
  522. verts.lock();
  523. S32 vertexIndex = 0;
  524. for (S32 i=0; i<numPoly; i++)
  525. {
  526. if (!drawBottom)
  527. {
  528. 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)
  529. continue;
  530. }
  531. if (!drawTop)
  532. {
  533. 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)
  534. continue;
  535. }
  536. totalPoly++;
  537. verts[vertexIndex].point = sphereMesh->poly[i].pnt[0];
  538. verts[vertexIndex].color = color;
  539. vertexIndex++;
  540. verts[vertexIndex].point = sphereMesh->poly[i].pnt[1];
  541. verts[vertexIndex].color = color;
  542. vertexIndex++;
  543. verts[vertexIndex].point = sphereMesh->poly[i].pnt[2];
  544. verts[vertexIndex].color = color;
  545. vertexIndex++;
  546. }
  547. verts.unlock();
  548. mDevice->setStateBlockByDesc( desc );
  549. mDevice->setVertexBuffer( verts );
  550. mDevice->setupGenericShaders();
  551. mDevice->drawPrimitive( GFXTriangleList, 0, totalPoly );
  552. GFX->popWorldMatrix();
  553. }
  554. //-----------------------------------------------------------------------------
  555. static const Point3F cubePoints[8] =
  556. {
  557. Point3F(-1, -1, -1), Point3F(-1, -1, 1), Point3F(-1, 1, -1), Point3F(-1, 1, 1),
  558. Point3F( 1, -1, -1), Point3F( 1, -1, 1), Point3F( 1, 1, -1), Point3F( 1, 1, 1)
  559. };
  560. static const U32 cubeFaces[6][4] =
  561. {
  562. { 0, 4, 6, 2 }, { 0, 2, 3, 1 }, { 0, 1, 5, 4 },
  563. { 3, 2, 6, 7 }, { 7, 6, 4, 5 }, { 3, 7, 5, 1 }
  564. };
  565. void GFXDrawUtil::drawTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm )
  566. {
  567. if ( desc.fillMode == GFXFillWireframe )
  568. _drawWireTriangle( desc, p0, p1, p2, color, xfm );
  569. else
  570. _drawSolidTriangle( desc, p0, p1, p2, color, xfm );
  571. }
  572. void GFXDrawUtil::_drawWireTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm )
  573. {
  574. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, 4, GFXBufferTypeVolatile);
  575. verts.lock();
  576. // Set up the line strip
  577. verts[0].point = p0;
  578. verts[0].color = color;
  579. verts[1].point = p1;
  580. verts[1].color = color;
  581. verts[2].point = p2;
  582. verts[2].color = color;
  583. verts[3].point = p0;
  584. verts[3].color = color;
  585. // Apply xfm if we were passed one.
  586. if ( xfm != NULL )
  587. {
  588. for ( U32 i = 0; i < 4; i++ )
  589. xfm->mulP( verts[i].point );
  590. }
  591. verts.unlock();
  592. GFXStateBlockRef sb = mDevice->createStateBlock( desc );
  593. mDevice->setStateBlock( sb );
  594. mDevice->setVertexBuffer( verts );
  595. mDevice->setupGenericShaders();
  596. mDevice->drawPrimitive( GFXLineStrip, 0, 3 );
  597. }
  598. void GFXDrawUtil::_drawSolidTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm )
  599. {
  600. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, 3, GFXBufferTypeVolatile);
  601. verts.lock();
  602. // Set up the line strip
  603. verts[0].point = p0;
  604. verts[0].color = color;
  605. verts[1].point = p1;
  606. verts[1].color = color;
  607. verts[2].point = p2;
  608. verts[2].color = color;
  609. // Apply xfm if we were passed one.
  610. if ( xfm != NULL )
  611. {
  612. for ( U32 i = 0; i < 3; i++ )
  613. xfm->mulP( verts[i].point );
  614. }
  615. verts.unlock();
  616. GFXStateBlockRef sb = mDevice->createStateBlock( desc );
  617. mDevice->setStateBlock( sb );
  618. mDevice->setVertexBuffer( verts );
  619. mDevice->setupGenericShaders();
  620. mDevice->drawPrimitive( GFXTriangleList, 0, 1 );
  621. }
  622. void GFXDrawUtil::drawPolygon( const GFXStateBlockDesc& desc, const Point3F* points, U32 numPoints, const ColorI& color, const MatrixF* xfm /* = NULL */ )
  623. {
  624. const bool isWireframe = ( desc.fillMode == GFXFillWireframe );
  625. const U32 numVerts = isWireframe ? numPoints + 1 : numPoints;
  626. GFXVertexBufferHandle< GFXVertexPC > verts( mDevice, numVerts, GFXBufferTypeVolatile );
  627. verts.lock();
  628. for( U32 i = 0; i < numPoints; ++ i )
  629. {
  630. verts[ i ].point = points[ i ];
  631. verts[ i ].color = color;
  632. }
  633. if( xfm )
  634. {
  635. for( U32 i = 0; i < numPoints; ++ i )
  636. xfm->mulP( verts[ i ].point );
  637. }
  638. if( isWireframe )
  639. {
  640. verts[ numVerts - 1 ].point = verts[ 0 ].point;
  641. verts[ numVerts - 1 ].color = color;
  642. }
  643. verts.unlock();
  644. mDevice->setStateBlockByDesc( desc );
  645. mDevice->setVertexBuffer( verts );
  646. mDevice->setupGenericShaders();
  647. if( desc.fillMode == GFXFillWireframe )
  648. mDevice->drawPrimitive( GFXLineStrip, 0, numPoints );
  649. else
  650. mDevice->drawPrimitive( GFXTriangleFan, 0, numPoints - 2 );
  651. }
  652. void GFXDrawUtil::drawCube( const GFXStateBlockDesc &desc, const Box3F &box, const ColorI &color, const MatrixF *xfm )
  653. {
  654. drawCube( desc, box.getExtents(), box.getCenter(), color, xfm );
  655. }
  656. void GFXDrawUtil::drawCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm )
  657. {
  658. if ( desc.fillMode == GFXFillWireframe )
  659. _drawWireCube( desc, size, pos, color, xfm );
  660. else
  661. _drawSolidCube( desc, size, pos, color, xfm );
  662. }
  663. void GFXDrawUtil::_drawWireCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm )
  664. {
  665. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, 30, GFXBufferTypeVolatile);
  666. verts.lock();
  667. Point3F halfSize = size * 0.5f;
  668. // setup 6 line loops
  669. U32 vertexIndex = 0;
  670. for(S32 i = 0; i < 6; i++)
  671. {
  672. for(S32 j = 0; j < 5; j++)
  673. {
  674. S32 idx = cubeFaces[i][j%4];
  675. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  676. verts[vertexIndex].color = color;
  677. vertexIndex++;
  678. }
  679. }
  680. // Apply xfm if we were passed one.
  681. if ( xfm != NULL )
  682. {
  683. for ( U32 i = 0; i < 30; i++ )
  684. xfm->mulP( verts[i].point );
  685. }
  686. // Apply position offset
  687. for ( U32 i = 0; i < 30; i++ )
  688. verts[i].point += pos;
  689. verts.unlock();
  690. mDevice->setStateBlockByDesc( desc );
  691. mDevice->setVertexBuffer( verts );
  692. mDevice->setupGenericShaders();
  693. for( U32 i=0; i<6; i++ )
  694. mDevice->drawPrimitive( GFXLineStrip, i*5, 4 );
  695. }
  696. void GFXDrawUtil::_drawSolidCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm )
  697. {
  698. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, 36, GFXBufferTypeVolatile);
  699. verts.lock();
  700. Point3F halfSize = size * 0.5f;
  701. // setup 6 line loops
  702. U32 vertexIndex = 0;
  703. U32 idx;
  704. for(S32 i = 0; i < 6; i++)
  705. {
  706. idx = cubeFaces[i][0];
  707. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  708. verts[vertexIndex].color = color;
  709. vertexIndex++;
  710. idx = cubeFaces[i][1];
  711. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  712. verts[vertexIndex].color = color;
  713. vertexIndex++;
  714. idx = cubeFaces[i][3];
  715. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  716. verts[vertexIndex].color = color;
  717. vertexIndex++;
  718. idx = cubeFaces[i][1];
  719. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  720. verts[vertexIndex].color = color;
  721. vertexIndex++;
  722. idx = cubeFaces[i][2];
  723. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  724. verts[vertexIndex].color = color;
  725. vertexIndex++;
  726. idx = cubeFaces[i][3];
  727. verts[vertexIndex].point = cubePoints[idx] * halfSize;
  728. verts[vertexIndex].color = color;
  729. vertexIndex++;
  730. }
  731. // Apply xfm if we were passed one.
  732. if ( xfm != NULL )
  733. {
  734. for ( U32 i = 0; i < 36; i++ )
  735. xfm->mulV( verts[i].point );
  736. }
  737. // Apply position offset
  738. for ( U32 i = 0; i < 36; i++ )
  739. verts[i].point += pos;
  740. verts.unlock();
  741. mDevice->setStateBlockByDesc( desc );
  742. mDevice->setVertexBuffer( verts );
  743. mDevice->setupGenericShaders();
  744. mDevice->drawPrimitive( GFXTriangleList, 0, 12 );
  745. }
  746. void GFXDrawUtil::drawPolyhedron( const GFXStateBlockDesc &desc, const AnyPolyhedron &poly, const ColorI &color, const MatrixF *xfm )
  747. {
  748. if ( desc.fillMode == GFXFillWireframe )
  749. _drawWirePolyhedron( desc, poly, color, xfm );
  750. else
  751. _drawSolidPolyhedron( desc, poly, color, xfm );
  752. }
  753. void GFXDrawUtil::_drawWirePolyhedron( const GFXStateBlockDesc &desc, const AnyPolyhedron &poly, const ColorI &color, const MatrixF *xfm )
  754. {
  755. GFXDEBUGEVENT_SCOPE( GFXDrawUtil_DrawWirePolyhedron, ColorI::GREEN );
  756. const U32 numEdges = poly.getNumEdges();
  757. const Point3F* points = poly.getPoints();
  758. const Polyhedron::Edge* edges = poly.getEdges();
  759. // Allocate a temporary vertex buffer.
  760. GFXVertexBufferHandle< GFXVertexPC > verts( mDevice, numEdges * 2, GFXBufferTypeVolatile);
  761. // Fill it with the vertices for the edges.
  762. verts.lock();
  763. for( U32 i = 0; i < numEdges; ++ i )
  764. {
  765. const U32 nvert = i * 2;
  766. verts[ nvert + 0 ].point = points[ edges[ i ].vertex[ 0 ] ];
  767. verts[ nvert + 0 ].color = color;
  768. verts[ nvert + 1 ].point = points[ edges[ i ].vertex[ 1 ] ];
  769. verts[ nvert + 1 ].color = color;
  770. }
  771. if( xfm )
  772. {
  773. for( U32 i = 0; i < numEdges; ++ i )
  774. {
  775. xfm->mulP( verts[ i + 0 ].point );
  776. xfm->mulP( verts[ i + 1 ].point );
  777. }
  778. }
  779. verts.unlock();
  780. // Render the line list.
  781. mDevice->setStateBlockByDesc( desc );
  782. mDevice->setVertexBuffer( verts );
  783. mDevice->setupGenericShaders();
  784. mDevice->drawPrimitive( GFXLineList, 0, numEdges );
  785. }
  786. void GFXDrawUtil::_drawSolidPolyhedron( const GFXStateBlockDesc &desc, const AnyPolyhedron &poly, const ColorI &color, const MatrixF *xfm )
  787. {
  788. GFXDEBUGEVENT_SCOPE( GFXDrawUtil_DrawSolidPolyhedron, ColorI::GREEN );
  789. const U32 numPoints = poly.getNumPoints();
  790. const Point3F* points = poly.getPoints();
  791. const PlaneF* planes = poly.getPlanes();
  792. const Point3F viewDir = GFX->getViewMatrix().getForwardVector();
  793. // Create a temp buffer for the vertices and
  794. // put all the polyhedron's points in there.
  795. GFXVertexBufferHandle< GFXVertexPC > verts( mDevice, numPoints, GFXBufferTypeVolatile );
  796. verts.lock();
  797. for( U32 i = 0; i < numPoints; ++ i )
  798. {
  799. verts[ i ].point = points[ i ];
  800. verts[ i ].color = color;
  801. }
  802. if( xfm )
  803. {
  804. for( U32 i = 0; i < numPoints; ++ i )
  805. xfm->mulP( verts[ i ].point );
  806. }
  807. verts.unlock();
  808. // Allocate a temp buffer for the face indices.
  809. const U32 numIndices = poly.getNumEdges() * 2;
  810. const U32 numPlanes = poly.getNumPlanes();
  811. GFXPrimitiveBufferHandle prims( mDevice, numIndices, 0, GFXBufferTypeVolatile );
  812. // Unfortunately, since polygons may have varying numbers of
  813. // vertices, we also need to retain that information.
  814. FrameTemp< U32 > numIndicesForPoly( numPlanes );
  815. U32 numPolys = 0;
  816. // Create all the polygon indices.
  817. U16* indices;
  818. prims.lock( &indices );
  819. U32 idx = 0;
  820. for( U32 i = 0; i < numPlanes; ++ i )
  821. {
  822. // Since face extraction is somewhat costly, don't bother doing it for
  823. // backfacing polygons if culling is enabled.
  824. if( !desc.cullDefined || desc.cullMode != GFXCullNone )
  825. {
  826. F32 dot = mDot( planes[ i ], viewDir );
  827. // See if it faces *the same way* as the view direction. This would
  828. // normally mean that the face is *not* backfacing but since we expect
  829. // planes on the polyhedron to be facing *inwards*, we need to reverse
  830. // the logic here.
  831. if( dot > 0.f )
  832. continue;
  833. }
  834. U32 numPoints = poly.extractFace( i, &indices[ idx ], numIndices - idx );
  835. numIndicesForPoly[ numPolys ] = numPoints;
  836. idx += numPoints;
  837. numPolys ++;
  838. }
  839. prims.unlock();
  840. // Set up state.
  841. mDevice->setStateBlockByDesc( desc );
  842. mDevice->setupGenericShaders();
  843. mDevice->setVertexBuffer( verts );
  844. mDevice->setPrimitiveBuffer( prims );
  845. // Render one triangle fan for each polygon.
  846. U32 startIndex = 0;
  847. for( U32 i = 0; i < numPolys; ++ i )
  848. {
  849. U32 numVerts = numIndicesForPoly[ i ];
  850. mDevice->drawIndexedPrimitive( GFXTriangleFan, 0, 0, numPoints, startIndex, numVerts - 2 );
  851. startIndex += numVerts;
  852. }
  853. }
  854. void GFXDrawUtil::drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const MatrixF &objMat, const ColorI &color )
  855. {
  856. GFXTransformSaver saver;
  857. mDevice->setStateBlockByDesc( desc );
  858. MatrixF scaledObjMat( true );
  859. scaledObjMat = objMat;
  860. scaledObjMat.scale( size );
  861. scaledObjMat.setPosition( pos );
  862. PrimBuild::color( color );
  863. PrimBuild::begin( GFXLineList, 48 );
  864. static const Point3F cubePoints[8] =
  865. {
  866. 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),
  867. 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)
  868. };
  869. // 8 corner points of the box
  870. for ( U32 i = 0; i < 8; i++ )
  871. {
  872. //const Point3F &start = cubePoints[i];
  873. // 3 lines per corner point
  874. for ( U32 j = 0; j < 3; j++ )
  875. {
  876. Point3F start = cubePoints[i];
  877. Point3F end = start;
  878. end[j] *= 0.8f;
  879. scaledObjMat.mulP(start);
  880. PrimBuild::vertex3fv(start);
  881. scaledObjMat.mulP(end);
  882. PrimBuild::vertex3fv(end);
  883. }
  884. }
  885. PrimBuild::end();
  886. }
  887. static const Point2F circlePoints[] =
  888. {
  889. Point2F(0.707107f, 0.707107f),
  890. Point2F(0.923880f, 0.382683f),
  891. Point2F(1.000000f, 0.000000f),
  892. Point2F(0.923880f, -0.382684f),
  893. Point2F(0.707107f, -0.707107f),
  894. Point2F(0.382683f, -0.923880f),
  895. Point2F(0.000000f, -1.000000f),
  896. Point2F(-0.382683f, -0.923880f),
  897. Point2F(-0.707107f, -0.707107f),
  898. Point2F(-0.923880f, -0.382684f),
  899. Point2F(-1.000000f, 0.000000f),
  900. Point2F(-0.923879f, 0.382684f),
  901. Point2F(-0.707107f, 0.707107f),
  902. Point2F(-0.382683f, 0.923880f),
  903. Point2F(0.000000f, 1.000000f),
  904. Point2F(0.382684f, 0.923879f)
  905. };
  906. void GFXDrawUtil::drawCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm )
  907. {
  908. if ( desc.fillMode == GFXFillWireframe )
  909. _drawWireCapsule( desc, center, radius, height, color, xfm );
  910. else
  911. _drawSolidCapsule( desc, center, radius, height, color, xfm );
  912. }
  913. void GFXDrawUtil::_drawSolidCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm )
  914. {
  915. MatrixF mat;
  916. if ( xfm )
  917. mat = *xfm;
  918. else
  919. mat = MatrixF::Identity;
  920. S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
  921. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, numPoints * 2 + 2, GFXBufferTypeVolatile);
  922. verts.lock();
  923. for (S32 i=0; i<numPoints + 1; i++)
  924. {
  925. S32 imod = i % numPoints;
  926. verts[2 * i].point = Point3F( circlePoints[imod].x * radius, circlePoints[imod].y * radius, height );
  927. verts[2 * i].color = color;
  928. verts[2 * i + 1].point = Point3F( circlePoints[imod].x * radius, circlePoints[imod].y * radius, -height );
  929. verts[2 * i + 1].color = color;
  930. }
  931. S32 totalNumPnts = numPoints * 2 + 2;
  932. // Apply xfm if we were passed one.
  933. for ( U32 i = 0; i < totalNumPnts; i++ )
  934. mat.mulP( verts[i].point );
  935. // Apply position offset
  936. for ( U32 i = 0; i < totalNumPnts; i++ )
  937. verts[i].point += center;
  938. verts.unlock();
  939. mDevice->setStateBlockByDesc( desc );
  940. mDevice->setVertexBuffer( verts );
  941. mDevice->setupGenericShaders();
  942. mDevice->drawPrimitive( GFXTriangleStrip, 0, 2 * numPoints );
  943. Point3F sphereCenter;
  944. MatrixF sphereMat;
  945. if ( xfm )
  946. sphereMat = *xfm;
  947. else
  948. sphereMat = MatrixF::Identity;
  949. sphereCenter.set( 0, 0, 0.5f * height );
  950. mat.mulV( sphereCenter );
  951. sphereCenter += center;
  952. drawSphere( desc, radius, sphereCenter, color, true, false, &sphereMat );
  953. sphereCenter.set( 0, 0, -0.5f * height );
  954. mat.mulV( sphereCenter );
  955. sphereCenter += center;
  956. drawSphere( desc, radius, sphereCenter, color, false, true, &sphereMat );
  957. }
  958. void GFXDrawUtil::_drawWireCapsule( const GFXStateBlockDesc &desc, const Point3F &center, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm )
  959. {
  960. MatrixF mat;
  961. if ( xfm )
  962. mat = *xfm;
  963. else
  964. mat = MatrixF::Identity;
  965. mat.scale( Point3F(radius,radius,height*0.5f) );
  966. mat.setPosition(center);
  967. mDevice->pushWorldMatrix();
  968. mDevice->multWorld(mat);
  969. S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
  970. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, numPoints, GFXBufferTypeVolatile);
  971. verts.lock();
  972. for (S32 i=0; i< numPoints; i++)
  973. {
  974. S32 idx = i & (~1); // just draw the even ones
  975. F32 z = i & 1 ? 1.0f : -1.0f;
  976. verts[i].point = Point3F(circlePoints[idx].x,circlePoints[idx].y, z);
  977. verts[i].color = color;
  978. }
  979. verts.unlock();
  980. mDevice->setStateBlockByDesc( desc );
  981. mDevice->setVertexBuffer( verts );
  982. mDevice->setupGenericShaders();
  983. for (S32 i=0; i<numPoints; i += 2)
  984. mDevice->drawPrimitive(GFXLineStrip, i, 1);
  985. mDevice->popWorldMatrix();
  986. Point3F sphereCenter;
  987. sphereCenter.z = center.z + 0.5f * height;
  988. drawSphere( desc, radius,sphereCenter,color,true,false);
  989. sphereCenter.z = center.z - 0.5f * height;
  990. drawSphere( desc, radius,sphereCenter,color,false,true);
  991. }
  992. void GFXDrawUtil::drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color )
  993. {
  994. VectorF uvec = tipPnt - basePnt;
  995. F32 height = uvec.len();
  996. uvec.normalize();
  997. MatrixF mat( true );
  998. MathUtils::getMatrixFromUpVector( uvec, &mat );
  999. mat.setPosition(basePnt);
  1000. Point3F scale( baseRadius, baseRadius, height );
  1001. mat.scale(scale);
  1002. GFXTransformSaver saver;
  1003. mDevice->pushWorldMatrix();
  1004. mDevice->multWorld(mat);
  1005. S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
  1006. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, numPoints + 2, GFXBufferTypeVolatile);
  1007. verts.lock();
  1008. verts[0].point = Point3F(0.0f,0.0f,1.0f);
  1009. verts[0].color = color;
  1010. for (S32 i=0; i<numPoints + 1; i++)
  1011. {
  1012. S32 imod = i % numPoints;
  1013. verts[i + 1].point = Point3F(circlePoints[imod].x,circlePoints[imod].y, 0.0f);
  1014. verts[i + 1].color = color;
  1015. }
  1016. verts.unlock();
  1017. mDevice->setStateBlockByDesc( desc );
  1018. mDevice->setVertexBuffer( verts );
  1019. mDevice->setupGenericShaders( GFXDevice::GSModColorTexture );
  1020. mDevice->drawPrimitive( GFXTriangleFan, 0, numPoints );
  1021. mDevice->drawPrimitive( GFXTriangleFan, 1, numPoints-1 );
  1022. mDevice->popWorldMatrix();
  1023. }
  1024. void GFXDrawUtil::drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 radius, const ColorI &color )
  1025. {
  1026. VectorF uvec = tipPnt - basePnt;
  1027. F32 height = uvec.len();
  1028. uvec.normalize();
  1029. MatrixF mat( true );
  1030. MathUtils::getMatrixFromUpVector( uvec, &mat );
  1031. mat.setPosition(basePnt);
  1032. Point3F scale( radius, radius, height * 2 );
  1033. mat.scale(scale);
  1034. GFXTransformSaver saver;
  1035. mDevice->pushWorldMatrix();
  1036. mDevice->multWorld(mat);
  1037. S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
  1038. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, numPoints * 4 + 4, GFXBufferTypeVolatile);
  1039. verts.lock();
  1040. for (S32 i=0; i<numPoints + 1; i++)
  1041. {
  1042. S32 imod = i % numPoints;
  1043. verts[i].point = Point3F(circlePoints[imod].x,circlePoints[imod].y, 0.5f);
  1044. verts[i].color = color;
  1045. verts[i + numPoints + 1].point = Point3F(circlePoints[imod].x,circlePoints[imod].y, 0);
  1046. verts[i + numPoints + 1].color = color;
  1047. verts[2*numPoints + 2 + 2 * i].point = Point3F(circlePoints[imod].x,circlePoints[imod].y, 0.5f);
  1048. verts[2*numPoints + 2 + 2 * i].color = color;
  1049. verts[2*numPoints + 2 + 2 * i + 1].point = Point3F(circlePoints[imod].x,circlePoints[imod].y, 0);
  1050. verts[2*numPoints + 2 + 2 * i + 1].color = color;
  1051. }
  1052. verts.unlock();
  1053. mDevice->setStateBlockByDesc( desc );
  1054. mDevice->setVertexBuffer( verts );
  1055. mDevice->setupGenericShaders( GFXDevice::GSModColorTexture );
  1056. mDevice->drawPrimitive( GFXTriangleFan, 0, numPoints );
  1057. mDevice->drawPrimitive( GFXTriangleFan, numPoints + 1, numPoints );
  1058. mDevice->drawPrimitive( GFXTriangleStrip, 2 * numPoints + 2, 2 * numPoints);
  1059. mDevice->popWorldMatrix();
  1060. }
  1061. void GFXDrawUtil::drawArrow( const GFXStateBlockDesc &desc, const Point3F &start, const Point3F &end, const ColorI &color )
  1062. {
  1063. GFXTransformSaver saver;
  1064. // Direction and length of the arrow.
  1065. VectorF dir = end - start;
  1066. F32 len = dir.len();
  1067. dir.normalize();
  1068. len *= 0.2f;
  1069. // Base of the cone will be a distance back from the end of the arrow
  1070. // proportional to the total distance of the arrow... 0.3f looks about right.
  1071. Point3F coneBase = end - dir * len * 0.3f;
  1072. // Calculate the radius of the cone given that we want the cone to have
  1073. // an angle of 25 degrees (just because it looks good).
  1074. F32 coneLen = ( end - coneBase ).len();
  1075. F32 coneDiameter = mTan( mDegToRad(25.0f) ) * coneLen;
  1076. // Draw the cone on at the arrow's tip.
  1077. drawCone( desc, coneBase, end, coneDiameter / 2.0f, color );
  1078. // Get the difference in length from
  1079. // the start of the cone to the end
  1080. // of the cylinder so we can put the
  1081. // end of the cylinder right against where
  1082. // the cone starts.
  1083. Point3F coneDiff = end - coneBase;
  1084. // Draw the cylinder.
  1085. F32 stickRadius = len * 0.025f;
  1086. drawCylinder( desc, start, end - coneDiff, stickRadius, color );
  1087. }
  1088. void GFXDrawUtil::drawFrustum( const Frustum &f, const ColorI &color )
  1089. {
  1090. const Point3F *points = f.getPoints();
  1091. // Draw near and far planes.
  1092. for (U32 offset = 0; offset < 8; offset+=4)
  1093. {
  1094. drawLine(points[offset+0], points[offset+1], color);
  1095. drawLine(points[offset+2], points[offset+3], color);
  1096. drawLine(points[offset+0], points[offset+2], color);
  1097. drawLine(points[offset+1], points[offset+3], color);
  1098. }
  1099. // connect the near and far planes
  1100. drawLine(points[Frustum::NearTopLeft], points[Frustum::FarTopLeft], color);
  1101. drawLine(points[Frustum::NearTopRight], points[Frustum::FarTopRight], color);
  1102. drawLine(points[Frustum::NearBottomLeft], points[Frustum::FarBottomLeft], color);
  1103. drawLine(points[Frustum::NearBottomRight], points[Frustum::FarBottomRight], color);
  1104. }
  1105. void GFXDrawUtil::drawSolidPlane( const GFXStateBlockDesc &desc, const Point3F &pos, const Point2F &size, const ColorI &color )
  1106. {
  1107. GFXVertexBufferHandle<GFXVertexPC> verts(mDevice, 4, GFXBufferTypeVolatile);
  1108. verts.lock();
  1109. verts[0].point = pos + Point3F( -size.x / 2.0f, -size.y / 2.0f, 0 );
  1110. verts[0].color = color;
  1111. verts[1].point = pos + Point3F( -size.x / 2.0f, size.y / 2.0f, 0 );
  1112. verts[1].color = color;
  1113. verts[2].point = pos + Point3F( size.x / 2.0f, size.y / 2.0f, 0 );
  1114. verts[2].color = color;
  1115. verts[3].point = pos + Point3F( size.x / 2.0f, -size.y / 2.0f, 0 );
  1116. verts[3].color = color;
  1117. verts.unlock();
  1118. mDevice->setStateBlockByDesc( desc );
  1119. mDevice->setVertexBuffer( verts );
  1120. mDevice->setupGenericShaders();
  1121. mDevice->drawPrimitive( GFXTriangleFan, 0, 2 );
  1122. }
  1123. void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &pos, const Point2F &size, const Point2F &step, const ColorI &color, Plane plane )
  1124. {
  1125. // Note that when calculating the number of steps, we +0.5 to round up,
  1126. // and +1 for the last line (ie. 4 steps needs 5 lines to be rendered)
  1127. U32 uSteps = 0;
  1128. if( step.x > 0 )
  1129. uSteps = size.x / step.x + 0.5 + 1;
  1130. U32 vSteps = 0;
  1131. if( step.y > 0 )
  1132. vSteps = size.y / step.y + 0.5 + 1;
  1133. if( uSteps <= 1 || vSteps <= 1 )
  1134. return;
  1135. const U32 numVertices = uSteps * 2 + vSteps * 2;
  1136. const U32 numLines = uSteps + vSteps;
  1137. Point3F origin;
  1138. switch( plane )
  1139. {
  1140. case PlaneXY:
  1141. origin = Point3F( pos.x - ( size.x / 2.0f ), pos.y - ( size.y / 2.0f ), pos.z );
  1142. break;
  1143. case PlaneXZ:
  1144. origin = Point3F( pos.x - ( size.x / 2.0f ), pos.y, pos.z - ( size.y / 2.0f ) );
  1145. break;
  1146. case PlaneYZ:
  1147. origin = Point3F( pos.x, pos.y - ( size.x / 2.0f ), pos.z - ( size.y / 2.0f ) );
  1148. break;
  1149. }
  1150. GFXVertexBufferHandle<GFXVertexPC> verts( mDevice, numVertices, GFXBufferTypeVolatile );
  1151. verts.lock();
  1152. U32 vertCount = 0;
  1153. if( plane == PlaneXY || plane == PlaneXZ )
  1154. {
  1155. F32 start = mFloor( origin.x / step.x + 0.5f ) * step.x;
  1156. for ( U32 i = 0; i < uSteps; i++ )
  1157. {
  1158. verts[vertCount].point = Point3F( start + step.x * i, origin.y, origin.z );
  1159. verts[vertCount].color = color;
  1160. ++vertCount;
  1161. if( plane == PlaneXY )
  1162. verts[vertCount].point = Point3F( start + step.x * i, origin.y + size.y, origin.z );
  1163. else
  1164. verts[vertCount].point = Point3F( start + step.x * i, origin.y, origin.z + size.y );
  1165. verts[vertCount].color = color;
  1166. ++vertCount;
  1167. }
  1168. }
  1169. if( plane == PlaneXY || plane == PlaneYZ )
  1170. {
  1171. U32 num;
  1172. F32 stp;
  1173. if( plane == PlaneXY )
  1174. {
  1175. num = vSteps;
  1176. stp = step.y;
  1177. }
  1178. else
  1179. {
  1180. num = uSteps;
  1181. stp = step.x;
  1182. }
  1183. F32 start = mFloor( origin.y / stp + 0.5f ) * stp;
  1184. for ( U32 i = 0; i < num; i++ )
  1185. {
  1186. verts[vertCount].point = Point3F( origin.x, start + stp * i, origin.z );
  1187. verts[vertCount].color = color;
  1188. ++vertCount;
  1189. if( plane == PlaneXY )
  1190. verts[vertCount].point = Point3F( origin.x + size.x, start + stp * i, origin.z );
  1191. else
  1192. verts[vertCount].point = Point3F( origin.x, start + stp * i, origin.z + size.x );
  1193. verts[vertCount].color = color;
  1194. ++vertCount;
  1195. }
  1196. }
  1197. if( plane == PlaneXZ || plane == PlaneYZ )
  1198. {
  1199. F32 start = mFloor( origin.z / step.y + 0.5f ) * step.y;
  1200. for ( U32 i = 0; i < vSteps; i++ )
  1201. {
  1202. verts[vertCount].point = Point3F( origin.x, origin.y, start + step.y * i );
  1203. verts[vertCount].color = color;
  1204. ++vertCount;
  1205. if( plane == PlaneXZ )
  1206. verts[vertCount].point = Point3F( origin.x + size.x, origin.y, start + step.y * i );
  1207. else
  1208. verts[vertCount].point = Point3F( origin.x, origin.y + size.x, start + step.y * i );
  1209. verts[vertCount].color = color;
  1210. ++vertCount;
  1211. }
  1212. }
  1213. verts.unlock();
  1214. mDevice->setStateBlockByDesc( desc );
  1215. mDevice->setVertexBuffer( verts );
  1216. mDevice->setupGenericShaders();
  1217. mDevice->drawPrimitive( GFXLineList, 0, numLines );
  1218. }
  1219. void GFXDrawUtil::drawTransform( const GFXStateBlockDesc &desc, const MatrixF &mat, const Point3F *scale, const ColorI colors[3] )
  1220. {
  1221. GFXTransformSaver saver;
  1222. GFX->multWorld( mat );
  1223. GFXVertexBufferHandle<GFXVertexPC> verts( mDevice, 6, GFXBufferTypeVolatile );
  1224. verts.lock();
  1225. const static ColorI defColors[3] =
  1226. {
  1227. ColorI::RED,
  1228. ColorI::GREEN,
  1229. ColorI::BLUE
  1230. };
  1231. const ColorI *colArray = ( colors != NULL ) ? colors : defColors;
  1232. verts[0].point = Point3F::Zero;
  1233. verts[0].color = colArray[0];
  1234. verts[1].point = Point3F( 1, 0, 0 );
  1235. verts[1].color = colArray[0];
  1236. verts[2].point = Point3F::Zero;
  1237. verts[2].color = colArray[1];
  1238. verts[3].point = Point3F( 0, 1, 0 );
  1239. verts[3].color = colArray[1];
  1240. verts[4].point = Point3F::Zero;
  1241. verts[4].color = colArray[2];
  1242. verts[5].point = Point3F( 0, 0, 1 );
  1243. verts[5].color = colArray[2];
  1244. if ( scale )
  1245. {
  1246. verts[1].point *= *scale;
  1247. verts[3].point *= *scale;
  1248. verts[5].point *= *scale;
  1249. }
  1250. verts.unlock();
  1251. mDevice->setStateBlockByDesc( desc );
  1252. mDevice->setVertexBuffer( verts );
  1253. mDevice->setupGenericShaders();
  1254. mDevice->drawPrimitive( GFXLineList, 0, 3 );
  1255. }