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

panda/src/grutil/lineSegs.cxx

Go to the documentation of this file.
00001 // Filename: lineSegs.cxx
00002 // Created by:  drose (16Mar02)
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 "lineSegs.h"
00020 
00021 ////////////////////////////////////////////////////////////////////
00022 //     Function: LineSegs::Constructor
00023 //       Access: Public
00024 //  Description: Constructs a LineSegs object, which can be used to
00025 //               create any number of disconnected lines or points of
00026 //               various thicknesses and colors through the visible
00027 //               scene.  After creating the object, call move_to() and
00028 //               draw_to() repeatedly to describe the path, then call
00029 //               create() to create a GeomNode which will render the
00030 //               described path.
00031 ////////////////////////////////////////////////////////////////////
00032 LineSegs::
00033 LineSegs(const string &name) : Namable(name) {
00034   _color.set(1.0f, 1.0f, 1.0f, 1.0f);
00035   _thick = 1.0f;
00036 }
00037 
00038 
00039 ////////////////////////////////////////////////////////////////////
00040 //     Function: LineSegs::Destructor
00041 //       Access: Public
00042 ////////////////////////////////////////////////////////////////////
00043 LineSegs::
00044 ~LineSegs() {
00045 }
00046 
00047 
00048 ////////////////////////////////////////////////////////////////////
00049 //     Function: LineSegs::reset
00050 //       Access: Public
00051 //  Description: Removes any lines in progress and resets to the
00052 //               initial empty state.
00053 ////////////////////////////////////////////////////////////////////
00054 void LineSegs::
00055 reset() {
00056   _list.clear();
00057 }
00058 
00059 
00060 ////////////////////////////////////////////////////////////////////
00061 //     Function: LineSegs::move_to
00062 //       Access: Public
00063 //  Description: Moves the pen to the given point without drawing a
00064 //               line.  When followed by draw_to(), this marks the
00065 //               first point of a line segment; when followed by
00066 //               move_to() or create(), this creates a single point.
00067 ////////////////////////////////////////////////////////////////////
00068 void LineSegs::
00069 move_to(const LVecBase3f &v) {
00070   // We create a new SegmentList with the initial point in it.
00071   SegmentList segs;
00072   segs.push_back(Point(v, _color));
00073 
00074   // And add this list to the list of segments.
00075   _list.push_back(segs);
00076 }
00077 
00078 ////////////////////////////////////////////////////////////////////
00079 //     Function: LineSegs::draw_to
00080 //       Access: Public
00081 //  Description: Draws a line segment from the pen's last position
00082 //               (the last call to move_to or draw_to) to the
00083 //               indicated point.  move_to() and draw_to() only update
00084 //               tables; the actual drawing is performed when create()
00085 //               is called.
00086 ////////////////////////////////////////////////////////////////////
00087 void LineSegs::
00088 draw_to(const LVecBase3f &v) {
00089   if (_list.empty()) {
00090     // Let our first call to draw_to() be an implicit move_to().
00091     move_to(v);
00092 
00093   } else {
00094     // Get the current SegmentList, which was the last one we added to
00095     // the LineList.
00096     SegmentList &segs = _list.back();
00097 
00098     // Add the new point.
00099     segs.push_back(Point(v, _color));
00100   }
00101 }
00102 
00103 ////////////////////////////////////////////////////////////////////
00104 //     Function: LineSegs::empty
00105 //       Access: Public
00106 //  Description: Returns true if move_to() or draw_to() have not been
00107 //               called since the last reset() or create(), false
00108 //               otherwise.
00109 ////////////////////////////////////////////////////////////////////
00110 bool LineSegs::
00111 is_empty() {
00112   return _list.empty();
00113 }
00114 
00115 ////////////////////////////////////////////////////////////////////
00116 //     Function: LineSegs::get_current_position
00117 //       Access: Public
00118 //  Description: Returns the pen's current position.  The next call to
00119 //               draw_to() will draw a line segment from this point.
00120 ////////////////////////////////////////////////////////////////////
00121 const Vertexf &LineSegs::
00122 get_current_position() {
00123   if (_list.empty()) {
00124     // Our pen isn't anywhere.  We'll put it somewhere.
00125     move_to(Vertexf(0.0f, 0.0f, 0.0f));
00126   }
00127 
00128   return _list.back().back()._point;
00129 }
00130 
00131 ////////////////////////////////////////////////////////////////////
00132 //     Function: LineSegs::create
00133 //       Access: Public
00134 //  Description: Appends to an existing GeomNode a new Geom that
00135 //               will render the series of line segments and points
00136 //               described via calls to move_to() and draw_to().  The
00137 //               lines and points are created with the color and
00138 //               thickness established by calls to set_color() and
00139 //               set_thick().
00140 //
00141 //               If frame_accurate is true, the line segments will be
00142 //               created as a frame-accurate index, so that later
00143 //               calls to set_vertex or set_vertex_color will be
00144 //               visually correct.
00145 ////////////////////////////////////////////////////////////////////
00146 GeomNode *LineSegs::
00147 create(GeomNode *previous, bool) {
00148   if (!_list.empty()) {
00149     _created_verts.clear();
00150     _created_colors.clear();
00151 
00152     // One array each for the indices into these arrays for points
00153     // and lines, and one for our line-segment lengths array.
00154     PTA_ushort point_index;
00155     PTA_ushort line_index;
00156     PTA_int lengths;
00157 
00158     // Now fill up the arrays.
00159     int v = 0;
00160     LineList::const_iterator ll;
00161     SegmentList::const_iterator sl;
00162 
00163     for (ll = _list.begin(); ll != _list.end(); ll++) {
00164       const SegmentList &segs = (*ll);
00165 
00166       if (segs.size() < 2) {
00167         point_index.push_back(v);
00168       } else {
00169         lengths.push_back(segs.size());
00170       }
00171 
00172       for (sl = segs.begin(); sl != segs.end(); sl++) {
00173         if (segs.size() >= 2) {
00174           line_index.push_back(v);
00175         }
00176         _created_verts.push_back((*sl)._point);
00177         _created_colors.push_back((*sl)._color);
00178         v++;
00179         nassertr(v == (int)_created_verts.size(), previous);
00180       }
00181     }
00182 
00183     // Now create the lines.
00184     if (line_index.size() > 0) {
00185       // Create a new Geom and add the line segments.
00186       Geom *geom;
00187       if (line_index.size() <= 2) {
00188         // Here's a special case: just one line segment.
00189         GeomLine *geom_line = new GeomLine;
00190         geom_line->set_num_prims(1);
00191         geom_line->set_width(_thick);
00192         geom = geom_line;
00193 
00194       } else {
00195         // The more normal case: multiple line segments, connected
00196         // end-to-end like a series of linestrips.
00197         GeomLinestrip *geom_linestrip = new GeomLinestrip;
00198         geom_linestrip->set_num_prims(lengths.size());
00199         geom_linestrip->set_lengths(lengths);
00200         geom_linestrip->set_width(_thick);
00201         geom = geom_linestrip;
00202       }
00203 
00204       geom->set_colors(_created_colors, G_PER_VERTEX, line_index);
00205       geom->set_coords(_created_verts, line_index);
00206 
00207       previous->add_geom(geom);
00208     }
00209 
00210     // And now create the points.
00211     if (point_index.size() > 0) {
00212       // Create a new Geom and add the points.
00213       GeomPoint *geom = new GeomPoint;
00214 
00215       geom->set_num_prims(point_index.size());
00216       geom->set_size(_thick);
00217       geom->set_colors(_created_colors, G_PER_VERTEX, point_index);
00218       geom->set_coords(_created_verts, point_index);
00219 
00220       previous->add_geom(geom);
00221     }
00222 
00223     // And reset for next time.
00224     reset();
00225   }
00226 
00227   return previous;
00228 }

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