Panda3D
 All Classes Functions Variables Enumerations
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 
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 0;
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  odetrimeshdata_cat.debug() << get_class_type() << "::remove_data(" << data->get_id() << ")" << "\n";
59  nassertv(_tri_mesh_data_map != (TriMeshDataMap *)NULL);
60  TriMeshDataMap::iterator iter;
61 
62  for (iter = _tri_mesh_data_map->begin();
63  iter != _tri_mesh_data_map->end();
64  ++iter) {
65  if ( iter->second == data ) {
66  break;
67  }
68  }
69 
70  while (iter != _tri_mesh_data_map->end()) {
71  _tri_mesh_data_map->erase(iter);
72 
73  for (iter = _tri_mesh_data_map->begin();
74  iter != _tri_mesh_data_map->end();
75  ++iter) {
76  if ( iter->second == data ) {
77  break;
78  }
79  }
80  }
81 }
82 
83 
84 ////////////////////////////////////////////////////////////////////
85 ////////////////////////////////////////////////////////////////////
86 
87 OdeTriMeshData::
88 OdeTriMeshData(const NodePath& model, bool use_normals) :
89  _id(dGeomTriMeshDataCreate()),
90  _vertices(0),
91  _faces(0),
92  _normals(0),
93  _num_vertices(0),
94  _num_faces(0) {
95  odetrimeshdata_cat.debug() << get_type() << "(" << _id << ")" << "\n";
96 
97  process_model(model, use_normals);
98 
99  write_faces(odetrimeshdata_cat.debug());
100 
101  if (!use_normals) {
102  build_single(_vertices, sizeof(StridedVertex), _num_vertices,
103  _faces, _num_faces * 3, sizeof(StridedTri));
104  } else {
105  build_single1(_vertices, sizeof(StridedVertex), _num_vertices,
106  _faces, _num_faces * 3, sizeof(StridedTri),
107  _normals);
108  }
109 
110  preprocess();
111 }
112 
113 // Private copy constructor, shouldn't be copying these objects
114 OdeTriMeshData::
115 OdeTriMeshData(const OdeTriMeshData &other) {
116 }
117 
118 OdeTriMeshData::
119 ~OdeTriMeshData() {
120  odetrimeshdata_cat.debug() << "~" << get_type() << "(" << _id << ")" << "\n";
121  destroy();
122  if (_vertices != 0) {
123  PANDA_FREE_ARRAY(_vertices);
124  _vertices = 0;
125  _num_vertices = 0;
126  }
127  if (_faces != 0) {
128  PANDA_FREE_ARRAY(_faces);
129  _faces = 0;
130  }
131  if (_normals != 0) {
132  // This is never allocated? Until we use _normals, assert that we
133  // don't accidentally free it here through some mistake.
134  nassertv(false);
135  PANDA_FREE_ARRAY(_normals);
136  }
137 }
138 
139 void OdeTriMeshData::
140 destroy() {
141  odetrimeshdata_cat.debug() << get_type() << "::destroy(" << _id << ")" << "\n";
142  if (_id != 0) {
143  dGeomTriMeshDataDestroy(_id);
144  remove_data(this);
145  _id = 0;
146  }
147 }
148 
149 // Private assignment operator, shouldn't be copying these objects
150 void OdeTriMeshData::
151 operator = (const OdeTriMeshData &other) {
152 }
153 
154 void OdeTriMeshData::
155 process_model(const NodePath& model, bool &use_normals) {
156  // TODO: assert if _vertices is something other than 0.
157  ostream &out = odetrimeshdata_cat.debug();
158  out << "process_model(" << model << ")" << "\n";
159 
160  NodePathCollection geomNodePaths = model.find_all_matches("**/+GeomNode");
161  if (model.node()->get_type() == GeomNode::get_class_type()) {
162  geomNodePaths.add_path(model);
163  }
164 
165  for (int i = 0; i < geomNodePaths.get_num_paths(); ++i) {
166  analyze((GeomNode*)geomNodePaths[i].node());
167  }
168 
169  odetrimeshdata_cat.debug() << "Found " << _num_vertices << " vertices.\n";
170  odetrimeshdata_cat.debug() << "Found " << _num_faces << " faces.\n";
171 
172  _vertices = (StridedVertex *)PANDA_MALLOC_ARRAY(_num_vertices * sizeof(StridedVertex));
173  _faces = (StridedTri *)PANDA_MALLOC_ARRAY(_num_faces * sizeof(StridedTri));
174 
175  _num_vertices = 0, _num_faces = 0;
176 
177  for (int i = 0; i < geomNodePaths.get_num_paths(); ++i) {
178  process_geom_node((GeomNode*)geomNodePaths[i].node());
179  odetrimeshdata_cat.debug() << "_num_vertices now at " << _num_vertices << "\n";
180  }
181 
182  odetrimeshdata_cat.debug() << "Filled " << _num_faces << " triangles(" \
183  << _num_vertices << " vertices)\n";
184 }
185 
186 void OdeTriMeshData::
187 process_geom_node(const GeomNode *geomNode) {
188  ostream &out = odetrimeshdata_cat.debug();
189  out.width(2); out << "" << "process_geom_node(" << *geomNode << ")" << "\n";
190  for (int i = 0; i < geomNode->get_num_geoms(); ++i) {
191  process_geom(geomNode->get_geom(i));
192  }
193 }
194 
195 void OdeTriMeshData::
196 process_geom(const Geom *geom) {
197  ostream &out = odetrimeshdata_cat.debug();
198  out.width(4); out << "" << "process_geom(" << *geom << ")" << "\n";
199  if (geom->get_primitive_type() != Geom::PT_polygons) {
200  return;
201  }
202 
203  CPT(GeomVertexData) vData = geom->get_vertex_data();
204 
205  for (int i = 0; i < geom->get_num_primitives(); ++i) {
206  process_primitive(geom->get_primitive(i), vData);
207  }
208 }
209 
210 void OdeTriMeshData::
211 process_primitive(const GeomPrimitive *primitive,
212  CPT(GeomVertexData) vData) {
213  GeomVertexReader vReader(vData, "vertex");
214  GeomVertexReader nReader(vData, "normal");
215  LVecBase3f vertex, normal;
216  //CPT(GeomPrimitive) dPrimitive = primitive->decompose();
217  CPT(GeomPrimitive) dPrimitive = primitive;
218  ostream &out = odetrimeshdata_cat.debug();
219  out.width(6); out << "" << "process_primitive(" << *dPrimitive << ")" << "\n";
220 
221 
222  if (dPrimitive->get_type() == GeomTriangles::get_class_type()) {
223  for (int i = 0; i < dPrimitive->get_num_primitives(); i++, _num_faces++) {
224  int s = dPrimitive->get_primitive_start(i);
225  int e = dPrimitive->get_primitive_end(i);
226  out.width(8); out << "" << "primitive " << i << ":" << "\n";
227  for (int j = s, m = 0; j < e; j++, m++, _num_vertices++) {
228  int vRowIndex = dPrimitive->get_vertex(j);
229  vReader.set_row_unsafe(vRowIndex);
230  nReader.set_row_unsafe(vRowIndex);
231  vertex = vReader.get_data3f();
232  //normal = nReader.get_data3f();
233  _faces[_num_faces].Indices[m] = _num_vertices;
234 
235  _vertices[_num_vertices].Vertex[0] = vertex[0];
236  _vertices[_num_vertices].Vertex[1] = vertex[1];
237  _vertices[_num_vertices].Vertex[2] = vertex[2];
238 
239  out.width(10); out << "" << "vertex " << j << " has: pos(" \
240  << vertex << ") normal(" << "normal" << ")" << "\n";
241  }
242  }
243  } else if (dPrimitive->get_type() == GeomTristrips::get_class_type()){
244  for (int i = 0; i < dPrimitive->get_num_primitives(); i++, _num_faces++) {
245  int s = dPrimitive->get_primitive_start(i);
246  int e = dPrimitive->get_primitive_end(i);
247  out.width(8); out << "" << "primitive " << i << ":" << "\n";
248  for (int j = s, m = 0; j < e; j++, m++, _num_vertices++) {
249  int vRowIndex = dPrimitive->get_vertex(j);
250  vReader.set_row_unsafe(vRowIndex);
251  nReader.set_row_unsafe(vRowIndex);
252  vertex = vReader.get_data3f();
253  //normal = nReader.get_data3f();
254 
255  _vertices[_num_vertices].Vertex[0] = vertex[0];
256  _vertices[_num_vertices].Vertex[1] = vertex[1];
257  _vertices[_num_vertices].Vertex[2] = vertex[2];
258  out.width(10); out << "" << "vertex " << j << " has: pos(" \
259  << vertex << ") normal(" << "normal" << ")" << "\n";
260  if (m < 3) {
261  _faces[_num_faces].Indices[m] = _num_vertices;
262  } else {
263  _num_faces++;
264  if ( m & 1) {
265  _faces[_num_faces].Indices[0] = _num_vertices-1;
266  _faces[_num_faces].Indices[1] = _num_vertices-2;
267  _faces[_num_faces].Indices[2] = _num_vertices;
268  } else {
269  _faces[_num_faces].Indices[0] = _num_vertices-2;
270  _faces[_num_faces].Indices[1] = _num_vertices-1;
271  _faces[_num_faces].Indices[2] = _num_vertices;
272  }
273  }
274  }
275  out << "\n";
276  }
277  }
278 }
279 void OdeTriMeshData::
280 analyze(const GeomNode *geomNode) {
281  for (int i = 0; i < geomNode->get_num_geoms(); ++i) {
282  analyze(geomNode->get_geom(i));
283  }
284 }
285 
286 void OdeTriMeshData::
287 analyze(const Geom *geom) {
288  if (geom->get_primitive_type() != Geom::PT_polygons) {
289  return;
290  }
291 
292  for (int i = 0; i < geom->get_num_primitives(); ++i) {
293  analyze(geom->get_primitive(i));
294  }
295 }
296 
297 void OdeTriMeshData::
298 analyze(const GeomPrimitive *primitive) {
299  for (int i = 0; i < primitive->get_num_primitives(); ++i) {
300  _num_vertices += primitive->get_primitive_num_vertices(i);
301  _num_faces += primitive->get_primitive_num_faces(i);
302  }
303 }
304 
305 void OdeTriMeshData::
306 write_faces(ostream &out) const {
307  out<<"\n";
308  for (unsigned int i = 0; i < _num_faces; ++i) {
309  out.width(2); out << "Face " << i << ":\n";
310  for (int j = 0; j < 3; ++j) {
311  out.width(4);
312  out << "(" << _vertices[_faces[i].Indices[j]].Vertex[0] \
313  << ", " << _vertices[_faces[i].Indices[j]].Vertex[1] \
314  << ", " << _vertices[_faces[i].Indices[j]].Vertex[2] << ")\n" ;
315  }
316  }
317 }
318 
319 void OdeTriMeshData::
320 write(ostream &out, unsigned int indent) const {
321  out.width(indent); out << "" << get_type() << "(id = " << _id << ") : " \
322  << "" << "Vertices: " << (_id ? _num_vertices : 0) << ", " \
323  << "" << "Triangles: " << (_id ? _num_faces : 0);
324 }
int get_primitive_start(int n) const
Returns the element within the _vertices list at which the nth primitive starts.
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.
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_paths() const
Returns the number of NodePaths in the collection.
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...
A container for geometry primitives.
Definition: geom.h:58
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
Defines a series of disconnected triangles.
Definition: geomTriangles.h:25
int get_primitive_num_faces(int n) const
Returns the number of triangles or other fundamental type (such as line segments) represented by the ...
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 any NodePath in this collection and can be ...
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
int get_num_geoms() const
Returns the number of geoms in the node.
Definition: geomNode.I:46
int get_num_primitives() const
Returns the number of individual primitives stored within this object.
int get_num_primitives() const
Returns the number of GeomPrimitive objects stored within the Geom, each of which represents a number...
Definition: geom.I:110
This is a set of zero or more NodePaths.