Panda3D
 All Classes Functions Variables Enumerations
bulletHelper.cxx
1 // Filename: bulletHelper.cxx
2 // Created by: enn0x (19Jan11)
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 
15 #include "bulletHelper.h"
16 #include "bulletRigidBodyNode.h"
17 #include "bulletGhostNode.h"
18 
19 #include "geomLines.h"
20 #include "geomTriangles.h"
21 #include "geomVertexRewriter.h"
22 
23 PT(InternalName) BulletHelper::_sb_index;
24 PT(InternalName) BulletHelper::_sb_flip;
25 
26 ////////////////////////////////////////////////////////////////////
27 // Function: BulletHelper::from_collision_solids
28 // Access: Published
29 // Description:
30 ////////////////////////////////////////////////////////////////////
32 from_collision_solids(NodePath &np, bool clear) {
33 
34  NodePathCollection result;
35 
36  // Iterate over all CollisionNodes below the given node
37  NodePathCollection npc = np.find_all_matches( "**/+CollisionNode" );
38 
39  for (int i=0; i<npc.get_num_paths(); i++) {
40  NodePath cnp = npc.get_path(i);
41  CollisionNode *cnode = DCAST(CollisionNode, cnp.node());
42 
43  PT(PandaNode) bnode = NULL;
44 
45  // Create a either a new rigid body or a new ghost for each CollisionNode,
46  // and add one shape per CollisionSolid contained in the CollisionNode
47  if (is_tangible(cnode)) {
48  PT(BulletRigidBodyNode) body;
49 
50  body = new BulletRigidBodyNode();
51  body->add_shapes_from_collision_solids(cnode);
52  body->set_transform(cnp.get_transform(np));
53  body->set_into_collide_mask(cnode->get_into_collide_mask());
54  body->set_mass(0.0f);
55  body->set_name(cnode->get_name());
56 
57  bnode = body;
58  }
59  else {
60  PT(BulletGhostNode) ghost;
61 
62  ghost = new BulletGhostNode();
63  ghost->add_shapes_from_collision_solids(cnode);
64  ghost->set_transform(cnp.get_transform(np));
65  ghost->set_into_collide_mask(cnode->get_into_collide_mask());
66  ghost->set_name(cnode->get_name());
67 
68  bnode = ghost;
69  }
70 
71  // Remove collision node if requested
72  if (clear) {
73  cnp.remove_node();
74  }
75 
76  result.add_path(NodePath::any_path(bnode));
77  }
78 
79  return result;
80 }
81 
82 ////////////////////////////////////////////////////////////////////
83 // Function: BulletHelper::is_tangible
84 // Access: Private
85 // Description: Returns TRUE if at least one CollisionSolid of
86 // the given CollisionNode is tangible. Returns FALSE
87 // if all CollisionSolids are intangible.
88 ////////////////////////////////////////////////////////////////////
89 bool BulletHelper::
90 is_tangible(CollisionNode *cnode) {
91 
92  for (int j=0; j<cnode->get_num_solids(); j++) {
93  CPT(CollisionSolid) solid = cnode->get_solid(j);
94  if (solid->is_tangible()) {
95  return true;
96  }
97  }
98 
99  return false;
100 }
101 
102 ////////////////////////////////////////////////////////////////////
103 // Function: BulletHelper::add_sb_index_column
104 // Access: Private
105 // Description:
106 ////////////////////////////////////////////////////////////////////
107 CPT(GeomVertexFormat) BulletHelper::
108 add_sb_index_column(const GeomVertexFormat *format) {
109 
110  PT(InternalName) name = BulletHelper::get_sb_index();
111 
112  if (format->has_column(name)) return format;
113 
114  PT(GeomVertexArrayFormat) array;
115  PT(GeomVertexFormat) unregistered_format;
116  CPT(GeomVertexFormat) registered_format;
117 
118  array = new GeomVertexArrayFormat();
119  array->add_column(name, 1, Geom::NT_uint16, Geom::C_index);
120 
121  unregistered_format = new GeomVertexFormat(*format);
122  unregistered_format->add_array(array);
123 
124  registered_format = GeomVertexFormat::register_format(unregistered_format);
125 
126  return registered_format;
127 }
128 
129 ////////////////////////////////////////////////////////////////////
130 // Function: BulletHelper::add_sb_flip_column
131 // Access: Private
132 // Description:
133 ////////////////////////////////////////////////////////////////////
134 CPT(GeomVertexFormat) BulletHelper::
135 add_sb_flip_column(const GeomVertexFormat *format) {
136 
137  PT(InternalName) name = BulletHelper::get_sb_flip();
138 
139  if (format->has_column(name)) return format;
140 
141  PT(GeomVertexArrayFormat) array;
142  PT(GeomVertexFormat) unregistered_format;
143  CPT(GeomVertexFormat) registered_format;
144 
145  array = new GeomVertexArrayFormat();
146  array->add_column(name, 1, Geom::NT_uint8, Geom::C_other);
147 
148  unregistered_format = new GeomVertexFormat(*format);
149  unregistered_format->add_array(array);
150 
151  registered_format = GeomVertexFormat::register_format(unregistered_format);
152 
153  return registered_format;
154 }
155 
156 ////////////////////////////////////////////////////////////////////
157 // Function: BulletHelper::make_geom_from_faces
158 // Access: Published
159 // Description:
160 ////////////////////////////////////////////////////////////////////
161 PT(Geom) BulletHelper::
162 make_geom_from_faces(BulletSoftBodyNode *node, const GeomVertexFormat *format, bool two_sided) {
163 
164  return make_geom(node, format, two_sided, true);
165 }
166 
167 ////////////////////////////////////////////////////////////////////
168 // Function: BulletHelper::make_geom_from_links
169 // Access: Published
170 // Description:
171 ////////////////////////////////////////////////////////////////////
172 PT(Geom) BulletHelper::
173 make_geom_from_links(BulletSoftBodyNode *node, const GeomVertexFormat *format) {
174 
175  return make_geom(node, format, false, false);
176 }
177 
178 ////////////////////////////////////////////////////////////////////
179 // Function: BulletHelper::make_geom
180 // Access: Private
181 // Description:
182 ////////////////////////////////////////////////////////////////////
183 PT(Geom) BulletHelper::
184 make_geom(BulletSoftBodyNode *node, const GeomVertexFormat *format, bool two_sided, bool use_faces) {
185 
186  btTransform trans = btTransform::getIdentity();
187  get_node_transform(trans, node);
188 
189  btSoftBody *body = (btSoftBody *)node->get_object();
190 
191  PT(Geom) geom;
192  PT(GeomPrimitive) prim;
193  PT(GeomVertexData) vdata;
194 
195  CPT(GeomVertexFormat) fmt = (format) ? format : GeomVertexFormat::get_v3n3t2();
196  fmt = BulletHelper::add_sb_flip_column(fmt);
197 
198  nassertr(fmt->has_column(InternalName::get_vertex()), NULL);
199  nassertr(fmt->has_column(InternalName::get_normal()), NULL);
200 
201  btSoftBody::tNodeArray &nodes(body->m_nodes);
202 
203  // Vertex data
204  vdata = new GeomVertexData("", fmt, Geom::UH_stream);
205 
206  GeomVertexWriter vwriter(vdata, InternalName::get_vertex());
207  GeomVertexWriter nwriter(vdata, InternalName::get_normal());
208  GeomVertexWriter fwriter(vdata, BulletHelper::get_sb_flip());
209 
210  for (int j=0; j<nodes.size(); ++j) {
211  btVector3 v = nodes[j].m_x;
212  btVector3 &n = nodes[j].m_n;
213 
214  v = trans.invXform(v);
215 
216  vwriter.add_data3((PN_stdfloat)v.getX(), (PN_stdfloat)v.getY(), (PN_stdfloat)v.getZ());
217  nwriter.add_data3((PN_stdfloat)n.getX(), (PN_stdfloat)n.getY(), (PN_stdfloat)n.getZ());
218  fwriter.add_data1i(0);
219  }
220 
221  if (two_sided) {
222  for (int j=0; j<nodes.size(); ++j) {
223  btVector3 v = nodes[j].m_x;
224  btVector3 &n = nodes[j].m_n;
225 
226  v = trans.invXform(v);
227 
228  vwriter.add_data3((PN_stdfloat)v.getX(), (PN_stdfloat)v.getY(), (PN_stdfloat)v.getZ());
229  nwriter.add_data3((PN_stdfloat)n.getX(), (PN_stdfloat)n.getY(), (PN_stdfloat)n.getZ());
230  fwriter.add_data1i(1);
231  }
232  }
233 
234  // Indices
235  btSoftBody::Node *node0 = &nodes[0];
236  int i0, i1, i2;
237 
238  if (use_faces) {
239 
240  btSoftBody::tFaceArray &faces(body->m_faces);
241 
242  prim = new GeomTriangles(Geom::UH_stream);
243  prim->set_shade_model(Geom::SM_uniform);
244 
245  for (int j=0; j<faces.size(); ++j) {
246  i0 = int(faces[j].m_n[0] - node0);
247  i1 = int(faces[j].m_n[1] - node0);
248  i2 = int(faces[j].m_n[2] - node0);
249 
250  prim->add_vertices(i0, i1, i2);
251  prim->close_primitive();
252 
253  if (two_sided) {
254  i0 = nodes.size() + int(faces[j].m_n[0] - node0);
255  i1 = nodes.size() + int(faces[j].m_n[2] - node0);
256  i2 = nodes.size() + int(faces[j].m_n[1] - node0);
257 
258  prim->add_vertices(i0, i1, i2);
259  prim->close_primitive();
260  }
261  }
262  }
263  else {
264  btSoftBody::tLinkArray &links(body->m_links);
265 
266  prim = new GeomLines(Geom::UH_stream);
267  prim->set_shade_model(Geom::SM_uniform);
268 
269  for (int j=0; j<links.size(); ++j) {
270  i0 = int(links[j].m_n[0] - node0);
271  i1 = int(links[j].m_n[1] - node0);
272 
273  prim->add_vertices(i0, i1);
274  prim->close_primitive();
275  }
276  }
277 
278  // Geom
279  geom = new Geom(vdata);
280  geom->add_primitive(prim);
281 
282  return geom;
283 }
284 
285 ////////////////////////////////////////////////////////////////////
286 // Function: BulletHelper::make_texcoords_for_patch
287 // Access: Published
288 // Description:
289 ////////////////////////////////////////////////////////////////////
290 void BulletHelper::
291 make_texcoords_for_patch(Geom *geom, int resx, int resy) {
292 
293  PT(GeomVertexData) vdata = geom->modify_vertex_data();
294 
295  nassertv(vdata->has_column(InternalName::get_texcoord()));
296 
297  GeomVertexRewriter texcoords(vdata, InternalName::get_texcoord());
298 
299  int n = resx * resy;
300  int i = 0;
301  int ix;
302  int iy;
303  float u;
304  float v;
305 
306  while (!texcoords.is_at_end()) {
307  ix = i / resx;
308  iy = i % resy;
309 
310  if (i > n) ix -= 1;
311 
312  u = (float)ix/(float)(resx - 1);
313  v = (float)iy/(float)(resy - 1);
314 
315  texcoords.set_data2f(u, v);
316  i++;
317  }
318 }
319 
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
void add_path(const NodePath &node_path)
Adds a new NodePath to the collection.
The abstract base class for all things that can collide with other things in the world, and all the things they can collide with (except geometry).
NodePath get_path(int index) const
Returns the nth NodePath in the collection.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:63
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:284
void add_primitive(const GeomPrimitive *primitive)
Adds a new GeomPrimitive structure to the Geom object.
Definition: geom.cxx:366
int get_num_paths() const
Returns the number of NodePaths in the collection.
static NodePath any_path(PandaNode *node, Thread *current_thread=Thread::get_current_thread())
Returns a new NodePath that represents any arbitrary path from the root to the indicated node...
Definition: nodePath.I:77
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
Defines a series of disconnected line segments.
Definition: geomLines.h:25
void remove_node(Thread *current_thread=Thread::get_current_thread())
Disconnects the referenced node from the scene graph.
Definition: nodePath.cxx:757
A node in the scene graph that can hold any number of CollisionSolids.
Definition: collisionNode.h:33
Defines a series of disconnected triangles.
Definition: geomTriangles.h:25
void set_data2f(float x, float y)
Sets the write row to a particular 2-component value, and advances the write row. ...
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
This object provides the functionality of both a GeomVertexReader and a GeomVertexWriter, combined together into one convenient package.
This is a set of zero or more NodePaths.