Panda3D
 All Classes Functions Variables Enumerations
pgFrameStyle.cxx
00001 // Filename: pgFrameStyle.cxx
00002 // Created by:  drose (03Jul01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pgFrameStyle.h"
00016 #include "geomNode.h"
00017 #include "pandaNode.h"
00018 #include "transparencyAttrib.h"
00019 #include "pointerTo.h"
00020 #include "nodePath.h"
00021 #include "textureAttrib.h"
00022 #include "renderState.h"
00023 #include "shadeModelAttrib.h"
00024 #include "colorAttrib.h"
00025 #include "geom.h"
00026 #include "geomTristrips.h"
00027 #include "geomVertexWriter.h"
00028 
00029 // Specifies the UV range of textures applied to the frame.  Maybe
00030 // we'll have a reason to make this a parameter of the frame style one
00031 // day, but for now it's hardcoded to fit the entire texture over the
00032 // rectangular frame.
00033 static const LVecBase4 uv_range = LVecBase4(0.0f, 1.0f, 0.0f, 1.0f);
00034 
00035 ostream &
00036 operator << (ostream &out, PGFrameStyle::Type type) {
00037   switch (type) {
00038   case PGFrameStyle::T_none:
00039     return out << "none";
00040 
00041   case PGFrameStyle::T_flat:
00042     return out << "flat";
00043 
00044   case PGFrameStyle::T_bevel_out:
00045     return out << "bevel_out";
00046 
00047   case PGFrameStyle::T_bevel_in:
00048     return out << "bevel_in";
00049 
00050   case PGFrameStyle::T_groove:
00051     return out << "groove";
00052 
00053   case PGFrameStyle::T_ridge:
00054     return out << "ridge";
00055 
00056   case PGFrameStyle::T_texture_border:
00057     return out << "texture_border";
00058   }
00059 
00060   return out << "**unknown(" << (int)type << ")**";
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: PGFrameStyle::get_internal_frame
00065 //       Access: Published
00066 //  Description: Computes the size of the internal frame, given the
00067 //               indicated external frame, appropriate for this kind
00068 //               of frame style.  This simply subtracts the border
00069 //               width for those frame styles that include a border.
00070 ////////////////////////////////////////////////////////////////////
00071 LVecBase4 PGFrameStyle::
00072 get_internal_frame(const LVecBase4 &frame) const {
00073   LPoint2 center((frame[0] + frame[1]) / 2.0f,
00074                   (frame[2] + frame[3]) / 2.0f);
00075   LVecBase4 scaled_frame
00076     ((frame[0] - center[0]) * _visible_scale[0] + center[0],
00077      (frame[1] - center[0]) * _visible_scale[0] + center[0],
00078      (frame[2] - center[1]) * _visible_scale[1] + center[1],
00079      (frame[3] - center[1]) * _visible_scale[1] + center[1]);
00080 
00081   switch (_type) {
00082   case T_none:
00083   case T_flat:
00084     return scaled_frame;
00085 
00086   default:
00087     break;
00088   }
00089 
00090   return LVecBase4(scaled_frame[0] + _width[0],
00091                     scaled_frame[1] - _width[0],
00092                     scaled_frame[2] + _width[1],
00093                     scaled_frame[3] - _width[1]);
00094 }
00095 
00096 ////////////////////////////////////////////////////////////////////
00097 //     Function: PGFrameStyle::output
00098 //       Access: Published
00099 //  Description: 
00100 ////////////////////////////////////////////////////////////////////
00101 void PGFrameStyle::
00102 output(ostream &out) const {
00103   out << _type << " color = " << _color << " width = " << _width;
00104   if (_visible_scale != LVecBase2(1.0f, 1.0f)) {
00105     out << "visible_scale = " << get_visible_scale();
00106   }
00107   if (has_texture()) {
00108     out << " texture = " << *get_texture();
00109   }
00110 }
00111 
00112 ////////////////////////////////////////////////////////////////////
00113 //     Function: PGFrameStyle::xform
00114 //       Access: Public
00115 //  Description: Applies the indicated transform to the FrameStyle.
00116 //               The return value is true if the frame style is
00117 //               transformed, or false if it was not affected by the
00118 //               transform.
00119 ////////////////////////////////////////////////////////////////////
00120 bool PGFrameStyle::
00121 xform(const LMatrix4 &mat) {
00122   // All we can do is scale the X and Y bevel sizes.
00123 
00124   // Extract the X and Z axes from the matrix.
00125   LVector3 x, z;
00126   mat.get_row3(x, 0);
00127   PN_stdfloat x_scale = x.length();
00128   
00129   mat.get_row3(z, 2);
00130   PN_stdfloat z_scale = z.length();
00131 
00132   _width[0] *= x_scale;
00133   _width[1] *= z_scale;
00134 
00135   switch (_type) {
00136   case T_none:
00137   case T_flat:
00138     return false;
00139 
00140   case T_bevel_out:
00141   case T_bevel_in:
00142   case T_groove:
00143   case T_ridge:
00144   case T_texture_border:
00145     return true;
00146   }
00147 
00148   // Shouldn't get here, but this makes the compiler happy.
00149   return true;
00150 }
00151 
00152 ////////////////////////////////////////////////////////////////////
00153 //     Function: PGFrameStyle::generate_into
00154 //       Access: Public
00155 //  Description: Generates geometry representing a frame of the
00156 //               indicated size, and parents it to the indicated node,
00157 //               with the indicated scene graph sort order.
00158 //
00159 //               The return value is the generated NodePath, if any,
00160 //               or an empty NodePath if nothing is generated.
00161 ////////////////////////////////////////////////////////////////////
00162 NodePath PGFrameStyle::
00163 generate_into(const NodePath &parent, const LVecBase4 &frame,
00164               int sort) {
00165   PT(PandaNode) new_node;
00166 
00167   LPoint2 center((frame[0] + frame[1]) / 2.0f,
00168                   (frame[2] + frame[3]) / 2.0f);
00169   LVecBase4 scaled_frame
00170     ((frame[0] - center[0]) * _visible_scale[0] + center[0],
00171      (frame[1] - center[0]) * _visible_scale[0] + center[0],
00172      (frame[2] - center[1]) * _visible_scale[1] + center[1],
00173      (frame[3] - center[1]) * _visible_scale[1] + center[1]);
00174 
00175   switch (_type) {
00176   case T_none:
00177     return NodePath();
00178 
00179   case T_flat:
00180     new_node = generate_flat_geom(scaled_frame);
00181     break;
00182 
00183   case T_bevel_out:
00184     new_node = generate_bevel_geom(scaled_frame, false);
00185     break;
00186 
00187   case T_bevel_in:
00188     new_node = generate_bevel_geom(scaled_frame, true);
00189     break;
00190 
00191   case T_groove:
00192     new_node = generate_groove_geom(scaled_frame, true);
00193     break;
00194 
00195   case T_ridge:
00196     new_node = generate_groove_geom(scaled_frame, false);
00197     break;
00198 
00199   case T_texture_border:
00200     new_node = generate_texture_border_geom(scaled_frame);
00201     break;
00202 
00203   default:
00204     break;
00205   }
00206 
00207   if (new_node != (PandaNode *)NULL && _color[3] != 1.0f) {
00208     // We've got some alpha on the color; we need transparency.
00209     new_node->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00210   }
00211 
00212   // Adding the node to the parent keeps the reference count.
00213   return parent.attach_new_node(new_node, sort);
00214 }
00215 
00216 ////////////////////////////////////////////////////////////////////
00217 //     Function: PGFrameStyle::generate_flat_geom
00218 //       Access: Private
00219 //  Description: Generates the GeomNode appropriate to a T_flat
00220 //               frame.
00221 ////////////////////////////////////////////////////////////////////
00222 PT(PandaNode) PGFrameStyle::
00223 generate_flat_geom(const LVecBase4 &frame) {
00224   PT(GeomNode) gnode = new GeomNode("flat");
00225 
00226   PN_stdfloat left = frame[0];
00227   PN_stdfloat right = frame[1];
00228   PN_stdfloat bottom = frame[2];
00229   PN_stdfloat top = frame[3];
00230 
00231   CPT(GeomVertexFormat) format;
00232   if (has_texture()) {
00233     format = GeomVertexFormat::get_v3t2();
00234   } else {
00235     format = GeomVertexFormat::get_v3();
00236   }
00237   
00238   PT(GeomVertexData) vdata = new GeomVertexData
00239     ("PGFrame", format, Geom::UH_static);
00240   
00241   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00242   vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
00243   vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
00244   vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
00245   vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
00246 
00247   if (has_texture()) {
00248     // Generate UV's.
00249     left = uv_range[0];
00250     right = uv_range[1];
00251     bottom = uv_range[2];
00252     top = uv_range[3];
00253     
00254     GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00255     texcoord.add_data2(left, top);
00256     texcoord.add_data2(left, bottom);
00257     texcoord.add_data2(right, top);
00258     texcoord.add_data2(right, bottom);
00259   }
00260   
00261   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
00262   strip->add_next_vertices(4);
00263   strip->close_primitive();
00264   
00265   CPT(RenderState) state = RenderState::make(ColorAttrib::make_flat(_color), -1);
00266   if (has_texture()) {
00267     state = state->set_attrib(TextureAttrib::make(get_texture()));
00268   }
00269   PT(Geom) geom = new Geom(vdata);
00270   geom->add_primitive(strip);
00271   gnode->add_geom(geom, state);
00272   
00273   return gnode.p();
00274 }
00275 
00276 ////////////////////////////////////////////////////////////////////
00277 //     Function: PGFrameStyle::generate_bevel_geom
00278 //       Access: Private
00279 //  Description: Generates the GeomNode appropriate to a T_bevel_in
00280 //               or T_bevel_out frame.
00281 ////////////////////////////////////////////////////////////////////
00282 PT(PandaNode) PGFrameStyle::
00283 generate_bevel_geom(const LVecBase4 &frame, bool in) {
00284   //
00285   // Colors:
00286   //
00287   // 
00288   //  * * * * * * * * * * * * * * * * * * * * * * *
00289   //  * *                                       * *
00290   //  *   *               ctop                *   *
00291   //  *     *                               *     *
00292   //  *       * * * * * * * * * * * * * * *       *
00293   //  *       *                           *       *
00294   //  *       *                           *       *
00295   //  * cleft *          _color           * cright*
00296   //  *       *                           *       *
00297   //  *       *                           *       *
00298   //  *       * * * * * * * * * * * * * * *       *
00299   //  *     *                               *     *
00300   //  *   *              cbottom              *   *
00301   //  * *                                       * *
00302   //  * * * * * * * * * * * * * * * * * * * * * * *
00303   //
00304   //
00305   // Vertices:
00306   //
00307   //  tristrip 1:
00308   //  4 * * * * * * * * * * * * * * * * * * * * * 6
00309   //  * *                                       *
00310   //  *   *                                   *
00311   //  *     *                               *
00312   //  *       5 * * * * * * * * * * * * * 7
00313   //  *       *
00314   //  *       *
00315   //  *       *
00316   //  *       *
00317   //  *       *
00318   //  *       3 * * * * * * * * * * * * * 1
00319   //  *     *                               *
00320   //  *   *                                   *
00321   //  * *                                       *
00322   //  2 * * * * * * * * * * * * * * * * * * * * * 0
00323   // 
00324   //  tristrip 2:
00325   //                                              1
00326   //                                            * *
00327   //                                          *   *
00328   //                                        *     *
00329   //          5 * * * * * * * * * * * * * 3       *
00330   //          *                           *       *
00331   //          *                           *       *
00332   //          *                           *       *
00333   //          *                           *       *
00334   //          *                           *       *
00335   //          4 * * * * * * * * * * * * * 2       *
00336   //                                        *     *
00337   //                                          *   *
00338   //                                            * *
00339   //                                              0
00340 
00341   PT(GeomNode) gnode = new GeomNode("bevel");
00342 
00343   PN_stdfloat left = frame[0];
00344   PN_stdfloat right = frame[1];
00345   PN_stdfloat bottom = frame[2];
00346   PN_stdfloat top = frame[3];
00347 
00348   PN_stdfloat cx = (left + right) * 0.5;
00349   PN_stdfloat cy = (top + bottom) * 0.5;
00350 
00351   PN_stdfloat inner_left = min(left + _width[0], cx);
00352   PN_stdfloat inner_right = max(right - _width[0], cx);
00353   PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
00354   PN_stdfloat inner_top = max(top - _width[1], cy);
00355 
00356   PN_stdfloat left_color_scale = 1.2;
00357   PN_stdfloat right_color_scale = 0.8;
00358   PN_stdfloat bottom_color_scale = 0.7;
00359   PN_stdfloat top_color_scale = 1.3;
00360 
00361   if (in) {
00362     right_color_scale = 1.2;
00363     left_color_scale = 0.8;
00364     top_color_scale = 0.7;
00365     bottom_color_scale = 1.3;
00366   }
00367 
00368   // Clamp all colors at white, and don't scale the alpha.
00369   LColor cleft(min(_color[0] * left_color_scale, (PN_stdfloat)1.0),
00370                min(_color[1] * left_color_scale, (PN_stdfloat)1.0),
00371                min(_color[2] * left_color_scale, (PN_stdfloat)1.0),
00372                _color[3]);
00373 
00374   LColor cright(min(_color[0] * right_color_scale, (PN_stdfloat)1.0),
00375                 min(_color[1] * right_color_scale, (PN_stdfloat)1.0),
00376                 min(_color[2] * right_color_scale, (PN_stdfloat)1.0),
00377                 _color[3]);
00378 
00379   LColor cbottom(min(_color[0] * bottom_color_scale, (PN_stdfloat)1.0),
00380                  min(_color[1] * bottom_color_scale, (PN_stdfloat)1.0),
00381                  min(_color[2] * bottom_color_scale, (PN_stdfloat)1.0),
00382                  _color[3]);
00383 
00384   LColor ctop(min(_color[0] * top_color_scale, (PN_stdfloat)1.0),
00385               min(_color[1] * top_color_scale, (PN_stdfloat)1.0),
00386               min(_color[2] * top_color_scale, (PN_stdfloat)1.0),
00387               _color[3]);
00388 
00389   CPT(GeomVertexFormat) format;
00390   if (has_texture()) {
00391     format = GeomVertexFormat::get_v3cpt2();
00392   } else {
00393     format = GeomVertexFormat::get_v3cp();
00394   }
00395 
00396   PT(GeomVertexData) vdata = new GeomVertexData
00397     ("PGFrame", format, Geom::UH_static);
00398   
00399   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00400   GeomVertexWriter color(vdata, InternalName::get_color());
00401   
00402   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
00403   // Tristrip 1.
00404   vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
00405   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
00406   vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
00407   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
00408   vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
00409   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
00410   vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
00411   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
00412   color.add_data4(cbottom);
00413   color.add_data4(cbottom);
00414   color.add_data4(cbottom);
00415   color.add_data4(cbottom);
00416   color.add_data4(cleft);
00417   color.add_data4(cleft);
00418   color.add_data4(ctop);
00419   color.add_data4(ctop);
00420   
00421   strip->add_next_vertices(8);
00422   strip->close_primitive();
00423   
00424   // Tristrip 2.
00425   vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
00426   vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
00427   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
00428   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
00429   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
00430   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
00431   color.add_data4(cright);
00432   color.add_data4(cright);
00433   color.add_data4(cright);
00434   color.add_data4(cright);
00435   color.add_data4(_color);
00436   color.add_data4(_color);
00437   
00438   strip->add_next_vertices(6);
00439   strip->close_primitive();
00440   strip->set_shade_model(Geom::SM_flat_last_vertex);
00441 
00442   if (has_texture()) {
00443     // Generate UV's.
00444     PN_stdfloat left = uv_range[0];
00445     PN_stdfloat right = uv_range[1];
00446     PN_stdfloat bottom = uv_range[2];
00447     PN_stdfloat top = uv_range[3];
00448 
00449     PN_stdfloat cx = (left + right) * 0.5;
00450     PN_stdfloat cy = (top + bottom) * 0.5;
00451     
00452     PN_stdfloat inner_left = min(left + _uv_width[0], cx);
00453     PN_stdfloat inner_right = max(right - _uv_width[0], cx);
00454     PN_stdfloat inner_bottom = min(bottom + _uv_width[1], cy);
00455     PN_stdfloat inner_top = max(top - _uv_width[1], cy);
00456 
00457     GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00458     texcoord.add_data2(right, bottom);
00459     texcoord.add_data2(inner_right, inner_bottom);
00460     texcoord.add_data2(left, bottom);
00461     texcoord.add_data2(inner_left, inner_bottom);
00462     texcoord.add_data2(left, top);
00463     texcoord.add_data2(inner_left, inner_top);
00464     texcoord.add_data2(right, top);
00465     texcoord.add_data2(inner_right, inner_top);
00466 
00467     texcoord.add_data2(right, bottom);
00468     texcoord.add_data2(right, top);
00469     texcoord.add_data2(inner_right, inner_bottom);
00470     texcoord.add_data2(inner_right, inner_top);
00471     texcoord.add_data2(inner_left, inner_bottom);
00472     texcoord.add_data2(inner_left, inner_top);
00473   }
00474   PT(Geom) geom = new Geom(vdata);
00475   geom->add_primitive(strip);
00476   
00477   CPT(RenderState) state;
00478   state = RenderState::make(ShadeModelAttrib::make(ShadeModelAttrib::M_flat),
00479                             ColorAttrib::make_vertex());
00480   if (has_texture()) {
00481     state = state->set_attrib(TextureAttrib::make(get_texture()));
00482   }
00483   gnode->add_geom(geom, state);
00484   
00485   return gnode.p();
00486 }
00487 
00488 ////////////////////////////////////////////////////////////////////
00489 //     Function: PGFrameStyle::generate_groove_geom
00490 //       Access: Private
00491 //  Description: Generates the GeomNode appropriate to a T_groove or
00492 //               T_ridge frame.
00493 ////////////////////////////////////////////////////////////////////
00494 PT(PandaNode) PGFrameStyle::
00495 generate_groove_geom(const LVecBase4 &frame, bool in) {
00496   //
00497   // Colors:
00498   //
00499   // 
00500   //  * * * * * * * * * * * * * * * * * * * * * * * * * * *
00501   //  * *                                               * *
00502   //  *   *                   ctop                    *   *
00503   //  *     *                                       *     *
00504   //  *       * * * * * * * * * * * * * * * * * * *       *
00505   //  *       * *                               * *       *
00506   //  *       *   *          cbottom          *   *       *
00507   //  *       *     *                       *     *       *
00508   //  *       *       * * * * * * * * * * *       *       *
00509   //  *       *       *                   *       *       *
00510   //  *       *       *                   *       *       *
00511   //  * cleft * cright*      _color       * cleft * cright*
00512   //  *       *       *                   *       *       *
00513   //  *       *       *                   *       *       *
00514   //  *       *       * * * * * * * * * * *       *       *
00515   //  *       *     *                       *     *       *
00516   //  *       *   *           ctop            *   *       *
00517   //  *       * *                               * *       *
00518   //  *       * * * * * * * * * * * * * * * * * * *       *
00519   //  *     *                                       *     *
00520   //  *   *                  cbottom                  *   *
00521   //  * *                                               * *
00522   //  * * * * * * * * * * * * * * * * * * * * * * * * * * *
00523   //
00524   //
00525   // Vertices:
00526   //
00527   //  tristrip 1:
00528   //  4 * * * * * * * * * * * * * * * * * * * * * * * * * 6
00529   //  * *                                               *
00530   //  *   *                                           *
00531   //  *     *                                       *
00532   //  *       5 * * * * * * * * * * * * * * * * * 7
00533   //  *       *
00534   //  *       *
00535   //  *       *
00536   //  *       *
00537   //  *       *
00538   //  *       *
00539   //  *       *
00540   //  *       *
00541   //  *       *
00542   //  *       *
00543   //  *       *
00544   //  *       *
00545   //  *       *
00546   //  *       3 * * * * * * * * * * * * * * * * * 1
00547   //  *     *                                       *
00548   //  *   *                                           *
00549   //  * *                                               *
00550   //  2 * * * * * * * * * * * * * * * * * * * * * * * * * 0
00551   //
00552   //  tristrip 2:
00553   //          4 * * * * * * * * * * * * * * * * * 6
00554   //          * *                               *
00555   //          *   *                           *
00556   //          *     *                       *
00557   //          *       5 * * * * * * * * * 7
00558   //          *       *
00559   //          *       *
00560   //          *       *
00561   //          *       *
00562   //          *       *
00563   //          *       3 * * * * * * * * * 1
00564   //          *     *                       *
00565   //          *   *                           *
00566   //          * *                               *
00567   //          2 * * * * * * * * * * * * * * * * * 0
00568   // 
00569   //  tristrip 3:
00570   //                                                      1
00571   //                                                    * *
00572   //                                                  *   *
00573   //                                                *     *
00574   //                                              3       *
00575   //                                            * *       *
00576   //                                          *   *       *
00577   //                                        *     *       *
00578   //                  7 * * * * * * * * * 5       *       *
00579   //                  *                   *       *       *
00580   //                  *                   *       *       *
00581   //                  *                   *       *       *
00582   //                  *                   *       *       *
00583   //                  *                   *       *       *
00584   //                  6 * * * * * * * * * 4       *       *
00585   //                                        *     *       *
00586   //                                          *   *       *
00587   //                                            * *       *
00588   //                                              2       *
00589   //                                                *     *
00590   //                                                  *   *
00591   //                                                    * *
00592   //                                                      0
00593 
00594   PT(GeomNode) gnode = new GeomNode("groove");
00595 
00596   PN_stdfloat left = frame[0];
00597   PN_stdfloat right = frame[1];
00598   PN_stdfloat bottom = frame[2];
00599   PN_stdfloat top = frame[3];
00600 
00601   PN_stdfloat cx = (left + right) * 0.5;
00602   PN_stdfloat cy = (top + bottom) * 0.5;
00603 
00604   PN_stdfloat mid_left = min(left + 0.5f * _width[0], cx);
00605   PN_stdfloat mid_right = max(right - 0.5f * _width[0], cx);
00606   PN_stdfloat mid_bottom = min(bottom + 0.5f * _width[1], cy);
00607   PN_stdfloat mid_top = max(top - 0.5f * _width[1], cy);
00608 
00609   PN_stdfloat inner_left = min(left + _width[0], cx);
00610   PN_stdfloat inner_right = max(right - _width[0], cx);
00611   PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
00612   PN_stdfloat inner_top = max(top - _width[1], cy);
00613 
00614   PN_stdfloat left_color_scale = 1.2;
00615   PN_stdfloat right_color_scale = 0.8f;
00616   PN_stdfloat bottom_color_scale = 0.7f;
00617   PN_stdfloat top_color_scale = 1.3;
00618 
00619   if (in) {
00620     right_color_scale = 1.2;
00621     left_color_scale = 0.8f;
00622     top_color_scale = 0.7f;
00623     bottom_color_scale = 1.3;
00624   }
00625 
00626   // Clamp all colors at white, and don't scale the alpha.
00627   LColor cleft(min(_color[0] * left_color_scale, (PN_stdfloat)1.0),
00628                min(_color[1] * left_color_scale, (PN_stdfloat)1.0),
00629                min(_color[2] * left_color_scale, (PN_stdfloat)1.0),
00630                _color[3]);
00631 
00632   LColor cright(min(_color[0] * right_color_scale, (PN_stdfloat)1.0),
00633                 min(_color[1] * right_color_scale, (PN_stdfloat)1.0),
00634                 min(_color[2] * right_color_scale, (PN_stdfloat)1.0),
00635                 _color[3]);
00636 
00637   LColor cbottom(min(_color[0] * bottom_color_scale, (PN_stdfloat)1.0),
00638                  min(_color[1] * bottom_color_scale, (PN_stdfloat)1.0),
00639                  min(_color[2] * bottom_color_scale, (PN_stdfloat)1.0),
00640                  _color[3]);
00641 
00642   LColor ctop(min(_color[0] * top_color_scale, (PN_stdfloat)1.0),
00643               min(_color[1] * top_color_scale, (PN_stdfloat)1.0),
00644               min(_color[2] * top_color_scale, (PN_stdfloat)1.0),
00645               _color[3]);
00646 
00647   CPT(GeomVertexFormat) format;
00648   if (has_texture()) {
00649     format = GeomVertexFormat::get_v3cpt2();
00650   } else {
00651     format = GeomVertexFormat::get_v3cp();
00652   }
00653   PT(GeomVertexData) vdata = new GeomVertexData
00654     ("PGFrame", format, Geom::UH_static);
00655   
00656   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00657   GeomVertexWriter color(vdata, InternalName::get_color());
00658   
00659   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
00660   // Tristrip 1.
00661   vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
00662   vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
00663   vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
00664   vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_bottom));
00665   vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
00666   vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_top));
00667   vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
00668   vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
00669   color.add_data4(cbottom);
00670   color.add_data4(cbottom);
00671   color.add_data4(cbottom);
00672   color.add_data4(cbottom);
00673   color.add_data4(cleft);
00674   color.add_data4(cleft);
00675   color.add_data4(ctop);
00676   color.add_data4(ctop);
00677   
00678   strip->add_next_vertices(8);
00679   strip->close_primitive();
00680   
00681   // Tristrip 2.
00682   vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
00683   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
00684   vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_bottom));
00685   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
00686   vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_top));
00687   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
00688   vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
00689   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
00690   color.add_data4(ctop);
00691   color.add_data4(ctop);
00692   color.add_data4(ctop);
00693   color.add_data4(ctop);
00694   color.add_data4(cright);
00695   color.add_data4(cright);
00696   color.add_data4(cbottom);
00697   color.add_data4(cbottom);
00698   
00699   strip->add_next_vertices(8);
00700   strip->close_primitive();
00701   
00702   // Tristrip 3.
00703   vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
00704   vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
00705   vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
00706   vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
00707   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
00708   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
00709   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
00710   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
00711   color.add_data4(cright);
00712   color.add_data4(cright);
00713   color.add_data4(cright);
00714   color.add_data4(cright);
00715   color.add_data4(cleft);
00716   color.add_data4(cleft);
00717   color.add_data4(_color);
00718   color.add_data4(_color);
00719   
00720   strip->add_next_vertices(8);
00721   strip->close_primitive();
00722   
00723   strip->set_shade_model(Geom::SM_flat_last_vertex);
00724 
00725   if (has_texture()) {
00726     // Generate UV's.
00727     PN_stdfloat left = uv_range[0];
00728     PN_stdfloat right = uv_range[1];
00729     PN_stdfloat bottom = uv_range[2];
00730     PN_stdfloat top = uv_range[3];
00731 
00732     PN_stdfloat cx = (left + right) * 0.5;
00733     PN_stdfloat cy = (top + bottom) * 0.5;
00734 
00735     PN_stdfloat mid_left = min(left + 0.5f * _width[0], cx);
00736     PN_stdfloat mid_right = max(right - 0.5f * _width[0], cx);
00737     PN_stdfloat mid_bottom = min(bottom + 0.5f * _width[1], cy);
00738     PN_stdfloat mid_top = max(top - 0.5f * _width[1], cy);
00739 
00740     PN_stdfloat inner_left = min(left + _width[0], cx);
00741     PN_stdfloat inner_right = max(right - _width[0], cx);
00742     PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
00743     PN_stdfloat inner_top = max(top - _width[1], cy);
00744 
00745     GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00746     texcoord.add_data2(right, bottom);
00747     texcoord.add_data2(mid_right, mid_bottom);
00748     texcoord.add_data2(left, bottom);
00749     texcoord.add_data2(mid_left, mid_bottom);
00750     texcoord.add_data2(left, top);
00751     texcoord.add_data2(mid_left, mid_top);
00752     texcoord.add_data2(right, top);
00753     texcoord.add_data2(mid_right, mid_top);
00754 
00755     texcoord.add_data2(mid_right, mid_bottom);
00756     texcoord.add_data2(inner_right, inner_bottom);
00757     texcoord.add_data2(mid_left, mid_bottom);
00758     texcoord.add_data2(inner_left, inner_bottom);
00759     texcoord.add_data2(mid_left, mid_top);
00760     texcoord.add_data2(inner_left, inner_top);
00761     texcoord.add_data2(mid_right, mid_top);
00762     texcoord.add_data2(inner_right, inner_top);
00763 
00764     texcoord.add_data2(right, bottom);
00765     texcoord.add_data2(right, top);
00766     texcoord.add_data2(mid_right, mid_bottom);
00767     texcoord.add_data2(mid_right, mid_top);
00768     texcoord.add_data2(inner_right, inner_bottom);
00769     texcoord.add_data2(inner_right, inner_top);
00770     texcoord.add_data2(inner_left, inner_bottom);
00771     texcoord.add_data2(inner_left, inner_top);
00772   }
00773 
00774   PT(Geom) geom = new Geom(vdata);
00775   geom->add_primitive(strip);
00776   
00777   CPT(RenderState) state = RenderState::make(ShadeModelAttrib::make(ShadeModelAttrib::M_flat),
00778                                              ColorAttrib::make_vertex());
00779   if (has_texture()) {
00780     state = state->set_attrib(TextureAttrib::make(get_texture()));
00781   }
00782   gnode->add_geom(geom, state);
00783 
00784   return gnode.p();
00785 }
00786 
00787 ////////////////////////////////////////////////////////////////////
00788 //     Function: PGFrameStyle::generate_texture_border_geom
00789 //       Access: Private
00790 //  Description: Generates the GeomNode appropriate to a
00791 //               T_texture_border frame.
00792 ////////////////////////////////////////////////////////////////////
00793 PT(PandaNode) PGFrameStyle::
00794 generate_texture_border_geom(const LVecBase4 &frame) {
00795   //
00796   // Vertices:
00797   //
00798   //  tristrip 1:
00799   //  0 * * * 2 * * * * * * * * * * * * * 4 * * * 6
00800   //  *     * *                     * * * *     * *
00801   //  *   *   *         * * * * * *       *   *   *
00802   //  * *     * * * * *                   * *     *
00803   //  1 * * * 3 * * * * * * * * * * * * * 5 * * * 7
00804   //
00805   //  tristrip 2:
00806   //  1 * * * 3 * * * * * * * * * * * * * 5 * * * 7
00807   //  *       *                         * *       *
00808   //  *     * *                     * *   *     * *
00809   //  *   *   *               * * *       *   *   *
00810   //  *   *   *         * * *             *   *   *
00811   //  * *     *     * *                   * *     *
00812   //  *       * * *                       *       *
00813   //  8 * * *10 * * * * * * * * * * * * *12 * * *14
00814   // 
00815   //  tristrip 3:
00816   //  8 * * *10 * * * * * * * * * * * * *12 * * *14
00817   //  *     * *                     * * * *     * *
00818   //  *   *   *         * * * * * *       *   *   *
00819   //  * *     * * * * *                   * *     *
00820   //  9 * * *11 * * * * * * * * * * * * *13 * * *15
00821 
00822   PT(GeomNode) gnode = new GeomNode("flat");
00823 
00824   PN_stdfloat left = frame[0];
00825   PN_stdfloat right = frame[1];
00826   PN_stdfloat bottom = frame[2];
00827   PN_stdfloat top = frame[3];
00828 
00829   PN_stdfloat cx = (left + right) * 0.5;
00830   PN_stdfloat cy = (top + bottom) * 0.5;
00831 
00832   PN_stdfloat inner_left = min(left + _width[0], cx);
00833   PN_stdfloat inner_right = max(right - _width[0], cx);
00834   PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
00835   PN_stdfloat inner_top = max(top - _width[1], cy);
00836 
00837   CPT(GeomVertexFormat) format;
00838   if (has_texture()) {
00839     format = GeomVertexFormat::get_v3t2();
00840   } else {
00841     format = GeomVertexFormat::get_v3();
00842   }
00843   
00844   PT(GeomVertexData) vdata = new GeomVertexData
00845     ("PGFrame", format, Geom::UH_static);
00846   
00847   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00848   
00849   // verts 0,1,2,3
00850   vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
00851   vertex.add_data3(LPoint3::rfu(left, 0.0f, inner_top));
00852   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, top));
00853   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
00854   // verts 4,5,6,7
00855   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, top));
00856   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
00857   vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
00858   vertex.add_data3(LPoint3::rfu(right, 0.0f, inner_top));
00859   // verts 8,9,10,11
00860   vertex.add_data3(LPoint3::rfu(left, 0.0f, inner_bottom));
00861   vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
00862   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
00863   vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, bottom));
00864   // verts 12,13,14,15
00865   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
00866   vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, bottom));
00867   vertex.add_data3(LPoint3::rfu(right, 0.0f, inner_bottom));
00868   vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
00869 
00870   if (has_texture()) {
00871     // Generate UV's.
00872     PN_stdfloat left = uv_range[0];
00873     PN_stdfloat right = uv_range[1];
00874     PN_stdfloat bottom = uv_range[2];
00875     PN_stdfloat top = uv_range[3];
00876 
00877     PN_stdfloat cx = (left + right) * 0.5;
00878     PN_stdfloat cy = (top + bottom) * 0.5;
00879     
00880     PN_stdfloat inner_left = min(left + _uv_width[0], cx);
00881     PN_stdfloat inner_right = max(right - _uv_width[0], cx);
00882     PN_stdfloat inner_bottom = min(bottom + _uv_width[1], cy);
00883     PN_stdfloat inner_top = max(top - _uv_width[1], cy);
00884 
00885     GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00886   
00887     // verts 0,1,2,3
00888     texcoord.add_data2(left, top);
00889     texcoord.add_data2(left, inner_top);
00890     texcoord.add_data2(inner_left, top);
00891     texcoord.add_data2(inner_left, inner_top);
00892     // verts 4,5,6,7
00893     texcoord.add_data2(inner_right, top);
00894     texcoord.add_data2(inner_right, inner_top);
00895     texcoord.add_data2(right, top);
00896     texcoord.add_data2(right, inner_top);
00897     // verts 8,9,10,11
00898     texcoord.add_data2(left, inner_bottom);
00899     texcoord.add_data2(left, bottom);
00900     texcoord.add_data2(inner_left, inner_bottom);
00901     texcoord.add_data2(inner_left, bottom);
00902     // verts 12,13,14,15
00903     texcoord.add_data2(inner_right, inner_bottom);
00904     texcoord.add_data2(inner_right, bottom);
00905     texcoord.add_data2(right, inner_bottom);
00906     texcoord.add_data2(right, bottom);
00907   }
00908   
00909   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
00910   
00911   // tristrip #1
00912   strip->add_consecutive_vertices(0, 8);
00913   strip->close_primitive();
00914   
00915   // tristrip #2
00916   strip->add_vertex(1);
00917   strip->add_vertex(8);
00918   strip->add_vertex(3);
00919   strip->add_vertex(10);
00920   strip->add_vertex(5);
00921   strip->add_vertex(12);
00922   strip->add_vertex(7);
00923   strip->add_vertex(14);
00924   strip->close_primitive();
00925   
00926   // tristrip #3
00927   strip->add_consecutive_vertices(8, 8);
00928   strip->close_primitive();
00929   
00930   CPT(RenderState) state = RenderState::make(ColorAttrib::make_flat(_color), -1);
00931   if (has_texture()) {
00932     state = state->set_attrib(TextureAttrib::make(get_texture()));
00933   }
00934 
00935   PT(Geom) geom = new Geom(vdata);
00936   geom->add_primitive(strip);
00937   gnode->add_geom(geom, state);
00938   
00939   return gnode.p();
00940 }
 All Classes Functions Variables Enumerations