Panda3D

bulletHelper.cxx

00001 // Filename: bulletHelper.cxx
00002 // Created by:  enn0x (19Jan11)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "bulletHelper.h"
00016 #include "bulletRigidBodyNode.h"
00017 #include "bulletGhostNode.h"
00018 
00019 #include "geomLines.h"
00020 #include "geomTriangles.h"
00021 #include "geomVertexRewriter.h"
00022 
00023 PT(InternalName) BulletHelper::_sb_index;
00024 PT(InternalName) BulletHelper::_sb_flip;
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: BulletHelper::from_collision_solids
00028 //       Access: Published
00029 //  Description:
00030 ////////////////////////////////////////////////////////////////////
00031 NodePathCollection BulletHelper::
00032 from_collision_solids(NodePath &np, bool clear) {
00033 
00034   NodePathCollection result;
00035 
00036   // Iterate over all CollisionNodes below the given node
00037   NodePathCollection npc = np.find_all_matches( "**/+CollisionNode" );
00038 
00039   for (int i=0; i<npc.get_num_paths(); i++) {
00040     NodePath cnp = npc.get_path(i);
00041     CollisionNode *cnode = DCAST(CollisionNode, cnp.node());
00042 
00043     PT(PandaNode) bnode = NULL;
00044 
00045     // Create a either a new rigid body or a new ghost for each CollisionNode,
00046     // and add one shape per CollisionSolid contained in the CollisionNode
00047     if (is_tangible(cnode)) {
00048       PT(BulletRigidBodyNode) body;
00049 
00050       body = new BulletRigidBodyNode();
00051       body->add_shapes_from_collision_solids(cnode);
00052       body->set_transform(cnp.get_transform(np));
00053       body->set_into_collide_mask(cnode->get_into_collide_mask());
00054       body->set_mass(0.0f);
00055       body->set_name(cnode->get_name());
00056 
00057       bnode = body;
00058     }
00059     else {
00060       PT(BulletGhostNode) ghost;
00061 
00062       ghost = new BulletGhostNode();
00063       ghost->add_shapes_from_collision_solids(cnode);
00064       ghost->set_transform(cnp.get_transform(np));
00065       ghost->set_into_collide_mask(cnode->get_into_collide_mask());
00066       ghost->set_name(cnode->get_name());
00067 
00068       bnode = ghost;
00069     }
00070 
00071     // Remove collision node if requested
00072     if (clear) {
00073       cnp.remove_node();
00074     }
00075 
00076     result.add_path(NodePath::any_path(bnode));
00077   }
00078 
00079   return result;
00080 }
00081 
00082 ////////////////////////////////////////////////////////////////////
00083 //     Function: BulletHelper::is_tangible
00084 //       Access: Private
00085 //  Description: Returns TRUE if at least one CollisionSolid of
00086 //               the given CollisionNode is tangible. Returns FALSE
00087 //               if all CollisionSolids are intangible.
00088 ////////////////////////////////////////////////////////////////////
00089 bool BulletHelper::
00090 is_tangible(CollisionNode *cnode) {
00091 
00092   for (int j=0; j<cnode->get_num_solids(); j++) {
00093     CPT(CollisionSolid) solid = cnode->get_solid(j);
00094     if (solid->is_tangible()) {
00095         return true;
00096     }
00097   }
00098 
00099   return false;
00100 }
00101 
00102 ////////////////////////////////////////////////////////////////////
00103 //     Function: BulletHelper::add_sb_index_column
00104 //       Access: Private
00105 //  Description: 
00106 ////////////////////////////////////////////////////////////////////
00107 CPT(GeomVertexFormat) BulletHelper::
00108 add_sb_index_column(const GeomVertexFormat *format) {
00109 
00110   PT(InternalName) name = BulletHelper::get_sb_index();
00111 
00112   if (format->has_column(name)) return format;
00113 
00114   PT(GeomVertexArrayFormat) array;
00115   PT(GeomVertexFormat) unregistered_format;
00116   CPT(GeomVertexFormat) registered_format;
00117 
00118   array = new GeomVertexArrayFormat();
00119   array->add_column(name, 1, Geom::NT_uint16, Geom::C_index);
00120 
00121   unregistered_format = new GeomVertexFormat(*format);
00122   unregistered_format->add_array(array);
00123 
00124   registered_format = GeomVertexFormat::register_format(unregistered_format);
00125 
00126   return registered_format;
00127 }
00128 
00129 ////////////////////////////////////////////////////////////////////
00130 //     Function: BulletHelper::add_sb_flip_column
00131 //       Access: Private
00132 //  Description: 
00133 ////////////////////////////////////////////////////////////////////
00134 CPT(GeomVertexFormat) BulletHelper::
00135 add_sb_flip_column(const GeomVertexFormat *format) {
00136 
00137   PT(InternalName) name = BulletHelper::get_sb_flip();
00138 
00139   if (format->has_column(name)) return format;
00140 
00141   PT(GeomVertexArrayFormat) array;
00142   PT(GeomVertexFormat) unregistered_format;
00143   CPT(GeomVertexFormat) registered_format;
00144 
00145   array = new GeomVertexArrayFormat();
00146   array->add_column(name, 1, Geom::NT_uint8, Geom::C_other);
00147 
00148   unregistered_format = new GeomVertexFormat(*format);
00149   unregistered_format->add_array(array);
00150 
00151   registered_format = GeomVertexFormat::register_format(unregistered_format);
00152 
00153   return registered_format;
00154 }
00155 
00156 ////////////////////////////////////////////////////////////////////
00157 //     Function: BulletHelper::make_geom_from_faces
00158 //       Access: Published
00159 //  Description:
00160 ////////////////////////////////////////////////////////////////////
00161 PT(Geom) BulletHelper::
00162 make_geom_from_faces(BulletSoftBodyNode *node, const GeomVertexFormat *format, bool two_sided) {
00163 
00164   return make_geom(node, format, two_sided, true);
00165 }
00166 
00167 ////////////////////////////////////////////////////////////////////
00168 //     Function: BulletHelper::make_geom_from_links
00169 //       Access: Published
00170 //  Description:
00171 ////////////////////////////////////////////////////////////////////
00172 PT(Geom) BulletHelper::
00173 make_geom_from_links(BulletSoftBodyNode *node, const GeomVertexFormat *format) {
00174 
00175   return make_geom(node, format, false, false);
00176 }
00177 
00178 ////////////////////////////////////////////////////////////////////
00179 //     Function: BulletHelper::make_geom
00180 //       Access: Private
00181 //  Description:
00182 ////////////////////////////////////////////////////////////////////
00183 PT(Geom) BulletHelper::
00184 make_geom(BulletSoftBodyNode *node, const GeomVertexFormat *format, bool two_sided, bool use_faces) {
00185 
00186   btTransform trans = btTransform::getIdentity();
00187   get_node_transform(trans, node);
00188 
00189   btSoftBody *body = (btSoftBody *)node->get_object();
00190 
00191   PT(Geom) geom;
00192   PT(GeomPrimitive) prim;
00193   PT(GeomVertexData) vdata;
00194 
00195   CPT(GeomVertexFormat) fmt = (format) ? format : GeomVertexFormat::get_v3n3t2();
00196   fmt = BulletHelper::add_sb_flip_column(fmt);
00197 
00198   nassertr(fmt->has_column(InternalName::get_vertex()), NULL);
00199   nassertr(fmt->has_column(InternalName::get_normal()), NULL);
00200 
00201   btSoftBody::tNodeArray &nodes(body->m_nodes);
00202 
00203   // Vertex data
00204   vdata = new GeomVertexData("", fmt, Geom::UH_stream);
00205 
00206   GeomVertexWriter vwriter(vdata, InternalName::get_vertex());
00207   GeomVertexWriter nwriter(vdata, InternalName::get_normal());
00208   GeomVertexWriter fwriter(vdata, BulletHelper::get_sb_flip());
00209 
00210   for (int j=0; j<nodes.size(); ++j) {
00211     btVector3 v = nodes[j].m_x;
00212     btVector3 &n = nodes[j].m_n;
00213 
00214     v = trans.invXform(v);
00215 
00216     vwriter.add_data3((PN_stdfloat)v.getX(), (PN_stdfloat)v.getY(), (PN_stdfloat)v.getZ());
00217     nwriter.add_data3((PN_stdfloat)n.getX(), (PN_stdfloat)n.getY(), (PN_stdfloat)n.getZ());
00218     fwriter.add_data1i(0);
00219   }
00220 
00221   if (two_sided) {
00222     for (int j=0; j<nodes.size(); ++j) {
00223       btVector3 &v = nodes[j].m_x;
00224       btVector3 &n = nodes[j].m_n;
00225 
00226       vwriter.add_data3((PN_stdfloat)v.getX(), (PN_stdfloat)v.getY(), (PN_stdfloat)v.getZ());
00227       nwriter.add_data3((PN_stdfloat)n.getX(), (PN_stdfloat)n.getY(), (PN_stdfloat)n.getZ());
00228       fwriter.add_data1i(1);
00229     }
00230   }
00231 
00232   // Indices
00233   btSoftBody::Node *node0 = &nodes[0];
00234 
00235   if (use_faces) {
00236     btSoftBody::tFaceArray &faces(body->m_faces);
00237 
00238     prim = new GeomTriangles(Geom::UH_stream);
00239     prim->set_shade_model(Geom::SM_uniform);
00240 
00241     for (int j=0; j<faces.size(); ++j) {
00242       prim->add_vertices(int(faces[j].m_n[0] - node0),
00243                          int(faces[j].m_n[1] - node0),
00244                          int(faces[j].m_n[2] - node0));
00245       prim->close_primitive();
00246 
00247       if (two_sided) {
00248         prim->add_vertices(nodes.size() + int(faces[j].m_n[0] - node0),
00249                            nodes.size() + int(faces[j].m_n[2] - node0),
00250                            nodes.size() + int(faces[j].m_n[1] - node0));
00251         prim->close_primitive();
00252       }
00253     }
00254   }
00255   else {
00256     btSoftBody::tLinkArray &links(body->m_links);
00257 
00258     prim = new GeomLines(Geom::UH_stream);
00259     prim->set_shade_model(Geom::SM_uniform);
00260 
00261     for (int j=0; j<links.size(); ++j) {
00262       prim->add_vertices(int(links[j].m_n[0] - node0),
00263                          int(links[j].m_n[1] - node0));
00264       prim->close_primitive();
00265     }
00266   }
00267 
00268   // Geom
00269   geom = new Geom(vdata);
00270   geom->add_primitive(prim);
00271 
00272   return geom;
00273 }
00274 
00275 ////////////////////////////////////////////////////////////////////
00276 //     Function: BulletHelper::make_texcoords_for_patch
00277 //       Access: Published
00278 //  Description:
00279 ////////////////////////////////////////////////////////////////////
00280 void BulletHelper::
00281 make_texcoords_for_patch(Geom *geom, int resx, int resy) {
00282 
00283   PT(GeomVertexData) vdata = geom->modify_vertex_data();
00284 
00285   nassertv(vdata->has_column(InternalName::get_texcoord()));
00286 
00287   GeomVertexRewriter texcoords(vdata, InternalName::get_texcoord());
00288 
00289   int n = resx * resy;
00290   int i = 0;
00291   int ix;
00292   int iy;
00293   float u;
00294   float v;
00295 
00296   while (!texcoords.is_at_end()) {
00297     ix = i / resx;
00298     iy = i % resy;
00299 
00300     if (i > n) ix -= 1;
00301 
00302     u = (float)ix/(float)(resx - 1);
00303     v = (float)iy/(float)(resy - 1);
00304 
00305     texcoords.set_data2f(u, v);
00306     i++;
00307   }
00308 }
00309 
 All Classes Functions Variables Enumerations