pgFrameStyle.cxx 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file pgFrameStyle.cxx
  10. * @author drose
  11. * @date 2001-07-03
  12. */
  13. #include "pgFrameStyle.h"
  14. #include "geomNode.h"
  15. #include "pandaNode.h"
  16. #include "transparencyAttrib.h"
  17. #include "pointerTo.h"
  18. #include "nodePath.h"
  19. #include "textureAttrib.h"
  20. #include "renderState.h"
  21. #include "shadeModelAttrib.h"
  22. #include "colorAttrib.h"
  23. #include "geom.h"
  24. #include "geomTristrips.h"
  25. #include "geomVertexWriter.h"
  26. using std::max;
  27. using std::min;
  28. // Specifies the UV range of textures applied to the frame. Maybe we'll have
  29. // a reason to make this a parameter of the frame style one day, but for now
  30. // it's hardcoded to fit the entire texture over the rectangular frame.
  31. static const LVecBase4 uv_range = LVecBase4(0.0f, 1.0f, 0.0f, 1.0f);
  32. std::ostream &
  33. operator << (std::ostream &out, PGFrameStyle::Type type) {
  34. switch (type) {
  35. case PGFrameStyle::T_none:
  36. return out << "none";
  37. case PGFrameStyle::T_flat:
  38. return out << "flat";
  39. case PGFrameStyle::T_bevel_out:
  40. return out << "bevel_out";
  41. case PGFrameStyle::T_bevel_in:
  42. return out << "bevel_in";
  43. case PGFrameStyle::T_groove:
  44. return out << "groove";
  45. case PGFrameStyle::T_ridge:
  46. return out << "ridge";
  47. case PGFrameStyle::T_texture_border:
  48. return out << "texture_border";
  49. }
  50. return out << "**unknown(" << (int)type << ")**";
  51. }
  52. /**
  53. * Computes the size of the internal frame, given the indicated external
  54. * frame, appropriate for this kind of frame style. This simply subtracts the
  55. * border width for those frame styles that include a border.
  56. */
  57. LVecBase4 PGFrameStyle::
  58. get_internal_frame(const LVecBase4 &frame) const {
  59. LPoint2 center((frame[0] + frame[1]) / 2.0f,
  60. (frame[2] + frame[3]) / 2.0f);
  61. LVecBase4 scaled_frame
  62. ((frame[0] - center[0]) * _visible_scale[0] + center[0],
  63. (frame[1] - center[0]) * _visible_scale[0] + center[0],
  64. (frame[2] - center[1]) * _visible_scale[1] + center[1],
  65. (frame[3] - center[1]) * _visible_scale[1] + center[1]);
  66. switch (_type) {
  67. case T_none:
  68. case T_flat:
  69. return scaled_frame;
  70. default:
  71. break;
  72. }
  73. return LVecBase4(scaled_frame[0] + _width[0],
  74. scaled_frame[1] - _width[0],
  75. scaled_frame[2] + _width[1],
  76. scaled_frame[3] - _width[1]);
  77. }
  78. /**
  79. *
  80. */
  81. void PGFrameStyle::
  82. output(std::ostream &out) const {
  83. out << _type << " color = " << _color << " width = " << _width;
  84. if (_visible_scale != LVecBase2(1.0f, 1.0f)) {
  85. out << "visible_scale = " << get_visible_scale();
  86. }
  87. if (has_texture()) {
  88. out << " texture = " << *get_texture();
  89. }
  90. }
  91. /**
  92. * Applies the indicated transform to the FrameStyle. The return value is
  93. * true if the frame style is transformed, or false if it was not affected by
  94. * the transform.
  95. */
  96. bool PGFrameStyle::
  97. xform(const LMatrix4 &mat) {
  98. // All we can do is scale the X and Y bevel sizes.
  99. // Extract the X and Z axes from the matrix.
  100. LVector3 x, z;
  101. mat.get_row3(x, 0);
  102. PN_stdfloat x_scale = x.length();
  103. mat.get_row3(z, 2);
  104. PN_stdfloat z_scale = z.length();
  105. _width[0] *= x_scale;
  106. _width[1] *= z_scale;
  107. switch (_type) {
  108. case T_none:
  109. case T_flat:
  110. return false;
  111. case T_bevel_out:
  112. case T_bevel_in:
  113. case T_groove:
  114. case T_ridge:
  115. case T_texture_border:
  116. return true;
  117. }
  118. // Shouldn't get here, but this makes the compiler happy.
  119. return true;
  120. }
  121. /**
  122. * Generates geometry representing a frame of the indicated size, and parents
  123. * it to the indicated node, with the indicated scene graph sort order.
  124. *
  125. * The return value is the generated NodePath, if any, or an empty NodePath if
  126. * nothing is generated.
  127. */
  128. NodePath PGFrameStyle::
  129. generate_into(const NodePath &parent, const LVecBase4 &frame,
  130. int sort) {
  131. PT(PandaNode) new_node;
  132. LPoint2 center((frame[0] + frame[1]) / 2.0f,
  133. (frame[2] + frame[3]) / 2.0f);
  134. LVecBase4 scaled_frame
  135. ((frame[0] - center[0]) * _visible_scale[0] + center[0],
  136. (frame[1] - center[0]) * _visible_scale[0] + center[0],
  137. (frame[2] - center[1]) * _visible_scale[1] + center[1],
  138. (frame[3] - center[1]) * _visible_scale[1] + center[1]);
  139. switch (_type) {
  140. case T_none:
  141. return NodePath();
  142. case T_flat:
  143. new_node = generate_flat_geom(scaled_frame);
  144. break;
  145. case T_bevel_out:
  146. new_node = generate_bevel_geom(scaled_frame, false);
  147. break;
  148. case T_bevel_in:
  149. new_node = generate_bevel_geom(scaled_frame, true);
  150. break;
  151. case T_groove:
  152. new_node = generate_groove_geom(scaled_frame, true);
  153. break;
  154. case T_ridge:
  155. new_node = generate_groove_geom(scaled_frame, false);
  156. break;
  157. case T_texture_border:
  158. new_node = generate_texture_border_geom(scaled_frame);
  159. break;
  160. default:
  161. break;
  162. }
  163. if (new_node != nullptr && _color[3] != 1.0f) {
  164. // We've got some alpha on the color; we need transparency.
  165. new_node->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
  166. }
  167. // Adding the node to the parent keeps the reference count.
  168. return parent.attach_new_node(new_node, sort);
  169. }
  170. /**
  171. * Generates the GeomNode appropriate to a T_flat frame.
  172. */
  173. PT(PandaNode) PGFrameStyle::
  174. generate_flat_geom(const LVecBase4 &frame) {
  175. PT(GeomNode) gnode = new GeomNode("flat");
  176. PN_stdfloat left = frame[0];
  177. PN_stdfloat right = frame[1];
  178. PN_stdfloat bottom = frame[2];
  179. PN_stdfloat top = frame[3];
  180. CPT(GeomVertexFormat) format;
  181. if (has_texture()) {
  182. format = GeomVertexFormat::get_v3t2();
  183. } else {
  184. format = GeomVertexFormat::get_v3();
  185. }
  186. PT(GeomVertexData) vdata = new GeomVertexData
  187. ("PGFrame", format, Geom::UH_static);
  188. GeomVertexWriter vertex(vdata, InternalName::get_vertex());
  189. vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
  190. vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
  191. vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
  192. vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
  193. if (has_texture()) {
  194. // Generate UV's.
  195. left = uv_range[0];
  196. right = uv_range[1];
  197. bottom = uv_range[2];
  198. top = uv_range[3];
  199. GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
  200. texcoord.add_data2(left, top);
  201. texcoord.add_data2(left, bottom);
  202. texcoord.add_data2(right, top);
  203. texcoord.add_data2(right, bottom);
  204. }
  205. PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
  206. strip->add_next_vertices(4);
  207. strip->close_primitive();
  208. CPT(RenderState) state = RenderState::make(ColorAttrib::make_flat(_color), -1);
  209. if (has_texture()) {
  210. state = state->set_attrib(TextureAttrib::make(get_texture()));
  211. }
  212. PT(Geom) geom = new Geom(vdata);
  213. geom->add_primitive(strip);
  214. gnode->add_geom(geom, state);
  215. return gnode;
  216. }
  217. /**
  218. * Generates the GeomNode appropriate to a T_bevel_in or T_bevel_out frame.
  219. */
  220. PT(PandaNode) PGFrameStyle::
  221. generate_bevel_geom(const LVecBase4 &frame, bool in) {
  222. /*
  223. * Colors: * * * * * * * * * * * * * * * * * * * * * * * * *
  224. * * * * * ctop * * * *
  225. * * * * * * * * * * * * * * * * * * * * * *
  226. * * * * * * * * cleft *
  227. * _color * cright* * * * * *
  228. * * * * * * * * * * * * * * * * * * * *
  229. * * * * * * * * cbottom
  230. * * * * * * * * * * * * * * * * * * *
  231. * * * * * * * * * * * * Vertices: tristrip 1: 4 * * * * * * * * * * * * * * *
  232. * * * * * * * 6 * * * * *
  233. * * * * * * 5 * * * * * * * * * * * *
  234. * * 7 * * * * * * * * * * * 3 * * * * * *
  235. * * * * * * * * 1 * * * * *
  236. * * * * * 2 * * * * * * * * * * * * * *
  237. * * * * * * * * 0 tristrip 2: 1 * * * * * * 5 * * * * * * * * * * * * *
  238. * 3 * * * * *
  239. * * * * * * *
  240. * * * * * * 4 * * * * * * * * * * * * *
  241. * 2 * * * * * * * 0
  242. */
  243. PT(GeomNode) gnode = new GeomNode("bevel");
  244. PN_stdfloat left = frame[0];
  245. PN_stdfloat right = frame[1];
  246. PN_stdfloat bottom = frame[2];
  247. PN_stdfloat top = frame[3];
  248. PN_stdfloat cx = (left + right) * 0.5;
  249. PN_stdfloat cy = (top + bottom) * 0.5;
  250. PN_stdfloat inner_left = min(left + _width[0], cx);
  251. PN_stdfloat inner_right = max(right - _width[0], cx);
  252. PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
  253. PN_stdfloat inner_top = max(top - _width[1], cy);
  254. PN_stdfloat left_color_scale = 1.2;
  255. PN_stdfloat right_color_scale = 0.8;
  256. PN_stdfloat bottom_color_scale = 0.7;
  257. PN_stdfloat top_color_scale = 1.3;
  258. if (in) {
  259. right_color_scale = 1.2;
  260. left_color_scale = 0.8;
  261. top_color_scale = 0.7;
  262. bottom_color_scale = 1.3;
  263. }
  264. // Clamp all colors at white, and don't scale the alpha.
  265. LColor cleft(min(_color[0] * left_color_scale, (PN_stdfloat)1.0),
  266. min(_color[1] * left_color_scale, (PN_stdfloat)1.0),
  267. min(_color[2] * left_color_scale, (PN_stdfloat)1.0),
  268. _color[3]);
  269. LColor cright(min(_color[0] * right_color_scale, (PN_stdfloat)1.0),
  270. min(_color[1] * right_color_scale, (PN_stdfloat)1.0),
  271. min(_color[2] * right_color_scale, (PN_stdfloat)1.0),
  272. _color[3]);
  273. LColor cbottom(min(_color[0] * bottom_color_scale, (PN_stdfloat)1.0),
  274. min(_color[1] * bottom_color_scale, (PN_stdfloat)1.0),
  275. min(_color[2] * bottom_color_scale, (PN_stdfloat)1.0),
  276. _color[3]);
  277. LColor ctop(min(_color[0] * top_color_scale, (PN_stdfloat)1.0),
  278. min(_color[1] * top_color_scale, (PN_stdfloat)1.0),
  279. min(_color[2] * top_color_scale, (PN_stdfloat)1.0),
  280. _color[3]);
  281. CPT(GeomVertexFormat) format;
  282. if (has_texture()) {
  283. format = GeomVertexFormat::get_v3cpt2();
  284. } else {
  285. format = GeomVertexFormat::get_v3cp();
  286. }
  287. PT(GeomVertexData) vdata = new GeomVertexData
  288. ("PGFrame", format, Geom::UH_static);
  289. GeomVertexWriter vertex(vdata, InternalName::get_vertex());
  290. GeomVertexWriter color(vdata, InternalName::get_color());
  291. PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
  292. // Tristrip 1.
  293. vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
  294. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
  295. vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
  296. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
  297. vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
  298. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
  299. vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
  300. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
  301. color.add_data4(cbottom);
  302. color.add_data4(cbottom);
  303. color.add_data4(cbottom);
  304. color.add_data4(cbottom);
  305. color.add_data4(cleft);
  306. color.add_data4(cleft);
  307. color.add_data4(ctop);
  308. color.add_data4(ctop);
  309. strip->add_next_vertices(8);
  310. strip->close_primitive();
  311. // Tristrip 2.
  312. vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
  313. vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
  314. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
  315. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
  316. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
  317. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
  318. color.add_data4(cright);
  319. color.add_data4(cright);
  320. color.add_data4(cright);
  321. color.add_data4(cright);
  322. color.add_data4(_color);
  323. color.add_data4(_color);
  324. strip->add_next_vertices(6);
  325. strip->close_primitive();
  326. strip->set_shade_model(Geom::SM_flat_last_vertex);
  327. if (has_texture()) {
  328. // Generate UV's.
  329. PN_stdfloat left = uv_range[0];
  330. PN_stdfloat right = uv_range[1];
  331. PN_stdfloat bottom = uv_range[2];
  332. PN_stdfloat top = uv_range[3];
  333. PN_stdfloat cx = (left + right) * 0.5;
  334. PN_stdfloat cy = (top + bottom) * 0.5;
  335. PN_stdfloat inner_left = min(left + _uv_width[0], cx);
  336. PN_stdfloat inner_right = max(right - _uv_width[0], cx);
  337. PN_stdfloat inner_bottom = min(bottom + _uv_width[1], cy);
  338. PN_stdfloat inner_top = max(top - _uv_width[1], cy);
  339. GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
  340. texcoord.add_data2(right, bottom);
  341. texcoord.add_data2(inner_right, inner_bottom);
  342. texcoord.add_data2(left, bottom);
  343. texcoord.add_data2(inner_left, inner_bottom);
  344. texcoord.add_data2(left, top);
  345. texcoord.add_data2(inner_left, inner_top);
  346. texcoord.add_data2(right, top);
  347. texcoord.add_data2(inner_right, inner_top);
  348. texcoord.add_data2(right, bottom);
  349. texcoord.add_data2(right, top);
  350. texcoord.add_data2(inner_right, inner_bottom);
  351. texcoord.add_data2(inner_right, inner_top);
  352. texcoord.add_data2(inner_left, inner_bottom);
  353. texcoord.add_data2(inner_left, inner_top);
  354. }
  355. PT(Geom) geom = new Geom(vdata);
  356. geom->add_primitive(strip);
  357. CPT(RenderState) state;
  358. state = RenderState::make(ShadeModelAttrib::make(ShadeModelAttrib::M_flat),
  359. ColorAttrib::make_vertex());
  360. if (has_texture()) {
  361. state = state->set_attrib(TextureAttrib::make(get_texture()));
  362. }
  363. gnode->add_geom(geom, state);
  364. return gnode;
  365. }
  366. /**
  367. * Generates the GeomNode appropriate to a T_groove or T_ridge frame.
  368. */
  369. PT(PandaNode) PGFrameStyle::
  370. generate_groove_geom(const LVecBase4 &frame, bool in) {
  371. /*
  372. * Colors: * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  373. * * * * * ctop * * * *
  374. * * * * * * * * * * * * * * * * * * * * * * * * * * *
  375. * * * * * * * cbottom * * * * *
  376. * * * * * * * * * * * * * * * * *
  377. * * * * * * * * * * *
  378. * * * * * * * cleft * cright* _color
  379. * * cleft * cright* * * * * * * *
  380. * * * * * * * * * * * * * * *
  381. * * * * * * * * * * * *
  382. * * * * * ctop * * * * * *
  383. * * * * * * * * * * * * * * * * * * * * * * * * * * *
  384. * * * * * cbottom * * * *
  385. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Vertices:
  386. * tristrip 1: 4 * * * * * * * * * * * * * * * * * * * * * * * * * 6 * *
  387. * * * * * * *
  388. * * * 5 * * * * * * * * * * * * * * * * * 7 * * * * *
  389. * * * * * * * * * * * * * * * * *
  390. * * * * * * * 3 * * * * * * * * * * * * * * * * * 1 * *
  391. * * * * * * *
  392. * * 2 * * * * * * * * * * * * * * * * * * * * * * * * * 0 tristrip 2: 4 * * *
  393. * * * * * * * * * * * * * * * 6 * * * * *
  394. * * * * * * 5 * * * * * * * * * 7 * * *
  395. * * * * * * * * * 3 * * * * * * * * * 1 * *
  396. * * * * * * * * 2 *
  397. * * * * * * * * * * * * * * * * * 0 tristrip 3: 1 * * * * * * 3 *
  398. * * * * * * * * * * 7 * * * * * * * * * 5 *
  399. * * * * * * * * *
  400. * * * * * * * * *
  401. * * * * * * 6 * * * * * * * * * 4 *
  402. * * * * * * * * * * * 2 * * * * * * * 0
  403. */
  404. PT(GeomNode) gnode = new GeomNode("groove");
  405. PN_stdfloat left = frame[0];
  406. PN_stdfloat right = frame[1];
  407. PN_stdfloat bottom = frame[2];
  408. PN_stdfloat top = frame[3];
  409. PN_stdfloat cx = (left + right) * 0.5;
  410. PN_stdfloat cy = (top + bottom) * 0.5;
  411. PN_stdfloat mid_left = min(left + 0.5f * _width[0], cx);
  412. PN_stdfloat mid_right = max(right - 0.5f * _width[0], cx);
  413. PN_stdfloat mid_bottom = min(bottom + 0.5f * _width[1], cy);
  414. PN_stdfloat mid_top = max(top - 0.5f * _width[1], cy);
  415. PN_stdfloat inner_left = min(left + _width[0], cx);
  416. PN_stdfloat inner_right = max(right - _width[0], cx);
  417. PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
  418. PN_stdfloat inner_top = max(top - _width[1], cy);
  419. PN_stdfloat left_color_scale = 1.2;
  420. PN_stdfloat right_color_scale = 0.8f;
  421. PN_stdfloat bottom_color_scale = 0.7f;
  422. PN_stdfloat top_color_scale = 1.3;
  423. if (in) {
  424. right_color_scale = 1.2;
  425. left_color_scale = 0.8f;
  426. top_color_scale = 0.7f;
  427. bottom_color_scale = 1.3;
  428. }
  429. // Clamp all colors at white, and don't scale the alpha.
  430. LColor cleft(min(_color[0] * left_color_scale, (PN_stdfloat)1.0),
  431. min(_color[1] * left_color_scale, (PN_stdfloat)1.0),
  432. min(_color[2] * left_color_scale, (PN_stdfloat)1.0),
  433. _color[3]);
  434. LColor cright(min(_color[0] * right_color_scale, (PN_stdfloat)1.0),
  435. min(_color[1] * right_color_scale, (PN_stdfloat)1.0),
  436. min(_color[2] * right_color_scale, (PN_stdfloat)1.0),
  437. _color[3]);
  438. LColor cbottom(min(_color[0] * bottom_color_scale, (PN_stdfloat)1.0),
  439. min(_color[1] * bottom_color_scale, (PN_stdfloat)1.0),
  440. min(_color[2] * bottom_color_scale, (PN_stdfloat)1.0),
  441. _color[3]);
  442. LColor ctop(min(_color[0] * top_color_scale, (PN_stdfloat)1.0),
  443. min(_color[1] * top_color_scale, (PN_stdfloat)1.0),
  444. min(_color[2] * top_color_scale, (PN_stdfloat)1.0),
  445. _color[3]);
  446. CPT(GeomVertexFormat) format;
  447. if (has_texture()) {
  448. format = GeomVertexFormat::get_v3cpt2();
  449. } else {
  450. format = GeomVertexFormat::get_v3cp();
  451. }
  452. PT(GeomVertexData) vdata = new GeomVertexData
  453. ("PGFrame", format, Geom::UH_static);
  454. GeomVertexWriter vertex(vdata, InternalName::get_vertex());
  455. GeomVertexWriter color(vdata, InternalName::get_color());
  456. PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
  457. // Tristrip 1.
  458. vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
  459. vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
  460. vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
  461. vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_bottom));
  462. vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
  463. vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_top));
  464. vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
  465. vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
  466. color.add_data4(cbottom);
  467. color.add_data4(cbottom);
  468. color.add_data4(cbottom);
  469. color.add_data4(cbottom);
  470. color.add_data4(cleft);
  471. color.add_data4(cleft);
  472. color.add_data4(ctop);
  473. color.add_data4(ctop);
  474. strip->add_next_vertices(8);
  475. strip->close_primitive();
  476. // Tristrip 2.
  477. vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
  478. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
  479. vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_bottom));
  480. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
  481. vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_top));
  482. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
  483. vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
  484. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
  485. color.add_data4(ctop);
  486. color.add_data4(ctop);
  487. color.add_data4(ctop);
  488. color.add_data4(ctop);
  489. color.add_data4(cright);
  490. color.add_data4(cright);
  491. color.add_data4(cbottom);
  492. color.add_data4(cbottom);
  493. strip->add_next_vertices(8);
  494. strip->close_primitive();
  495. // Tristrip 3.
  496. vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
  497. vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
  498. vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
  499. vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
  500. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
  501. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
  502. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
  503. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
  504. color.add_data4(cright);
  505. color.add_data4(cright);
  506. color.add_data4(cright);
  507. color.add_data4(cright);
  508. color.add_data4(cleft);
  509. color.add_data4(cleft);
  510. color.add_data4(_color);
  511. color.add_data4(_color);
  512. strip->add_next_vertices(8);
  513. strip->close_primitive();
  514. strip->set_shade_model(Geom::SM_flat_last_vertex);
  515. if (has_texture()) {
  516. // Generate UV's.
  517. PN_stdfloat left = uv_range[0];
  518. PN_stdfloat right = uv_range[1];
  519. PN_stdfloat bottom = uv_range[2];
  520. PN_stdfloat top = uv_range[3];
  521. PN_stdfloat cx = (left + right) * 0.5;
  522. PN_stdfloat cy = (top + bottom) * 0.5;
  523. PN_stdfloat mid_left = min(left + 0.5f * _width[0], cx);
  524. PN_stdfloat mid_right = max(right - 0.5f * _width[0], cx);
  525. PN_stdfloat mid_bottom = min(bottom + 0.5f * _width[1], cy);
  526. PN_stdfloat mid_top = max(top - 0.5f * _width[1], cy);
  527. PN_stdfloat inner_left = min(left + _width[0], cx);
  528. PN_stdfloat inner_right = max(right - _width[0], cx);
  529. PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
  530. PN_stdfloat inner_top = max(top - _width[1], cy);
  531. GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
  532. texcoord.add_data2(right, bottom);
  533. texcoord.add_data2(mid_right, mid_bottom);
  534. texcoord.add_data2(left, bottom);
  535. texcoord.add_data2(mid_left, mid_bottom);
  536. texcoord.add_data2(left, top);
  537. texcoord.add_data2(mid_left, mid_top);
  538. texcoord.add_data2(right, top);
  539. texcoord.add_data2(mid_right, mid_top);
  540. texcoord.add_data2(mid_right, mid_bottom);
  541. texcoord.add_data2(inner_right, inner_bottom);
  542. texcoord.add_data2(mid_left, mid_bottom);
  543. texcoord.add_data2(inner_left, inner_bottom);
  544. texcoord.add_data2(mid_left, mid_top);
  545. texcoord.add_data2(inner_left, inner_top);
  546. texcoord.add_data2(mid_right, mid_top);
  547. texcoord.add_data2(inner_right, inner_top);
  548. texcoord.add_data2(right, bottom);
  549. texcoord.add_data2(right, top);
  550. texcoord.add_data2(mid_right, mid_bottom);
  551. texcoord.add_data2(mid_right, mid_top);
  552. texcoord.add_data2(inner_right, inner_bottom);
  553. texcoord.add_data2(inner_right, inner_top);
  554. texcoord.add_data2(inner_left, inner_bottom);
  555. texcoord.add_data2(inner_left, inner_top);
  556. }
  557. PT(Geom) geom = new Geom(vdata);
  558. geom->add_primitive(strip);
  559. CPT(RenderState) state = RenderState::make(ShadeModelAttrib::make(ShadeModelAttrib::M_flat),
  560. ColorAttrib::make_vertex());
  561. if (has_texture()) {
  562. state = state->set_attrib(TextureAttrib::make(get_texture()));
  563. }
  564. gnode->add_geom(geom, state);
  565. return gnode;
  566. }
  567. /**
  568. * Generates the GeomNode appropriate to a T_texture_border frame.
  569. */
  570. PT(PandaNode) PGFrameStyle::
  571. generate_texture_border_geom(const LVecBase4 &frame) {
  572. /*
  573. * Vertices: tristrip 1: 0 * * * 2 * * * * * * * * * * * * * 4 * * * 6 * *
  574. * * * * * * * * * * * * * * * * * *
  575. * * * * * * * * * * * * * 1 * * * 3 * * * * * * *
  576. * * * * * * * 5 * * * 7 tristrip 2: 1 * * * 3 * * * * * * * * * * * * * 5 * *
  577. * * 7 * * * * * * * *
  578. * * * * * * * * * * * * * * * * * *
  579. * * * * * * * * * * * * * * * *
  580. * * * * * * 8 * * *10 * * * * * * * * * * * * *12
  581. * * * *14 tristrip 3: 8 * * *10 * * * * * * * * * * * * *12 * * *14 * * *
  582. * * * * * * * * * * * * * * * * * * * * * * * *
  583. * * * * * * 9 * * *11 * * * * * * * * * * * * *13 * *
  584. * *15
  585. */
  586. PT(GeomNode) gnode = new GeomNode("flat");
  587. PN_stdfloat left = frame[0];
  588. PN_stdfloat right = frame[1];
  589. PN_stdfloat bottom = frame[2];
  590. PN_stdfloat top = frame[3];
  591. PN_stdfloat cx = (left + right) * 0.5;
  592. PN_stdfloat cy = (top + bottom) * 0.5;
  593. PN_stdfloat inner_left = min(left + _width[0], cx);
  594. PN_stdfloat inner_right = max(right - _width[0], cx);
  595. PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
  596. PN_stdfloat inner_top = max(top - _width[1], cy);
  597. CPT(GeomVertexFormat) format;
  598. if (has_texture()) {
  599. format = GeomVertexFormat::get_v3t2();
  600. } else {
  601. format = GeomVertexFormat::get_v3();
  602. }
  603. PT(GeomVertexData) vdata = new GeomVertexData
  604. ("PGFrame", format, Geom::UH_static);
  605. GeomVertexWriter vertex(vdata, InternalName::get_vertex());
  606. // verts 0,1,2,3
  607. vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
  608. vertex.add_data3(LPoint3::rfu(left, 0.0f, inner_top));
  609. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, top));
  610. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
  611. // verts 4,5,6,7
  612. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, top));
  613. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
  614. vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
  615. vertex.add_data3(LPoint3::rfu(right, 0.0f, inner_top));
  616. // verts 8,9,10,11
  617. vertex.add_data3(LPoint3::rfu(left, 0.0f, inner_bottom));
  618. vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
  619. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
  620. vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, bottom));
  621. // verts 12,13,14,15
  622. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
  623. vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, bottom));
  624. vertex.add_data3(LPoint3::rfu(right, 0.0f, inner_bottom));
  625. vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
  626. if (has_texture()) {
  627. // Generate UV's.
  628. PN_stdfloat left = uv_range[0];
  629. PN_stdfloat right = uv_range[1];
  630. PN_stdfloat bottom = uv_range[2];
  631. PN_stdfloat top = uv_range[3];
  632. PN_stdfloat cx = (left + right) * 0.5;
  633. PN_stdfloat cy = (top + bottom) * 0.5;
  634. PN_stdfloat inner_left = min(left + _uv_width[0], cx);
  635. PN_stdfloat inner_right = max(right - _uv_width[0], cx);
  636. PN_stdfloat inner_bottom = min(bottom + _uv_width[1], cy);
  637. PN_stdfloat inner_top = max(top - _uv_width[1], cy);
  638. GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
  639. // verts 0,1,2,3
  640. texcoord.add_data2(left, top);
  641. texcoord.add_data2(left, inner_top);
  642. texcoord.add_data2(inner_left, top);
  643. texcoord.add_data2(inner_left, inner_top);
  644. // verts 4,5,6,7
  645. texcoord.add_data2(inner_right, top);
  646. texcoord.add_data2(inner_right, inner_top);
  647. texcoord.add_data2(right, top);
  648. texcoord.add_data2(right, inner_top);
  649. // verts 8,9,10,11
  650. texcoord.add_data2(left, inner_bottom);
  651. texcoord.add_data2(left, bottom);
  652. texcoord.add_data2(inner_left, inner_bottom);
  653. texcoord.add_data2(inner_left, bottom);
  654. // verts 12,13,14,15
  655. texcoord.add_data2(inner_right, inner_bottom);
  656. texcoord.add_data2(inner_right, bottom);
  657. texcoord.add_data2(right, inner_bottom);
  658. texcoord.add_data2(right, bottom);
  659. }
  660. PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
  661. // tristrip #1
  662. strip->add_consecutive_vertices(0, 8);
  663. strip->close_primitive();
  664. // tristrip #2
  665. strip->add_vertex(1);
  666. strip->add_vertex(8);
  667. strip->add_vertex(3);
  668. strip->add_vertex(10);
  669. strip->add_vertex(5);
  670. strip->add_vertex(12);
  671. strip->add_vertex(7);
  672. strip->add_vertex(14);
  673. strip->close_primitive();
  674. // tristrip #3
  675. strip->add_consecutive_vertices(8, 8);
  676. strip->close_primitive();
  677. CPT(RenderState) state = RenderState::make(ColorAttrib::make_flat(_color), -1);
  678. if (has_texture()) {
  679. state = state->set_attrib(TextureAttrib::make(get_texture()));
  680. }
  681. PT(Geom) geom = new Geom(vdata);
  682. geom->add_primitive(strip);
  683. gnode->add_geom(geom, state);
  684. return gnode;
  685. }