llrenderutils.cpp 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081
  1. /**
  2. * @file llrenderutils.cpp
  3. * @brief Utility 2D and 3D GL rendering functions implementation
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "linden_common.h"
  33. #include "llrenderutils.h"
  34. #include "llcolor4.h"
  35. #include "llgl.h"
  36. #include "llgltexture.h"
  37. #include "llmatrix3.h"
  38. #include "llrender.h"
  39. #include "llvector2.h"
  40. #include "llvector3.h"
  41. // Puts GL into 2D drawing mode by turning off lighting, setting to an
  42. // orthographic projection, etc.
  43. void gl_state_for_2d(S32 width, S32 height)
  44. {
  45. F32 window_width = (F32)width; //gViewerWindowp->getWindowWidth();
  46. F32 window_height = (F32)height; //gViewerWindowp->getWindowHeight();
  47. gGL.matrixMode(LLRender::MM_PROJECTION);
  48. gGL.loadIdentity();
  49. gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height, 1.f),
  50. -1.0f, 1.0f);
  51. gGL.matrixMode(LLRender::MM_MODELVIEW);
  52. gGL.loadIdentity();
  53. }
  54. void gl_draw_x(const LLRect& rect, const LLColor4& color)
  55. {
  56. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  57. gGL.color4fv(color.mV);
  58. gGL.begin(LLRender::LINES);
  59. gGL.vertex2i(rect.mLeft, rect.mTop);
  60. gGL.vertex2i(rect.mRight, rect.mBottom);
  61. gGL.vertex2i(rect.mLeft, rect.mBottom);
  62. gGL.vertex2i(rect.mRight, rect.mTop);
  63. gGL.end();
  64. }
  65. void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, bool filled)
  66. {
  67. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  68. // Counterclockwise triangles face the camera
  69. if (filled)
  70. {
  71. gGL.begin(LLRender::TRIANGLES);
  72. gGL.vertex2i(left, top);
  73. gGL.vertex2i(left, bottom);
  74. gGL.vertex2i(right, top);
  75. gGL.vertex2i(right, top);
  76. gGL.vertex2i(left, bottom);
  77. gGL.vertex2i(right, bottom);
  78. gGL.end();
  79. }
  80. else
  81. {
  82. gGL.begin(LLRender::LINE_STRIP);
  83. gGL.vertex2i(left, top);
  84. gGL.vertex2i(left, bottom);
  85. gGL.vertex2i(right, bottom);
  86. gGL.vertex2i(right, top);
  87. gGL.vertex2i(left, top);
  88. gGL.end();
  89. }
  90. }
  91. // Given a rectangle on the screen, draws a drop shadow _outside_ the right and
  92. // bottom edges of it. Along the right it has width "lines" and along the
  93. // bottom it has height "lines".
  94. void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom,
  95. const LLColor4& start_color, S32 lines)
  96. {
  97. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  98. LLColor4 end_color = start_color;
  99. end_color.mV[VALPHA] = 0.f;
  100. gGL.begin(LLRender::TRIANGLES);
  101. // Right edge, CCW faces screen
  102. gGL.color4fv(start_color.mV);
  103. // HACK: Overlap with the rectangle by a single pixel.
  104. // (--right; ++bottom; ++lines;)
  105. gGL.vertex2i(--right, top - ++lines);
  106. gGL.vertex2i(right, ++bottom);
  107. gGL.color4fv(end_color.mV);
  108. gGL.vertex2i(right + lines, bottom);
  109. gGL.vertex2i(right + lines, bottom);
  110. gGL.vertex2i(right + lines, top - lines);
  111. gGL.color4fv(start_color.mV);
  112. gGL.vertex2i(right, top - lines);
  113. // Bottom edge, CCW faces screen
  114. gGL.vertex2i(left + lines, bottom);
  115. gGL.color4fv(end_color.mV);
  116. gGL.vertex2i(left + lines, bottom - lines);
  117. gGL.vertex2i(right, bottom - lines);
  118. gGL.vertex2i(right, bottom - lines);
  119. gGL.color4fv(start_color.mV);
  120. gGL.vertex2i(right, bottom);
  121. gGL.vertex2i(left + lines, bottom);
  122. // bottom left Corner
  123. gGL.color4fv(start_color.mV);
  124. gGL.vertex2i(left + lines, bottom);
  125. gGL.color4fv(end_color.mV);
  126. gGL.vertex2i(left, bottom);
  127. gGL.vertex2i(left + lines, bottom - lines);
  128. gGL.vertex2i(left + lines, bottom - lines);
  129. gGL.vertex2i(left, bottom);
  130. // make the bottom left corner not sharp
  131. gGL.vertex2i(left + 1, bottom - lines + 1);
  132. // bottom right corner
  133. gGL.color4fv(start_color.mV);
  134. gGL.vertex2i(right, bottom);
  135. gGL.color4fv(end_color.mV);
  136. gGL.vertex2i(right, bottom - lines);
  137. gGL.vertex2i(right + lines, bottom);
  138. gGL.vertex2i(right + lines, bottom);
  139. gGL.vertex2i(right, bottom - lines);
  140. // make the rightmost corner not sharp
  141. gGL.vertex2i(right + lines - 1, bottom - lines + 1);
  142. // top right corner
  143. gGL.color4fv(start_color.mV);
  144. gGL.vertex2i(right, top - lines);
  145. gGL.color4fv(end_color.mV);
  146. gGL.vertex2i(right + lines, top - lines);
  147. gGL.vertex2i(right, top);
  148. gGL.vertex2i(right, top);
  149. gGL.vertex2i(right + lines, top - lines);
  150. // make the corner not sharp
  151. gGL.vertex2i(right + lines - 1, top - 1);
  152. gGL.end();
  153. }
  154. void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2)
  155. {
  156. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  157. gGL.begin(LLRender::LINES);
  158. gGL.vertex2i(x1, y1);
  159. gGL.vertex2i(x2, y2);
  160. gGL.end();
  161. }
  162. void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4& color)
  163. {
  164. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  165. gGL.color4fv(color.mV);
  166. gGL.begin(LLRender::LINES);
  167. gGL.vertex2i(x1, y1);
  168. gGL.vertex2i(x2, y2);
  169. gGL.end();
  170. }
  171. void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3,
  172. const LLColor4& color, bool filled)
  173. {
  174. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  175. gGL.color4fv(color.mV);
  176. gGL.begin(filled ? LLRender::TRIANGLES : LLRender::LINE_LOOP);
  177. gGL.vertex2i(x1, y1);
  178. gGL.vertex2i(x2, y2);
  179. gGL.vertex2i(x3, y3);
  180. gGL.end();
  181. }
  182. void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length,
  183. F32 max_frac)
  184. {
  185. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  186. length = llmin((S32)(max_frac * (right - left)), length);
  187. length = llmin((S32)(max_frac * (top - bottom)), length);
  188. gGL.begin(LLRender::LINES);
  189. gGL.vertex2i(left, top);
  190. gGL.vertex2i(left + length, top);
  191. gGL.vertex2i(left, top);
  192. gGL.vertex2i(left, top - length);
  193. gGL.vertex2i(left, bottom);
  194. gGL.vertex2i(left + length, bottom);
  195. gGL.vertex2i(left, bottom);
  196. gGL.vertex2i(left, bottom + length);
  197. gGL.vertex2i(right, top);
  198. gGL.vertex2i(right - length, top);
  199. gGL.vertex2i(right, top);
  200. gGL.vertex2i(right, top - length);
  201. gGL.vertex2i(right, bottom);
  202. gGL.vertex2i(right - length, bottom);
  203. gGL.vertex2i(right, bottom);
  204. gGL.vertex2i(right, bottom + length);
  205. gGL.end();
  206. }
  207. void gl_draw_image(S32 x, S32 y, LLGLTexture* texp, const LLColor4& color,
  208. const LLRectf& uv_rect)
  209. {
  210. if (!texp)
  211. {
  212. llwarns << "NULL image pointer, aborting function" << llendl;
  213. return;
  214. }
  215. gl_draw_scaled_rotated_image(x, y, texp->getWidth(0), texp->getHeight(0),
  216. 0.f, texp, color, uv_rect);
  217. }
  218. void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height,
  219. LLGLTexture* texp, const LLColor4& color,
  220. const LLRectf& uv_rect)
  221. {
  222. if (!texp)
  223. {
  224. llwarns << "NULL image pointer, aborting function" << llendl;
  225. return;
  226. }
  227. gl_draw_scaled_rotated_image(x, y, width, height, 0.f, texp, color,
  228. uv_rect);
  229. }
  230. void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width,
  231. S32 border_height, S32 width, S32 height,
  232. LLGLTexture* texp,
  233. const LLColor4& color, bool solid_color,
  234. const LLRectf& uv_rect)
  235. {
  236. if (!texp)
  237. {
  238. llwarns << "NULL image pointer, aborting function" << llendl;
  239. return;
  240. }
  241. // scale screen size of borders down
  242. F32 border_width_fraction = (F32)border_width / (F32)texp->getWidth(0);
  243. F32 border_height_fraction = (F32)border_height / (F32)texp->getHeight(0);
  244. LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction,
  245. 1.f - border_width_fraction, border_height_fraction);
  246. gl_draw_scaled_image_with_border(x, y, width, height, texp, color,
  247. solid_color, uv_rect, scale_rect);
  248. }
  249. void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height,
  250. LLGLTexture* texp,
  251. const LLColor4& color, bool solid_color,
  252. const LLRectf& uv_rect,
  253. const LLRectf& scale_rect)
  254. {
  255. if (!texp)
  256. {
  257. llwarns << "NULL image pointer, aborting function" << llendl;
  258. return;
  259. }
  260. LLTexUnit* unit0 = gGL.getTexUnit(0);
  261. if (solid_color)
  262. {
  263. gSolidColorProgram.bind();
  264. }
  265. // Add in offset of current image to current UI translation
  266. LLVector3 ui_scale = gGL.getUIScale();
  267. LLVector3 ui_translation =
  268. (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale);
  269. F32 uv_width = uv_rect.getWidth();
  270. F32 uv_height = uv_rect.getHeight();
  271. // Shrink scaling region to be proportional to clipped image region
  272. LLRectf uv_center_rect(uv_rect.mLeft + scale_rect.mLeft * uv_width,
  273. uv_rect.mBottom + scale_rect.mTop * uv_height,
  274. uv_rect.mLeft + scale_rect.mRight * uv_width,
  275. uv_rect.mBottom + scale_rect.mBottom * uv_height);
  276. F32 image_width = texp->getWidth(0);
  277. F32 image_height = texp->getHeight(0);
  278. S32 image_natural_width = ll_roundp(image_width * uv_width);
  279. S32 image_natural_height = ll_roundp(image_height * uv_height);
  280. LLRectf draw_center_rect(uv_center_rect.mLeft * image_width,
  281. uv_center_rect.mTop * image_height,
  282. uv_center_rect.mRight * image_width,
  283. uv_center_rect.mBottom * image_height);
  284. // Scale fixed region of image to drawn region
  285. draw_center_rect.mRight += width - image_natural_width;
  286. draw_center_rect.mTop += height - image_natural_height;
  287. S32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight);
  288. S32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop);
  289. F32 shrink_width_ratio =
  290. scale_rect.getWidth() == 1.f ? 0.f
  291. : border_shrink_width /
  292. ((F32)image_natural_width *
  293. (1.f - scale_rect.getWidth()));
  294. F32 shrink_height_ratio =
  295. scale_rect.getHeight() == 1.f ? 0.f
  296. : border_shrink_height /
  297. ((F32)image_natural_height *
  298. (1.f - scale_rect.getHeight()));
  299. F32 border_shrink_scale =
  300. 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
  301. draw_center_rect.mLeft *= border_shrink_scale;
  302. draw_center_rect.mTop = ll_round(lerp((F32)height,
  303. (F32)draw_center_rect.mTop,
  304. border_shrink_scale));
  305. draw_center_rect.mRight = ll_round(lerp((F32)width,
  306. (F32)draw_center_rect.mRight,
  307. border_shrink_scale));
  308. draw_center_rect.mBottom *= border_shrink_scale;
  309. draw_center_rect.mLeft = ll_round(ui_translation.mV[VX] +
  310. (F32)draw_center_rect.mLeft *
  311. ui_scale.mV[VX]);
  312. draw_center_rect.mTop = ll_round(ui_translation.mV[VY] +
  313. (F32)draw_center_rect.mTop *
  314. ui_scale.mV[VY]);
  315. draw_center_rect.mRight = ll_round(ui_translation.mV[VX] +
  316. (F32)draw_center_rect.mRight *
  317. ui_scale.mV[VX]);
  318. draw_center_rect.mBottom = ll_round(ui_translation.mV[VY] +
  319. (F32)draw_center_rect.mBottom *
  320. ui_scale.mV[VY]);
  321. LLRectf draw_outer_rect(ui_translation.mV[VX],
  322. ui_translation.mV[VY] + height * ui_scale.mV[VY],
  323. ui_translation.mV[VX] + width * ui_scale.mV[VX],
  324. ui_translation.mV[VY]);
  325. LLGLSUIDefault gls_ui;
  326. unit0->bind(texp);
  327. gGL.color4fv(color.mV);
  328. constexpr S32 NUM_VERTICES = 9 * 6; // 9 quads turned into triangles
  329. LLVector2 uv[NUM_VERTICES];
  330. LLVector3 pos[NUM_VERTICES];
  331. gGL.begin(LLRender::TRIANGLES);
  332. {
  333. S32 index = 0;
  334. // draw bottom left
  335. uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
  336. pos[index++].set(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f);
  337. uv[index] = LLVector2(uv_center_rect.mLeft, uv_rect.mBottom);
  338. pos[index++].set(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
  339. uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
  340. pos[index++].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
  341. uv[index] = uv[index - 3];
  342. pos[index] = pos[index - 3];
  343. ++index;
  344. uv[index] = uv[index - 2];
  345. pos[index] = pos[index - 2];
  346. ++index;
  347. uv[index] = LLVector2(uv_rect.mLeft, uv_center_rect.mBottom);
  348. pos[index++].set(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
  349. // draw bottom middle
  350. uv[index] = LLVector2(uv_center_rect.mLeft, uv_rect.mBottom);
  351. pos[index++].set(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
  352. uv[index] = LLVector2(uv_center_rect.mRight, uv_rect.mBottom);
  353. pos[index++].set(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
  354. uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
  355. pos[index++].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
  356. uv[index] = uv[index - 3];
  357. pos[index] = pos[index - 3];
  358. ++index;
  359. uv[index] = uv[index - 2];
  360. pos[index] = pos[index - 2];
  361. ++index;
  362. uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
  363. pos[index++].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
  364. // draw bottom right
  365. uv[index] = LLVector2(uv_center_rect.mRight, uv_rect.mBottom);
  366. pos[index++].set(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
  367. uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
  368. pos[index++].set(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f);
  369. uv[index] = LLVector2(uv_rect.mRight, uv_center_rect.mBottom);
  370. pos[index++].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
  371. uv[index] = uv[index - 3];
  372. pos[index] = pos[index - 3];
  373. ++index;
  374. uv[index] = uv[index - 2];
  375. pos[index] = pos[index - 2];
  376. ++index;
  377. uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
  378. pos[index++].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
  379. // draw left
  380. uv[index] = LLVector2(uv_rect.mLeft, uv_center_rect.mBottom);
  381. pos[index++].set(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
  382. uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
  383. pos[index++].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
  384. uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
  385. pos[index++].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
  386. uv[index] = uv[index - 3];
  387. pos[index] = pos[index - 3];
  388. ++index;
  389. uv[index] = uv[index - 2];
  390. pos[index] = pos[index - 2];
  391. ++index;
  392. uv[index] = LLVector2(uv_rect.mLeft, uv_center_rect.mTop);
  393. pos[index++].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
  394. // draw middle
  395. uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
  396. pos[index++].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
  397. uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
  398. pos[index++].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
  399. uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
  400. pos[index++].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
  401. uv[index] = uv[index - 3];
  402. pos[index] = pos[index - 3];
  403. ++index;
  404. uv[index] = uv[index - 2];
  405. pos[index] = pos[index - 2];
  406. ++index;
  407. uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
  408. pos[index++].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
  409. // draw right
  410. uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
  411. pos[index++].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
  412. uv[index] = LLVector2(uv_rect.mRight, uv_center_rect.mBottom);
  413. pos[index++].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
  414. uv[index] = LLVector2(uv_rect.mRight, uv_center_rect.mTop);
  415. pos[index++].set(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
  416. uv[index] = uv[index - 3];
  417. pos[index] = pos[index - 3];
  418. ++index;
  419. uv[index] = uv[index - 2];
  420. pos[index] = pos[index - 2];
  421. ++index;
  422. uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
  423. pos[index++].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
  424. // draw top left
  425. uv[index] = LLVector2(uv_rect.mLeft, uv_center_rect.mTop);
  426. pos[index++].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
  427. uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
  428. pos[index++].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
  429. uv[index] = LLVector2(uv_center_rect.mLeft, uv_rect.mTop);
  430. pos[index++].set(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
  431. uv[index] = uv[index - 3];
  432. pos[index] = pos[index - 3];
  433. ++index;
  434. uv[index] = uv[index - 2];
  435. pos[index] = pos[index - 2];
  436. ++index;
  437. uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
  438. pos[index++].set(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f);
  439. // draw top middle
  440. uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
  441. pos[index++].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
  442. uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
  443. pos[index++].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
  444. uv[index] = LLVector2(uv_center_rect.mRight, uv_rect.mTop);
  445. pos[index++].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
  446. uv[index] = uv[index - 3];
  447. pos[index] = pos[index - 3];
  448. ++index;
  449. uv[index] = uv[index - 2];
  450. pos[index] = pos[index - 2];
  451. ++index;
  452. uv[index] = LLVector2(uv_center_rect.mLeft, uv_rect.mTop);
  453. pos[index++].set(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
  454. // draw top right
  455. uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
  456. pos[index++].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
  457. uv[index] = LLVector2(uv_rect.mRight, uv_center_rect.mTop);
  458. pos[index++].set(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
  459. uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
  460. pos[index++].set(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f);
  461. uv[index] = uv[index - 3];
  462. pos[index] = pos[index - 3];
  463. ++index;
  464. uv[index] = uv[index - 2];
  465. pos[index] = pos[index - 2];
  466. ++index;
  467. uv[index] = LLVector2(uv_center_rect.mRight, uv_rect.mTop);
  468. pos[index].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
  469. gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
  470. }
  471. gGL.end();
  472. if (solid_color)
  473. {
  474. gUIProgram.bind();
  475. }
  476. }
  477. void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLGLTexture* texp,
  478. const LLColor4& color, const LLRectf& uv_rect)
  479. {
  480. gl_draw_scaled_rotated_image(x, y, texp->getWidth(0), texp->getHeight(0),
  481. degrees, texp, color, uv_rect);
  482. }
  483. void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height,
  484. F32 degrees, LLGLTexture* texp,
  485. const LLColor4& color,
  486. const LLRectf& uv_rect)
  487. {
  488. if (!texp)
  489. {
  490. llwarns << "NULL image pointer, aborting function" << llendl;
  491. return;
  492. }
  493. LLGLSUIDefault gls_ui;
  494. LLTexUnit* unit0 = gGL.getTexUnit(0);
  495. unit0->bind(texp);
  496. gGL.color4fv(color.mV);
  497. if (degrees == 0.f)
  498. {
  499. constexpr S32 NUM_VERTICES = 6;
  500. LLVector2 uv[NUM_VERTICES];
  501. LLVector3 pos[NUM_VERTICES];
  502. gGL.begin(LLRender::TRIANGLES);
  503. {
  504. LLVector3 ui_scale = gGL.getUIScale();
  505. LLVector3 ui_translation = gGL.getUITranslation();
  506. ui_translation.mV[VX] += x;
  507. ui_translation.mV[VY] += y;
  508. ui_translation.scaleVec(ui_scale);
  509. S32 index = 0;
  510. S32 scaled_width = ll_roundp(width * ui_scale.mV[VX]);
  511. S32 scaled_height = ll_roundp(height * ui_scale.mV[VY]);
  512. uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
  513. pos[index++] = LLVector3(ui_translation.mV[VX] + scaled_width,
  514. ui_translation.mV[VY] + scaled_height,
  515. 0.f);
  516. uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
  517. pos[index++] = LLVector3(ui_translation.mV[VX],
  518. ui_translation.mV[VY] + scaled_height,
  519. 0.f);
  520. uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
  521. pos[index++] = LLVector3(ui_translation.mV[VX],
  522. ui_translation.mV[VY], 0.f);
  523. uv[index] = uv[index - 3];
  524. pos[index] = pos[index - 3];
  525. ++index;
  526. uv[index] = uv[index - 2];
  527. pos[index] = pos[index - 2];
  528. ++index;
  529. uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
  530. pos[index++] = LLVector3(ui_translation.mV[VX] + scaled_width,
  531. ui_translation.mV[VY], 0.f);
  532. gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
  533. }
  534. gGL.end();
  535. }
  536. else
  537. {
  538. F32 offset_x = F32(width / 2);
  539. F32 offset_y = F32(height / 2);
  540. gGL.pushUIMatrix();
  541. gGL.translateUI((F32)x, (F32)y, 0.f);
  542. gGL.translateUI(offset_x, offset_y, 0.f);
  543. LLMatrix3 quat(0.f, 0.f, degrees * DEG_TO_RAD);
  544. unit0->bind(texp);
  545. gGL.color4fv(color.mV);
  546. gGL.begin(LLRender::TRIANGLES);
  547. {
  548. LLVector3 v1 = LLVector3(-offset_x, offset_y, 0.f) * quat;
  549. gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
  550. gGL.vertex2f(v1.mV[0], v1.mV[1]);
  551. v1 = LLVector3(-offset_x, -offset_y, 0.f) * quat;
  552. gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
  553. gGL.vertex2f(v1.mV[0], v1.mV[1]);
  554. LLVector3 v2 = LLVector3(offset_x, offset_y, 0.f) * quat;
  555. gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
  556. gGL.vertex2f(v2.mV[0], v2.mV[1]);
  557. gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
  558. gGL.vertex2f(v2.mV[0], v2.mV[1]);
  559. gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
  560. gGL.vertex2f(v1.mV[0], v1.mV[1]);
  561. v1 = LLVector3(offset_x, -offset_y, 0.f) * quat;
  562. gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
  563. gGL.vertex2f(v1.mV[0], v1.mV[1]);
  564. }
  565. gGL.end();
  566. gGL.popUIMatrix();
  567. }
  568. }
  569. void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, bool filled,
  570. F32 start_angle, F32 end_angle)
  571. {
  572. if (end_angle < start_angle)
  573. {
  574. end_angle += F_TWO_PI;
  575. }
  576. gGL.pushUIMatrix();
  577. gGL.translateUI(center_x, center_y, 0.f);
  578. {
  579. // Inexact, but reasonably fast.
  580. F32 delta = (end_angle - start_angle) / steps;
  581. F32 sin_delta = sinf(delta);
  582. F32 cos_delta = cosf(delta);
  583. F32 x = cosf(start_angle) * radius;
  584. F32 y = sinf(start_angle) * radius;
  585. if (filled)
  586. {
  587. gGL.begin(LLRender::TRIANGLE_FAN);
  588. gGL.vertex2f(0.f, 0.f);
  589. // make sure circle is complete
  590. ++steps;
  591. }
  592. else
  593. {
  594. gGL.begin(LLRender::LINE_STRIP);
  595. }
  596. while (steps--)
  597. {
  598. // Successive rotations
  599. gGL.vertex2f(x, y);
  600. F32 x_new = x * cos_delta - y * sin_delta;
  601. y = x * sin_delta + y * cos_delta;
  602. x = x_new;
  603. }
  604. gGL.end();
  605. }
  606. gGL.popUIMatrix();
  607. }
  608. void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps,
  609. bool filled)
  610. {
  611. gGL.pushUIMatrix();
  612. {
  613. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  614. gGL.translateUI(center_x, center_y, 0.f);
  615. // Inexact, but reasonably fast.
  616. F32 delta = F_TWO_PI / steps;
  617. F32 sin_delta = sinf(delta);
  618. F32 cos_delta = cosf(delta);
  619. F32 x = radius;
  620. F32 y = 0.f;
  621. if (filled)
  622. {
  623. gGL.begin(LLRender::TRIANGLE_FAN);
  624. gGL.vertex2f(0.f, 0.f);
  625. // make sure circle is complete
  626. ++steps;
  627. }
  628. else
  629. {
  630. gGL.begin(LLRender::LINE_LOOP);
  631. }
  632. while (steps--)
  633. {
  634. // Successive rotations
  635. gGL.vertex2f(x, y);
  636. F32 x_new = x * cos_delta - y * sin_delta;
  637. y = x * sin_delta + y * cos_delta;
  638. x = x_new;
  639. }
  640. gGL.end();
  641. }
  642. gGL.popUIMatrix();
  643. }
  644. // Renders a ring with sides (tube shape)
  645. void gl_deep_circle(F32 radius, F32 depth, S32 steps)
  646. {
  647. F32 x = radius;
  648. F32 y = 0.f;
  649. F32 angle_delta = F_TWO_PI / (F32)steps;
  650. gGL.begin(LLRender::TRIANGLE_STRIP);
  651. {
  652. S32 step = steps + 1; // An extra step to close the circle.
  653. while (step--)
  654. {
  655. gGL.vertex3f(x, y, depth);
  656. gGL.vertex3f(x, y, 0.f);
  657. F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta);
  658. y = x * sinf(angle_delta) + y * cosf(angle_delta);
  659. x = x_new;
  660. }
  661. }
  662. gGL.end();
  663. }
  664. void gl_ring(F32 radius, F32 width, const LLColor4& center_color,
  665. const LLColor4& side_color, S32 steps, bool render_center)
  666. {
  667. gGL.pushUIMatrix();
  668. gGL.translateUI(0.f, 0.f, -width / 2);
  669. {
  670. if (render_center)
  671. {
  672. gGL.color4fv(center_color.mV);
  673. gl_deep_circle(radius, width, steps);
  674. }
  675. else
  676. {
  677. gGL.color4fv(side_color.mV);
  678. gl_washer_2d(radius, radius - width, steps, side_color, side_color);
  679. gGL.translatef(0.f, 0.f, width);
  680. gl_washer_2d(radius - width, radius, steps, side_color, side_color);
  681. }
  682. }
  683. gGL.popUIMatrix();
  684. }
  685. // Draws the area between two concentric circles, like
  686. // a doughnut or washer.
  687. void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps,
  688. const LLColor4& inner_color, const LLColor4& outer_color)
  689. {
  690. const F32 delta = F_TWO_PI / steps;
  691. const F32 sin_delta = sinf(delta);
  692. const F32 cos_delta = cosf(delta);
  693. F32 x1 = outer_radius;
  694. F32 y1 = 0.f;
  695. F32 x2 = inner_radius;
  696. F32 y2 = 0.f;
  697. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  698. gGL.begin(LLRender::TRIANGLE_STRIP);
  699. {
  700. ++steps; // An extra step to close the circle.
  701. while (steps--)
  702. {
  703. gGL.color4fv(outer_color.mV);
  704. gGL.vertex2f(x1, y1);
  705. gGL.color4fv(inner_color.mV);
  706. gGL.vertex2f(x2, y2);
  707. F32 x1_new = x1 * cos_delta - y1 * sin_delta;
  708. y1 = x1 * sin_delta + y1 * cos_delta;
  709. x1 = x1_new;
  710. F32 x2_new = x2 * cos_delta - y2 * sin_delta;
  711. y2 = x2 * sin_delta + y2 * cos_delta;
  712. x2 = x2_new;
  713. }
  714. }
  715. gGL.end();
  716. }
  717. // Draws the area between two concentric circles, like a doughnut or washer.
  718. void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius,
  719. F32 start_radians, F32 end_radians,
  720. S32 steps, const LLColor4& inner_color,
  721. const LLColor4& outer_color)
  722. {
  723. const F32 delta = (end_radians - start_radians) / steps;
  724. const F32 sin_delta = sinf(delta);
  725. const F32 cos_delta = cosf(delta);
  726. F32 x1 = outer_radius * cosf(start_radians);
  727. F32 y1 = outer_radius * sinf(start_radians);
  728. F32 x2 = inner_radius * cosf(start_radians);
  729. F32 y2 = inner_radius * sinf(start_radians);
  730. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  731. gGL.begin(LLRender::TRIANGLE_STRIP);
  732. {
  733. ++steps; // An extra step to close the circle.
  734. while (steps--)
  735. {
  736. gGL.color4fv(outer_color.mV);
  737. gGL.vertex2f(x1, y1);
  738. gGL.color4fv(inner_color.mV);
  739. gGL.vertex2f(x2, y2);
  740. F32 x1_new = x1 * cos_delta - y1 * sin_delta;
  741. y1 = x1 * sin_delta + y1 * cos_delta;
  742. x1 = x1_new;
  743. F32 x2_new = x2 * cos_delta - y2 * sin_delta;
  744. y2 = x2 * sin_delta + y2 * cos_delta;
  745. x2 = x2_new;
  746. }
  747. }
  748. gGL.end();
  749. }
  750. // Draws spokes around a circle.
  751. void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count,
  752. const LLColor4& inner_color,
  753. const LLColor4& outer_color)
  754. {
  755. const F32 delta = F_TWO_PI / count;
  756. const F32 half_delta = delta * 0.5f;
  757. const F32 sin_delta = sinf(delta);
  758. const F32 cos_delta = cosf(delta);
  759. F32 x1 = outer_radius * cosf(half_delta);
  760. F32 y1 = outer_radius * sinf(half_delta);
  761. F32 x2 = inner_radius * cosf(half_delta);
  762. F32 y2 = inner_radius * sinf(half_delta);
  763. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  764. gGL.begin(LLRender::LINES);
  765. {
  766. while (count--)
  767. {
  768. gGL.color4fv(outer_color.mV);
  769. gGL.vertex2f(x1, y1);
  770. gGL.color4fv(inner_color.mV);
  771. gGL.vertex2f(x2, y2);
  772. F32 x1_new = x1 * cos_delta - y1 * sin_delta;
  773. y1 = x1 * sin_delta + y1 * cos_delta;
  774. x1 = x1_new;
  775. F32 x2_new = x2 * cos_delta - y2 * sin_delta;
  776. y2 = x2 * sin_delta + y2 * cos_delta;
  777. x2 = x2_new;
  778. }
  779. }
  780. gGL.end();
  781. }
  782. void gl_rect_2d_simple_tex(S32 width, S32 height)
  783. {
  784. gGL.begin(LLRender::TRIANGLES);
  785. {
  786. gGL.texCoord2f(1.f, 1.f);
  787. gGL.vertex2i(width, height);
  788. gGL.texCoord2f(0.f, 1.f);
  789. gGL.vertex2i(0, height);
  790. gGL.texCoord2f(0.f, 0.f);
  791. gGL.vertex2i(0, 0);
  792. gGL.texCoord2f(1.f, 1.f);
  793. gGL.vertex2i(width, height);
  794. gGL.texCoord2f(0.f, 0.f);
  795. gGL.vertex2i(0, 0);
  796. gGL.texCoord2f(1.f, 0.f);
  797. gGL.vertex2i(width, 0);
  798. }
  799. gGL.end();
  800. }
  801. void gl_rect_2d_simple(S32 width, S32 height)
  802. {
  803. // Important: we MUST draw the triangles counterclockwise so that they
  804. // "face" the camera (else, the rectangle drawn with gl_rect_2d_simple()
  805. // won't occlude the UI+world view, such as in the model preview floater,
  806. // for example).
  807. gGL.begin(LLRender::TRIANGLES);
  808. {
  809. gGL.vertex2i(width, height);
  810. gGL.vertex2i(0, height);
  811. gGL.vertex2i(0, 0);
  812. gGL.vertex2i(width, height);
  813. gGL.vertex2i(0, 0);
  814. gGL.vertex2i(width, 0);
  815. }
  816. gGL.end();
  817. }
  818. void gl_segmented_rect_2d_tex(S32 left, S32 top, S32 right, S32 bottom,
  819. S32 texture_width, S32 texture_height,
  820. S32 border_size, U32 edges)
  821. {
  822. S32 width = abs(right - left);
  823. S32 height = abs(top - bottom);
  824. gGL.pushUIMatrix();
  825. gGL.translateUI((F32)left, (F32)bottom, 0.f);
  826. LLVector2 border_uv_scale((F32)border_size / (F32)texture_width,
  827. (F32)border_size / (F32)texture_height);
  828. if (border_uv_scale.mV[VX] > 0.5f)
  829. {
  830. border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
  831. }
  832. if (border_uv_scale.mV[VY] > 0.5f)
  833. {
  834. border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
  835. }
  836. F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f,
  837. (F32)height * 0.5f);
  838. LLVector2 border_width_left, border_width_right,
  839. border_height_bottom, border_height_top;
  840. if ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0)
  841. {
  842. border_width_left = LLVector2(border_scale, 0.f);
  843. }
  844. if ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0)
  845. {
  846. border_width_right = LLVector2(border_scale, 0.f);
  847. }
  848. if ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0)
  849. {
  850. border_height_bottom = LLVector2(0.f, border_scale);
  851. }
  852. if ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0)
  853. {
  854. border_height_top = LLVector2(0.f, border_scale);
  855. }
  856. LLVector2 width_vec((F32)width, 0.f);
  857. LLVector2 height_vec(0.f, (F32)height);
  858. gGL.begin(LLRender::TRIANGLES);
  859. {
  860. // draw bottom left
  861. gGL.texCoord2f(0.f, 0.f);
  862. gGL.vertex2f(0.f, 0.f);
  863. F32 border_uv_scale_x = border_uv_scale.mV[VX];
  864. F32 border_uv_scale_y = border_uv_scale.mV[VY];
  865. gGL.texCoord2f(border_uv_scale_x, 0.f);
  866. gGL.vertex2fv(border_width_left.mV);
  867. LLVector2 bwl_bhb = border_width_left + border_height_bottom;
  868. gGL.texCoord2f(border_uv_scale_x, border_uv_scale_y);
  869. gGL.vertex2fv(bwl_bhb.mV);
  870. gGL.texCoord2f(0.f, 0.f);
  871. gGL.vertex2f(0.f, 0.f);
  872. gGL.texCoord2f(border_uv_scale_x, border_uv_scale_y);
  873. gGL.vertex2fv(bwl_bhb.mV);
  874. gGL.texCoord2f(0.f, border_uv_scale_y);
  875. gGL.vertex2fv(border_height_bottom.mV);
  876. // draw bottom middle
  877. gGL.texCoord2f(border_uv_scale_x, 0.f);
  878. gGL.vertex2fv(border_width_left.mV);
  879. LLVector2 wv_bwr = width_vec - border_width_right;
  880. gGL.texCoord2f(1.f - border_uv_scale_x, 0.f);
  881. gGL.vertex2fv(wv_bwr.mV);
  882. LLVector2 wv_bwr_bhb = width_vec - border_width_right +
  883. border_height_bottom;
  884. gGL.texCoord2f(1.f - border_uv_scale_x, border_uv_scale_y);
  885. gGL.vertex2fv(wv_bwr_bhb.mV);
  886. gGL.texCoord2f(border_uv_scale_x, 0.f);
  887. gGL.vertex2fv(border_width_left.mV);
  888. gGL.texCoord2f(1.f - border_uv_scale_x, border_uv_scale_y);
  889. gGL.vertex2fv(wv_bwr_bhb.mV);
  890. gGL.texCoord2f(border_uv_scale_x, border_uv_scale_y);
  891. gGL.vertex2fv(bwl_bhb.mV);
  892. // draw bottom right
  893. gGL.texCoord2f(1.f - border_uv_scale_x, 0.f);
  894. gGL.vertex2fv(wv_bwr.mV);
  895. gGL.texCoord2f(1.f, 0.f);
  896. gGL.vertex2fv(width_vec.mV);
  897. LLVector2 wv_bhb = width_vec + border_height_bottom;
  898. gGL.texCoord2f(1.f, border_uv_scale_y);
  899. gGL.vertex2fv(wv_bhb.mV);
  900. gGL.texCoord2f(1.f - border_uv_scale_x, 0.f);
  901. gGL.vertex2fv(wv_bwr.mV);
  902. gGL.texCoord2f(1.f, border_uv_scale_y);
  903. gGL.vertex2fv(wv_bhb.mV);
  904. gGL.texCoord2f(1.f - border_uv_scale_x, border_uv_scale_y);
  905. gGL.vertex2fv(wv_bwr_bhb.mV);
  906. // draw left
  907. gGL.texCoord2f(0.f, border_uv_scale_y);
  908. gGL.vertex2fv(border_height_bottom.mV);
  909. gGL.texCoord2f(border_uv_scale_x, border_uv_scale_y);
  910. gGL.vertex2fv(bwl_bhb.mV);
  911. LLVector2 bwl_hv_bht = border_width_left + height_vec -
  912. border_height_top;
  913. gGL.texCoord2f(border_uv_scale_x, 1.f - border_uv_scale_y);
  914. gGL.vertex2fv(bwl_hv_bht.mV);
  915. gGL.texCoord2f(0.f, border_uv_scale_y);
  916. gGL.vertex2fv(border_height_bottom.mV);
  917. gGL.texCoord2f(border_uv_scale_x, 1.f - border_uv_scale_y);
  918. gGL.vertex2fv(bwl_hv_bht.mV);
  919. LLVector2 hv_bht = height_vec - border_height_top;
  920. gGL.texCoord2f(0.f, 1.f - border_uv_scale_y);
  921. gGL.vertex2fv(hv_bht.mV);
  922. // draw middle
  923. gGL.texCoord2f(border_uv_scale_x, border_uv_scale_y);
  924. gGL.vertex2fv(bwl_bhb.mV);
  925. gGL.texCoord2f(1.f - border_uv_scale_x, border_uv_scale_y);
  926. gGL.vertex2fv(wv_bwr_bhb.mV);
  927. LLVector2 wv_bwr_hv_bht = width_vec - border_width_right + height_vec -
  928. border_height_top;
  929. gGL.texCoord2f(1.f - border_uv_scale_x, 1.f - border_uv_scale_y);
  930. gGL.vertex2fv(wv_bwr_hv_bht.mV);
  931. gGL.texCoord2f(border_uv_scale_x, border_uv_scale_y);
  932. gGL.vertex2fv(bwl_bhb.mV);
  933. gGL.texCoord2f(1.f - border_uv_scale_x, 1.f - border_uv_scale_y);
  934. gGL.vertex2fv(wv_bwr_hv_bht.mV);
  935. gGL.texCoord2f(border_uv_scale_x, 1.f - border_uv_scale_y);
  936. gGL.vertex2fv(bwl_hv_bht.mV);
  937. // draw right
  938. gGL.texCoord2f(1.f - border_uv_scale_x, border_uv_scale_y);
  939. gGL.vertex2fv(wv_bwr_bhb.mV);
  940. gGL.texCoord2f(1.f, border_uv_scale_y);
  941. gGL.vertex2fv(wv_bhb.mV);
  942. LLVector2 wv_hv_bht = width_vec + height_vec - border_height_top;
  943. gGL.texCoord2f(1.f, 1.f - border_uv_scale_y);
  944. gGL.vertex2fv(wv_hv_bht.mV);
  945. gGL.texCoord2f(1.f - border_uv_scale_x, border_uv_scale_y);
  946. gGL.vertex2fv(wv_bwr_bhb.mV);
  947. gGL.texCoord2f(1.f, 1.f - border_uv_scale_y);
  948. gGL.vertex2fv(wv_hv_bht.mV);
  949. gGL.texCoord2f(1.f - border_uv_scale_x, 1.f - border_uv_scale_y);
  950. gGL.vertex2fv(wv_bwr_hv_bht.mV);
  951. // draw top left
  952. gGL.texCoord2f(0.f, 1.f - border_uv_scale_y);
  953. gGL.vertex2fv(hv_bht.mV);
  954. gGL.texCoord2f(border_uv_scale_x, 1.f - border_uv_scale_y);
  955. gGL.vertex2fv(bwl_hv_bht.mV);
  956. LLVector2 bwl_hv = border_width_left + height_vec;
  957. gGL.texCoord2f(border_uv_scale_x, 1.f);
  958. gGL.vertex2fv(bwl_hv.mV);
  959. gGL.texCoord2f(0.f, 1.f - border_uv_scale_y);
  960. gGL.vertex2fv(hv_bht.mV);
  961. gGL.texCoord2f(border_uv_scale_x, 1.f);
  962. gGL.vertex2fv(bwl_hv.mV);
  963. gGL.texCoord2f(0.f, 1.f);
  964. gGL.vertex2fv(height_vec.mV);
  965. // draw top middle
  966. gGL.texCoord2f(border_uv_scale_x, 1.f - border_uv_scale_y);
  967. gGL.vertex2fv(bwl_hv_bht.mV);
  968. gGL.texCoord2f(1.f - border_uv_scale_x, 1.f - border_uv_scale_y);
  969. gGL.vertex2fv(wv_bwr_hv_bht.mV);
  970. LLVector2 wv_bwr_hv = width_vec - border_width_right + height_vec;
  971. gGL.texCoord2f(1.f - border_uv_scale_x, 1.f);
  972. gGL.vertex2fv(wv_bwr_hv.mV);
  973. gGL.texCoord2f(border_uv_scale_x, 1.f - border_uv_scale_y);
  974. gGL.vertex2fv(bwl_hv_bht.mV);
  975. gGL.texCoord2f(1.f - border_uv_scale_x, 1.f);
  976. gGL.vertex2fv(wv_bwr_hv.mV);
  977. gGL.texCoord2f(border_uv_scale_x, 1.f);
  978. gGL.vertex2fv(bwl_hv.mV);
  979. // draw top right
  980. gGL.texCoord2f(1.f - border_uv_scale_x, 1.f - border_uv_scale_y);
  981. gGL.vertex2fv(wv_bwr_hv_bht.mV);
  982. gGL.texCoord2f(1.f, 1.f - border_uv_scale_y);
  983. gGL.vertex2fv(wv_hv_bht.mV);
  984. LLVector2 wv_hv = width_vec + height_vec;
  985. gGL.texCoord2f(1.f, 1.f);
  986. gGL.vertex2fv(wv_hv.mV);
  987. gGL.texCoord2f(1.f - border_uv_scale_x, 1.f - border_uv_scale_y);
  988. gGL.vertex2fv(wv_bwr_hv_bht.mV);
  989. gGL.texCoord2f(1.f, 1.f);
  990. gGL.vertex2fv(wv_hv.mV);
  991. gGL.texCoord2f(1.f - border_uv_scale_x, 1.f);
  992. gGL.vertex2fv(wv_bwr_hv.mV);
  993. }
  994. gGL.end();
  995. gGL.popUIMatrix();
  996. }
  997. void gl_segmented_rect_2d_fragment_tex(S32 left, S32 top, S32 right,
  998. S32 bottom, S32 texture_width,
  999. S32 texture_height, S32 border_size,
  1000. F32 start_fragment, F32 end_fragment,
  1001. U32 edges)
  1002. {
  1003. S32 width = abs(right - left);
  1004. S32 height = abs(top - bottom);
  1005. gGL.pushUIMatrix();
  1006. gGL.translateUI((F32)left, (F32)bottom, 0.f);
  1007. LLVector2 border_uv_scale((F32)border_size / (F32)texture_width,
  1008. (F32)border_size / (F32)texture_height);
  1009. if (border_uv_scale.mV[VX] > 0.5f)
  1010. {
  1011. border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
  1012. }
  1013. if (border_uv_scale.mV[VY] > 0.5f)
  1014. {
  1015. border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
  1016. }
  1017. F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f,
  1018. (F32)height * 0.5f);
  1019. LLVector2 border_width_left, border_width_right,
  1020. border_height_bottom, border_height_top;
  1021. if ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0)
  1022. {
  1023. border_width_left = LLVector2(border_scale, 0.f);
  1024. }
  1025. if ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0)
  1026. {
  1027. border_width_right = LLVector2(border_scale, 0.f);
  1028. }
  1029. if ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0)
  1030. {
  1031. border_height_bottom = LLVector2(0.f, border_scale);
  1032. }
  1033. if ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0)
  1034. {
  1035. border_height_top = LLVector2(0.f, border_scale);
  1036. }
  1037. LLVector2 width_vec((F32)width, 0.f);
  1038. LLVector2 height_vec(0.f, (F32)height);
  1039. F32 middle_start = border_scale / (F32)width;
  1040. F32 middle_end = 1.f - middle_start;
  1041. F32 u_min = 0.f;
  1042. F32 u_max = 0.f;
  1043. LLVector2 x_min;
  1044. LLVector2 x_max;
  1045. gGL.begin(LLRender::TRIANGLES);
  1046. {
  1047. if (start_fragment < middle_start)
  1048. {
  1049. F32 start_factor = start_fragment / middle_start;
  1050. F32 end_factor = llmin(end_fragment / middle_start, 1.f);
  1051. u_min = start_factor * border_uv_scale.mV[VX];
  1052. u_max = end_factor * border_uv_scale.mV[VX];
  1053. x_min = start_factor * border_width_left;
  1054. x_max = end_factor * border_width_left;
  1055. // draw bottom left
  1056. gGL.texCoord2f(u_min, 0.f);
  1057. gGL.vertex2fv(x_min.mV);
  1058. gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
  1059. gGL.vertex2fv(x_max.mV);
  1060. gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
  1061. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1062. gGL.texCoord2f(u_min, 0.f);
  1063. gGL.vertex2fv(x_min.mV);
  1064. gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
  1065. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1066. gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
  1067. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1068. // draw left
  1069. gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
  1070. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1071. gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
  1072. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1073. gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
  1074. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1075. gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
  1076. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1077. gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
  1078. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1079. gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
  1080. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1081. // draw top left
  1082. gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
  1083. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1084. gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
  1085. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1086. gGL.texCoord2f(u_max, 1.f);
  1087. gGL.vertex2fv((x_max + height_vec).mV);
  1088. gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
  1089. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1090. gGL.texCoord2f(u_max, 1.f);
  1091. gGL.vertex2fv((x_max + height_vec).mV);
  1092. gGL.texCoord2f(u_min, 1.f);
  1093. gGL.vertex2fv((x_min + height_vec).mV);
  1094. }
  1095. if (end_fragment > middle_start || start_fragment < middle_end)
  1096. {
  1097. x_min = border_width_left + width_vec *
  1098. (llclamp(start_fragment, middle_start, middle_end) -
  1099. middle_start);
  1100. x_max = border_width_left + width_vec *
  1101. (llclamp(end_fragment, middle_start, middle_end) -
  1102. middle_start);
  1103. // draw bottom middle
  1104. gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
  1105. gGL.vertex2fv(x_min.mV);
  1106. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
  1107. gGL.vertex2fv((x_max).mV);
  1108. gGL.texCoord2f(1.f - border_uv_scale.mV[VX],
  1109. border_uv_scale.mV[VY]);
  1110. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1111. gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
  1112. gGL.vertex2fv(x_min.mV);
  1113. gGL.texCoord2f(1.f - border_uv_scale.mV[VX],
  1114. border_uv_scale.mV[VY]);
  1115. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1116. gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  1117. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1118. // draw middle
  1119. gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  1120. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1121. gGL.texCoord2f(1.f - border_uv_scale.mV[VX],
  1122. border_uv_scale.mV[VY]);
  1123. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1124. gGL.texCoord2f(1.f - border_uv_scale.mV[VX],
  1125. 1.f - border_uv_scale.mV[VY]);
  1126. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1127. gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  1128. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1129. gGL.texCoord2f(1.f - border_uv_scale.mV[VX],
  1130. 1.f - border_uv_scale.mV[VY]);
  1131. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1132. gGL.texCoord2f(border_uv_scale.mV[VX],
  1133. 1.f - border_uv_scale.mV[VY]);
  1134. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1135. // draw top middle
  1136. gGL.texCoord2f(border_uv_scale.mV[VX],
  1137. 1.f - border_uv_scale.mV[VY]);
  1138. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1139. gGL.texCoord2f(1.f - border_uv_scale.mV[VX],
  1140. 1.f - border_uv_scale.mV[VY]);
  1141. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1142. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
  1143. gGL.vertex2fv((x_max + height_vec).mV);
  1144. gGL.texCoord2f(border_uv_scale.mV[VX],
  1145. 1.f - border_uv_scale.mV[VY]);
  1146. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1147. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
  1148. gGL.vertex2fv((x_max + height_vec).mV);
  1149. gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
  1150. gGL.vertex2fv((x_min + height_vec).mV);
  1151. }
  1152. if (end_fragment > middle_end)
  1153. {
  1154. F32 start_factor =
  1155. 1.f - llmax(0.f, (start_fragment - middle_end) / middle_start);
  1156. F32 end_factor = 1.f - (end_fragment - middle_end) / middle_start;
  1157. u_min = start_factor * border_uv_scale.mV[VX];
  1158. u_max = end_factor * border_uv_scale.mV[VX];
  1159. x_min = width_vec - start_factor * border_width_right;
  1160. x_max = width_vec - end_factor * border_width_right;
  1161. // draw bottom right
  1162. gGL.texCoord2f(u_min, 0.f);
  1163. gGL.vertex2fv((x_min).mV);
  1164. gGL.texCoord2f(u_max, 0.f);
  1165. gGL.vertex2fv(x_max.mV);
  1166. gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
  1167. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1168. gGL.texCoord2f(u_min, 0.f);
  1169. gGL.vertex2fv((x_min).mV);
  1170. gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
  1171. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1172. gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
  1173. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1174. // draw right
  1175. gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
  1176. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1177. gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
  1178. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1179. gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
  1180. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1181. gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
  1182. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1183. gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
  1184. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1185. gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
  1186. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1187. // draw top right
  1188. gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
  1189. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1190. gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
  1191. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1192. gGL.texCoord2f(u_max, 1.f);
  1193. gGL.vertex2fv((x_max + height_vec).mV);
  1194. gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
  1195. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1196. gGL.texCoord2f(u_max, 1.f);
  1197. gGL.vertex2fv((x_max + height_vec).mV);
  1198. gGL.texCoord2f(u_min, 1.f);
  1199. gGL.vertex2fv((x_min + height_vec).mV);
  1200. }
  1201. }
  1202. gGL.end();
  1203. gGL.popUIMatrix();
  1204. }
  1205. void gl_segmented_rect_3d_tex(const LLVector2& border_scale,
  1206. const LLVector3& border_width,
  1207. const LLVector3& border_height,
  1208. const LLVector3& width_vec,
  1209. const LLVector3& height_vec, U32 edges)
  1210. {
  1211. LLVector3 left_border_width, right_border_width,
  1212. top_border_height, bottom_border_height;
  1213. if ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0)
  1214. {
  1215. left_border_width = border_width;
  1216. }
  1217. if ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0)
  1218. {
  1219. right_border_width = border_width;
  1220. }
  1221. if ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0)
  1222. {
  1223. top_border_height = border_height;
  1224. }
  1225. if ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0)
  1226. {
  1227. bottom_border_height = border_height;
  1228. }
  1229. gGL.begin(LLRender::TRIANGLES);
  1230. {
  1231. F32 border_scale_x = border_scale.mV[VX];
  1232. F32 border_scale_y = border_scale.mV[VY];
  1233. // draw bottom left
  1234. gGL.texCoord2f(0.f, 0.f);
  1235. gGL.vertex3f(0.f, 0.f, 0.f);
  1236. gGL.texCoord2f(border_scale_x, 0.f);
  1237. gGL.vertex3fv(left_border_width.mV);
  1238. LLVector3 lbw_bbh = left_border_width + bottom_border_height;
  1239. gGL.texCoord2f(border_scale_x, border_scale_y);
  1240. gGL.vertex3fv(lbw_bbh.mV);
  1241. gGL.texCoord2f(0.f, 0.f);
  1242. gGL.vertex3f(0.f, 0.f, 0.f);
  1243. gGL.texCoord2f(border_scale_x, border_scale_y);
  1244. gGL.vertex3fv(lbw_bbh.mV);
  1245. gGL.texCoord2f(0.f, border_scale_y);
  1246. gGL.vertex3fv(bottom_border_height.mV);
  1247. // draw bottom middle
  1248. gGL.texCoord2f(border_scale_x, 0.f);
  1249. gGL.vertex3fv(left_border_width.mV);
  1250. LLVector3 wv_rbw = width_vec - right_border_width;
  1251. gGL.texCoord2f(1.f - border_scale_x, 0.f);
  1252. gGL.vertex3fv(wv_rbw.mV);
  1253. LLVector3 wv_rbw_bbh = width_vec - right_border_width +
  1254. bottom_border_height;
  1255. gGL.texCoord2f(1.f - border_scale_x, border_scale_y);
  1256. gGL.vertex3fv(wv_rbw_bbh.mV);
  1257. gGL.texCoord2f(border_scale_x, 0.f);
  1258. gGL.vertex3fv(left_border_width.mV);
  1259. gGL.texCoord2f(1.f - border_scale_x, border_scale_y);
  1260. gGL.vertex3fv(wv_rbw_bbh.mV);
  1261. gGL.texCoord2f(border_scale_x, border_scale_y);
  1262. gGL.vertex3fv(lbw_bbh.mV);
  1263. // draw bottom right
  1264. gGL.texCoord2f(1.f - border_scale_x, 0.f);
  1265. gGL.vertex3fv(wv_rbw.mV);
  1266. gGL.texCoord2f(1.f, 0.f);
  1267. gGL.vertex3fv(width_vec.mV);
  1268. LLVector3 wv_bbh = width_vec + bottom_border_height;
  1269. gGL.texCoord2f(1.f, border_scale_y);
  1270. gGL.vertex3fv(wv_bbh.mV);
  1271. gGL.texCoord2f(1.f - border_scale_x, 0.f);
  1272. gGL.vertex3fv(wv_rbw.mV);
  1273. gGL.texCoord2f(1.f, border_scale_y);
  1274. gGL.vertex3fv(wv_bbh.mV);
  1275. gGL.texCoord2f(1.f - border_scale_x, border_scale_y);
  1276. gGL.vertex3fv(wv_rbw_bbh.mV);
  1277. // draw left
  1278. gGL.texCoord2f(0.f, border_scale_y);
  1279. gGL.vertex3fv(bottom_border_height.mV);
  1280. gGL.texCoord2f(border_scale_x, border_scale_y);
  1281. gGL.vertex3fv(lbw_bbh.mV);
  1282. LLVector3 lbw_hv_tbh = left_border_width + height_vec -
  1283. top_border_height;
  1284. gGL.texCoord2f(border_scale_x, 1.f - border_scale_y);
  1285. gGL.vertex3fv(lbw_hv_tbh.mV);
  1286. gGL.texCoord2f(0.f, border_scale_y);
  1287. gGL.vertex3fv(bottom_border_height.mV);
  1288. gGL.texCoord2f(border_scale_x, 1.f - border_scale_y);
  1289. gGL.vertex3fv(lbw_hv_tbh.mV);
  1290. LLVector3 hv_tbh = height_vec - top_border_height;
  1291. gGL.texCoord2f(0.f, 1.f - border_scale_y);
  1292. gGL.vertex3fv(hv_tbh.mV);
  1293. // draw middle
  1294. gGL.texCoord2f(border_scale_x, border_scale_y);
  1295. gGL.vertex3fv(lbw_bbh.mV);
  1296. gGL.texCoord2f(1.f - border_scale_x, border_scale_y);
  1297. gGL.vertex3fv(wv_rbw_bbh.mV);
  1298. LLVector3 wv_rbw_hv_tbh = width_vec - right_border_width + height_vec -
  1299. top_border_height;
  1300. gGL.texCoord2f(1.f - border_scale_x, 1.f - border_scale_y);
  1301. gGL.vertex3fv(wv_rbw_hv_tbh.mV);
  1302. gGL.texCoord2f(border_scale_x, border_scale_y);
  1303. gGL.vertex3fv(lbw_bbh.mV);
  1304. gGL.texCoord2f(1.f - border_scale_x, 1.f - border_scale_y);
  1305. gGL.vertex3fv(wv_rbw_hv_tbh.mV);
  1306. gGL.texCoord2f(border_scale_x, 1.f - border_scale_y);
  1307. gGL.vertex3fv(lbw_hv_tbh.mV);
  1308. // draw right
  1309. gGL.texCoord2f(1.f - border_scale_x, border_scale_y);
  1310. gGL.vertex3fv(wv_rbw_bbh.mV);
  1311. gGL.texCoord2f(1.f, border_scale_y);
  1312. gGL.vertex3fv(wv_bbh.mV);
  1313. LLVector3 wv_hv_tbh = width_vec + height_vec - top_border_height;
  1314. gGL.texCoord2f(1.f, 1.f - border_scale_y);
  1315. gGL.vertex3fv(wv_hv_tbh.mV);
  1316. gGL.texCoord2f(1.f - border_scale_x, border_scale_y);
  1317. gGL.vertex3fv(wv_rbw_bbh.mV);
  1318. gGL.texCoord2f(1.f, 1.f - border_scale_y);
  1319. gGL.vertex3fv(wv_hv_tbh.mV);
  1320. gGL.texCoord2f(1.f - border_scale_x, 1.f - border_scale_y);
  1321. gGL.vertex3fv(wv_rbw_hv_tbh.mV);
  1322. // draw top left
  1323. gGL.texCoord2f(0.f, 1.f - border_scale_y);
  1324. gGL.vertex3fv(hv_tbh.mV);
  1325. gGL.texCoord2f(border_scale_x, 1.f - border_scale_y);
  1326. gGL.vertex3fv(lbw_hv_tbh.mV);
  1327. LLVector3 lbw_hv = left_border_width + height_vec;
  1328. gGL.texCoord2f(border_scale_x, 1.f);
  1329. gGL.vertex3fv(lbw_hv.mV);
  1330. gGL.texCoord2f(0.f, 1.f - border_scale_y);
  1331. gGL.vertex3fv(hv_tbh.mV);
  1332. gGL.texCoord2f(border_scale_x, 1.f);
  1333. gGL.vertex3fv(lbw_hv.mV);
  1334. gGL.texCoord2f(0.f, 1.f);
  1335. gGL.vertex3fv((height_vec).mV);
  1336. // draw top middle
  1337. gGL.texCoord2f(border_scale_x, 1.f - border_scale_y);
  1338. gGL.vertex3fv(lbw_hv_tbh.mV);
  1339. gGL.texCoord2f(1.f - border_scale_x, 1.f - border_scale_y);
  1340. gGL.vertex3fv(wv_rbw_hv_tbh.mV);
  1341. LLVector3 wv_rbw_hv = width_vec - right_border_width + height_vec;
  1342. gGL.texCoord2f(1.f - border_scale_x, 1.f);
  1343. gGL.vertex3fv(wv_rbw_hv.mV);
  1344. gGL.texCoord2f(border_scale_x, 1.f - border_scale_y);
  1345. gGL.vertex3fv(lbw_hv_tbh.mV);
  1346. gGL.texCoord2f(1.f - border_scale_x, 1.f);
  1347. gGL.vertex3fv(wv_rbw_hv.mV);
  1348. gGL.texCoord2f(border_scale_x, 1.f);
  1349. gGL.vertex3fv(lbw_hv.mV);
  1350. // draw top right
  1351. gGL.texCoord2f(1.f - border_scale_x, 1.f - border_scale_y);
  1352. gGL.vertex3fv(wv_rbw_hv_tbh.mV);
  1353. gGL.texCoord2f(1.f, 1.f - border_scale_y);
  1354. gGL.vertex3fv(wv_hv_tbh.mV);
  1355. LLVector3 wv_hv = width_vec + height_vec;
  1356. gGL.texCoord2f(1.f, 1.f);
  1357. gGL.vertex3fv(wv_hv.mV);
  1358. gGL.texCoord2f(1.f - border_scale_x, 1.f - border_scale_y);
  1359. gGL.vertex3fv(wv_rbw_hv_tbh.mV);
  1360. gGL.texCoord2f(1.f, 1.f);
  1361. gGL.vertex3fv(wv_hv.mV);
  1362. gGL.texCoord2f(1.f - border_scale_x, 1.f);
  1363. gGL.vertex3fv(wv_rbw_hv.mV);
  1364. }
  1365. gGL.end();
  1366. }
  1367. void gl_draw_3d_cross_lines(const LLVector3& center, F32 dx, F32 dy, F32 dz)
  1368. {
  1369. const F32& x = center.mV[VX];
  1370. const F32& y = center.mV[VY];
  1371. const F32& z = center.mV[VZ];
  1372. gGL.vertex3f(x - dx, y, z);
  1373. gGL.vertex3f(x + dx, y, z);
  1374. gGL.vertex3f(x, y - dy, z);
  1375. gGL.vertex3f(x, y + dy, z);
  1376. gGL.vertex3f(x, y, z - dz);
  1377. gGL.vertex3f(x, y, z + dz);
  1378. }
  1379. void gl_draw_3d_line_cube(F32 width, const LLVector3& center)
  1380. {
  1381. width *= 0.5f;
  1382. const F32& x = center.mV[VX];
  1383. const F32 x1 = x + width;
  1384. const F32 x2 = x - width;
  1385. const F32& y = center.mV[VY];
  1386. const F32 y1 = y + width;
  1387. const F32 y2 = y - width;
  1388. const F32& z = center.mV[VZ];
  1389. const F32 z1 = z + width;
  1390. const F32 z2 = z - width;
  1391. gGL.vertex3f(x1, y1, z1);
  1392. gGL.vertex3f(x2, y1, z1);
  1393. gGL.vertex3f(x2, y1, z1);
  1394. gGL.vertex3f(x2, y2, z1);
  1395. gGL.vertex3f(x2, y2, z1);
  1396. gGL.vertex3f(x1, y2, z1);
  1397. gGL.vertex3f(x1, y2, z1);
  1398. gGL.vertex3f(x1, y1, z1);
  1399. gGL.vertex3f(x1, y1, z2);
  1400. gGL.vertex3f(x2, y1, z2);
  1401. gGL.vertex3f(x2, y1, z2);
  1402. gGL.vertex3f(x2, y2, z2);
  1403. gGL.vertex3f(x2, y2, z2);
  1404. gGL.vertex3f(x1, y2, z2);
  1405. gGL.vertex3f(x1, y2, z2);
  1406. gGL.vertex3f(x1, y1, z2);
  1407. gGL.vertex3f(x1, y1, z1);
  1408. gGL.vertex3f(x1, y1, z2);
  1409. gGL.vertex3f(x2, y1, z1);
  1410. gGL.vertex3f(x2, y1, z2);
  1411. gGL.vertex3f(x2, y2, z1);
  1412. gGL.vertex3f(x2, y2, z2);
  1413. gGL.vertex3f(x1, y2, z1);
  1414. gGL.vertex3f(x1, y2, z2);
  1415. }
  1416. void gl_draw_box(const LLVector3& c, const LLVector3& r)
  1417. {
  1418. static const LLVector3 v1(-1.f, 1.f, -1.f);
  1419. static const LLVector3 v2(-1.f, 1.f, 1.f);
  1420. static const LLVector3 v3(1.f, 1.f, -1.f);
  1421. static const LLVector3 v4(1.f, 1.f, 1.f);
  1422. static const LLVector3 v5(1.f, -1.f, -1.f);
  1423. static const LLVector3 v6(1.f, -1.f, 1.f);
  1424. static const LLVector3 v7(-1.f, -1.f, -1.f);
  1425. static const LLVector3 v8(-1.f, -1.f, 1.f);
  1426. if (!c.isFinite() || !r.isFinite())
  1427. {
  1428. return;
  1429. }
  1430. gGL.begin(LLRender::TRIANGLE_STRIP);
  1431. // Left front
  1432. gGL.vertex3fv((c + r.scaledVec(v1)).mV);
  1433. gGL.vertex3fv((c + r.scaledVec(v2)).mV);
  1434. // Right front
  1435. gGL.vertex3fv((c + r.scaledVec(v3)).mV);
  1436. gGL.vertex3fv((c + r.scaledVec(v4)).mV);
  1437. // Right back
  1438. gGL.vertex3fv((c + r.scaledVec(v5)).mV);
  1439. gGL.vertex3fv((c + r.scaledVec(v6)).mV);
  1440. // Left back
  1441. gGL.vertex3fv((c + r.scaledVec(v7)).mV);
  1442. gGL.vertex3fv((c + r.scaledVec(v8)).mV);
  1443. // Left front
  1444. gGL.vertex3fv((c + r.scaledVec(v1)).mV);
  1445. gGL.vertex3fv((c + r.scaledVec(v2)).mV);
  1446. gGL.end();
  1447. // Bottom
  1448. gGL.begin(LLRender::TRIANGLE_STRIP);
  1449. gGL.vertex3fv((c + r.scaledVec(v3)).mV);
  1450. gGL.vertex3fv((c + r.scaledVec(v5)).mV);
  1451. gGL.vertex3fv((c + r.scaledVec(v1)).mV);
  1452. gGL.vertex3fv((c + r.scaledVec(v7)).mV);
  1453. gGL.end();
  1454. // Top
  1455. gGL.begin(LLRender::TRIANGLE_STRIP);
  1456. gGL.vertex3fv((c + r.scaledVec(v4)).mV);
  1457. gGL.vertex3fv((c + r.scaledVec(v2)).mV);
  1458. gGL.vertex3fv((c + r.scaledVec(v6)).mV);
  1459. gGL.vertex3fv((c + r.scaledVec(v8)).mV);
  1460. gGL.end();
  1461. }
  1462. void gl_draw_box_outline(const LLVector3& pos, const LLVector3& size)
  1463. {
  1464. if (!pos.isFinite() || !size.isFinite())
  1465. {
  1466. return;
  1467. }
  1468. LLVector3 v1 = size.scaledVec(LLVector3(1.f, 1.f, 1.f));
  1469. LLVector3 v2 = size.scaledVec(LLVector3(-1.f, 1.f, 1.f));
  1470. LLVector3 v3 = size.scaledVec(LLVector3(-1.f, -1.f, 1.f));
  1471. LLVector3 v4 = size.scaledVec(LLVector3(1.f, -1.f, 1.f));
  1472. gGL.begin(LLRender::LINES);
  1473. // Top
  1474. gGL.vertex3fv((pos + v1).mV);
  1475. gGL.vertex3fv((pos + v2).mV);
  1476. gGL.vertex3fv((pos + v2).mV);
  1477. gGL.vertex3fv((pos + v3).mV);
  1478. gGL.vertex3fv((pos + v3).mV);
  1479. gGL.vertex3fv((pos + v4).mV);
  1480. gGL.vertex3fv((pos + v4).mV);
  1481. gGL.vertex3fv((pos + v1).mV);
  1482. // Bottom
  1483. gGL.vertex3fv((pos - v1).mV);
  1484. gGL.vertex3fv((pos - v2).mV);
  1485. gGL.vertex3fv((pos - v2).mV);
  1486. gGL.vertex3fv((pos - v3).mV);
  1487. gGL.vertex3fv((pos - v3).mV);
  1488. gGL.vertex3fv((pos - v4).mV);
  1489. gGL.vertex3fv((pos - v4).mV);
  1490. gGL.vertex3fv((pos - v1).mV);
  1491. // Right
  1492. gGL.vertex3fv((pos + v1).mV);
  1493. gGL.vertex3fv((pos - v3).mV);
  1494. gGL.vertex3fv((pos + v4).mV);
  1495. gGL.vertex3fv((pos - v2).mV);
  1496. // Left
  1497. gGL.vertex3fv((pos + v2).mV);
  1498. gGL.vertex3fv((pos - v4).mV);
  1499. gGL.vertex3fv((pos + v3).mV);
  1500. gGL.vertex3fv((pos - v1).mV);
  1501. gGL.end();
  1502. }
  1503. ///////////////////////////////////////////////////////////////////////////////
  1504. // LLBox / gBox. This used to be in llbox.cpp
  1505. ///////////////////////////////////////////////////////////////////////////////
  1506. LLBox gBox;
  1507. // These routines support multiple textures on a box
  1508. void LLBox::prerender()
  1509. {
  1510. F32 size = 1.f;
  1511. mTriangleCount = 6 * 2;
  1512. mVertex[0][0] = mVertex[1][0] = mVertex[2][0] = mVertex[3][0] = -size / 2;
  1513. mVertex[4][0] = mVertex[5][0] = mVertex[6][0] = mVertex[7][0] = size / 2;
  1514. mVertex[0][1] = mVertex[1][1] = mVertex[4][1] = mVertex[5][1] = -size / 2;
  1515. mVertex[2][1] = mVertex[3][1] = mVertex[6][1] = mVertex[7][1] = size / 2;
  1516. mVertex[0][2] = mVertex[3][2] = mVertex[4][2] = mVertex[7][2] = -size / 2;
  1517. mVertex[1][2] = mVertex[2][2] = mVertex[5][2] = mVertex[6][2] = size / 2;
  1518. }
  1519. // These routines support multiple textures on a box
  1520. void LLBox::cleanupGL()
  1521. {
  1522. // No GL state, a noop.
  1523. }
  1524. void LLBox::renderface(S32 which_face)
  1525. {
  1526. #if 0
  1527. static F32 normals[6][3] =
  1528. {
  1529. { -1.f, 0.f, 0.f },
  1530. { 0.f, 1.f, 0.f },
  1531. { 1.f, 0.f, 0.f },
  1532. { 0.f, -1.f, 0.f },
  1533. { 0.f, 0.f, 1.f },
  1534. { 0.f, 0.f, -1.f }
  1535. };
  1536. #endif
  1537. static S32 faces[6][4] =
  1538. {
  1539. { 0, 1, 2, 3 },
  1540. { 3, 2, 6, 7 },
  1541. { 7, 6, 5, 4 },
  1542. { 4, 5, 1, 0 },
  1543. { 5, 6, 2, 1 },
  1544. { 7, 4, 0, 3 }
  1545. };
  1546. gGL.begin(LLRender::TRIANGLES);
  1547. {
  1548. #if 0
  1549. gGL.normal3fv(&normals[which_face][0]);
  1550. #endif
  1551. gGL.texCoord2f(1.f, 0.f);
  1552. gGL.vertex3fv(&mVertex[faces[which_face][0]][0]);
  1553. gGL.texCoord2f(1.f, 1.f);
  1554. gGL.vertex3fv(&mVertex[faces[which_face][1]][0]);
  1555. gGL.texCoord2f(0.f, 1.f);
  1556. gGL.vertex3fv(&mVertex[faces[which_face][2]][0]);
  1557. gGL.texCoord2f(1.f, 0.f);
  1558. gGL.vertex3fv(&mVertex[faces[which_face][0]][0]);
  1559. gGL.texCoord2f(0.f, 1.f);
  1560. gGL.vertex3fv(&mVertex[faces[which_face][2]][0]);
  1561. gGL.texCoord2f(0.f, 0.f);
  1562. gGL.vertex3fv(&mVertex[faces[which_face][3]][0]);
  1563. }
  1564. gGL.end();
  1565. }
  1566. void LLBox::render()
  1567. {
  1568. // This is a flattend representation of the box as render here
  1569. // .
  1570. // (-++) (+++) /|\t
  1571. // +------------+ | (texture coordinates)
  1572. // |2 1| |
  1573. // | 4 | (*) --->s
  1574. // | TOP |
  1575. // | |
  1576. // (-++) (--+)|3 0|(+-+) (+++) (-++)
  1577. // +------------+------------+------------+------------+
  1578. // |2 1|2 1|2 1|2 1|
  1579. // | 0 | 1 | 2 | 3 |
  1580. // | BACK | RIGHT | FRONT | LEFT |
  1581. // | | | | |
  1582. // |3 0|3 0|3 0|3 0|
  1583. // +------------+------------+------------+------------+
  1584. // (-+-) (---)|2 1|(+--) (++-) (-+-)
  1585. // | 5 |
  1586. // | BOTTOM |
  1587. // | |
  1588. // |3 0|
  1589. // +------------+
  1590. // (-+-) (++-)
  1591. renderface(5);
  1592. renderface(4);
  1593. renderface(3);
  1594. renderface(2);
  1595. renderface(1);
  1596. renderface(0);
  1597. }
  1598. ///////////////////////////////////////////////////////////////////////////////
  1599. // LLCone / gCone. This used to be in llcylinder.cpp
  1600. ///////////////////////////////////////////////////////////////////////////////
  1601. LLCone gCone;
  1602. void LLCone::render(S32 sides)
  1603. {
  1604. gGL.begin(LLRender::TRIANGLE_FAN);
  1605. gGL.vertex3f(0, 0, 0);
  1606. for (S32 i = 0; i < sides; ++i)
  1607. {
  1608. F32 a = (F32)i / sides * F_PI * 2.f;
  1609. F32 x = cosf(a) * 0.5f;
  1610. F32 y = sinf(a) * 0.5f;
  1611. gGL.vertex3f(x, y, -.5f);
  1612. }
  1613. gGL.vertex3f(cosf(0.f) * 0.5f, sinf(0.f) * 0.5f, -0.5f);
  1614. gGL.end();
  1615. gGL.begin(LLRender::TRIANGLE_FAN);
  1616. gGL.vertex3f(0.f, 0.f, 0.5f);
  1617. for (S32 i = 0; i < sides; ++i)
  1618. {
  1619. F32 a = (F32)i / sides * F_PI * 2.f;
  1620. F32 x = cosf(a) * 0.5f;
  1621. F32 y = sinf(a) * 0.5f;
  1622. gGL.vertex3f(x, y, -0.5f);
  1623. }
  1624. gGL.vertex3f(cosf(0.f) * 0.5f, sinf(0.f) * 0.5f, -0.5f);
  1625. gGL.end();
  1626. }
  1627. ///////////////////////////////////////////////////////////////////////////////
  1628. // LLRenderSphere / gSphere. This used to be in llrendersphere.cpp
  1629. ///////////////////////////////////////////////////////////////////////////////
  1630. LLRenderSphere gSphere;
  1631. void LLRenderSphere::render()
  1632. {
  1633. renderGGL();
  1634. gGL.flush();
  1635. }
  1636. LL_INLINE LLVector3 polar_to_cart(F32 latitude, F32 longitude)
  1637. {
  1638. return LLVector3(sinf(F_TWO_PI * latitude) * cosf(F_TWO_PI * longitude),
  1639. sinf(F_TWO_PI * latitude) * sinf(F_TWO_PI * longitude),
  1640. cosf(F_TWO_PI * latitude));
  1641. }
  1642. void LLRenderSphere::renderGGL()
  1643. {
  1644. constexpr S32 LATITUDE_SLICES = 20;
  1645. constexpr S32 LONGITUDE_SLICES = 30;
  1646. if (mSpherePoints.empty())
  1647. {
  1648. mSpherePoints.resize(LATITUDE_SLICES + 1);
  1649. for (S32 lat_i = 0; lat_i < LATITUDE_SLICES + 1; lat_i++)
  1650. {
  1651. mSpherePoints[lat_i].resize(LONGITUDE_SLICES + 1);
  1652. for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES + 1; lon_i++)
  1653. {
  1654. F32 lat = (F32)lat_i / LATITUDE_SLICES;
  1655. F32 lon = (F32)lon_i / LONGITUDE_SLICES;
  1656. mSpherePoints[lat_i][lon_i] = polar_to_cart(lat, lon);
  1657. }
  1658. }
  1659. }
  1660. gGL.begin(LLRender::TRIANGLES);
  1661. for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++)
  1662. {
  1663. for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++)
  1664. {
  1665. gGL.vertex3fv(mSpherePoints[lat_i][lon_i].mV);
  1666. gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV);
  1667. gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV);
  1668. gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV);
  1669. gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV);
  1670. gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i+1].mV);
  1671. }
  1672. }
  1673. gGL.end();
  1674. }