00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00028
00029
00030
00031 NodePathCollection BulletHelper::
00032 from_collision_solids(NodePath &np, bool clear) {
00033
00034 NodePathCollection result;
00035
00036
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
00046
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
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
00084
00085
00086
00087
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
00104
00105
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
00131
00132
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
00158
00159
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
00169
00170
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
00180
00181
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
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
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
00269 geom = new Geom(vdata);
00270 geom->add_primitive(prim);
00271
00272 return geom;
00273 }
00274
00275
00276
00277
00278
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