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