00001 // Filename: lineSegs.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 "lineSegs.h" 00016 #include "renderState.h" 00017 #include "renderModeAttrib.h" 00018 #include "geom.h" 00019 #include "geomLinestrips.h" 00020 #include "geomPoints.h" 00021 #include "geomVertexReader.h" 00022 #include "geomVertexWriter.h" 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Function: LineSegs::Constructor 00026 // Access: Public 00027 // Description: Constructs a LineSegs object, which can be used to 00028 // create any number of disconnected lines or points of 00029 // various thicknesses and colors through the visible 00030 // scene. After creating the object, call move_to() and 00031 // draw_to() repeatedly to describe the path, then call 00032 // create() to create a GeomNode which will render the 00033 // described path. 00034 //////////////////////////////////////////////////////////////////// 00035 LineSegs:: 00036 LineSegs(const string &name) : Namable(name) { 00037 _color.set(1.0f, 1.0f, 1.0f, 1.0f); 00038 _thick = 1.0f; 00039 } 00040 00041 00042 //////////////////////////////////////////////////////////////////// 00043 // Function: LineSegs::Destructor 00044 // Access: Public 00045 //////////////////////////////////////////////////////////////////// 00046 LineSegs:: 00047 ~LineSegs() { 00048 } 00049 00050 00051 //////////////////////////////////////////////////////////////////// 00052 // Function: LineSegs::reset 00053 // Access: Public 00054 // Description: Removes any lines in progress and resets to the 00055 // initial empty state. 00056 //////////////////////////////////////////////////////////////////// 00057 void LineSegs:: 00058 reset() { 00059 _list.clear(); 00060 } 00061 00062 00063 //////////////////////////////////////////////////////////////////// 00064 // Function: LineSegs::move_to 00065 // Access: Public 00066 // Description: Moves the pen to the given point without drawing a 00067 // line. When followed by draw_to(), this marks the 00068 // first point of a line segment; when followed by 00069 // move_to() or create(), this creates a single point. 00070 //////////////////////////////////////////////////////////////////// 00071 void LineSegs:: 00072 move_to(const LVecBase3 &v) { 00073 // We create a new SegmentList with the initial point in it. 00074 SegmentList segs; 00075 segs.push_back(Point(v, _color)); 00076 00077 // And add this list to the list of segments. 00078 _list.push_back(segs); 00079 } 00080 00081 //////////////////////////////////////////////////////////////////// 00082 // Function: LineSegs::draw_to 00083 // Access: Public 00084 // Description: Draws a line segment from the pen's last position 00085 // (the last call to move_to or draw_to) to the 00086 // indicated point. move_to() and draw_to() only update 00087 // tables; the actual drawing is performed when create() 00088 // is called. 00089 //////////////////////////////////////////////////////////////////// 00090 void LineSegs:: 00091 draw_to(const LVecBase3 &v) { 00092 if (_list.empty()) { 00093 // Let our first call to draw_to() be an implicit move_to(). 00094 move_to(v); 00095 00096 } else { 00097 // Get the current SegmentList, which was the last one we added to 00098 // the LineList. 00099 SegmentList &segs = _list.back(); 00100 00101 // Add the new point. 00102 segs.push_back(Point(v, _color)); 00103 } 00104 } 00105 00106 //////////////////////////////////////////////////////////////////// 00107 // Function: LineSegs::empty 00108 // Access: Public 00109 // Description: Returns true if move_to() or draw_to() have not been 00110 // called since the last reset() or create(), false 00111 // otherwise. 00112 //////////////////////////////////////////////////////////////////// 00113 bool LineSegs:: 00114 is_empty() { 00115 return _list.empty(); 00116 } 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: LineSegs::get_vertex 00120 // Access: Public 00121 // Description: Returns the nth point or vertex of the line segment 00122 // sequence generated by the last call to create(). The 00123 // first move_to() generates vertex 0; subsequent 00124 // move_to() and draw_to() calls generate consecutively 00125 // higher vertex numbers. 00126 //////////////////////////////////////////////////////////////////// 00127 LVertex LineSegs:: 00128 get_vertex(int n) const { 00129 nassertr(_created_data != (GeomVertexData *)NULL, LVertex::zero()); 00130 GeomVertexReader vertex(_created_data, InternalName::get_vertex()); 00131 vertex.set_row_unsafe(n); 00132 return vertex.get_data3(); 00133 } 00134 00135 //////////////////////////////////////////////////////////////////// 00136 // Function: LineSegs::set_vertex 00137 // Access: Public 00138 // Description: Moves the nth point or vertex of the line segment 00139 // sequence generated by the last call to create(). The 00140 // first move_to() generates vertex 0; subsequent 00141 // move_to() and draw_to() calls generate consecutively 00142 // higher vertex numbers. 00143 //////////////////////////////////////////////////////////////////// 00144 void LineSegs:: 00145 set_vertex(int n, const LVertex &vert) { 00146 nassertv(_created_data != (GeomVertexData *)NULL); 00147 GeomVertexWriter vertex(_created_data, InternalName::get_vertex()); 00148 vertex.set_row_unsafe(n); 00149 vertex.set_data3(vert); 00150 } 00151 00152 //////////////////////////////////////////////////////////////////// 00153 // Function: LineSegs::get_vertex_color 00154 // Access: Public 00155 // Description: Returns the color of the nth point or vertex. 00156 //////////////////////////////////////////////////////////////////// 00157 LColor LineSegs:: 00158 get_vertex_color(int n) const { 00159 nassertr(_created_data != (GeomVertexData *)NULL, LColor::zero()); 00160 GeomVertexReader color(_created_data, InternalName::get_color()); 00161 color.set_row_unsafe(n); 00162 return color.get_data4(); 00163 } 00164 00165 //////////////////////////////////////////////////////////////////// 00166 // Function: LineSegs::set_vertex_color 00167 // Access: Public 00168 // Description: Changes the vertex color of the nth point or vertex. 00169 // See set_vertex(). 00170 //////////////////////////////////////////////////////////////////// 00171 void LineSegs:: 00172 set_vertex_color(int n, const LColor &c) { 00173 nassertv(_created_data != (GeomVertexData *)NULL); 00174 GeomVertexWriter color(_created_data, InternalName::get_color()); 00175 color.set_row_unsafe(n); 00176 color.set_data4(c); 00177 } 00178 00179 //////////////////////////////////////////////////////////////////// 00180 // Function: LineSegs::get_current_position 00181 // Access: Public 00182 // Description: Returns the pen's current position. The next call to 00183 // draw_to() will draw a line segment from this point. 00184 //////////////////////////////////////////////////////////////////// 00185 const LVertex &LineSegs:: 00186 get_current_position() { 00187 if (_list.empty()) { 00188 // Our pen isn't anywhere. We'll put it somewhere. 00189 move_to(LVertex(0.0f, 0.0f, 0.0f)); 00190 } 00191 00192 return _list.back().back()._point; 00193 } 00194 00195 //////////////////////////////////////////////////////////////////// 00196 // Function: LineSegs::create 00197 // Access: Public 00198 // Description: Appends to an existing GeomNode a new Geom that 00199 // will render the series of line segments and points 00200 // described via calls to move_to() and draw_to(). The 00201 // lines and points are created with the color and 00202 // thickness established by calls to set_color() and 00203 // set_thick(). 00204 // 00205 // If dynamic is true, the line segments will be created 00206 // with the dynamic Geom setting, optimizing them for 00207 // runtime vertex animation. 00208 //////////////////////////////////////////////////////////////////// 00209 GeomNode *LineSegs:: 00210 create(GeomNode *previous, bool dynamic) { 00211 if (!_list.empty()) { 00212 CPT(RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, _thick); 00213 CPT(RenderAttrib) vtxcolor = ColorAttrib::make_vertex(); 00214 CPT(RenderState) state = RenderState::make(thick, vtxcolor); 00215 00216 _created_data = new GeomVertexData 00217 ("lineSegs", GeomVertexFormat::get_v3cp(), 00218 dynamic ? Geom::UH_dynamic : Geom::UH_static); 00219 GeomVertexWriter vertex(_created_data, InternalName::get_vertex()); 00220 GeomVertexWriter color(_created_data, InternalName::get_color()); 00221 00222 PT(GeomLinestrips) lines = new GeomLinestrips(Geom::UH_static); 00223 PT(GeomPoints) points = new GeomPoints(Geom::UH_static); 00224 00225 int v = 0; 00226 LineList::const_iterator ll; 00227 SegmentList::const_iterator sl; 00228 00229 for (ll = _list.begin(); ll != _list.end(); ll++) { 00230 const SegmentList &segs = (*ll); 00231 00232 if (segs.size() < 2) { 00233 // A segment of length 1 is just a point. 00234 for (sl = segs.begin(); sl != segs.end(); sl++) { 00235 points->add_vertex(v); 00236 vertex.add_data3((*sl)._point); 00237 color.add_data4((*sl)._color); 00238 v++; 00239 } 00240 points->close_primitive(); 00241 00242 } else { 00243 // A segment of length 2 or more is a line segment or 00244 // segments. 00245 for (sl = segs.begin(); sl != segs.end(); sl++) { 00246 lines->add_vertex(v); 00247 vertex.add_data3((*sl)._point); 00248 color.add_data4((*sl)._color); 00249 v++; 00250 } 00251 lines->close_primitive(); 00252 } 00253 } 00254 00255 if (lines->get_num_vertices() != 0) { 00256 PT(Geom) geom = new Geom(_created_data); 00257 geom->add_primitive(lines); 00258 previous->add_geom(geom, state); 00259 } 00260 if (points->get_num_vertices() != 0) { 00261 PT(Geom) geom = new Geom(_created_data); 00262 geom->add_primitive(points); 00263 previous->add_geom(geom, state); 00264 } 00265 00266 // And reset for next time. 00267 reset(); 00268 } 00269 00270 return previous; 00271 }