Panda3D
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 
16 using std::ostream;
17 
18 TypeHandle OdeTriMeshData::_type_handle;
19 OdeTriMeshData::TriMeshDataMap *OdeTriMeshData::_tri_mesh_data_map = nullptr;
20 
21 void OdeTriMeshData::
22 link_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 
29 PT(OdeTriMeshData) OdeTriMeshData::
30 get_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 
39 void OdeTriMeshData::
40 unlink_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 
51 void OdeTriMeshData::
52 print_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 
63 void OdeTriMeshData::
64 remove_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 
96 OdeTriMeshData::
97 OdeTriMeshData(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
138 OdeTriMeshData::
139 OdeTriMeshData(const OdeTriMeshData &other) {
140 }
141 
142 OdeTriMeshData::
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 
165 void OdeTriMeshData::
166 destroy() {
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
178 void OdeTriMeshData::
179 operator = (const OdeTriMeshData &other) {
180 }
181 
182 void OdeTriMeshData::
183 process_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 
225 void OdeTriMeshData::
226 process_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 
236 void OdeTriMeshData::
237 process_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 
253 void OdeTriMeshData::
254 process_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 }
322 void OdeTriMeshData::
323 analyze(const GeomNode *geomNode) {
324  for (int i = 0; i < geomNode->get_num_geoms(); ++i) {
325  analyze(geomNode->get_geom(i));
326  }
327 }
328 
329 void OdeTriMeshData::
330 analyze(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 
340 void OdeTriMeshData::
341 analyze(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 
348 void OdeTriMeshData::
349 write_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 
362 void OdeTriMeshData::
363 write(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...
Definition: geomPrimitive.h:56
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_start(int n) const
Returns the element within the _vertices list at which the nth primitive starts.
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:358
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.