Panda3D
 All Classes Functions Variables Enumerations
cLwoPolygons.cxx
00001 // Filename: cLwoPolygons.cxx
00002 // Created by:  drose (25Apr01)
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 "cLwoPolygons.h"
00016 #include "lwoToEggConverter.h"
00017 #include "cLwoPoints.h"
00018 #include "cLwoLayer.h"
00019 #include "cLwoSurface.h"
00020 
00021 #include "lwoPolygonTags.h"
00022 #include "lwoTags.h"
00023 #include "lwoDiscontinuousVertexMap.h"
00024 #include "eggData.h"
00025 #include "eggPolygon.h"
00026 #include "eggPoint.h"
00027 #include "deg_2_rad.h"
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: CLwoPolygons::add_ptags
00031 //       Access: Public
00032 //  Description: Associates the indicated PolygonTags and Tags with
00033 //               the polygons in this chunk.  This may define features
00034 //               such as per-polygon surfaces, parts, and smoothing
00035 //               groups.
00036 ////////////////////////////////////////////////////////////////////
00037 void CLwoPolygons::
00038 add_ptags(const LwoPolygonTags *lwo_ptags, const LwoTags *tags) {
00039   if (_tags != (LwoTags *)NULL && _tags != tags) {
00040     nout << "Multiple Tags fields in effect on the same polygons.\n";
00041   }
00042   _tags = tags;
00043 
00044   IffId type = lwo_ptags->_tag_type;
00045 
00046   bool inserted = _ptags.insert(PTags::value_type(type, lwo_ptags)).second;
00047   if (!inserted) {
00048     nout << "Multiple polygon tags on the same polygons of type "
00049          << type << "\n";
00050 
00051   } else {
00052     if (type == IffId("SURF")) {
00053       _surf_ptags = lwo_ptags;
00054     }
00055   }
00056 }
00057 
00058 ////////////////////////////////////////////////////////////////////
00059 //     Function: CLwoPolygons::add_vmad
00060 //       Access: Public
00061 //  Description: Associates the indicated DiscontinousVertexMap with
00062 //               the polygons.  This can be used in conjunction with
00063 //               (or in place of) the VertexMap associated with the
00064 //               points set, to define per-polygon UV's etc.
00065 ////////////////////////////////////////////////////////////////////
00066 void CLwoPolygons::
00067 add_vmad(const LwoDiscontinuousVertexMap *lwo_vmad) {
00068   IffId map_type = lwo_vmad->_map_type;
00069   const string &name = lwo_vmad->_name;
00070 
00071   bool inserted;
00072   if (map_type == IffId("TXUV")) {
00073     inserted =
00074       _txuv.insert(VMad::value_type(name, lwo_vmad)).second;
00075 
00076   } else {
00077     return;
00078   }
00079 
00080   if (!inserted) {
00081     nout << "Multiple discontinous vertex maps on the same polygons of type "
00082          << map_type << " named " << name << "\n";
00083   }
00084 }
00085 
00086 ////////////////////////////////////////////////////////////////////
00087 //     Function: CLwoPolygons::get_surface
00088 //       Access: Public
00089 //  Description: Returns the surface associated with the given
00090 //               polygon, or NULL if no surface is associated.
00091 ////////////////////////////////////////////////////////////////////
00092 CLwoSurface *CLwoPolygons::
00093 get_surface(int polygon_index) const {
00094   if (_surf_ptags == (LwoPolygonTags *)NULL) {
00095     // No surface definitions.
00096     return (CLwoSurface *)NULL;
00097   }
00098 
00099   if (!_surf_ptags->has_tag(polygon_index)) {
00100     // The polygon isn't tagged.
00101     return (CLwoSurface *)NULL;
00102   }
00103 
00104   int tag_index = _surf_ptags->get_tag(polygon_index);
00105   if (_tags == (LwoTags *)NULL || tag_index < 0 ||
00106       tag_index >= _tags->get_num_tags()) {
00107     // The tag index is out-of-bounds.
00108     nout << "Invalid polygon tag index " << tag_index << "\n";
00109     return (CLwoSurface *)NULL;
00110   }
00111 
00112   string tag = _tags->get_tag(tag_index);
00113 
00114   // Now look up the surface name in the header.
00115   CLwoSurface *surface = _converter->get_surface(tag);
00116   if (surface == (CLwoSurface *)NULL) {
00117     nout << "Unknown surface " << tag << "\n";
00118     return (CLwoSurface *)NULL;
00119   }
00120 
00121   return surface;
00122 }
00123 
00124 ////////////////////////////////////////////////////////////////////
00125 //     Function: CLwoPolygons::get_uv
00126 //       Access: Public
00127 //  Description: Returns true if there is a UV of the indicated name
00128 //               associated with the given vertex of the indicated
00129 //               polygon, false otherwise.  If true, fills in uv with
00130 //               the value.
00131 //
00132 //               This performs a lookup in the optional
00133 //               "discontinuous" vertex mapping, which provides the
00134 //               ability to map different UV's per each polygon for
00135 //               the same vertex.  If the UV is not defined here, it
00136 //               may also be defined in the standard vertex map, which
00137 //               is associated with the points themselves.
00138 ////////////////////////////////////////////////////////////////////
00139 bool CLwoPolygons::
00140 get_uv(const string &uv_name, int pi, int vi, LPoint2 &uv) const {
00141   VMad::const_iterator ni = _txuv.find(uv_name);
00142   if (ni == _txuv.end()) {
00143     return false;
00144   }
00145 
00146   const LwoDiscontinuousVertexMap *vmad = (*ni).second;
00147   if (vmad->_dimension != 2) {
00148     nout << "Unexpected dimension of " << vmad->_dimension
00149          << " for discontinuous UV map " << uv_name << "\n";
00150     return false;
00151   }
00152 
00153   if (!vmad->has_value(pi, vi)) {
00154     return false;
00155   }
00156 
00157   PTA_stdfloat value = vmad->get_value(pi, vi);
00158 
00159   uv.set(value[0], value[1]);
00160   return true;
00161 }
00162 
00163 ////////////////////////////////////////////////////////////////////
00164 //     Function: CLwoPolygons::make_egg
00165 //       Access: Public
00166 //  Description: Creates the egg structures associated with this
00167 //               Lightwave object.
00168 ////////////////////////////////////////////////////////////////////
00169 void CLwoPolygons::
00170 make_egg() {
00171   // First, we need a temporary group to hold all of the polygons
00172   // we'll create.
00173   _egg_group = new EggGroup;
00174 
00175   if (_polygons->_polygon_type == IffId("CURV")) {
00176     nout << "Ignoring Catmull-Rom splines.\n";
00177 
00178   } else if (_polygons->_polygon_type == IffId("PTCH")) {
00179     nout << "Treating subdivision patches as ordinary polygons.\n";
00180     make_faces();
00181 
00182   } else if (_polygons->_polygon_type == IffId("MBAL")) {
00183     nout << "Ignoring metaballs.\n";
00184 
00185   } else if (_polygons->_polygon_type == IffId("BONE")) {
00186     nout << "Ignoring bones.\n";
00187 
00188   } else if (_polygons->_polygon_type == IffId("FACE")) {
00189     make_faces();
00190 
00191   } else {
00192     nout << "Ignoring unknown geometry type " << _polygons->_polygon_type
00193          << ".\n";
00194   }
00195 }
00196 
00197 ////////////////////////////////////////////////////////////////////
00198 //     Function: CLwoPolygons::connect_egg
00199 //       Access: Public
00200 //  Description: Connects all the egg structures together.
00201 ////////////////////////////////////////////////////////////////////
00202 void CLwoPolygons::
00203 connect_egg() {
00204   nassertv(_points->_layer->_egg_group != (EggGroup *)NULL);
00205   nassertv(_egg_group != (EggGroup *)NULL);
00206   _points->_layer->_egg_group->steal_children(*_egg_group);
00207 }
00208 
00209 
00210 ////////////////////////////////////////////////////////////////////
00211 //     Function: CLwoPolygons::make_faces
00212 //       Access: Public
00213 //  Description: Generates "face" polygons, i.e. actual polygons.
00214 ////////////////////////////////////////////////////////////////////
00215 void CLwoPolygons::
00216 make_faces() {
00217   PN_stdfloat smooth_angle = -1.0;
00218 
00219   int num_polygons = _polygons->get_num_polygons();
00220   for (int pindex = 0; pindex < num_polygons; pindex++) {
00221     LwoPolygons::Polygon *poly = _polygons->get_polygon(pindex);
00222     CLwoSurface *surface = get_surface(pindex);
00223 
00224     bool is_valid = true;
00225 
00226     // Set up the vertices.
00227     const LwoPoints *points = _points->_points;
00228     int num_points = points->get_num_points();
00229     EggVertexPool *egg_vpool = _points->_egg_vpool;
00230 
00231     // We reverse the vertex ordering to compensate for Lightwave's
00232     // clockwise ordering convention.  We also want to start with the
00233     // last vertex, so that the first convex angle is the first angle
00234     // in the EggPolygon (for determining correct normals).
00235     PT(EggPrimitive) egg_prim;
00236 
00237     if (poly->_vertices.size() == 1) {
00238       egg_prim = new EggPoint;
00239     } else {
00240       egg_prim = new EggPolygon;
00241     }
00242 
00243     // First, we have to create a temporary vector of vertices for the
00244     // polygon, so we can possibly adjust the properties of these
00245     // vertices (like the UV's) in the shader before we create them.
00246     vector_PT_EggVertex egg_vertices;
00247 
00248     int num_vertices = poly->_vertices.size();
00249     for (int vi = num_vertices; vi > 0; vi--) {
00250       int vindex = poly->_vertices[vi % num_vertices];
00251       if (vindex < 0 || vindex >= num_points) {
00252         nout << "Invalid vertex index " << vindex << " in polygon.\n";
00253         is_valid = false;
00254       } else {
00255         PT(EggVertex) egg_vertex = new EggVertex;
00256         LPoint3d pos = LCAST(double, points->get_point(vindex));
00257         egg_vertex->set_pos(pos);
00258 
00259         // Does the vertex used named UV's?
00260         if (surface != (CLwoSurface *)NULL && surface->has_named_uvs()) {
00261           string uv_name = surface->get_uv_name();
00262           LPoint2 uv;
00263           if (get_uv(uv_name, pindex, vindex, uv)) {
00264             // This UV is defined in a "discontinuous" map, that
00265             // associated a particular UV per each polygon.
00266             egg_vertex->set_uv(LCAST(double, uv));
00267 
00268           } else if (_points->get_uv(uv_name, vindex, uv)) {
00269             // The UV does not appear in a discontinuous map, but it
00270             // is defined in the points set.
00271             egg_vertex->set_uv(LCAST(double, uv));
00272           }
00273         }
00274 
00275         egg_vertices.push_back(egg_vertex);
00276       }
00277     }
00278 
00279     if (is_valid) {
00280       if (surface != (CLwoSurface *)NULL) {
00281         surface->apply_properties(egg_prim, egg_vertices, smooth_angle);
00282       }
00283 
00284       // Now add all the vertices officially to the primitive.
00285       vector_PT_EggVertex::const_iterator evi;
00286       for (evi = egg_vertices.begin(); evi != egg_vertices.end(); ++evi) {
00287         EggVertex *egg_vertex = (*evi);
00288         EggVertex *new_vertex = egg_vpool->create_unique_vertex(*egg_vertex);
00289         egg_prim->add_vertex(new_vertex);
00290       }
00291 
00292       // And add the primitive to its parent.
00293       _egg_group->add_child(egg_prim.p());
00294     }
00295   }
00296 
00297   CoordinateSystem cs = _converter->get_egg_data()->get_coordinate_system();
00298   if (smooth_angle > 0.0) {
00299     _egg_group->recompute_vertex_normals(rad_2_deg(smooth_angle), cs);
00300   } else {
00301     _egg_group->recompute_polygon_normals(cs);
00302   }
00303 }
00304 
 All Classes Functions Variables Enumerations