Panda3D
Loading...
Searching...
No Matches
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
28using std::max;
29using 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.
34static const LVecBase4 uv_range = LVecBase4(0.0f, 1.0f, 0.0f, 1.0f);
35
36std::ostream &
37operator << (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 */
70get_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 */
97void PGFrameStyle::
98output(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 */
114xform(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 */
153generate_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 */
209PT(PandaNode) PGFrameStyle::
210generate_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()) {
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 */
266PT(PandaNode) PGFrameStyle::
267generate_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()) {
341 } else {
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 */
440PT(PandaNode) PGFrameStyle::
441generate_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()) {
532 } else {
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 */
672PT(PandaNode) PGFrameStyle::
673generate_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()) {
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}
A node that holds Geom objects, renderable pieces of geometry.
Definition geomNode.h:34
Defines a series of triangle strips.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This class defines the physical layout of the vertex data stored within a Geom.
static const GeomVertexFormat * get_v3cpt2()
Returns a standard vertex format with a 2-component texture coordinate pair, a packed color,...
static const GeomVertexFormat * get_v3t2()
Returns a standard vertex format with a 2-component texture coordinate pair and a 3-component vertex ...
static const GeomVertexFormat * get_v3cp()
Returns a standard vertex format with a packed color and a 3-component vertex position.
static const GeomVertexFormat * get_v3()
Returns a standard vertex format with just a 3-component vertex position.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
void add_data2(PN_stdfloat x, PN_stdfloat y)
Sets the write row to a particular 2-component value, and advances the write row.
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.
A container for geometry primitives.
Definition geom.h:54
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
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:599
bool xform(const LMatrix4 &mat)
Applies the indicated transform to the FrameStyle.
const LVecBase2 & get_visible_scale() const
Returns the scale factor on the visible representation of the frame, in the X and Y directions.
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,...
bool has_texture() const
Returns true if a texture has been applied to the frame.
LVecBase4 get_internal_frame(const LVecBase4 &frame) const
Computes the size of the internal frame, given the indicated external frame, appropriate for this kin...
Texture * get_texture() const
Returns the texture that has been applied to the frame, or NULL if no texture has been applied.
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition renderState.h:47
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.