Panda3D
geomLinestrips.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file geomLinestrips.cxx
10  * @author drose
11  * @date 2005-03-22
12  */
13 
14 #include "geomLinestrips.h"
15 #include "geomLines.h"
16 #include "geomVertexRewriter.h"
17 #include "pStatTimer.h"
18 #include "bamReader.h"
19 #include "bamWriter.h"
22 
23 using std::map;
24 
25 TypeHandle GeomLinestrips::_type_handle;
26 
27 /**
28  *
29  */
30 GeomLinestrips::
31 GeomLinestrips(GeomLinestrips::UsageHint usage_hint) :
32  GeomPrimitive(usage_hint)
33 {
34 }
35 
36 /**
37  *
38  */
39 GeomLinestrips::
40 GeomLinestrips(const GeomLinestrips &copy) :
41  GeomPrimitive(copy)
42 {
43 }
44 
45 /**
46  *
47  */
48 GeomLinestrips::
49 ~GeomLinestrips() {
50 }
51 
52 /**
53  *
54  */
55 PT(GeomPrimitive) GeomLinestrips::
56 make_copy() const {
57  return new GeomLinestrips(*this);
58 }
59 
60 /**
61  * Returns the fundamental rendering type of this primitive: whether it is
62  * points, lines, or polygons.
63  *
64  * This is used to set up the appropriate antialiasing settings when
65  * AntialiasAttrib::M_auto is in effect; it also implies the type of primitive
66  * that will be produced when decompose() is called.
67  */
68 GeomPrimitive::PrimitiveType GeomLinestrips::
69 get_primitive_type() const {
70  return PT_lines;
71 }
72 
73 /**
74  * Returns the set of GeomRendering bits that represent the rendering
75  * properties required to properly render this primitive.
76  */
77 int GeomLinestrips::
78 get_geom_rendering() const {
79  if (is_indexed()) {
80  if (get_num_primitives() > 1) {
81  return GR_line_strip | GR_indexed_other | GR_strip_cut_index;
82  } else {
83  return GR_line_strip | GR_indexed_other;
84  }
85  } else {
86  return GR_line_strip;
87  }
88 }
89 
90 /**
91  * Adds adjacency information to this primitive. May return null if this type
92  * of geometry does not support adjacency information.
93  */
94 CPT(GeomPrimitive) GeomLinestrips::
95 make_adjacency() const {
96  Thread *current_thread = Thread::get_current_thread();
98 
99  GeomPrimitivePipelineReader from(this, current_thread);
100  int num_vertices = from.get_num_vertices();
101  CPTA_int ends = get_ends();
102 
103  const int num_unused = 1;
104 
105  // First, build a map of each vertex to its next vertex, and another map
106  // doing the exact reverse.
107  map<int, int> forward_map, reverse_map;
108  int vi = -num_unused;
109  int li = 0;
110  while (li < (int)ends.size()) {
111  // Skip unused vertices between linestrips.
112  vi += num_unused;
113  int end = ends[li];
114  nassertr(vi + 1 <= end, nullptr);
115  int v0 = from.get_vertex(vi++);
116  while (vi < end) {
117  int v1 = from.get_vertex(vi++);
118  forward_map[v0] = v1;
119  reverse_map[v1] = v0;
120  v0 = v1;
121  }
122  ++li;
123  }
124  nassertr(vi == num_vertices, nullptr);
125 
126  // Now build up the new vertex data. For each linestrip, we prepend and
127  // append the appropriate connecting vertices.
128  vi = -num_unused;
129  li = 0;
130  while (li < (int)ends.size()) {
131  // Skip unused vertices between linestrips.
132  vi += num_unused;
133  int end = ends[li];
134  nassertr(vi + 1 <= end, nullptr);
135 
136  // Look for the line segment connected to the beginning of this strip.
137  int v0 = from.get_vertex(vi++);
138  auto it = reverse_map.find(v0);
139  if (it != reverse_map.end()) {
140  adj->add_vertex(it->second);
141  } else {
142  // Um, no adjoining line segment? Just repeat the vertex, I guess.
143  adj->add_vertex(v0);
144  }
145 
146  // Add the actual vertices in the strip.
147  adj->add_vertex(v0);
148  int v1 = v0;
149  while (vi < end) {
150  v1 = from.get_vertex(vi++);
151  adj->add_vertex(v1);
152  }
153 
154  // Do the same for the last vertex in the strip.
155  it = forward_map.find(v1);
156  if (it != forward_map.end()) {
157  adj->add_vertex(it->second);
158  } else {
159  adj->add_vertex(v1);
160  }
161 
162  adj->close_primitive();
163  ++li;
164  }
165  nassertr(vi == num_vertices, nullptr);
166 
167  return adj;
168 }
169 
170 /**
171  * Returns the minimum number of vertices that must be added before
172  * close_primitive() may legally be called.
173  */
174 int GeomLinestrips::
175 get_min_num_vertices_per_primitive() const {
176  return 2;
177 }
178 
179 /**
180  * Returns the number of vertices that are added between primitives that
181  * aren't, strictly speaking, part of the primitives themselves. This is
182  * used, for instance, to define degenerate triangles to connect otherwise
183  * disconnected triangle strips.
184  */
185 int GeomLinestrips::
186 get_num_unused_vertices_per_primitive() const {
187  return 1;
188 }
189 
190 /**
191  * Calls the appropriate method on the GSG to draw the primitive.
192  */
193 bool GeomLinestrips::
195  bool force) const {
196  return gsg->draw_linestrips(reader, force);
197 }
198 
199 /**
200  * Decomposes a complex primitive type into a simpler primitive type, for
201  * instance line strips to lines, and returns a pointer to the new primitive
202  * definition. If the decomposition cannot be performed, this might return
203  * the original object.
204  *
205  * This method is useful for application code that wants to iterate through
206  * the set of lines on the primitive without having to write handlers for each
207  * possible kind of primitive type.
208  */
209 CPT(GeomPrimitive) GeomLinestrips::
210 decompose_impl() const {
211  PT(GeomLines) lines = new GeomLines(get_usage_hint());
212  lines->set_shade_model(get_shade_model());
213  CPTA_int ends = get_ends();
214 
215  int num_unused = get_num_unused_vertices_per_primitive();
216 
217  int vi = -num_unused;
218  int li = 0;
219  while (li < (int)ends.size()) {
220  // Skip unused vertices between tristrips.
221  vi += num_unused;
222  int end = ends[li];
223  nassertr(vi + 1 <= end, lines);
224  int v0 = get_vertex(vi);
225  ++vi;
226  while (vi < end) {
227  int v1 = get_vertex(vi);
228  ++vi;
229  lines->add_vertex(v0);
230  lines->add_vertex(v1);
231  v0 = v1;
232  lines->close_primitive();
233  }
234  ++li;
235  }
236  nassertr(vi == get_num_vertices(), nullptr);
237 
238  return lines;
239 }
240 
241 /**
242  * The virtual implementation of do_rotate().
243  */
244 CPT(GeomVertexArrayData) GeomLinestrips::
245 rotate_impl() const {
246  // To rotate a line strip, we just reverse the vertices.
247  CPTA_int ends = get_ends();
248  PT(GeomVertexArrayData) new_vertices = make_index_data();
249  new_vertices->set_num_rows(get_num_vertices());
250 
251  if (is_indexed()) {
252  CPT(GeomVertexArrayData) vertices = get_vertices();
253  GeomVertexReader from(vertices, 0);
254  GeomVertexWriter to(new_vertices, 0);
255 
256  int begin = 0;
257  CPTA_int::const_iterator ei;
258  for (ei = ends.begin(); ei != ends.end(); ++ei) {
259  int end = (*ei);
260  for (int vi = end - 1; vi >= begin; --vi) {
261  from.set_row_unsafe(vi);
262  to.set_data1i(from.get_data1i());
263  }
264  begin = end;
265  }
266 
267  nassertr(to.is_at_end(), nullptr);
268 
269  } else {
270  // Nonindexed case.
271  int first_vertex = get_first_vertex();
272  GeomVertexWriter to(new_vertices, 0);
273 
274  int begin = 0;
275  CPTA_int::const_iterator ei;
276  for (ei = ends.begin(); ei != ends.end(); ++ei) {
277  int end = (*ei);
278  for (int vi = end - 1; vi >= begin; --vi) {
279  to.set_data1i(vi + first_vertex);
280  }
281  begin = end;
282  }
283 
284  nassertr(to.is_at_end(), nullptr);
285  }
286  return new_vertices;
287 }
288 
289 /**
290  * Should be redefined to return true in any primitive that implements
291  * append_unused_vertices().
292  */
293 bool GeomLinestrips::
294 requires_unused_vertices() const {
295  return true;
296 }
297 
298 /**
299  * Called when a new primitive is begun (other than the first primitive), this
300  * should add some degenerate vertices between primitives, if the primitive
301  * type requires that. The second parameter is the first vertex that begins
302  * the new primitive.
303  */
304 void GeomLinestrips::
305 append_unused_vertices(GeomVertexArrayData *vertices, int vertex) {
306  GeomVertexWriter to(vertices, 0);
307  to.set_row_unsafe(vertices->get_num_rows());
308  to.add_data1i(get_strip_cut_index());
309 }
310 
311 /**
312  * Tells the BamReader how to create objects of type Geom.
313  */
314 void GeomLinestrips::
316  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
317 }
318 
319 /**
320  * This function is called by the BamReader's factory when a new object of
321  * type Geom is encountered in the Bam file. It should create the Geom and
322  * extract its information from the file.
323  */
324 TypedWritable *GeomLinestrips::
325 make_from_bam(const FactoryParams &params) {
326  GeomLinestrips *object = new GeomLinestrips(UH_unspecified);
327  DatagramIterator scan;
328  BamReader *manager;
329 
330  parse_params(params, scan, manager);
331  object->fillin(scan, manager);
332 
333  return object;
334 }
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
get_vertex
Returns the ith vertex index in the table.
Definition: geomPrimitive.h:99
UsageHint get_usage_hint() const
Returns the minimum (i.e.
Definition: geom.cxx:110
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56
get_num_vertices
Returns the number of indices used by all the primitives in this object.
Definition: geomPrimitive.h:99
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(GeomPrimitive) GeomLinestrips
Returns the fundamental rendering type of this primitive: whether it is points, lines,...
int get_first_vertex() const
Returns the first vertex number referenced by the primitive.
Definition: geomPrimitive.I:98
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition: bamReader.I:275
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
CPTA_int get_ends() const
Returns a const pointer to the primitive ends array so application code can read it directly.
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:73
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_strip_cut_index
Returns the index of the indicated type that is reserved for use as a strip cut index,...
Defines a series of disconnected line segments.
Definition: geomLines.h:23
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
int get_num_rows() const
Returns the number of rows stored in the array, based on the number of bytes and the stride.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
int get_num_primitives() const
Returns the number of individual primitives stored within this object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A thread; that is, a lightweight process.
Definition: thread.h:46
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
Defines a series of line strips.
get_shade_model
Returns the ShadeModel hint for this primitive.
Definition: geomPrimitive.h:77
static void register_with_read_factory()
Tells the BamReader how to create objects of type Geom.
A class to retrieve the individual data elements previously stored in a Datagram.
Defines a series of line strips with adjacency information.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
Definition: geomPrimitive.I:86
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Similar to PointerToArray, except that its contents may not be modified.
This is the data for one array of a GeomVertexData structure.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.