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

panda/src/builder/builderFuncs.I

Go to the documentation of this file.
00001 // Filename: builderFuncs.I
00002 // Created by:  drose (09Sep97)
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 "builderPrim.h"
00020 #include "mesherTempl.h"
00021 #include "builderNormalVisualizer.h"
00022 #include "config_builder.h"
00023 
00024 #include <geom.h>
00025 #include <geomprimitives.h>
00026 
00027 #include <algorithm>
00028 
00029 struct DecompVtx {
00030   int index;
00031   BuilderV coord;
00032   struct DecompVtx *next;
00033 };
00034 
00035 ////////////////////////////////////////////////////////////////////
00036 //     Function: decomp_concave
00037 //  Description: Decomposes a concave polygon into triangles.  Returns
00038 //               true if successful, false if the polygon is
00039 //               self-intersecting.
00040 ////////////////////////////////////////////////////////////////////
00041 template <class PrimType, class OutputIterator>
00042 static bool
00043 decomp_concave(const PrimType &prim, BuilderBucket &bucket,
00044                OutputIterator result,
00045                int asum, int x, int y) {
00046 #define VX(p, c)    p->coord[c]
00047 
00048   pvector<PrimType> output_prims;
00049 
00050   DecompVtx *p0, *p1, *p2, *t0, *vert;
00051   DecompVtx *m[3];
00052   float xmin, xmax, ymin, ymax;
00053   int i, init, csum, chek;
00054   float a[3], b[3], c[3], s[3];
00055 
00056   int num_verts = prim.get_num_verts();
00057   nassertr(num_verts >= 3, false);
00058 
00059   /* Make linked list of verts */
00060   vert = (DecompVtx *) alloca(sizeof(DecompVtx));
00061   vert->index = 0;
00062   vert->coord = prim.get_vertex(0).get_coord_value(bucket);
00063   p1 = vert;
00064 
00065   for (i = 1; i < num_verts; i++) {
00066     p0 = (DecompVtx *) alloca(sizeof(DecompVtx));
00067     p0->index = i;
00068     p0->coord = prim.get_vertex(i).get_coord_value(bucket);
00069     // There shouldn't be two consecutive identical vertices.  If
00070     // there are, skip one.
00071     if (!(p0->coord == p1->coord)) {
00072       p1->next = p0;
00073       p1 = p0;
00074     }
00075   }
00076   p1->next = vert;
00077 
00078   p0 = vert;
00079   p1 = p0->next;
00080   p2 = p1->next;
00081   m[0] = p0;
00082   m[1] = p1;
00083   m[2] = p2;
00084   chek = 0;
00085 
00086   while (p0 != p2->next) {
00087     /* Polygon is self-intersecting so punt */
00088     if (chek &&
00089         m[0] == p0 &&
00090         m[1] == p1 &&
00091         m[2] == p2) {
00092 
00093       //      builder_cat.info() << "Could not decompose concave polygon!";
00094       return false;
00095     }
00096 
00097     chek = 1;
00098 
00099     a[0] = VX(p1, y) - VX(p2, y);
00100     b[0] = VX(p2, x) - VX(p1, x);
00101     a[2] = VX(p0, y) - VX(p1, y);
00102     b[2] = VX(p1, x) - VX(p0, x);
00103 
00104     csum = ((b[0] * a[2] - b[2] * a[0] >= 0.0) ? 1 : 0);
00105 
00106     if (csum ^ asum) {
00107       /* current angle is concave */
00108       p0 = p1;
00109       p1 = p2;
00110       p2 = p2->next;
00111 
00112     } else {
00113       /* current angle is convex */
00114       xmin = (VX(p0, x) < VX(p1, x)) ? VX(p0, x) : VX(p1, x);
00115       if (xmin > VX(p2, x))
00116         xmin = VX(p2, x);
00117 
00118       xmax = (VX(p0, x) > VX(p1, x)) ? VX(p0, x) : VX(p1, x);
00119       if (xmax < VX(p2, x))
00120         xmax = VX(p2, x);
00121 
00122       ymin = (VX(p0, y) < VX(p1, y)) ? VX(p0, y) : VX(p1, y);
00123       if (ymin > VX(p2, y))
00124         ymin = VX(p2, y);
00125 
00126       ymax = (VX(p0, y) > VX(p1, y)) ? VX(p0, y) : VX(p1, y);
00127       if (ymax < VX(p2, y))
00128         ymax = VX(p2, y);
00129 
00130       for (init = 1, t0 = p2->next; t0 != p0; t0 = t0->next) {
00131         if (VX(t0, x) >= xmin && VX(t0, x) <= xmax &&
00132             VX(t0, y) >= ymin && VX(t0, y) <= ymax) {
00133           if (init) {
00134             a[1] = VX(p2, y) - VX(p0, y);
00135             b[1] = VX(p0, x) - VX(p2, x);
00136             init = 0;
00137             c[0] = VX(p1, x) * VX(p2, y) - VX(p2, x) * VX(p1, y);
00138             c[1] = VX(p2, x) * VX(p0, y) - VX(p0, x) * VX(p2, y);
00139             c[2] = VX(p0, x) * VX(p1, y) - VX(p1, x) * VX(p0, y);
00140           }
00141 
00142           s[0] = a[0] * VX(t0, x) + b[0] * VX(t0, y) + c[0];
00143           s[1] = a[1] * VX(t0, x) + b[1] * VX(t0, y) + c[1];
00144           s[2] = a[2] * VX(t0, x) + b[2] * VX(t0, y) + c[2];
00145 
00146           if (asum) {
00147             if (s[0] >= 0.0 && s[1] >= 0.0 && s[2] >= 0.0)
00148               break;
00149           } else {
00150             if (s[0] <= 0.0 && s[1] <= 0.0 && s[2] <= 0.0)
00151               break;
00152           }
00153         }
00154       }
00155 
00156       if (t0 != p0) {
00157         p0 = p1;
00158         p1 = p2;
00159         p2 = p2->next;
00160       } else {
00161         PrimType new_prim(prim);
00162         new_prim.set_type(BPT_tri);
00163         new_prim.clear_vertices();
00164         new_prim.add_vertex(prim.get_vertex(p0->index));
00165         new_prim.add_vertex(prim.get_vertex(p1->index));
00166         new_prim.add_vertex(prim.get_vertex(p2->index));
00167         output_prims.push_back(new_prim);
00168 
00169         p0->next = p1->next;
00170         p1 = p2;
00171         p2 = p2->next;
00172 
00173         m[0] = p0;
00174         m[1] = p1;
00175         m[2] = p2;
00176         chek = 0;
00177       }
00178     }
00179   }
00180 
00181   PrimType new_prim(prim);
00182   new_prim.set_type(BPT_tri);
00183   new_prim.clear_vertices();
00184   new_prim.add_vertex(prim.get_vertex(p0->index));
00185   new_prim.add_vertex(prim.get_vertex(p1->index));
00186   new_prim.add_vertex(prim.get_vertex(p2->index));
00187   output_prims.push_back(new_prim);
00188 
00189   copy(output_prims.begin(), output_prims.end(), result);
00190   return true;
00191 }
00192 
00193 
00194 ////////////////////////////////////////////////////////////////////
00195 //     Function: triangulate_poly
00196 //  Description: Breaks a (possibly concave) higher-order polygon into
00197 //               a series of constituent triangles.
00198 ////////////////////////////////////////////////////////////////////
00199 template <class PrimType, class OutputIterator>
00200 static bool
00201 triangulate_poly(const PrimType &prim, BuilderBucket &bucket,
00202                  OutputIterator result) {
00203   BuilderV p0, p1, as;
00204   float dx1, dy1, dx2, dy2, max;
00205   int i, flag, asum, csum, index, x, y, v0, v1, v, even;
00206 
00207   // First see if the polygon is just a triangle
00208   int num_verts = prim.get_num_verts();
00209   if (num_verts == 3) {
00210     PrimType new_prim(prim);
00211     new_prim.set_type(BPT_tri);
00212     *result++ = new_prim;
00213 
00214     return true;
00215 
00216   } else if (num_verts < 3) {
00217     // Or if it's a degenerate polygon.
00218     return false;
00219   }
00220 
00221   // calculate signed areas
00222   as[0] = 0.0;
00223   as[1] = 0.0;
00224   as[2] = 0.0;
00225 
00226   for (i = 0; i < num_verts; i++) {
00227     p0 = prim.get_vertex(i).get_coord_value(bucket);
00228     p1 = prim.get_vertex((i + 1) % num_verts).get_coord_value(bucket);
00229     as[0] += p0[0] * p1[1] - p0[1] * p1[0];
00230     as[1] += p0[0] * p1[2] - p0[2] * p1[0];
00231     as[2] += p0[1] * p1[2] - p0[2] * p1[1];
00232   }
00233 
00234   /* select largest signed area */
00235   max = 0.0;
00236   index = 0;
00237   flag = 0;
00238   for (i = 0; i < 3; i++) {
00239     if (as[i] >= 0.0) {
00240       if (as[i] > max) {
00241         max = as[i];
00242         index = i;
00243         flag = 1;
00244       }
00245     } else {
00246       as[i] = -as[i];
00247       if (as[i] > max) {
00248         max = as[i];
00249         index = i;
00250         flag = 0;
00251       }
00252     }
00253   }
00254 
00255   /* pointer offsets */
00256   switch (index) {
00257   case 0:
00258     x = 0;
00259     y = 1;
00260     break;
00261 
00262   case 1:
00263     x = 0;
00264     y = 2;
00265     break;
00266 
00267   default: // case 2
00268     x = 1;
00269     y = 2;
00270     break;
00271   }
00272 
00273   /* concave check */
00274   p0 = prim.get_vertex(0).get_coord_value(bucket);
00275   p1 = prim.get_vertex(1).get_coord_value(bucket);
00276   dx1 = p1[x] - p0[x];
00277   dy1 = p1[y] - p0[y];
00278   p0 = p1;
00279   p1 = prim.get_vertex(2).get_coord_value(bucket);
00280 
00281   dx2 = p1[x] - p0[x];
00282   dy2 = p1[y] - p0[y];
00283   asum = ((dx1 * dy2 - dx2 * dy1 >= 0.0) ? 1 : 0);
00284 
00285   for (i = 0; i < num_verts - 1; i++) {
00286     p0 = p1;
00287     p1 = prim.get_vertex((i+3) % num_verts).get_coord_value(bucket);
00288 
00289     dx1 = dx2;
00290     dy1 = dy2;
00291     dx2 = p1[x] - p0[x];
00292     dy2 = p1[y] - p0[y];
00293     csum = ((dx1 * dy2 - dx2 * dy1 >= 0.0) ? 1 : 0);
00294 
00295     if (csum ^ asum) {
00296       return decomp_concave(prim, bucket, result, flag, x, y);
00297     }
00298   }
00299 
00300   v0 = 0;
00301   v1 = 1;
00302   v = num_verts - 1;
00303 
00304   even = 1;
00305 
00306   /*
00307    * Convert to triangles only. Do not fan out from a single vertex
00308    * but zigzag into triangle strip.
00309    */
00310   for (i = 0; i < num_verts - 2; i++) {
00311     if (even) {
00312       PrimType new_prim(prim);
00313       new_prim.set_type(BPT_tri);
00314       new_prim.clear_vertices();
00315       new_prim.add_vertex(prim.get_vertex(v0));
00316       new_prim.add_vertex(prim.get_vertex(v1));
00317       new_prim.add_vertex(prim.get_vertex(v));
00318       *result++ = new_prim;
00319       v0 = v1;
00320       v1 = v;
00321       v = v0 + 1;
00322     } else {
00323       PrimType new_prim(prim);
00324       new_prim.set_type(BPT_tri);
00325       new_prim.clear_vertices();
00326       new_prim.add_vertex(prim.get_vertex(v1));
00327       new_prim.add_vertex(prim.get_vertex(v0));
00328       new_prim.add_vertex(prim.get_vertex(v));
00329       *result++ = new_prim;
00330       v0 = v1;
00331       v1 = v;
00332       v = v0 - 1;
00333     }
00334 
00335     even = !even;
00336   }
00337 
00338   return true;
00339 }
00340 
00341 
00342 ////////////////////////////////////////////////////////////////////
00343 //     Function: expand_polys
00344 //  Description: Identifies a single polygon as a triangle, quad, or
00345 //               higher-order polygon, and writes it into the result
00346 //               list.
00347 ////////////////////////////////////////////////////////////////////
00348 template <class PrimType, class OutputIterator>
00349 static bool
00350 expand_polys(PrimType &prim, BuilderBucket &,
00351              OutputIterator result) {
00352   switch (prim.get_num_verts()) {
00353   case 0:
00354   case 1:
00355   case 2:
00356     return false;
00357 
00358   case 3:
00359     prim.set_type(BPT_tri);
00360     break;
00361 
00362   case 4:
00363     prim.set_type(BPT_quad);
00364     break;
00365 
00366   default:
00367     prim.set_type(BPT_poly);
00368   }
00369 
00370   *result++ = prim;
00371   return true;
00372 }
00373 
00374 
00375 ////////////////////////////////////////////////////////////////////
00376 //     Function: expand_points
00377 //  Description: Expands a light points primitive into its individual
00378 //               component points, with one point per primitive.
00379 ////////////////////////////////////////////////////////////////////
00380 template <class PrimType, class OutputIterator>
00381 static bool
00382 expand_points(const PrimType &prim, BuilderBucket &,
00383               OutputIterator result) {
00384   // Each vertex goes in its own primitive.
00385 
00386   int num_verts = prim.get_num_verts();
00387   for (int i = 0; i < num_verts; i++) {
00388     PrimType new_prim(prim);
00389     new_prim.clear_vertices();
00390     new_prim.add_vertex(prim.get_vertex(i));
00391     *result++ = new_prim;
00392   }
00393   return true;
00394 }
00395 
00396 
00397 ////////////////////////////////////////////////////////////////////
00398 //     Function: expand_lines
00399 //  Description: Expands a linestrip primitive into its component line
00400 //               primitives.
00401 ////////////////////////////////////////////////////////////////////
00402 template <class PrimType, class OutputIterator>
00403 static bool
00404 expand_lines(const PrimType &prim, BuilderBucket &,
00405              OutputIterator result) {
00406   // Each line segment goes in its own primitive.  This breaks up the
00407   // linestrips already defined; we'll re-strip them later if the
00408   // generate-tstrips flag is enabled.
00409 
00410   int num_verts = prim.get_num_verts();
00411   for (int i = 1; i < num_verts; i++) {
00412     PrimType new_prim(prim);
00413     new_prim.clear_vertices();
00414     new_prim.add_vertex(prim.get_vertex(i-1));
00415     new_prim.add_vertex(prim.get_vertex(i));
00416     *result++ = new_prim;
00417   }
00418   return true;
00419 }
00420 
00421 
00422 
00423 ////////////////////////////////////////////////////////////////////
00424 //     Function: expand
00425 //  Description: Receives a single primitive as a BuilderPrim or
00426 //               BuilderPrimI object, as input by the user.  Does some
00427 //               initial processing on the primitive to verify
00428 //               internal consistency (for instance, that a quad has
00429 //               four vertices), and returns a new BuilderPrim or
00430 //               series of BuilderPrim objects, suitable for building
00431 //               with.
00432 //
00433 //               More than one primitive might be returned because
00434 //               higher-order polygons may be broken up into
00435 //               triangles, and linestrips and points are broken into
00436 //               their component pieces.  The output primitives are
00437 //               written into the STL container defined by result.
00438 ////////////////////////////////////////////////////////////////////
00439 template <class PrimType, class OutputIterator>
00440 bool
00441 expand(const PrimType &prim, BuilderBucket &bucket, OutputIterator result) {
00442   // Make a copy of the prim so we can fiddle with it.
00443   PrimType new_prim = prim;
00444 
00445   switch (new_prim.get_type()) {
00446   case BPT_poly:
00447   case BPT_tri:
00448   case BPT_quad:
00449     // These three types are all treated the same, as polygons.  We
00450     // don't entirely trust the user to match the polygon type with
00451     // the number of verts, so we'll do it ourselves later.
00452     new_prim.remove_doubled_verts(true);
00453 
00454     if (!bucket._subdivide_polys ||
00455         (bucket._mesh && new_prim.get_num_verts() <= 4)) {
00456       // If we're meshing, we'd like to send quads through without
00457       // subdividing.  The mesher can take advantage of the extra
00458       // information (and will eventually produce tris anyway).
00459       return expand_polys(new_prim, bucket, result);
00460     } else {
00461       // If we're not meshing, we'll break them into tris now.
00462       return triangulate_poly(new_prim, bucket, result);
00463     }
00464 
00465   case BPT_point:
00466     new_prim.remove_doubled_verts(false);
00467     return expand_points(new_prim, bucket, result);
00468 
00469   case BPT_line:
00470     new_prim.remove_doubled_verts(false);
00471     return expand_lines(new_prim, bucket, result);
00472 
00473   default:
00474     builder_cat.error() << "Unknown prim type\n";
00475     return false;
00476   }
00477 }
00478 
00479 
00480 ////////////////////////////////////////////////////////////////////
00481 //     Function: build_geoms
00482 //  Description: Accepts a list of BuilderPrim or BuilderPrimI
00483 //               objects, defined by the iterators first and last, and
00484 //               creates corresponding geometry for them in the
00485 //               indicated GeomNode.
00486 ////////////////////////////////////////////////////////////////////
00487 template<class InputIterator, class PrimType>
00488 static int
00489 build_geoms(InputIterator first, InputIterator last,
00490             BuilderBucket &bucket, GeomNode *geom_node,
00491             PrimType *) {
00492   if (first==last) {
00493     return 0;
00494   }
00495 
00496   // By the time we get here, we have a list of primitives that all have
00497   // the same properties:
00498 
00499   // 1. The BuilderBucket.
00500   // 2. The indexed/nonindexed type.
00501   // 3. The primitive type (polygon, line, point).
00502   // 4. The pixel size.
00503 
00504   // The binding of normals, colors, or texcoords: per-vertex,
00505   // per-prim, or per-component, will generally be the same across all
00506   // primitives, but it might not always be the same, because in
00507   // certain special cases the mesher might have changed these
00508   // properties when it built tristrips.
00509 
00510   typedef TYPENAME PrimType::VType VType;
00511   typedef TYPENAME PrimType::NType NType;
00512   typedef TYPENAME PrimType::TType TType;
00513   typedef TYPENAME PrimType::CType CType;
00514 
00515   // We need to determine the common binding type for all primitives.
00516   // For a given attribute, say normals, there are at most five cases,
00517   // in the order of priority:
00518   //
00519   //  1. If at least one primitive in the list does not have normals,
00520   //     the binding will be G_OFF.
00521   //
00522   //  2. If at least one primitive has per-vertex normals, the binding
00523   //     will be G_PER_VERTEX.
00524   //
00525   //  3. If at least one primitive has per-component normals, the
00526   //     binding will be G_PER_COMPONENT.
00527   //
00528   //  4. If none of the first three apply, it follows that all
00529   //     primitives have an overall normal.  If any primitive's
00530   //     overall normal differs from any other, the binding will be
00531   //     G_PER_PRIM.
00532   //
00533   //  5. If none of the above apply, the binding will be G_OVERALL.
00534   //
00535   // An exception to the above is for texcoords, which is either G_OFF
00536   // (by rule 1) or G_PER_VERTEX.
00537 
00538   GeomBindType bind_normals = G_OVERALL;
00539   GeomBindType bind_colors = G_OVERALL;
00540   GeomBindType bind_texcoords = G_PER_VERTEX;
00541 
00542   NType overall_normal(0);
00543   CType overall_color(0);
00544   bool first_normal = true;
00545   bool first_color = true;
00546 
00547   InputIterator i;
00548   for (i = first; i != last; ++i) {
00549 
00550     // Normals.
00551 
00552     // Test rule 1.
00553     if (!(*i).has_any_normal()) {
00554       bind_normals = G_OFF;
00555     } else if (bind_normals != G_OFF) {
00556       // Test rule 2.
00557       if ((*i).has_vertex_normal()) {
00558         bind_normals = G_PER_VERTEX;
00559       } else if (bind_normals != G_PER_VERTEX) {
00560         // Test rule 3.
00561         if ((*i).has_component_normal()) {
00562           bind_normals = G_PER_COMPONENT;
00563         } else if (bind_normals != G_PER_COMPONENT) {
00564           // Test rule 4.
00565           nassertr((*i).has_overall_normal(), 0);
00566           if (first_normal) {
00567             overall_normal = (*i).get_normal();
00568             first_normal = false;
00569           } else if ( !((*i).get_normal() == overall_normal)) {
00570             bind_normals = G_PER_PRIM;
00571           }
00572         }
00573       }
00574     }
00575 
00576     // Colors.
00577 
00578     // Test rule 1.
00579     if (!(*i).has_any_color()) {
00580       bind_colors = G_OFF;
00581     } else if (bind_colors != G_OFF) {
00582       // Test rule 2.
00583       if ((*i).has_vertex_color()) {
00584         bind_colors = G_PER_VERTEX;
00585       } else if (bind_colors != G_PER_VERTEX) {
00586         // Test rule 3.
00587         if ((*i).has_component_color()) {
00588           bind_colors = G_PER_COMPONENT;
00589         } else if (bind_colors != G_PER_COMPONENT) {
00590           // Test rule 4.
00591           nassertr((*i).has_overall_color(), 0);
00592           if (first_color) {
00593             overall_color = (*i).get_color();
00594             first_color = false;
00595           } else if ( !((*i).get_color() == overall_color)) {
00596             bind_colors = G_PER_PRIM;
00597           }
00598         }
00599       }
00600     }
00601 
00602     // Texcoords.
00603 
00604     // Test rule 1.
00605     if (!(*i).has_any_texcoord()) {
00606       bind_texcoords = G_OFF;
00607     }
00608   }
00609 
00610   // Determine the primitive type and build the lengths array, if needed.
00611   PTA_int lengths;
00612   bool want_lengths = false;
00613   int j;
00614 
00615   Geom *geom = NULL;
00616   BuilderPrimType type = (*first).get_type();
00617   switch (type) {
00618   case BPT_poly:
00619     geom = new GeomPolygon;
00620     want_lengths = true;
00621     break;
00622 
00623   case BPT_tristrip:
00624     geom = new GeomTristrip;
00625     want_lengths = true;
00626     break;
00627 
00628   case BPT_trifan:
00629     geom = new GeomTrifan;
00630     want_lengths = true;
00631     break;
00632 
00633   case BPT_line:
00634     geom = new GeomLine;
00635     break;
00636 
00637   case BPT_point:
00638     geom = new GeomPoint;
00639     break;
00640 
00641   case BPT_tri:
00642     geom = new GeomTri;
00643     break;
00644 
00645   case BPT_quad:
00646     geom = new GeomQuad;
00647     break;
00648 
00649   default:
00650     builder_cat.fatal() << "Invalid primitive type.\n";
00651     abort();
00652   }
00653 
00654   if (geom == NULL) {
00655     builder_cat.error() << "Unsupported primitive type " << type << "\n";
00656     return 0;
00657   }
00658 
00659   // Count up the number of prims we're actually building.
00660   int num_prims = 0;
00661   for (i = first; i != last; ++i) {
00662     if ((*i).is_valid()) {
00663       num_prims++;
00664     }
00665   }
00666 
00667   if (num_prims==0) {
00668     builder_cat.error() << "All primitives were invalid!\n";
00669     return 0;
00670   }
00671 
00672   if (want_lengths) {
00673     lengths = PTA_int::empty_array(num_prims);
00674     j = 0;
00675     for (i = first; i != last; ++i) {
00676       if ((*i).is_valid()) {
00677         lengths[j++] = (*i).get_num_verts();
00678       }
00679     }
00680     nassertr(j == num_prims, 0);
00681   }
00682 
00683   // Now build up some arrays.
00684   PTA(VType) coords=PTA(VType)::empty_array(0);
00685   PTA(NType) normals=PTA(NType)::empty_array(0);
00686   PTA(TType) texcoords=PTA(TType)::empty_array(0);
00687   PTA(CType) colors=PTA(CType)::empty_array(0);
00688 
00689   int total_verts = 0;
00690   int total_components = 0;
00691 
00692   int v, num_verts;
00693   int c, num_components;
00694   for (i = first; i != last; ++i) {
00695     if ((*i).is_valid()) {
00696       num_verts = (*i).get_num_verts();
00697       total_verts += num_verts;
00698       for (v = 0; v < num_verts; v++) {
00699         coords.push_back((*i).get_vertex(v).get_coord());
00700 
00701         if (bind_normals == G_PER_VERTEX) {
00702           normals.push_back((*i).get_vertex(v).get_normal());
00703         }
00704         if (bind_texcoords == G_PER_VERTEX) {
00705           texcoords.push_back((*i).get_vertex(v).get_texcoord());
00706         }
00707         if (bind_colors == G_PER_VERTEX) {
00708           colors.push_back((*i).get_vertex(v).get_color());
00709         }
00710       }
00711 
00712       num_components = (*i).get_num_components();
00713       total_components += num_components;
00714       for (c = 0; c < num_components; c++) {
00715         if (bind_normals == G_PER_COMPONENT) {
00716           normals.push_back((*i).get_component(c).get_normal());
00717         }
00718         if (bind_colors == G_PER_COMPONENT) {
00719           colors.push_back((*i).get_component(c).get_color());
00720         }
00721       }
00722 
00723       if (bind_normals == G_PER_PRIM) {
00724         normals.push_back((*i).get_normal());
00725       }
00726       if (bind_colors == G_PER_PRIM) {
00727         colors.push_back((*i).get_color());
00728       }
00729     }
00730   }
00731 
00732   if (bind_normals == G_OVERALL) {
00733     normals.push_back(overall_normal);
00734   }
00735   if (bind_colors == G_OVERALL) {
00736     colors.push_back(overall_color);
00737   }
00738 
00739   // Now add all the stuff to our Geom.
00740 
00741   geom->set_num_prims(num_prims);
00742 
00743   if (lengths != (int *)NULL) {
00744     geom->set_lengths(lengths);
00745   }
00746 
00747   PrimType::fill_geom(geom, coords,
00748                       bind_normals, normals,
00749                       bind_texcoords, texcoords,
00750                       bind_colors, colors,
00751                       bucket, num_prims,
00752                       total_components, total_verts);
00753 
00754     /*
00755   if ((*first).has_pixel_size()) {
00756     // Again, we only have to test the first one in the list for a
00757     // pixel_size attribute.  If this one has it, then they all have
00758     // the same value.
00759     geom->setPntSize((*first).get_pixel_size());
00760     geom->setLineWidth((*first).get_pixel_size());
00761   }
00762     */
00763 
00764   //  geom->setDrawBin(bucket._drawBin);
00765   //  geom->setDrawOrder(bucket._drawOrder);
00766 
00767   Geom *new_geom = bucket.done_geom(geom);
00768   if (new_geom != (Geom *)NULL) {
00769     geom_node->add_geom(new_geom, bucket._state);
00770   }
00771 
00772   return 1;
00773 }
00774 
00775 
00776 /////////////////////////////////////////////////////////////////////
00777 //       Class : PrimByType
00778 // Description : An STL function object to sort primitives in order by
00779 //               type.
00780 ////////////////////////////////////////////////////////////////////
00781 template<class PrimType>
00782 class PrimByType {
00783 public:
00784   int operator () (const PrimType &p1, const PrimType &p2) const {
00785     return p1.get_type() < p2.get_type();
00786   }
00787 };
00788 
00789 
00790 ////////////////////////////////////////////////////////////////////
00791 //     Function: __mesh_and_build
00792 //  Description: The implementation of mesh_and_build(), below.  This
00793 //               extra function call is just to allow mesh_and_build()
00794 //               to infer the PrimType (BuilderPrim or BuilderPrimI)
00795 //               from the iterator's value type, and template on that.
00796 ////////////////////////////////////////////////////////////////////
00797 template<class InputIterator, class PrimType>
00798 static int
00799 __mesh_and_build(InputIterator first, InputIterator last,
00800                  BuilderBucket &bucket, GeomNode *geom_node,
00801                  PrimType *) {
00802   if (first==last) {
00803     return 0;
00804   }
00805 
00806   typedef pvector<PrimType> Prims;
00807   Prims prims;
00808   BuilderBucket *local_bucket = NULL;
00809   BuilderBucket *bucket_ptr = &bucket;
00810 
00811   if (bucket._mesh) {
00812     // Send all the prims through the mesher.  First, make a copy of
00813     // the bucket so the mesher can modify it if it wants.
00814     local_bucket = bucket.make_copy();
00815     bucket_ptr = local_bucket;
00816     MesherTempl<PrimType> mesher(local_bucket);
00817 
00818     for (InputIterator ii = first; ii != last; ++ii) {
00819       mesher.add_prim(*ii);
00820     }
00821     mesher.mesh();
00822     PrimType prim;
00823     prim = mesher.getPrim();
00824     while (prim.get_num_verts() > 0) {
00825       prims.push_back(prim);
00826       prim = mesher.getPrim();
00827     }
00828 
00829   } else {
00830     // Send the prims through without meshing.
00831     copy(first, last, back_inserter(prims));
00832   }
00833 
00834   // Now we have an array of prims which all share the same
00835   // properties, except possibly type.  Sort them by type and send
00836   // them to build_geoms.
00837   sort(prims.begin(), prims.end(), PrimByType<PrimType>());
00838 
00839   int count = 0;
00840   if (!prims.empty()) {
00841     TYPENAME Prims::iterator pi, last_pi;
00842     pi = prims.begin();
00843     last_pi = pi;
00844     for (++pi; pi != prims.end(); ++pi) {
00845       if ((*pi).get_type() != (*last_pi).get_type()) {
00846         count += build_geoms(last_pi, pi, *bucket_ptr, geom_node, (PrimType*)0);
00847         last_pi = pi;
00848       }
00849     }
00850     count += build_geoms(last_pi, pi, *bucket_ptr, geom_node, (PrimType*)0);
00851   }
00852 
00853   if (local_bucket!=NULL) {
00854     delete local_bucket;
00855   }
00856 
00857   // Finally, if the user so requested, create some visualization for
00858   // the normals.
00859 #ifdef SUPPORT_SHOW_NORMALS
00860   if (bucket._show_normals) {
00861     BuilderNormalVisualizer bnv(bucket);
00862     for (InputIterator ii = first; ii != last; ++ii) {
00863       bnv.add_prim(*ii);
00864     }
00865     bnv.show_normals(geom_node);
00866   }
00867 #endif
00868 
00869   return count;
00870 }
00871 
00872 
00873 ////////////////////////////////////////////////////////////////////
00874 //     Function: mesh_and_build
00875 //  Description: Accepts a list of BuilderPrim or BuilderPrimI
00876 //               objects, defined by the iterators first and list,
00877 //               runs them through the mesher if specified by the
00878 //               bucket, and builds them into the indicated GeomNode.
00879 ////////////////////////////////////////////////////////////////////
00880 template<class InputIterator, class value_type>
00881 int
00882 mesh_and_build(InputIterator first, InputIterator last,
00883                BuilderBucket &bucket, GeomNode *geom_node,
00884                value_type *value_type_ptr) {
00885   return __mesh_and_build(first, last, bucket, geom_node, value_type_ptr);
00886 }
00887 
00888 
00889 ////////////////////////////////////////////////////////////////////
00890 //     Function: split
00891 //  Description: Splits an STL list into two other lists, according to
00892 //               the return value from pred.
00893 ////////////////////////////////////////////////////////////////////
00894 template <class InputIterator, class OutputIterator, class Predicate>
00895 OutputIterator split(InputIterator first, InputIterator last,
00896                      OutputIterator true_result, OutputIterator false_result,
00897                      Predicate pred) {
00898   while (first != last) {
00899     if (pred(*first)) {
00900       *true_result++ = *first++;
00901     } else {
00902       *false_result++ = *first++;
00903     }
00904   }
00905   return true_result;
00906 }
00907 

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