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