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