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