Panda3D
|
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 }