Panda3D
|
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