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