Panda3D
Loading...
Searching...
No Matches
geomTriangles.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 geomTriangles.cxx
10 * @author drose
11 * @date 2005-03-06
12 */
13
14#include "geomTriangles.h"
15#include "geomVertexRewriter.h"
16#include "pStatTimer.h"
17#include "bamReader.h"
18#include "bamWriter.h"
21
22using std::map;
23
24TypeHandle GeomTriangles::_type_handle;
25
26/**
27 *
28 */
29GeomTriangles::
30GeomTriangles(GeomTriangles::UsageHint usage_hint) :
31 GeomPrimitive(usage_hint)
32{
33}
34
35/**
36 *
37 */
38GeomTriangles::
39GeomTriangles(const GeomTriangles &copy) :
40 GeomPrimitive(copy)
41{
42}
43
44/**
45 *
46 */
47GeomTriangles::
48~GeomTriangles() {
49}
50
51/**
52 *
53 */
54PT(GeomPrimitive) GeomTriangles::
55make_copy() const {
56 return new GeomTriangles(*this);
57}
58
59/**
60 * Returns the fundamental rendering type of this primitive: whether it is
61 * points, lines, or polygons.
62 *
63 * This is used to set up the appropriate antialiasing settings when
64 * AntialiasAttrib::M_auto is in effect; it also implies the type of primitive
65 * that will be produced when decompose() is called.
66 */
67GeomPrimitive::PrimitiveType GeomTriangles::
68get_primitive_type() const {
69 return PT_polygons;
70}
71
72/**
73 * Adds adjacency information to this primitive. May return null if this type
74 * of geometry does not support adjacency information.
75 */
76CPT(GeomPrimitive) GeomTriangles::
77make_adjacency() const {
78 using std::make_pair;
79
80 Thread *current_thread = Thread::get_current_thread();
82
83 GeomPrimitivePipelineReader from(this, current_thread);
84 int num_vertices = from.get_num_vertices();
85
86 PT(GeomVertexArrayData) new_vertices = adj->make_index_data();
87 new_vertices->set_num_rows(num_vertices * 2);
88
89 // First, build a map of each triangle's halfedges to its opposing vertices.
90 map<std::pair<int, int>, int> edge_map;
91 for (int i = 0; i < num_vertices; i += 3) {
92 int v0 = from.get_vertex(i);
93 int v1 = from.get_vertex(i + 1);
94 int v2 = from.get_vertex(i + 2);
95 edge_map[make_pair(v0, v1)] = v2;
96 edge_map[make_pair(v1, v2)] = v0;
97 edge_map[make_pair(v2, v0)] = v1;
98 }
99
100 // Now build up the new vertex data. For each edge, we insert the
101 // appropriate connecting vertex.
102 {
103 GeomVertexWriter to(new_vertices, 0);
104 for (int i = 0; i < num_vertices; i += 3) {
105 int v0 = from.get_vertex(i);
106 int v1 = from.get_vertex(i + 1);
107 int v2 = from.get_vertex(i + 2);
108
109 // Get the third vertex of the triangle adjoining this edge.
110 to.set_data1(v0);
111 auto it = edge_map.find(make_pair(v1, v0));
112 if (it != edge_map.end()) {
113 to.set_data1i(it->second);
114 } else {
115 // Um, no adjoining triangle? Just repeat the vertex, I guess.
116 to.set_data1i(v0);
117 }
118
119 // Do the same for the other two edges.
120 to.set_data1(v1);
121 it = edge_map.find(make_pair(v2, v1));
122 if (it != edge_map.end()) {
123 to.set_data1i(it->second);
124 } else {
125 to.set_data1i(v1);
126 }
127
128 to.set_data1(v2);
129 it = edge_map.find(make_pair(v0, v2));
130 if (it != edge_map.end()) {
131 to.set_data1i(it->second);
132 } else {
133 to.set_data1i(v2);
134 }
135 }
136
137 nassertr(to.is_at_end(), nullptr);
138 }
139
140 adj->set_vertices(std::move(new_vertices));
141 return adj;
142}
143
144/**
145 * If the primitive type is a simple type in which all primitives have the
146 * same number of vertices, like triangles, returns the number of vertices per
147 * primitive. If the primitive type is a more complex type in which different
148 * primitives might have different numbers of vertices, for instance a
149 * triangle strip, returns 0.
150 */
151int GeomTriangles::
152get_num_vertices_per_primitive() const {
153 return 3;
154}
155
156/**
157 * Calls the appropriate method on the GSG to draw the primitive.
158 */
159bool GeomTriangles::
161 bool force) const {
162 return gsg->draw_triangles(reader, force);
163}
164
165/**
166 * The virtual implementation of doubleside().
167 */
168CPT(GeomPrimitive) GeomTriangles::
169doubleside_impl() const {
170 Thread *current_thread = Thread::get_current_thread();
171 PT(GeomTriangles) reversed = new GeomTriangles(*this);
172
173 GeomPrimitivePipelineReader from(this, current_thread);
174
175 // This is like reverse(), except we don't clear the vertices first. That
176 // way we double the vertices up.
177
178 // First, rotate the original copy, if necessary, so the flat-firstflat-last
179 // nature of the vertices is consistent throughout the primitive.
180 bool needs_rotate = false;
181 switch (from.get_shade_model()) {
182 case SM_flat_first_vertex:
183 case SM_flat_last_vertex:
184 reversed = (GeomTriangles *)DCAST(GeomTriangles, reversed->rotate());
185 needs_rotate = true;
186
187 default:
188 break;
189 }
190
191 // Now append all the new vertices, in reverse order.
192 for (int i = from.get_num_vertices() - 1; i >= 0; --i) {
193 reversed->add_vertex(from.get_vertex(i));
194 }
195
196 // Finally, re-rotate the whole thing to get back to the original shade
197 // model.
198 if (needs_rotate) {
199 reversed = (GeomTriangles *)DCAST(GeomTriangles, reversed->rotate());
200 }
201
202 return reversed;
203}
204
205/**
206 * The virtual implementation of reverse().
207 */
208CPT(GeomPrimitive) GeomTriangles::
209reverse_impl() const {
210 Thread *current_thread = Thread::get_current_thread();
211 PT(GeomTriangles) reversed = new GeomTriangles(*this);
212
213 GeomPrimitivePipelineReader from(this, current_thread);
214 reversed->clear_vertices();
215
216 for (int i = from.get_num_vertices() - 1; i >= 0; --i) {
217 reversed->add_vertex(from.get_vertex(i));
218 }
219
220 switch (from.get_shade_model()) {
221 case SM_flat_first_vertex:
222 reversed->set_shade_model(SM_flat_last_vertex);
223 reversed = (GeomTriangles *)DCAST(GeomTriangles, reversed->rotate());
224 break;
225
226 case SM_flat_last_vertex:
227 reversed->set_shade_model(SM_flat_first_vertex);
228 reversed = (GeomTriangles *)DCAST(GeomTriangles, reversed->rotate());
229 break;
230
231 default:
232 break;
233 }
234
235 return reversed;
236}
237
238/**
239 * The virtual implementation of rotate().
240 */
241CPT(GeomVertexArrayData) GeomTriangles::
242rotate_impl() const {
243 // To rotate triangles, we just move one vertex from the front to the back,
244 // or vice-versa; but we have to know what direction we're going.
245 ShadeModel shade_model = get_shade_model();
246 int num_vertices = get_num_vertices();
247
248 PT(GeomVertexArrayData) new_vertices = make_index_data();
249 new_vertices->set_num_rows(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 switch (shade_model) {
257 case SM_flat_first_vertex:
258 // Move the first vertex to the end.
259 {
260 for (int begin = 0; begin < num_vertices; begin += 3) {
261 from.set_row_unsafe(begin + 1);
262 to.set_data1i(from.get_data1i());
263 to.set_data1i(from.get_data1i());
264 from.set_row_unsafe(begin);
265 to.set_data1i(from.get_data1i());
266 }
267 }
268 break;
269
270 case SM_flat_last_vertex:
271 // Move the last vertex to the front.
272 {
273 for (int begin = 0; begin < num_vertices; begin += 3) {
274 from.set_row_unsafe(begin + 2);
275 to.set_data1i(from.get_data1i());
276 from.set_row_unsafe(begin);
277 to.set_data1i(from.get_data1i());
278 to.set_data1i(from.get_data1i());
279 }
280 }
281 break;
282
283 default:
284 // This shouldn't get called with any other shade model.
285 nassertr(false, vertices);
286 }
287
288 nassertr(to.is_at_end(), nullptr);
289
290 } else {
291 // Nonindexed case.
292 int first_vertex = get_first_vertex();
293 GeomVertexWriter to(new_vertices, 0);
294
295 switch (shade_model) {
296 case SM_flat_first_vertex:
297 // Move the first vertex to the end.
298 {
299 for (int begin = 0; begin < num_vertices; begin += 3) {
300 to.set_data1i(begin + 1 + first_vertex);
301 to.set_data1i(begin + 2 + first_vertex);
302 to.set_data1i(begin + first_vertex);
303 }
304 }
305 break;
306
307 case SM_flat_last_vertex:
308 // Move the last vertex to the front.
309 {
310 for (int begin = 0; begin < num_vertices; begin += 3) {
311 to.set_data1i(begin + 2 + first_vertex);
312 to.set_data1i(begin + first_vertex);
313 to.set_data1i(begin + 1 + first_vertex);
314 }
315 }
316 break;
317
318 default:
319 // This shouldn't get called with any other shade model.
320 nassertr(false, nullptr);
321 }
322
323 nassertr(to.is_at_end(), nullptr);
324 }
325
326 return new_vertices;
327}
328
329/**
330 * Tells the BamReader how to create objects of type Geom.
331 */
332void GeomTriangles::
333register_with_read_factory() {
334 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
335}
336
337/**
338 * This function is called by the BamReader's factory when a new object of
339 * type Geom is encountered in the Bam file. It should create the Geom and
340 * extract its information from the file.
341 */
342TypedWritable *GeomTriangles::
343make_from_bam(const FactoryParams &params) {
344 GeomTriangles *object = new GeomTriangles(UH_unspecified);
345 DatagramIterator scan;
346 BamReader *manager;
347
348 parse_params(params, scan, manager);
349 object->fillin(scan, manager);
350
351 return object;
352}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
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
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition bamReader.I:177
A class to retrieve the individual data elements previously stored in a Datagram.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
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
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
get_usage_hint
Returns the usage hint for this primitive.
get_num_vertices
Returns the number of indices used by all the primitives in this object.
int get_first_vertex() const
Returns the first vertex number referenced by the primitive.
get_shade_model
Returns the ShadeModel hint for this primitive.
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
Defines a series of disconnected triangles, with adjacency information.
Defines a series of disconnected triangles.
This is the data for one array of a GeomVertexData structure.
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
A thread; that is, a lightweight process.
Definition thread.h:46
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition thread.h:109
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
Base class for objects that can be written to and read from Bam files.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.