gfxDrawUtil.cpp 62 KB

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