00001 // Filename: physxShape.cxx 00002 // Created by: enn0x (16Sep09) 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 "physxShape.h" 00016 #include "physxManager.h" 00017 #include "physxActor.h" 00018 #include "physxBoxShape.h" 00019 #include "physxCapsuleShape.h" 00020 #include "physxPlaneShape.h" 00021 #include "physxSphereShape.h" 00022 #include "physxConvexShape.h" 00023 #include "physxHeightFieldShape.h" 00024 #include "physxTriangleMeshShape.h" 00025 #include "physxWheelShape.h" 00026 #include "physxGroupsMask.h" 00027 #include "physxBounds3.h" 00028 #include "physxSphere.h" 00029 #include "physxBox.h" 00030 #include "physxCapsule.h" 00031 #include "physxRay.h" 00032 #include "physxRaycastHit.h" 00033 00034 TypeHandle PhysxShape::_type_handle; 00035 00036 //////////////////////////////////////////////////////////////////// 00037 // Function: PhysxShape::release 00038 // Access: Published 00039 // Description: 00040 //////////////////////////////////////////////////////////////////// 00041 void PhysxShape:: 00042 release() { 00043 00044 nassertv(_error_type == ET_ok); 00045 00046 unlink(); 00047 ptr()->getActor().releaseShape(*ptr()); 00048 } 00049 00050 //////////////////////////////////////////////////////////////////// 00051 // Function: PhysxShape::factory 00052 // Access: Public 00053 // Description: 00054 //////////////////////////////////////////////////////////////////// 00055 PhysxShape *PhysxShape:: 00056 factory(NxShapeType shapeType) { 00057 00058 switch (shapeType) { 00059 00060 case NX_SHAPE_PLANE: 00061 return new PhysxPlaneShape(); 00062 00063 case NX_SHAPE_SPHERE: 00064 return new PhysxSphereShape(); 00065 00066 case NX_SHAPE_BOX: 00067 return new PhysxBoxShape(); 00068 00069 case NX_SHAPE_CAPSULE: 00070 return new PhysxCapsuleShape(); 00071 00072 case NX_SHAPE_CONVEX: 00073 return new PhysxConvexShape(); 00074 00075 case NX_SHAPE_MESH: 00076 return new PhysxTriangleMeshShape(); 00077 00078 case NX_SHAPE_HEIGHTFIELD: 00079 return new PhysxHeightFieldShape(); 00080 00081 case NX_SHAPE_WHEEL: 00082 return new PhysxWheelShape(); 00083 } 00084 00085 physx_cat.error() << "Unknown shape type.\n"; 00086 return NULL; 00087 } 00088 00089 //////////////////////////////////////////////////////////////////// 00090 // Function: PhysxShape::get_actor 00091 // Access: Published 00092 // Description: Retrieves the actor which this shape is associated 00093 // with. 00094 //////////////////////////////////////////////////////////////////// 00095 PhysxActor *PhysxShape:: 00096 get_actor() const { 00097 00098 nassertr(_error_type == ET_ok, NULL); 00099 return (PhysxActor *)(ptr()->getActor().userData); 00100 } 00101 00102 //////////////////////////////////////////////////////////////////// 00103 // Function: PhysxShape::set_name 00104 // Access: Published 00105 // Description: Sets a name string for this object. The name can 00106 // be retrieved again with get_name(). 00107 // This is for debugging and is not used by the 00108 // physics engine. 00109 //////////////////////////////////////////////////////////////////// 00110 void PhysxShape:: 00111 set_name(const char *name) { 00112 00113 nassertv(_error_type == ET_ok); 00114 00115 _name = name ? name : ""; 00116 ptr()->setName(_name.c_str()); 00117 } 00118 00119 //////////////////////////////////////////////////////////////////// 00120 // Function: PhysxShape::get_name 00121 // Access: Published 00122 // Description: Returns the name string. 00123 //////////////////////////////////////////////////////////////////// 00124 const char *PhysxShape:: 00125 get_name() const { 00126 00127 nassertr(_error_type == ET_ok, ""); 00128 return ptr()->getName(); 00129 } 00130 00131 //////////////////////////////////////////////////////////////////// 00132 // Function: PhysxShape::set_flag 00133 // Access: Published 00134 // Description: Sets the specified shape flag. 00135 // 00136 // The shape may be turned into a trigger by setting 00137 // one or more of the TriggerFlags to true. A trigger 00138 // shape will not collide with other shapes. Instead, 00139 // if a shape enters the trigger's volume, a trigger 00140 // event will be sent. Trigger events can be listened 00141 // to by DirectObjects. 00142 // The following trigger events can be sent: 00143 // - physx-trigger-enter 00144 // - physx-trigger-stay 00145 // - physx-trigger-leave 00146 //////////////////////////////////////////////////////////////////// 00147 void PhysxShape:: 00148 set_flag(PhysxShapeFlag flag, bool value) { 00149 00150 nassertv(_error_type == ET_ok); 00151 00152 ptr()->setFlag((NxShapeFlag)flag, value); 00153 } 00154 00155 //////////////////////////////////////////////////////////////////// 00156 // Function: PhysxShape::get_flag 00157 // Access: Published 00158 // Description: Returns the specified shape flag. 00159 //////////////////////////////////////////////////////////////////// 00160 bool PhysxShape:: 00161 get_flag(PhysxShapeFlag flag) const { 00162 00163 nassertr(_error_type == ET_ok, false); 00164 00165 return (ptr()->getFlag((NxShapeFlag)flag)) ? true : false; 00166 } 00167 00168 //////////////////////////////////////////////////////////////////// 00169 // Function: PhysxShape::set_skin_width 00170 // Access: Published 00171 // Description: Sets the skin width. 00172 // The skin width must be non-negative. 00173 //////////////////////////////////////////////////////////////////// 00174 void PhysxShape:: 00175 set_skin_width(float skinWidth) { 00176 00177 nassertv(_error_type == ET_ok); 00178 nassertv(skinWidth >= 0.0f); 00179 00180 ptr()->setSkinWidth(skinWidth); 00181 } 00182 00183 //////////////////////////////////////////////////////////////////// 00184 // Function: PhysxShape::get_skin_width 00185 // Access: Published 00186 // Description: Returns the skin width. 00187 //////////////////////////////////////////////////////////////////// 00188 float PhysxShape:: 00189 get_skin_width() const { 00190 00191 nassertr(_error_type == ET_ok, 0.0f); 00192 00193 return ptr()->getSkinWidth(); 00194 } 00195 00196 //////////////////////////////////////////////////////////////////// 00197 // Function: PhysxShape::set_group 00198 // Access: Published 00199 // Description: Sets which collision group this shape is part of. 00200 // 00201 // Default group is 0. Maximum possible group is 31. 00202 // Collision groups are sets of shapes which may or 00203 // may not be set to collision detect with each other; 00204 // this can be set using 00205 // PhysxScene::set_group_collision_flag(). 00206 //////////////////////////////////////////////////////////////////// 00207 void PhysxShape:: 00208 set_group(unsigned short group) { 00209 00210 nassertv(_error_type == ET_ok); 00211 nassertv(group < 32); 00212 00213 ptr()->setGroup(group); 00214 } 00215 00216 //////////////////////////////////////////////////////////////////// 00217 // Function: PhysxShape::get_group 00218 // Access: Published 00219 // Description: Retrieves the collision group set for this shape. 00220 // The collision group is an integer between 0 and 00221 // 31. 00222 //////////////////////////////////////////////////////////////////// 00223 unsigned short PhysxShape:: 00224 get_group() const { 00225 00226 nassertr(_error_type == ET_ok, 0); 00227 00228 return ptr()->getGroup(); 00229 } 00230 00231 //////////////////////////////////////////////////////////////////// 00232 // Function: PhysxShape::set_local_pos 00233 // Access: Published 00234 // Description: Set the position of the shape in actor space, i.e. 00235 // relative to the actor it is owned by. 00236 // 00237 // Calling this method does NOT wake the associated 00238 // actor up automatically. 00239 // 00240 // Calling this method does not automatically update 00241 // the inertia properties of the owning actor (if 00242 // applicable); use 00243 // PhysxActor::update_mass_from_shapes() to do this. 00244 //////////////////////////////////////////////////////////////////// 00245 void PhysxShape:: 00246 set_local_pos(const LPoint3f &pos) { 00247 00248 nassertv(_error_type == ET_ok); 00249 00250 ptr()->setLocalPosition(PhysxManager::point3_to_nxVec3(pos)); 00251 } 00252 00253 //////////////////////////////////////////////////////////////////// 00254 // Function: PhysxShape::get_local_pos 00255 // Access: Published 00256 // Description: Retrieve the position of the shape in actor space, 00257 // i.e. relative to the actor it is owned by. 00258 //////////////////////////////////////////////////////////////////// 00259 LPoint3f PhysxShape:: 00260 get_local_pos() const { 00261 00262 nassertr(_error_type == ET_ok, LPoint3f::zero()); 00263 00264 return PhysxManager::nxVec3_to_point3(ptr()->getLocalPosition()); 00265 } 00266 00267 //////////////////////////////////////////////////////////////////// 00268 // Function: PhysxShape::set_local_mat 00269 // Access: Published 00270 // Description: Set the transform of the shape in actor space, 00271 // i.e. relative to the actor it is owned by. 00272 // 00273 // Calling this method does NOT wake the associated 00274 // actor up automatically. 00275 // 00276 // Calling this method does not automatically update 00277 // the inertia properties of the owning actor (if 00278 // applicable); use 00279 // PhysxActor::update_mass_from_shapes() to do this. 00280 //////////////////////////////////////////////////////////////////// 00281 void PhysxShape:: 00282 set_local_mat(const LMatrix4f &mat) { 00283 00284 nassertv(_error_type == ET_ok); 00285 00286 ptr()->setLocalPose(PhysxManager::mat4_to_nxMat34(mat)); 00287 } 00288 00289 //////////////////////////////////////////////////////////////////// 00290 // Function: PhysxShape::get_local_mat 00291 // Access: Published 00292 // Description: Retrieve the transform of the shape in actor space, 00293 // i.e. relative to the actor it is owned by. 00294 //////////////////////////////////////////////////////////////////// 00295 LMatrix4f PhysxShape:: 00296 get_local_mat() const { 00297 00298 nassertr(_error_type == ET_ok, LMatrix4f::zeros_mat()); 00299 00300 return PhysxManager::nxMat34_to_mat4(ptr()->getLocalPose()); 00301 } 00302 00303 //////////////////////////////////////////////////////////////////// 00304 // Function: PhysxShape::get_material_index 00305 // Access: Published 00306 // Description: Returns the material index currently assigned to 00307 // the shape. 00308 //////////////////////////////////////////////////////////////////// 00309 unsigned short PhysxShape:: 00310 get_material_index() const { 00311 00312 nassertr(_error_type == ET_ok, 0); 00313 NxMaterialIndex index = ptr()->getMaterial(); 00314 return (unsigned int)index; 00315 } 00316 00317 //////////////////////////////////////////////////////////////////// 00318 // Function: PhysxShape::set_material 00319 // Access: Published 00320 // Description: Assigns a material to the shape. 00321 //////////////////////////////////////////////////////////////////// 00322 void PhysxShape:: 00323 set_material(const PhysxMaterial &material) { 00324 00325 nassertv(_error_type == ET_ok); 00326 ptr()->setMaterial(material.ptr()->getMaterialIndex()); 00327 } 00328 00329 //////////////////////////////////////////////////////////////////// 00330 // Function: PhysxShape::set_material_index 00331 // Access: Published 00332 // Description: Assigns a material index to the shape. 00333 // 00334 // The material index can be retrieved by calling 00335 // PhysxMaterial::get_material_index(). If the material 00336 // index is invalid, it will still be recorded, but 00337 // the default material (at index 0) will effectively 00338 // be used for simulation. 00339 //////////////////////////////////////////////////////////////////// 00340 void PhysxShape:: 00341 set_material_index(unsigned short index) { 00342 00343 nassertv(_error_type == ET_ok); 00344 ptr()->setMaterial((NxMaterialIndex)index); 00345 } 00346 00347 //////////////////////////////////////////////////////////////////// 00348 // Function: PhysxShape::set_groups_mask 00349 // Access: Published 00350 // Description: Sets 128-bit mask used for collision filtering. 00351 // Does NOT wake the associated actor up 00352 // automatically. 00353 //////////////////////////////////////////////////////////////////// 00354 void PhysxShape:: 00355 set_groups_mask(const PhysxGroupsMask &mask) { 00356 00357 nassertv(_error_type == ET_ok); 00358 ptr()->setGroupsMask(mask.get_mask()); 00359 } 00360 00361 //////////////////////////////////////////////////////////////////// 00362 // Function: PhysxShape::get_groups_mask 00363 // Access: Published 00364 // Description: Gets 128-bit mask used for collision filtering. 00365 //////////////////////////////////////////////////////////////////// 00366 PhysxGroupsMask PhysxShape:: 00367 get_groups_mask() const { 00368 00369 PhysxGroupsMask mask; 00370 nassertr(_error_type == ET_ok, mask); 00371 mask.set_mask(ptr()->getGroupsMask()); 00372 return mask; 00373 } 00374 00375 //////////////////////////////////////////////////////////////////// 00376 // Function: PhysxShape::get_world_bounds 00377 // Access: Published 00378 // Description: Returns a world space AABB enclosing this shape. 00379 //////////////////////////////////////////////////////////////////// 00380 PhysxBounds3 PhysxShape:: 00381 get_world_bounds() const { 00382 00383 PhysxBounds3 bounds; 00384 nassertr(_error_type == ET_ok, bounds); 00385 ptr()->getWorldBounds(bounds._bounds); 00386 return bounds; 00387 } 00388 00389 //////////////////////////////////////////////////////////////////// 00390 // Function: PhysxShape::check_overlap_aabb 00391 // Access: Published 00392 // Description: Checks whether the shape overlaps a world-space 00393 // AABB or not. 00394 //////////////////////////////////////////////////////////////////// 00395 bool PhysxShape:: 00396 check_overlap_aabb(const PhysxBounds3 &world_bounds) const { 00397 00398 nassertr(_error_type == ET_ok, false); 00399 return ptr()->checkOverlapAABB(world_bounds._bounds); 00400 } 00401 00402 //////////////////////////////////////////////////////////////////// 00403 // Function: PhysxShape::check_overlap_capsule 00404 // Access: Published 00405 // Description: Checks whether the shape overlaps a world-space 00406 // capsule or not. 00407 //////////////////////////////////////////////////////////////////// 00408 bool PhysxShape:: 00409 check_overlap_capsule(const PhysxCapsule &world_capsule) const { 00410 00411 nassertr(_error_type == ET_ok, false); 00412 return ptr()->checkOverlapCapsule(world_capsule._capsule); 00413 } 00414 00415 //////////////////////////////////////////////////////////////////// 00416 // Function: PhysxShape::check_overlap_obb 00417 // Access: Published 00418 // Description: Checks whether the shape overlaps a world-space 00419 // OBB or not. 00420 //////////////////////////////////////////////////////////////////// 00421 bool PhysxShape:: 00422 check_overlap_obb(const PhysxBox &world_box) const { 00423 00424 nassertr(_error_type == ET_ok, false); 00425 return ptr()->checkOverlapOBB(world_box._box); 00426 } 00427 00428 //////////////////////////////////////////////////////////////////// 00429 // Function: PhysxShape::check_overlap_sphere 00430 // Access: Published 00431 // Description: Checks whether the shape overlaps a world-space 00432 // sphere or not. 00433 //////////////////////////////////////////////////////////////////// 00434 bool PhysxShape:: 00435 check_overlap_sphere(const PhysxSphere &world_sphere) const { 00436 00437 nassertr(_error_type == ET_ok, false); 00438 return ptr()->checkOverlapSphere(world_sphere._sphere); 00439 } 00440 00441 //////////////////////////////////////////////////////////////////// 00442 // Function: PhysxShape::raycast 00443 // Access: Published 00444 // Description: 00445 //////////////////////////////////////////////////////////////////// 00446 PhysxRaycastHit PhysxShape:: 00447 raycast(const PhysxRay &worldRay, bool firstHit, bool smoothNormal) const { 00448 00449 NxRaycastHit hit; 00450 nassertr(_error_type == ET_ok, hit); 00451 00452 NxU32 hints = NX_RAYCAST_SHAPE | NX_RAYCAST_IMPACT | NX_RAYCAST_DISTANCE; 00453 if (smoothNormal == true) { 00454 hints |= NX_RAYCAST_NORMAL; 00455 } 00456 else { 00457 hints |= NX_RAYCAST_FACE_NORMAL; 00458 } 00459 00460 ptr()->raycast(worldRay._ray, worldRay._length, hints, hit, firstHit); 00461 return PhysxRaycastHit(hit); 00462 } 00463