Panda3D
Loading...
Searching...
No Matches
odeTriMeshData.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 odeTriMeshData.cxx
10 * @author joswilso
11 * @date 2006-12-27
12 */
13
14#include "odeTriMeshData.h"
15
16using std::ostream;
17
18TypeHandle OdeTriMeshData::_type_handle;
19OdeTriMeshData::TriMeshDataMap *OdeTriMeshData::_tri_mesh_data_map = nullptr;
20
21void OdeTriMeshData::
22link_data(dGeomID id, PT(OdeTriMeshData) data) {
23 if (odetrimeshdata_cat.is_debug()) {
24 odetrimeshdata_cat.debug() << get_class_type() << "::link_data(" << id << "->" << data << ")" << "\n";
25 }
26 get_tri_mesh_data_map()[id] = data;
27}
28
29PT(OdeTriMeshData) OdeTriMeshData::
30get_data(dGeomID id) {
31 const TriMeshDataMap &data_map = get_tri_mesh_data_map();
32 TriMeshDataMap::const_iterator iter = data_map.find(id);
33 if (iter != data_map.end()) {
34 return iter->second;
35 }
36 return nullptr;
37}
38
39void OdeTriMeshData::
40unlink_data(dGeomID id) {
41 if (odetrimeshdata_cat.is_debug()) {
42 odetrimeshdata_cat.debug() << get_class_type() << "::unlink_data(" << id << ")" << "\n";
43 }
44 nassertv(_tri_mesh_data_map != nullptr);
45 TriMeshDataMap::iterator iter = _tri_mesh_data_map->find(id);
46 if (iter != _tri_mesh_data_map->end()) {
47 _tri_mesh_data_map->erase(iter);
48 }
49}
50
51void OdeTriMeshData::
52print_data(const std::string &marker) {
53 if (odetrimeshdata_cat.is_debug()) {
54 odetrimeshdata_cat.debug() << get_class_type() << "::print_data(" << marker << ")\n";
55 const TriMeshDataMap &data_map = get_tri_mesh_data_map();
56 TriMeshDataMap::const_iterator iter = data_map.begin();
57 for (;iter != data_map.end(); ++iter) {
58 odetrimeshdata_cat.debug() << "\t" << iter->first << " : " << iter->second << "\n";
59 }
60 }
61}
62
63void OdeTriMeshData::
64remove_data(OdeTriMeshData *data) {
65 if (odetrimeshdata_cat.is_debug()) {
66 odetrimeshdata_cat.debug()
67 << get_class_type() << "::remove_data(" << data->get_id() << ")" << "\n";
68 }
69 if (_tri_mesh_data_map == nullptr) {
70 return;
71 }
72
73 TriMeshDataMap::iterator iter;
74 for (iter = _tri_mesh_data_map->begin();
75 iter != _tri_mesh_data_map->end();
76 ++iter) {
77 if (iter->second == data) {
78 break;
79 }
80 }
81
82 while (iter != _tri_mesh_data_map->end()) {
83 _tri_mesh_data_map->erase(iter);
84
85 for (iter = _tri_mesh_data_map->begin();
86 iter != _tri_mesh_data_map->end();
87 ++iter) {
88 if (iter->second == data) {
89 break;
90 }
91 }
92 }
93}
94
95
96OdeTriMeshData::
97OdeTriMeshData(const NodePath& model, bool use_normals) :
98 _id(dGeomTriMeshDataCreate()),
99 _vertices(nullptr),
100 _faces(nullptr),
101 _normals(nullptr),
102 _num_vertices(0),
103 _num_faces(0) {
104 if (odetrimeshdata_cat.is_debug()) {
105 odetrimeshdata_cat.debug() << get_type() << "(" << _id << ")" << "\n";
106 }
107
108 process_model(model, use_normals);
109
110 if (odetrimeshdata_cat.is_debug()) {
111 write_faces(odetrimeshdata_cat.debug());
112 }
113
114#ifdef dSINGLE
115 if (!use_normals) {
116 build_single(_vertices, sizeof(StridedVertex), _num_vertices,
117 _faces, _num_faces * 3, sizeof(StridedTri));
118 } else {
119 build_single1(_vertices, sizeof(StridedVertex), _num_vertices,
120 _faces, _num_faces * 3, sizeof(StridedTri),
121 _normals);
122 }
123#else
124 if (!use_normals) {
125 build_double(_vertices, sizeof(StridedVertex), _num_vertices,
126 _faces, _num_faces * 3, sizeof(StridedTri));
127 } else {
128 build_double1(_vertices, sizeof(StridedVertex), _num_vertices,
129 _faces, _num_faces * 3, sizeof(StridedTri),
130 _normals);
131 }
132#endif
133
134 preprocess();
135}
136
137// Private copy constructor, shouldn't be copying these objects
138OdeTriMeshData::
139OdeTriMeshData(const OdeTriMeshData &other) {
140}
141
142OdeTriMeshData::
143~OdeTriMeshData() {
144 if (odetrimeshdata_cat.is_debug()) {
145 odetrimeshdata_cat.debug() << "~" << get_type() << "(" << _id << ")" << "\n";
146 }
147 destroy();
148 if (_vertices != nullptr) {
149 PANDA_FREE_ARRAY(_vertices);
150 _vertices = nullptr;
151 _num_vertices = 0;
152 }
153 if (_faces != nullptr) {
154 PANDA_FREE_ARRAY(_faces);
155 _faces = nullptr;
156 }
157 if (_normals != nullptr) {
158 // This is never allocated? Until we use _normals, assert that we don't
159 // accidentally free it here through some mistake.
160 nassertv(false);
161 PANDA_FREE_ARRAY(_normals);
162 }
163}
164
165void OdeTriMeshData::
166destroy() {
167 if (odetrimeshdata_cat.is_debug()) {
168 odetrimeshdata_cat.debug() << get_type() << "::destroy(" << _id << ")" << "\n";
169 }
170 if (_id != nullptr) {
171 dGeomTriMeshDataDestroy(_id);
172 remove_data(this);
173 _id = nullptr;
174 }
175}
176
177// Private assignment operator, shouldn't be copying these objects
178void OdeTriMeshData::
179operator = (const OdeTriMeshData &other) {
180}
181
182void OdeTriMeshData::
183process_model(const NodePath& model, bool &use_normals) {
184 // TODO: assert if _vertices is something other than 0.
185 if (odetrimeshdata_cat.is_debug()) {
186 odetrimeshdata_cat.debug()
187 << "process_model(" << model << ")" << "\n";
188 }
189 if (model.is_empty()) {
190 return;
191 }
192
193 NodePathCollection geomNodePaths = model.find_all_matches("**/+GeomNode");
194 if (model.node()->get_type() == GeomNode::get_class_type()) {
195 geomNodePaths.add_path(model);
196 }
197
198 for (int i = 0; i < geomNodePaths.get_num_paths(); ++i) {
199 analyze((GeomNode*)geomNodePaths[i].node());
200 }
201
202 if (odetrimeshdata_cat.is_debug()) {
203 odetrimeshdata_cat.debug() << "Found " << _num_vertices << " vertices.\n";
204 odetrimeshdata_cat.debug() << "Found " << _num_faces << " faces.\n";
205 }
206
207 _vertices = (StridedVertex *)PANDA_MALLOC_ARRAY(_num_vertices * sizeof(StridedVertex));
208 _faces = (StridedTri *)PANDA_MALLOC_ARRAY(_num_faces * sizeof(StridedTri));
209
210 _num_vertices = 0, _num_faces = 0;
211
212 for (int i = 0; i < geomNodePaths.get_num_paths(); ++i) {
213 process_geom_node((GeomNode*)geomNodePaths[i].node());
214 if (odetrimeshdata_cat.is_debug()) {
215 odetrimeshdata_cat.debug() << "_num_vertices now at " << _num_vertices << "\n";
216 }
217 }
218
219 if (odetrimeshdata_cat.is_debug()) {
220 odetrimeshdata_cat.debug()
221 << "Filled " << _num_faces << " triangles(" << _num_vertices << " vertices)\n";
222 }
223}
224
225void OdeTriMeshData::
226process_geom_node(const GeomNode *geomNode) {
227 if (odetrimeshdata_cat.is_debug()) {
228 ostream &out = odetrimeshdata_cat.debug();
229 out.width(2); out << "" << "process_geom_node(" << *geomNode << ")" << "\n";
230 }
231 for (int i = 0; i < geomNode->get_num_geoms(); ++i) {
232 process_geom(geomNode->get_geom(i));
233 }
234}
235
236void OdeTriMeshData::
237process_geom(const Geom *geom) {
238 if (odetrimeshdata_cat.is_debug()) {
239 ostream &out = odetrimeshdata_cat.debug();
240 out.width(4); out << "" << "process_geom(" << *geom << ")" << "\n";
241 }
242 if (geom->get_primitive_type() != Geom::PT_polygons) {
243 return;
244 }
245
246 CPT(GeomVertexData) vData = geom->get_vertex_data();
247
248 for (size_t i = 0; i < geom->get_num_primitives(); ++i) {
249 process_primitive(geom->get_primitive(i), vData);
250 }
251}
252
253void OdeTriMeshData::
254process_primitive(const GeomPrimitive *primitive,
255 CPT(GeomVertexData) vData) {
256 GeomVertexReader vReader(vData, "vertex");
257 GeomVertexReader nReader(vData, "normal");
258 LVecBase3f vertex;
259 // CPT(GeomPrimitive) dPrimitive = primitive->decompose();
260 CPT(GeomPrimitive) dPrimitive = primitive;
261 ostream &out = odetrimeshdata_cat.debug();
262 out.width(6); out << "" << "process_primitive(" << *dPrimitive << ")" << "\n";
263
264
265 if (dPrimitive->get_type() == GeomTriangles::get_class_type()) {
266 for (int i = 0; i < dPrimitive->get_num_primitives(); i++, _num_faces++) {
267 int s = dPrimitive->get_primitive_start(i);
268 int e = dPrimitive->get_primitive_end(i);
269 out.width(8); out << "" << "primitive " << i << ":" << "\n";
270 for (int j = s, m = 0; j < e; j++, m++, _num_vertices++) {
271 int vRowIndex = dPrimitive->get_vertex(j);
272 vReader.set_row_unsafe(vRowIndex);
273 nReader.set_row_unsafe(vRowIndex);
274 vertex = vReader.get_data3f();
275 // normal = nReader.get_data3f();
276 _faces[_num_faces].Indices[m] = _num_vertices;
277
278 _vertices[_num_vertices].Vertex[0] = vertex[0];
279 _vertices[_num_vertices].Vertex[1] = vertex[1];
280 _vertices[_num_vertices].Vertex[2] = vertex[2];
281
282 out.width(10); out << "" << "vertex " << j << " has: pos(" \
283 << vertex << ") normal(" << "normal" << ")" << "\n";
284 }
285 }
286 } else if (dPrimitive->get_type() == GeomTristrips::get_class_type()){
287 for (int i = 0; i < dPrimitive->get_num_primitives(); i++, _num_faces++) {
288 int s = dPrimitive->get_primitive_start(i);
289 int e = dPrimitive->get_primitive_end(i);
290 out.width(8); out << "" << "primitive " << i << ":" << "\n";
291 for (int j = s, m = 0; j < e; j++, m++, _num_vertices++) {
292 int vRowIndex = dPrimitive->get_vertex(j);
293 vReader.set_row_unsafe(vRowIndex);
294 nReader.set_row_unsafe(vRowIndex);
295 vertex = vReader.get_data3f();
296 // normal = nReader.get_data3f();
297
298 _vertices[_num_vertices].Vertex[0] = vertex[0];
299 _vertices[_num_vertices].Vertex[1] = vertex[1];
300 _vertices[_num_vertices].Vertex[2] = vertex[2];
301 out.width(10); out << "" << "vertex " << j << " has: pos(" \
302 << vertex << ") normal(" << "normal" << ")" << "\n";
303 if (m < 3) {
304 _faces[_num_faces].Indices[m] = _num_vertices;
305 } else {
306 _num_faces++;
307 if ( m & 1) {
308 _faces[_num_faces].Indices[0] = _num_vertices-1;
309 _faces[_num_faces].Indices[1] = _num_vertices-2;
310 _faces[_num_faces].Indices[2] = _num_vertices;
311 } else {
312 _faces[_num_faces].Indices[0] = _num_vertices-2;
313 _faces[_num_faces].Indices[1] = _num_vertices-1;
314 _faces[_num_faces].Indices[2] = _num_vertices;
315 }
316 }
317 }
318 out << "\n";
319 }
320 }
321}
322void OdeTriMeshData::
323analyze(const GeomNode *geomNode) {
324 for (int i = 0; i < geomNode->get_num_geoms(); ++i) {
325 analyze(geomNode->get_geom(i));
326 }
327}
328
329void OdeTriMeshData::
330analyze(const Geom *geom) {
331 if (geom->get_primitive_type() != Geom::PT_polygons) {
332 return;
333 }
334
335 for (size_t i = 0; i < geom->get_num_primitives(); ++i) {
336 analyze(geom->get_primitive(i));
337 }
338}
339
340void OdeTriMeshData::
341analyze(const GeomPrimitive *primitive) {
342 for (int i = 0; i < primitive->get_num_primitives(); ++i) {
343 _num_vertices += primitive->get_primitive_num_vertices(i);
344 _num_faces += primitive->get_primitive_num_faces(i);
345 }
346}
347
348void OdeTriMeshData::
349write_faces(ostream &out) const {
350 out<<"\n";
351 for (unsigned int i = 0; i < _num_faces; ++i) {
352 out.width(2); out << "Face " << i << ":\n";
353 for (int j = 0; j < 3; ++j) {
354 out.width(4);
355 out << "(" << _vertices[_faces[i].Indices[j]].Vertex[0] \
356 << ", " << _vertices[_faces[i].Indices[j]].Vertex[1] \
357 << ", " << _vertices[_faces[i].Indices[j]].Vertex[2] << ")\n" ;
358 }
359 }
360}
361
362void OdeTriMeshData::
363write(ostream &out, unsigned int indent) const {
364 out.width(indent); out << "" << get_type() << "(id = " << _id << ") : " \
365 << "" << "Vertices: " << (_id ? _num_vertices : 0) << ", " \
366 << "" << "Triangles: " << (_id ? _num_faces : 0);
367}
A node that holds Geom objects, renderable pieces of geometry.
Definition geomNode.h:34
get_num_geoms
Returns the number of geoms in the node.
Definition geomNode.h:71
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
int get_primitive_num_faces(int n) const
Returns the number of triangles or other fundamental type (such as line segments) represented by the ...
int get_num_primitives() const
Returns the number of individual primitives stored within this object.
int get_primitive_num_vertices(int n) const
Returns the number of vertices used by the nth primitive.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
A container for geometry primitives.
Definition geom.h:54
get_primitive_type
Returns the fundamental primitive type that is common to all GeomPrimitives added within the Geom.
Definition geom.h:74
This is a set of zero or more NodePaths.
void add_path(const NodePath &node_path)
Adds a new NodePath to the collection.
get_num_paths
Returns the number of NodePaths in the collection.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition nodePath.I:188
NodePathCollection find_all_matches(const std::string &path) const
Returns the complete set of all NodePaths that begin with this NodePath and can be extended by path.
Definition nodePath.cxx:357
PandaNode * node() const
Returns the referenced node of the path.
Definition nodePath.I:227
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
This is our own Panda specialization on the default STL map.
Definition pmap.h:49
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition indent.cxx:20
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.