Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/pgraph/geomTransformer.cxx

Go to the documentation of this file.
00001 // Filename: geomTransformer.cxx
00002 // Created by:  drose (14Mar02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "geomTransformer.h"
00020 #include "geomNode.h"
00021 #include "renderState.h"
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //     Function: GeomTransformer::Constructor
00025 //       Access: Public
00026 //  Description:
00027 ////////////////////////////////////////////////////////////////////
00028 GeomTransformer::
00029 GeomTransformer() {
00030 }
00031 
00032 ////////////////////////////////////////////////////////////////////
00033 //     Function: GeomTransformer::Destructor
00034 //       Access: Public
00035 //  Description:
00036 ////////////////////////////////////////////////////////////////////
00037 GeomTransformer::
00038 ~GeomTransformer() {
00039 }
00040 
00041 ////////////////////////////////////////////////////////////////////
00042 //     Function: GeomTransformer::transform_vertices
00043 //       Access: Public
00044 //  Description: Transforms the vertices and the normals in the
00045 //               indicated Geom by the indicated matrix.  Returns true
00046 //               if the Geom was changed, false otherwise.
00047 ////////////////////////////////////////////////////////////////////
00048 bool GeomTransformer::
00049 transform_vertices(Geom *geom, const LMatrix4f &mat) {
00050   bool transformed = false;
00051 
00052   nassertr(geom != (Geom *)NULL, false);
00053 
00054   PTA_Vertexf coords;
00055   PTA_ushort index;
00056 
00057   geom->get_coords(coords, index);
00058 
00059   if (!coords.empty()) {
00060     // Look up the Geom's coords in our table--have we already
00061     // transformed this array?
00062     SourceVertices sv;
00063     sv._mat = mat;
00064     sv._coords = coords;
00065 
00066     PTA_Vertexf &new_coords = _vertices[sv];
00067 
00068     if (new_coords.is_null()) {
00069       // We have not transformed the array yet.  Do so now.
00070       new_coords.reserve(coords.size());
00071       PTA_Vertexf::const_iterator vi;
00072       for (vi = coords.begin(); vi != coords.end(); ++vi) {
00073         new_coords.push_back((*vi) * mat);
00074       }
00075       nassertr(new_coords.size() == coords.size(), false);
00076     }
00077 
00078     geom->set_coords(new_coords, index);
00079     transformed = true;
00080   }
00081 
00082   // Now do the same thing for normals.
00083   PTA_Normalf norms;
00084   GeomBindType bind;
00085 
00086   geom->get_normals(norms, bind, index);
00087 
00088   if (bind != G_OFF) {
00089     SourceNormals sn;
00090     sn._mat = mat;
00091     sn._norms = norms;
00092 
00093     PTA_Normalf &new_norms = _normals[sn];
00094 
00095     if (new_norms.is_null()) {
00096       // We have not transformed the array yet.  Do so now.
00097       new_norms.reserve(norms.size());
00098       PTA_Normalf::const_iterator ni;
00099       for (ni = norms.begin(); ni != norms.end(); ++ni) {
00100         Normalf new_norm = (*ni) * mat;
00101         new_norm.normalize();
00102         new_norms.push_back(new_norm);
00103       }
00104       nassertr(new_norms.size() == norms.size(), false);
00105     }
00106 
00107     geom->set_normals(new_norms, bind, index);
00108     transformed = true;
00109   }
00110 
00111   return transformed;
00112 }
00113 
00114 
00115 ////////////////////////////////////////////////////////////////////
00116 //     Function: GeomTransformer::transform_vertices
00117 //       Access: Public
00118 //  Description: Transforms the vertices and the normals in all of the
00119 //               Geoms within the indicated GeomNode by the indicated
00120 //               matrix.  Does not destructively change Geoms;
00121 //               instead, a copy will be made of each Geom to be
00122 //               changed, in case multiple GeomNodes reference the
00123 //               same Geom. Returns true if the GeomNode was changed,
00124 //               false otherwise.
00125 ////////////////////////////////////////////////////////////////////
00126 bool GeomTransformer::
00127 transform_vertices(GeomNode *node, const LMatrix4f &mat) {
00128   bool any_changed = false;
00129 
00130   GeomNode::CDWriter cdata(node->_cycler);
00131   GeomNode::Geoms::iterator gi;
00132   for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
00133     GeomNode::GeomEntry &entry = (*gi);
00134     PT(Geom) new_geom = entry._geom->make_copy();
00135     if (transform_vertices(new_geom, mat)) {
00136       entry._geom = new_geom;
00137       any_changed = true;
00138     }
00139   }
00140 
00141   return any_changed;
00142 }
00143 
00144 
00145 ////////////////////////////////////////////////////////////////////
00146 //     Function: GeomTransformer::transform_texcoords
00147 //       Access: Public
00148 //  Description: Transforms the texture coordinates in the indicated
00149 //               Geom by the indicated matrix.  Returns true if the
00150 //               Geom was changed, false otherwise.
00151 ////////////////////////////////////////////////////////////////////
00152 bool GeomTransformer::
00153 transform_texcoords(Geom *geom, const LMatrix4f &mat) {
00154   bool transformed = false;
00155 
00156   nassertr(geom != (Geom *)NULL, false);
00157 
00158   PTA_TexCoordf texcoords;
00159   GeomBindType bind;
00160   PTA_ushort index;
00161 
00162   geom->get_texcoords(texcoords, bind, index);
00163 
00164   if (bind != G_OFF) {
00165     // Look up the Geom's texcoords in our table--have we already
00166     // transformed this array?
00167     SourceTexCoords stc;
00168     stc._mat = mat;
00169     stc._texcoords = texcoords;
00170 
00171     PTA_TexCoordf &new_texcoords = _texcoords[stc];
00172 
00173     if (new_texcoords.is_null()) {
00174       // We have not transformed the array yet.  Do so now.
00175       new_texcoords.reserve(texcoords.size());
00176       PTA_TexCoordf::const_iterator tci;
00177       for (tci = texcoords.begin(); tci != texcoords.end(); ++tci) {
00178         const TexCoordf &tc = (*tci);
00179         LVecBase4f v4(tc[0], tc[1], 0.0f, 1.0f);
00180         v4 = v4 * mat;
00181         new_texcoords.push_back(TexCoordf(v4[0] / v4[3], v4[1] / v4[3]));
00182       }
00183       nassertr(new_texcoords.size() == texcoords.size(), false);
00184     }
00185 
00186     geom->set_texcoords(new_texcoords, bind, index);
00187     transformed = true;
00188   }
00189 
00190   return transformed;
00191 }
00192 
00193 
00194 ////////////////////////////////////////////////////////////////////
00195 //     Function: GeomTransformer::transform_texcoords
00196 //       Access: Public
00197 //  Description: Transforms the texture coordinates in all of the
00198 //               Geoms within the indicated GeomNode by the indicated
00199 //               matrix.  Does not destructively change Geoms;
00200 //               instead, a copy will be made of each Geom to be
00201 //               changed, in case multiple GeomNodes reference the
00202 //               same Geom. Returns true if the GeomNode was changed,
00203 //               false otherwise.
00204 ////////////////////////////////////////////////////////////////////
00205 bool GeomTransformer::
00206 transform_texcoords(GeomNode *node, const LMatrix4f &mat) {
00207   bool any_changed = false;
00208 
00209   GeomNode::CDWriter cdata(node->_cycler);
00210   GeomNode::Geoms::iterator gi;
00211   for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
00212     GeomNode::GeomEntry &entry = (*gi);
00213     PT(Geom) new_geom = entry._geom->make_copy();
00214     if (transform_texcoords(new_geom, mat)) {
00215       entry._geom = new_geom;
00216       any_changed = true;
00217     }
00218   }
00219 
00220   return any_changed;
00221 }
00222 
00223 
00224 ////////////////////////////////////////////////////////////////////
00225 //     Function: GeomTransformer::set_color
00226 //       Access: Public
00227 //  Description: Overrides the color indicated within the Geom with
00228 //               the given replacement color.  Returns true if the
00229 //               Geom was changed, false otherwise.
00230 ////////////////////////////////////////////////////////////////////
00231 bool GeomTransformer::
00232 set_color(Geom *geom, const Colorf &color) {
00233   // In this case, we always replace whatever color array was there
00234   // with a new color array containing just this color.
00235 
00236   // We do want to share this one-element array between Geoms, though.
00237   PTA_Colorf &new_colors = _fcolors[color];
00238 
00239   if (new_colors.is_null()) {
00240     // We haven't seen this color before; define a new color array.
00241     new_colors.push_back(color);
00242   }
00243 
00244   geom->set_colors(new_colors, G_OVERALL);
00245   return true;
00246 }
00247 
00248 
00249 ////////////////////////////////////////////////////////////////////
00250 //     Function: GeomTransformer::transform_texcoords
00251 //       Access: Public
00252 //  Description: Overrides the color indicated within the GeomNode
00253 //               with the given replacement color.  Returns true if
00254 //               any Geom in the GeomNode was changed, false
00255 //               otherwise.
00256 ////////////////////////////////////////////////////////////////////
00257 bool GeomTransformer::
00258 set_color(GeomNode *node, const Colorf &color) {
00259   bool any_changed = false;
00260 
00261   GeomNode::CDWriter cdata(node->_cycler);
00262   GeomNode::Geoms::iterator gi;
00263   for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
00264     GeomNode::GeomEntry &entry = (*gi);
00265     PT(Geom) new_geom = entry._geom->make_copy();
00266     if (set_color(new_geom, color)) {
00267       entry._geom = new_geom;
00268       any_changed = true;
00269     }
00270   }
00271 
00272   return any_changed;
00273 }
00274 
00275 ////////////////////////////////////////////////////////////////////
00276 //     Function: GeomTransformer::transform_colors
00277 //       Access: Public
00278 //  Description: Transforms the colors in the indicated Geom by the
00279 //               indicated scale.  Returns true if the Geom was
00280 //               changed, false otherwise.
00281 ////////////////////////////////////////////////////////////////////
00282 bool GeomTransformer::
00283 transform_colors(Geom *geom, const LVecBase4f &scale) {
00284   bool transformed = false;
00285 
00286   nassertr(geom != (Geom *)NULL, false);
00287 
00288   PTA_Colorf colors;
00289   GeomBindType bind;
00290   PTA_ushort index;
00291 
00292   geom->get_colors(colors, bind, index);
00293 
00294   if (bind != G_OFF) {
00295     // Look up the Geom's colors in our table--have we already
00296     // transformed this array?
00297     SourceColors sc;
00298     sc._scale = scale;
00299     sc._colors = colors;
00300 
00301     PTA_Colorf &new_colors = _tcolors[sc];
00302 
00303     if (new_colors.is_null()) {
00304       // We have not transformed the array yet.  Do so now.
00305       new_colors.reserve(colors.size());
00306       PTA_Colorf::const_iterator ci;
00307       for (ci = colors.begin(); ci != colors.end(); ++ci) {
00308         const Colorf &c = (*ci);
00309         Colorf transformed(c[0] * scale[0], 
00310                            c[1] * scale[1], 
00311                            c[2] * scale[2],
00312                            c[3] * scale[3]);
00313         new_colors.push_back(transformed);
00314       }
00315       nassertr(new_colors.size() == colors.size(), false);
00316     }
00317 
00318     geom->set_colors(new_colors, bind, index);
00319     transformed = true;
00320   }
00321 
00322   return transformed;
00323 }
00324 
00325 
00326 ////////////////////////////////////////////////////////////////////
00327 //     Function: GeomTransformer::transform_colors
00328 //       Access: Public
00329 //  Description: Transforms the colors in all of the Geoms within the
00330 //               indicated GeomNode by the indicated scale.  Does
00331 //               not destructively change Geoms; instead, a copy will
00332 //               be made of each Geom to be changed, in case multiple
00333 //               GeomNodes reference the same Geom. Returns true if
00334 //               the GeomNode was changed, false otherwise.
00335 ////////////////////////////////////////////////////////////////////
00336 bool GeomTransformer::
00337 transform_colors(GeomNode *node, const LVecBase4f &scale) {
00338   bool any_changed = false;
00339 
00340   GeomNode::CDWriter cdata(node->_cycler);
00341   GeomNode::Geoms::iterator gi;
00342   for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
00343     GeomNode::GeomEntry &entry = (*gi);
00344     PT(Geom) new_geom = entry._geom->make_copy();
00345     if (transform_colors(new_geom, scale)) {
00346       entry._geom = new_geom;
00347       any_changed = true;
00348     }
00349   }
00350 
00351   return any_changed;
00352 }
00353 
00354 
00355 ////////////////////////////////////////////////////////////////////
00356 //     Function: GeomTransformer::apply_state
00357 //       Access: Public
00358 //  Description: Applies the indicated render state to all the of
00359 //               Geoms.  Returns true if the GeomNode was changed,
00360 //               false otherwise.
00361 ////////////////////////////////////////////////////////////////////
00362 bool GeomTransformer::
00363 apply_state(GeomNode *node, const RenderState *state) {
00364   bool any_changed = false;
00365 
00366   GeomNode::CDWriter cdata(node->_cycler);
00367   GeomNode::Geoms::iterator gi;
00368   for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
00369     GeomNode::GeomEntry &entry = (*gi);
00370     CPT(RenderState) new_state = state->compose(entry._state);
00371     if (entry._state != new_state) {
00372       entry._state = new_state;
00373       any_changed = true;
00374     }
00375   }
00376 
00377   return any_changed;
00378 }

Generated on Fri May 2 00:41:41 2003 for Panda by doxygen1.3