Panda3D

cardMaker.cxx

00001 // Filename: cardMaker.cxx
00002 // Created by:  drose (16Mar02)
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 "cardMaker.h"
00016 #include "geomNode.h"
00017 #include "transformState.h"
00018 #include "colorAttrib.h"
00019 #include "sceneGraphReducer.h"
00020 #include "geom.h"
00021 #include "geomTristrips.h"
00022 #include "geomVertexWriter.h"
00023 #include "geomVertexFormat.h"
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: CardMaker::reset
00027 //       Access: Public
00028 //  Description: Resets all the parameters to their initial defaults.
00029 ////////////////////////////////////////////////////////////////////
00030 void CardMaker::
00031 reset() {
00032   _has_uvs = true;
00033   _has_3d_uvs = false;
00034 
00035   _ll_pos.set(0.0f, 0.0f, 0.0f);
00036   _lr_pos.set(1.0f, 0.0f, 0.0f);
00037   _ur_pos.set(1.0f, 0.0f, 1.0f);
00038   _ul_pos.set(0.0f, 0.0f, 1.0f);
00039 
00040   _ll_tex.set(0.0f, 0.0f, 0.0f);
00041   _lr_tex.set(1.0f, 0.0f, 0.0f);
00042   _ur_tex.set(1.0f, 1.0f, 0.0f);
00043   _ul_tex.set(0.0f, 1.0f, 0.0f);
00044 
00045   _has_color = false;
00046   _color.set(1.0f, 1.0f, 1.0f, 1.0f);
00047 
00048   _has_normals = true;
00049   _source_geometry = (PandaNode *)NULL;
00050   _source_frame.set(0.0f, 0.0f, 0.0f, 0.0f);
00051 }
00052 
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: CardMaker::generate
00056 //       Access: Public
00057 //  Description: Generates a GeomNode that renders the specified
00058 //               geometry.
00059 ////////////////////////////////////////////////////////////////////
00060 PT(PandaNode) CardMaker::
00061 generate() {
00062   if (_source_geometry != (PandaNode *)NULL) {
00063     return rescale_source_geometry();
00064   }
00065 
00066   PT(GeomNode) gnode = new GeomNode(get_name());
00067 
00068   CPT(GeomVertexFormat) format;
00069   if (_has_normals) {
00070     if (_has_uvs) {
00071       if (_has_3d_uvs) {
00072         format = GeomVertexFormat::register_format
00073           (new GeomVertexArrayFormat
00074            (InternalName::get_vertex(), 3,
00075             GeomEnums::NT_stdfloat, GeomEnums::C_point,
00076             InternalName::get_normal(), 3,
00077             GeomEnums::NT_stdfloat, GeomEnums::C_vector,
00078             InternalName::get_texcoord(), 3,
00079             GeomEnums::NT_stdfloat, GeomEnums::C_texcoord));
00080       } else {
00081         format = GeomVertexFormat::get_v3n3t2();
00082       }
00083     } else {
00084       format = GeomVertexFormat::get_v3n3();
00085     }
00086   } else {
00087     if (_has_uvs) {
00088       if (_has_3d_uvs) {
00089         format = GeomVertexFormat::register_format
00090           (new GeomVertexArrayFormat
00091            (InternalName::get_vertex(), 3,
00092             GeomEnums::NT_stdfloat, GeomEnums::C_point,
00093             InternalName::get_texcoord(), 3,
00094             GeomEnums::NT_stdfloat, GeomEnums::C_texcoord));
00095       } else {
00096         format = GeomVertexFormat::get_v3t2();
00097       }
00098     } else {
00099       format = GeomVertexFormat::get_v3();
00100     }
00101   }
00102   
00103   PT(GeomVertexData) vdata = new GeomVertexData
00104     ("card", format, Geom::UH_static);
00105   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00106   
00107   vertex.add_data3(_ul_pos);
00108   vertex.add_data3(_ll_pos);
00109   vertex.add_data3(_ur_pos);
00110   vertex.add_data3(_lr_pos);
00111   
00112   if (_has_uvs) {
00113     GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00114     texcoord.add_data3(_ul_tex);
00115     texcoord.add_data3(_ll_tex);
00116     texcoord.add_data3(_ur_tex);
00117     texcoord.add_data3(_lr_tex);
00118   }
00119   
00120   if (_has_normals) {
00121     GeomVertexWriter normal(vdata, InternalName::get_normal());
00122     LVector3 n;
00123     n = (_ll_pos - _ul_pos).cross(_ur_pos - _ul_pos);
00124     n.normalize();
00125     normal.add_data3(n);
00126     n = (_lr_pos - _ll_pos).cross(_ul_pos - _ll_pos);
00127     n.normalize();
00128     normal.add_data3(n);
00129     n = (_ul_pos - _ur_pos).cross(_lr_pos - _ur_pos);
00130     n.normalize();
00131     normal.add_data3(n);
00132     n = (_ur_pos - _lr_pos).cross(_ll_pos - _lr_pos);
00133     n.normalize();
00134     normal.add_data3(n);
00135   }
00136   
00137   PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
00138   strip->set_shade_model(Geom::SM_uniform);
00139   strip->add_next_vertices(4);
00140   strip->close_primitive();
00141   
00142   PT(Geom) geom = new Geom(vdata);
00143   geom->add_primitive(strip);
00144 
00145   CPT(RenderState) state = RenderState::make_empty();
00146   if (_has_color) {
00147     state = RenderState::make(ColorAttrib::make_flat(_color));
00148   }
00149   
00150   gnode->add_geom(geom, state);
00151   
00152   return gnode.p();
00153 }
00154 
00155 ////////////////////////////////////////////////////////////////////
00156 //     Function: CardMaker::set_uv_range
00157 //       Access: Public
00158 //  Description: Sets the range of UV's that will be applied to the
00159 //               vertices.  If set_has_uvs() is true (as it is by
00160 //               default), the vertices will be generated with the
00161 //               indicated range of UV's, which will be useful if a
00162 //               texture is applied.
00163 ////////////////////////////////////////////////////////////////////
00164 void CardMaker::
00165 set_uv_range(const LTexCoord3 &ll, const LTexCoord3 &lr, const LTexCoord3 &ur, const LTexCoord3 &ul) {
00166   _ll_tex = ll;
00167   _lr_tex = lr;
00168   _ur_tex = ur;
00169   _ul_tex = ul;
00170   _has_uvs = true;
00171   _has_3d_uvs = true;
00172 }
00173 
00174 ////////////////////////////////////////////////////////////////////
00175 //     Function: CardMaker::set_uv_range
00176 //       Access: Public
00177 //  Description: Sets the range of UV's that will be applied to the
00178 //               vertices.  If set_has_uvs() is true (as it is by
00179 //               default), the vertices will be generated with the
00180 //               indicated range of UV's, which will be useful if a
00181 //               texture is applied.
00182 ////////////////////////////////////////////////////////////////////
00183 void CardMaker::
00184 set_uv_range(const LTexCoord &ll, const LTexCoord &lr, const LTexCoord &ur, const LTexCoord &ul) {
00185   _ll_tex.set(ll[0], ll[1], 0.0f);
00186   _lr_tex.set(lr[0], lr[1], 0.0f);
00187   _ur_tex.set(ur[0], ur[1], 0.0f);
00188   _ul_tex.set(ul[0], ul[1], 0.0f);
00189   _has_uvs = true;
00190   _has_3d_uvs = false;
00191 }
00192 
00193 ////////////////////////////////////////////////////////////////////
00194 //     Function: CardMaker::set_uv_range
00195 //       Access: Public
00196 //  Description: Sets the range of UV's that will be applied to the
00197 //               vertices.  If set_has_uvs() is true (as it is by
00198 //               default), the vertices will be generated with the
00199 //               indicated range of UV's, which will be useful if a
00200 //               texture is applied.
00201 ////////////////////////////////////////////////////////////////////
00202 void CardMaker::
00203 set_uv_range(const LTexCoord &ll, const LTexCoord &ur) {
00204   _ll_tex.set(ll[0], ll[1], 0.0f);
00205   _lr_tex.set(ur[0], ll[1], 0.0f);
00206   _ur_tex.set(ur[0], ur[1], 0.0f);
00207   _ul_tex.set(ll[0], ur[1], 0.0f);
00208   _has_uvs = true;
00209   _has_3d_uvs = false;
00210 }
00211 
00212 ////////////////////////////////////////////////////////////////////
00213 //     Function: CardMaker::set_uv_range
00214 //       Access: Public
00215 //  Description: Sets the range of UV's that will be applied to the
00216 //               vertices.  If set_has_uvs() is true (as it is by
00217 //               default), the vertices will be generated with the
00218 //               indicated range of UV's, which will be useful if a
00219 //               texture is applied.
00220 ////////////////////////////////////////////////////////////////////
00221 void CardMaker::
00222 set_uv_range(const LVector4 &x, const LVector4 &y, const LVector4 &z) {
00223   _ll_tex.set(x[0], y[0], z[0]);
00224   _lr_tex.set(x[1], y[1], z[1]);
00225   _ur_tex.set(x[2], y[2], z[2]);
00226   _ul_tex.set(x[3], y[3], z[3]);
00227   _has_uvs = true;
00228   _has_3d_uvs = true;
00229 }
00230 
00231 ////////////////////////////////////////////////////////////////////
00232 //     Function: CardMaker::set_uv_range_cube
00233 //       Access: Public
00234 //  Description: Sets the range of UV's that will be applied to the
00235 //               vertices appropriately for a cube-map face.
00236 ////////////////////////////////////////////////////////////////////
00237 void CardMaker::
00238 set_uv_range_cube(int face) {
00239   LVector4 varya(-1,  1,  1, -1);
00240   LVector4 varyb(-1, -1,  1,  1);
00241   LVector4 fixed( 1,  1,  1,  1);
00242   switch(face) {
00243   case 0: set_uv_range( fixed, -varyb, -varya); break; // positive_x
00244   case 1: set_uv_range(-fixed, -varyb,  varya); break; // negative_x
00245   case 2: set_uv_range( varya,  fixed,  varyb); break; // positive_y
00246   case 3: set_uv_range( varya, -fixed, -varyb); break; // negative_y
00247   case 4: set_uv_range( varya, -varyb,  fixed); break; // positive_z
00248   case 5: set_uv_range(-varya, -varyb, -fixed); break; // negative_z
00249   }
00250 }
00251 
00252 ////////////////////////////////////////////////////////////////////
00253 //     Function: CardMaker::set_uv_range
00254 //       Access: Public
00255 //  Description: Sets the range of UV's that will be applied to the
00256 //               vertices appropriately to show the non-pad region
00257 //               of the texture.
00258 ////////////////////////////////////////////////////////////////////
00259 void CardMaker::
00260 set_uv_range(const Texture *tex) {
00261   nassertv(tex->get_texture_type() == Texture::TT_2d_texture);
00262   int nonpadx = tex->get_x_size() - tex->get_pad_x_size();
00263   int nonpady = tex->get_y_size() - tex->get_pad_y_size();
00264   double maxu = (nonpadx*1.0) / tex->get_x_size();
00265   double maxv = (nonpady*1.0) / tex->get_y_size();
00266   set_uv_range(LTexCoord(0.0,0.0), LTexCoord(maxu,maxv));
00267 }
00268 
00269 ////////////////////////////////////////////////////////////////////
00270 //     Function: CardMaker::rescale_source_geometry
00271 //       Access: Private
00272 //  Description: Generates the card by rescaling the source geometry
00273 //               appropriately.
00274 ////////////////////////////////////////////////////////////////////
00275 PT(PandaNode) CardMaker::
00276 rescale_source_geometry() {
00277   PT(PandaNode) root = _source_geometry->copy_subgraph();
00278 
00279   // Determine the translate and scale appropriate for our geometry.
00280   LVector3 frame_max = _ll_pos.fmax(_lr_pos.fmax(_ur_pos.fmax(_ul_pos)));
00281   LVector3 frame_min = _ll_pos.fmin(_lr_pos.fmin(_ur_pos.fmax(_ul_pos)));
00282   LVector3 frame_ctr = (frame_max + frame_min) * 0.5f;
00283   
00284   LVector3 geom_center((_source_frame[0] + _source_frame[1]) * 0.5f,
00285                         frame_ctr[1],
00286                         (_source_frame[2] + _source_frame[3]) * 0.5f);
00287 
00288   LVector3 scale((frame_max[0] - frame_min[0]) / (_source_frame[1] - _source_frame[0]),
00289                   0.0,
00290                   (frame_max[2] - frame_min[2]) / (_source_frame[3] - _source_frame[2]));
00291   
00292   LVector3 trans = frame_ctr - geom_center;
00293 
00294   CPT(TransformState) transform = 
00295     TransformState::make_pos_hpr_scale(trans, LPoint3(0.0f, 0.0f, 0.0f), scale);
00296   root->set_transform(transform);
00297 
00298   if (_has_color) {
00299     root->set_attrib(ColorAttrib::make_flat(_color));
00300   }
00301 
00302   // Now flatten out the geometry as much as we can.
00303   SceneGraphReducer reducer;
00304   reducer.apply_attribs(root);
00305   reducer.flatten(root, ~0);
00306 
00307   return root;
00308 }
 All Classes Functions Variables Enumerations