Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2009-04-20 19:06:46 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2009-04-20 19:06:46 +0400
commit874c29cea8e6f9bc411fccf2d6f4cb07e94328d0 (patch)
tree5971e577cf7c02e05a1e37b5ad058c71a6744877 /source/gameengine/Physics
parent7555bfa793a2b0fc187c6211c56986f35b2d7b09 (diff)
parentc5bc4e4fb1a33eda8c31f2ea02e91f32f74c8fa5 (diff)
2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r19323:HEAD
Notes: * blenderbuttons and ICON_SNAP_PEEL_OBJECT were not merged.
Diffstat (limited to 'source/gameengine/Physics')
-rw-r--r--source/gameengine/Physics/BlOde/OdePhysicsController.h4
-rw-r--r--source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h1
-rw-r--r--source/gameengine/Physics/Bullet/CMakeLists.txt10
-rw-r--r--source/gameengine/Physics/Bullet/CcdGraphicController.cpp112
-rw-r--r--source/gameengine/Physics/Bullet/CcdGraphicController.h74
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp338
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h47
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp655
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h15
-rw-r--r--source/gameengine/Physics/Bullet/Makefile8
-rw-r--r--source/gameengine/Physics/Bullet/SConscript16
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h1
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsController.h5
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h1
-rw-r--r--source/gameengine/Physics/common/CMakeLists.txt2
-rw-r--r--source/gameengine/Physics/common/PHY_DynamicTypes.h35
-rw-r--r--source/gameengine/Physics/common/PHY_IController.cpp39
-rw-r--r--source/gameengine/Physics/common/PHY_IController.h53
-rw-r--r--source/gameengine/Physics/common/PHY_IGraphicController.cpp39
-rw-r--r--source/gameengine/Physics/common/PHY_IGraphicController.h56
-rw-r--r--source/gameengine/Physics/common/PHY_IMotionState.h2
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.h14
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h4
-rw-r--r--source/gameengine/Physics/common/PHY_Pro.h6
-rw-r--r--source/gameengine/Physics/common/SConscript2
25 files changed, 1401 insertions, 138 deletions
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsController.h b/source/gameengine/Physics/BlOde/OdePhysicsController.h
index 925f5b6686a..e97afdb68c3 100644
--- a/source/gameengine/Physics/BlOde/OdePhysicsController.h
+++ b/source/gameengine/Physics/BlOde/OdePhysicsController.h
@@ -124,6 +124,10 @@ public:
float getFriction() { return m_friction;}
float getRestitution() { return m_restitution;}
+ float GetLinVelocityMin() const { return 0.f; }
+ void SetLinVelocityMin(float val) { }
+ float GetLinVelocityMax() const { return 0.f; }
+ void SetLinVelocityMax(float val) { }
private:
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
index dcc87d614c0..2e4709cf420 100644
--- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
+++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
@@ -55,6 +55,7 @@ public:
virtual void removeConstraint(void * constraintid);
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes) { return false; }
//gamelogic callbacks
diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt
index 6c733786caf..ec2cdede683 100644
--- a/source/gameengine/Physics/Bullet/CMakeLists.txt
+++ b/source/gameengine/Physics/Bullet/CMakeLists.txt
@@ -24,16 +24,24 @@
#
# ***** END GPL LICENSE BLOCK *****
-SET(SRC CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp)
+SET(SRC CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp CcdGraphicController.cpp)
SET(INC
.
../common
../../../../extern/bullet2/src
+ ../../../../extern/glew/include
../../../../intern/moto/include
../../../kernel/gen_system
../../../../intern/string
+ ../../../../intern/SoundSystem
../../Rasterizer
+ ../../Ketsji
+ ../../Expressions
+ ../../GameLogic
+ ../../SceneGraph
+ ../../../../source/blender/makesdna
+ ${PYTHON_INC}
)
BLENDERLIB(bf_bullet "${SRC}" "${INC}")
diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.cpp b/source/gameengine/Physics/Bullet/CcdGraphicController.cpp
new file mode 100644
index 00000000000..caf18fd28ba
--- /dev/null
+++ b/source/gameengine/Physics/Bullet/CcdGraphicController.cpp
@@ -0,0 +1,112 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "CcdPhysicsEnvironment.h"
+#include "CcdGraphicController.h"
+#include "btBulletDynamicsCommon.h"
+#include "MT_Point3.h"
+
+
+CcdGraphicController::CcdGraphicController (CcdPhysicsEnvironment* phyEnv, PHY_IMotionState* motionState) :
+ m_localAabbMin(0.f, 0.f, 0.f),
+ m_localAabbMax(0.f, 0.f, 0.f),
+ m_motionState(motionState),
+ m_phyEnv(phyEnv),
+ m_handle(NULL),
+ m_newClientInfo(NULL)
+{
+}
+
+CcdGraphicController::~CcdGraphicController()
+{
+ if (m_phyEnv)
+ m_phyEnv->removeCcdGraphicController(this);
+
+ if (m_motionState)
+ delete m_motionState;
+}
+
+void CcdGraphicController::setLocalAabb(const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ m_localAabbMin = aabbMin;
+ m_localAabbMax = aabbMax;
+ SetGraphicTransform();
+}
+
+void CcdGraphicController::setLocalAabb(const MT_Point3& aabbMin,const MT_Point3& aabbMax)
+{
+ m_localAabbMin = btVector3(aabbMin[0],aabbMin[1],aabbMin[2]);
+ m_localAabbMax = btVector3(aabbMax[0],aabbMax[1],aabbMax[2]);
+ SetGraphicTransform();
+}
+
+
+void CcdGraphicController::getAabb(btVector3& aabbMin, btVector3& aabbMax)
+{
+ btVector3 pos;
+ btVector3 scale;
+ float ori[12];
+ m_motionState->getWorldPosition(pos.m_floats[0],pos.m_floats[1],pos.m_floats[2]);
+ m_motionState->getWorldScaling(scale.m_floats[0],scale.m_floats[1],scale.m_floats[2]);
+ m_motionState->getWorldOrientation(ori);
+ btMatrix3x3 rot(ori[0], ori[4], ori[8],
+ ori[1], ori[5], ori[9],
+ ori[2], ori[6], ori[10]);
+
+ btVector3 localAabbMin = m_localAabbMin;
+ btVector3 localAabbMax = m_localAabbMax;
+ btVector3 tmpAabbMin = m_localAabbMin * scale;
+ btVector3 tmpAabbMax = m_localAabbMax * scale;
+
+ localAabbMin[0] = (scale.getX() >= 0.) ? tmpAabbMin[0] : tmpAabbMax[0];
+ localAabbMin[1] = (scale.getY() >= 0.) ? tmpAabbMin[1] : tmpAabbMax[1];
+ localAabbMin[2] = (scale.getZ() >= 0.) ? tmpAabbMin[2] : tmpAabbMax[2];
+ localAabbMax[0] = (scale.getX() <= 0.) ? tmpAabbMin[0] : tmpAabbMax[0];
+ localAabbMax[1] = (scale.getY() <= 0.) ? tmpAabbMin[1] : tmpAabbMax[1];
+ localAabbMax[2] = (scale.getZ() <= 0.) ? tmpAabbMin[2] : tmpAabbMax[2];
+
+ btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
+ btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
+
+ btMatrix3x3 abs_b = rot.absolute();
+ btVector3 center = rot*localCenter + pos;
+ btVector3 extent = abs_b*localHalfExtents;
+ aabbMin = center - extent;
+ aabbMax = center + extent;
+}
+
+bool CcdGraphicController::SetGraphicTransform()
+{
+ if (!m_handle)
+ return false;
+ btVector3 aabbMin;
+ btVector3 aabbMax;
+ getAabb(aabbMin, aabbMax);
+ // update Aabb in broadphase
+ m_phyEnv->getCullingTree()->setAabb(m_handle,aabbMin,aabbMax,NULL);
+ return true;
+}
+
+PHY_IGraphicController* CcdGraphicController::GetReplica(class PHY_IMotionState* motionState)
+{
+ CcdGraphicController* replica = new CcdGraphicController(*this);
+ replica->m_motionState = motionState;
+ replica->m_newClientInfo = NULL;
+ replica->m_handle = NULL;
+ m_phyEnv->addCcdGraphicController(replica);
+ return replica;
+}
+
+
diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.h b/source/gameengine/Physics/Bullet/CcdGraphicController.h
new file mode 100644
index 00000000000..8faa0944313
--- /dev/null
+++ b/source/gameengine/Physics/Bullet/CcdGraphicController.h
@@ -0,0 +1,74 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BULLET2_GRAPHICCONTROLLER_H
+#define BULLET2_GRAPHICCONTROLLER_H
+
+#include "PHY_IGraphicController.h"
+
+#include "btBulletDynamicsCommon.h"
+#include "LinearMath/btTransform.h"
+
+#include "PHY_IMotionState.h"
+#include "MT_Point3.h"
+
+class CcdPhysicsEnvironment;
+class btCollisionObject;
+
+///CcdGraphicController is a graphic object that supports view frustrum culling and occlusion
+class CcdGraphicController : public PHY_IGraphicController
+{
+public:
+ CcdGraphicController(CcdPhysicsEnvironment* phyEnv, PHY_IMotionState* motionState);
+
+ virtual ~CcdGraphicController();
+
+ void setLocalAabb(const btVector3& aabbMin,const btVector3& aabbMax);
+ void setLocalAabb(const MT_Point3& aabbMin,const MT_Point3& aabbMax);
+
+ PHY_IMotionState* GetMotionState() { return m_motionState; }
+ void getAabb(btVector3& aabbMin, btVector3& aabbMax);
+
+ virtual void setBroadphaseHandle(btBroadphaseProxy* handle) { m_handle = handle; }
+ virtual btBroadphaseProxy* getBroadphaseHandle() { return m_handle; }
+
+ ////////////////////////////////////
+ // PHY_IGraphicController interface
+ ////////////////////////////////////
+
+ /**
+ * Updates the Aabb based on the motion state
+ */
+ virtual bool SetGraphicTransform();
+
+ // client info for culling
+ virtual void* getNewClientInfo() { return m_newClientInfo; }
+ virtual void setNewClientInfo(void* clientinfo) { m_newClientInfo = clientinfo; }
+ virtual PHY_IGraphicController* GetReplica(class PHY_IMotionState* motionstate);
+
+private:
+ // unscaled aabb corner
+ btVector3 m_localAabbMin;
+ btVector3 m_localAabbMax;
+
+ PHY_IMotionState* m_motionState;
+ CcdPhysicsEnvironment* m_phyEnv;
+ btBroadphaseProxy* m_handle;
+ void* m_newClientInfo;
+
+};
+
+#endif //BULLET2_PHYSICSCONTROLLER_H
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index eecdea55349..0b9da8f46d3 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -16,6 +16,9 @@ subject to the following restrictions:
#include "CcdPhysicsController.h"
#include "btBulletDynamicsCommon.h"
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
+
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
+
#include "PHY_IMotionState.h"
#include "CcdPhysicsEnvironment.h"
#include "RAS_MeshObject.h"
@@ -24,10 +27,14 @@ subject to the following restrictions:
#include "BulletSoftBody/btSoftBodyHelpers.h"
#include "LinearMath/btConvexHull.h"
#include "BulletCollision/Gimpact/btGImpactShape.h"
+#include "BulletCollision/Gimpact/btGImpactShape.h"
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
class BP_Proxy;
///todo: fill all the empty CcdPhysicsController methods, hook them up to the btRigidBody class
@@ -577,7 +584,19 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time)
if (body && !body->isStaticObject())
{
-
+
+ if ((m_cci.m_clamp_vel_max>0.0) || (m_cci.m_clamp_vel_min>0.0))
+ {
+ const btVector3& linvel = body->getLinearVelocity();
+ float len= linvel.length();
+
+ if((m_cci.m_clamp_vel_max>0.0) && (len > m_cci.m_clamp_vel_max))
+ body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len));
+
+ else if ((m_cci.m_clamp_vel_min>0.0) && btFuzzyZero(len)==0 && (len < m_cci.m_clamp_vel_min))
+ body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len));
+ }
+
const btVector3& worldPos = body->getCenterOfMassPosition();
m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
@@ -1238,6 +1257,22 @@ void DefaultMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,flo
quatReal = m_worldTransform.getRotation()[3];
}
+void DefaultMotionState::getWorldOrientation(float* ori)
+{
+ *ori++ = m_worldTransform.getBasis()[0].x();
+ *ori++ = m_worldTransform.getBasis()[1].x();
+ *ori++ = m_worldTransform.getBasis()[1].x();
+ *ori++ = 0.f;
+ *ori++ = m_worldTransform.getBasis()[0].y();
+ *ori++ = m_worldTransform.getBasis()[1].y();
+ *ori++ = m_worldTransform.getBasis()[1].y();
+ *ori++ = 0.f;
+ *ori++ = m_worldTransform.getBasis()[0].z();
+ *ori++ = m_worldTransform.getBasis()[1].z();
+ *ori++ = m_worldTransform.getBasis()[1].z();
+ *ori++ = 0.f;
+}
+
void DefaultMotionState::setWorldPosition(float posX,float posY,float posZ)
{
btVector3 pos(posX,posY,posZ);
@@ -1272,123 +1307,212 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes
bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bool useGimpact)
{
+ int numpolys;
+
m_useGimpact = useGimpact;
// assume no shape information
// no support for dynamic change of shape yet
assert(IsUnused());
m_shapeType = PHY_SHAPE_NONE;
- m_vertexArray.clear();
- m_polygonIndexArray.clear();
m_meshObject = NULL;
- if (!meshobj)
- return false;
-
- // Mesh has no polygons!
- int numpolys = meshobj->NumPolygons();
- if (!numpolys)
- {
+ // No mesh object or mesh has no polys
+ if (!meshobj || meshobj->HasColliderPolygon()==false) {
+ m_vertexArray.clear();
+ m_polygonIndexArray.clear();
+ m_triFaceArray.clear();
return false;
}
- // check that we have at least one colliding polygon
- int numvalidpolys = 0;
+ numpolys = meshobj->NumPolygons();
- for (int p=0; p<numpolys; p++)
- {
- RAS_Polygon* poly = meshobj->GetPolygon(p);
+ m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH;
- // only add polygons that have the collisionflag set
- if (poly->IsCollider())
+ /* Convert blender geometry into bullet mesh, need these vars for mapping */
+ vector<bool> vert_tag_array(meshobj->GetMesh()->totvert, false);
+ unsigned int tot_bt_verts= 0;
+ unsigned int orig_index;
+ int i;
+
+ if (polytope)
+ {
+ // Tag verts we're using
+ for (int p2=0; p2<numpolys; p2++)
{
- numvalidpolys++;
- break;
- }
- }
+ RAS_Polygon* poly= meshobj->GetPolygon(p2);
- // No collision polygons
- if (numvalidpolys < 1)
- return false;
+ // only add polygons that have the collision flag set
+ if (poly->IsCollider())
+ {
+ for(i=0; i<poly->VertexCount(); i++) {
+ orig_index= poly->GetVertex(i)->getOrigIndex();
+ if (vert_tag_array[orig_index]==false)
+ {
+ vert_tag_array[orig_index]= true;
+ tot_bt_verts++;
+ }
+ }
+ }
+ }
- m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH;
+ m_vertexArray.resize(tot_bt_verts);
- numvalidpolys = 0;
+ btVector3 *bt= &m_vertexArray[0];
- for (int p2=0; p2<numpolys; p2++)
- {
- RAS_Polygon* poly = meshobj->GetPolygon(p2);
+ for (int p2=0; p2<numpolys; p2++)
+ {
+ RAS_Polygon* poly= meshobj->GetPolygon(p2);
- // only add polygons that have the collisionflag set
- if (poly->IsCollider())
- {
- //Bullet can raycast any shape, so
- if (polytope)
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
{
- for (int i=0;i<poly->VertexCount();i++)
- {
- const float* vtx = poly->GetVertex(i)->getXYZ();
- btVector3 point(vtx[0],vtx[1],vtx[2]);
- //avoid duplicates (could better directly use vertex offsets, rather than a vertex compare)
- bool found = false;
- for (int j=0;j<m_vertexArray.size();j++)
+ for(i=0; i<poly->VertexCount(); i++) {
+ RAS_TexVert *v= poly->GetVertex(i);
+ orig_index= v->getOrigIndex();
+
+ if (vert_tag_array[orig_index]==true)
{
- if (m_vertexArray[j]==point)
- {
- found = true;
- break;
- }
- }
- if (!found)
- m_vertexArray.push_back(point);
+ const float* vtx = v->getXYZ();
+ vert_tag_array[orig_index]= false;
- numvalidpolys++;
+ bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]);
+ bt++;
+ }
}
- } else
+ }
+ }
+ }
+ else {
+ unsigned int tot_bt_tris= 0;
+ vector<int> vert_remap_array(meshobj->GetMesh()->totvert, 0);
+
+ // Tag verts we're using
+ for (int p2=0; p2<numpolys; p2++)
+ {
+ RAS_Polygon* poly= meshobj->GetPolygon(p2);
+
+ // only add polygons that have the collision flag set
+ if (poly->IsCollider())
{
- {
- const float* vtx = poly->GetVertex(2)->getXYZ();
- btVector3 vertex0(vtx[0],vtx[1],vtx[2]);
+ for(i=0; i<poly->VertexCount(); i++) {
+ orig_index= poly->GetVertex(i)->getOrigIndex();
+ if (vert_tag_array[orig_index]==false)
+ {
+ vert_tag_array[orig_index]= true;
+ vert_remap_array[orig_index]= tot_bt_verts;
+ tot_bt_verts++;
+ }
+ }
+
+ tot_bt_tris += (i==4 ? 2:1); /* a quad or a tri */
+ }
+ }
- vtx = poly->GetVertex(1)->getXYZ();
- btVector3 vertex1(vtx[0],vtx[1],vtx[2]);
+ m_vertexArray.resize(tot_bt_verts);
+ m_polygonIndexArray.resize(tot_bt_tris);
+ m_triFaceArray.resize(tot_bt_tris*3);
- vtx = poly->GetVertex(0)->getXYZ();
- btVector3 vertex2(vtx[0],vtx[1],vtx[2]);
+ btVector3 *bt= &m_vertexArray[0];
+ int *poly_index_pt= &m_polygonIndexArray[0];
+ int *tri_pt= &m_triFaceArray[0];
- m_vertexArray.push_back(vertex0);
- m_vertexArray.push_back(vertex1);
- m_vertexArray.push_back(vertex2);
- m_polygonIndexArray.push_back(p2);
- numvalidpolys++;
+
+ for (int p2=0; p2<numpolys; p2++)
+ {
+ RAS_Polygon* poly= meshobj->GetPolygon(p2);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ {
+ RAS_TexVert *v1= poly->GetVertex(0);
+ RAS_TexVert *v2= poly->GetVertex(1);
+ RAS_TexVert *v3= poly->GetVertex(2);
+ int i1= v1->getOrigIndex();
+ int i2= v2->getOrigIndex();
+ int i3= v3->getOrigIndex();
+ const float* vtx;
+
+ // the face indicies
+ tri_pt[0]= vert_remap_array[i1];
+ tri_pt[1]= vert_remap_array[i2];
+ tri_pt[2]= vert_remap_array[i3];
+ tri_pt= tri_pt+3;
+
+ // m_polygonIndexArray
+ *poly_index_pt= p2;
+ poly_index_pt++;
+
+ // the vertex location
+ if (vert_tag_array[i1]==true) { /* *** v1 *** */
+ vert_tag_array[i1]= false;
+ vtx = v1->getXYZ();
+ bt->setX(vtx[0]); bt->setY( vtx[1]); bt->setZ(vtx[2]);
+ bt++;
+ }
+ if (vert_tag_array[i2]==true) { /* *** v2 *** */
+ vert_tag_array[i2]= false;
+ vtx = v2->getXYZ();
+ bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]);
+ bt++;
}
- if (poly->VertexCount() == 4)
+ if (vert_tag_array[i3]==true) { /* *** v3 *** */
+ vert_tag_array[i3]= false;
+ vtx = v3->getXYZ();
+ bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]);
+ bt++;
+ }
+
+ if (poly->VertexCount()==4)
{
- const float* vtx = poly->GetVertex(3)->getXYZ();
- btVector3 vertex0(vtx[0],vtx[1],vtx[2]);
+ RAS_TexVert *v4= poly->GetVertex(3);
+ int i4= v4->getOrigIndex();
+
+ tri_pt[0]= vert_remap_array[i1];
+ tri_pt[1]= vert_remap_array[i3];
+ tri_pt[2]= vert_remap_array[i4];
+ tri_pt= tri_pt+3;
+
+ // m_polygonIndexArray
+ *poly_index_pt= p2;
+ poly_index_pt++;
+
+ // the vertex location
+ if (vert_tag_array[i4]==true) { /* *** v4 *** */
+ vert_tag_array[i4]= false;
+ vtx = v4->getXYZ();
+ bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]);
+ bt++;
+ }
+ }
+ }
+ }
- vtx = poly->GetVertex(2)->getXYZ();
- btVector3 vertex1(vtx[0],vtx[1],vtx[2]);
- vtx = poly->GetVertex(0)->getXYZ();
- btVector3 vertex2(vtx[0],vtx[1],vtx[2]);
+ /* If this ever gets confusing, print out an OBJ file for debugging */
+#if 0
+ printf("# vert count %d\n", m_vertexArray.size());
+ for(i=0; i<m_vertexArray.size(); i+=1) {
+ printf("v %.6f %.6f %.6f\n", m_vertexArray[i].x(), m_vertexArray[i].y(), m_vertexArray[i].z());
+ }
- m_vertexArray.push_back(vertex0);
- m_vertexArray.push_back(vertex1);
- m_vertexArray.push_back(vertex2);
- m_polygonIndexArray.push_back(p2);
- numvalidpolys++;
- }
- }
+ printf("# face count %d\n", m_triFaceArray.size());
+ for(i=0; i<m_triFaceArray.size(); i+=3) {
+ printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1);
}
+#endif
+
}
- if (!numvalidpolys)
+#if 0
+ if (validpolys==false)
{
// should not happen
m_shapeType = PHY_SHAPE_NONE;
return false;
}
+#endif
+
m_meshObject = meshobj;
if (!polytope)
{
@@ -1413,7 +1537,6 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
{
btCollisionShape* collisionShape = 0;
btTriangleMeshShape* concaveShape = 0;
- btTriangleMesh* collisionMeshData = 0;
btCompoundShape* compoundShape = 0;
CcdShapeConstructionInfo* nextShapeInfo;
@@ -1454,18 +1577,17 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
// One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1
// and btScaledBvhTriangleMeshShape otherwise.
if (m_useGimpact)
- {
- collisionMeshData = new btTriangleMesh();
-
- bool removeDuplicateVertices=true;
-
- // m_vertexArray is necessarily a multiple of 3
- for (int i=0;i<m_vertexArray.size(); i+=3 )
- {
- collisionMeshData->addTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i],removeDuplicateVertices);
- }
+ {
+ btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray(
+ m_polygonIndexArray.size(),
+ &m_triFaceArray[0],
+ 3*sizeof(int),
+ m_vertexArray.size(),
+ (btScalar*) &m_vertexArray[0].x(),
+ sizeof(btVector3)
+ );
- btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(collisionMeshData);
+ btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(indexVertexArrays);
collisionShape = gimpactShape;
gimpactShape->updateBound();
@@ -1474,17 +1596,39 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
{
if (!m_unscaledShape)
{
- collisionMeshData = new btTriangleMesh(true,false);
- collisionMeshData->m_weldingThreshold = m_weldingThreshold;
+
+ btTriangleIndexVertexArray* indexVertexArrays = 0;
- bool removeDuplicateVertices=true;
- // m_vertexArray is necessarily a multiple of 3
- for (int i=0;i<m_vertexArray.size(); i+=3 )
+ ///enable welding, only for the objects that need it (such as soft bodies)
+ if (0.f != m_weldingThreshold1)
{
- collisionMeshData->addTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i],removeDuplicateVertices);
+ btTriangleMesh* collisionMeshData = new btTriangleMesh(true,false);
+ collisionMeshData->m_weldingThreshold = m_weldingThreshold1;
+ bool removeDuplicateVertices=true;
+ // m_vertexArray not in multiple of 3 anymore, use m_triFaceArray
+ for(int i=0; i<m_triFaceArray.size(); i+=3) {
+ collisionMeshData->addTriangle(
+ m_vertexArray[m_triFaceArray[i]],
+ m_vertexArray[m_triFaceArray[i+1]],
+ m_vertexArray[m_triFaceArray[i+2]],
+ removeDuplicateVertices
+ );
+ }
+ indexVertexArrays = collisionMeshData;
+
+ } else
+ {
+ indexVertexArrays = new btTriangleIndexVertexArray(
+ m_polygonIndexArray.size(),
+ &m_triFaceArray[0],
+ 3*sizeof(int),
+ m_vertexArray.size(),
+ (btScalar*) &m_vertexArray[0].x(),
+ sizeof(btVector3));
}
+
// this shape will be shared and not deleted until shapeInfo is deleted
- m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true );
+ m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true );
m_unscaledShape->recalcLocalAabb();
}
collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f));
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index deb3c0880e9..4510bbddf65 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -72,7 +72,7 @@ public:
m_meshObject(NULL),
m_unscaledShape(NULL),
m_useGimpact(false),
- m_weldingThreshold(0.f),
+ m_weldingThreshold1(0.f),
m_shapeProxy(NULL)
{
m_childTrans.setIdentity();
@@ -107,7 +107,7 @@ public:
}
CcdShapeConstructionInfo* GetChildShape(int i)
{
- if (i < 0 || i >= m_shapeArray.size())
+ if (i < 0 || i >= (int)m_shapeArray.size())
return NULL;
return m_shapeArray.at(i);
@@ -116,7 +116,7 @@ public:
{
if (shapeInfo == NULL)
return -1;
- for (int i=0; i<m_shapeArray.size(); i++)
+ for (int i=0; i<(int)m_shapeArray.size(); i++)
{
CcdShapeConstructionInfo* childInfo = m_shapeArray.at(i);
if ((userData == NULL || userData == childInfo->m_userData) &&
@@ -130,10 +130,10 @@ public:
bool RemoveChildShape(int i)
{
- if (i < 0 || i >= m_shapeArray.size())
+ if (i < 0 || i >= (int)m_shapeArray.size())
return false;
m_shapeArray.at(i)->Release();
- if (i < m_shapeArray.size()-1)
+ if (i < (int)m_shapeArray.size()-1)
m_shapeArray[i] = m_shapeArray.back();
m_shapeArray.pop_back();
return true;
@@ -167,14 +167,17 @@ public:
std::vector<int> m_polygonIndexArray; // Contains the array of polygon index in the
// original mesh that correspond to shape triangles.
// only set for concave mesh shape.
+
+ std::vector<int> m_triFaceArray; // Contains an array of triplets of face indicies
+ // quads turn into 2 tris
- void setVertexWeldingThreshold(float threshold)
+ void setVertexWeldingThreshold1(float threshold)
{
- m_weldingThreshold = threshold;
+ m_weldingThreshold1 = threshold;
}
- float getVertexWeldingThreshold() const
+ float getVertexWeldingThreshold1() const
{
- return m_weldingThreshold;
+ return m_weldingThreshold1;
}
protected:
static std::map<RAS_MeshObject*, CcdShapeConstructionInfo*> m_meshShapeMap;
@@ -185,7 +188,7 @@ protected:
// the actual shape is of type btScaledBvhTriangleMeshShape
std::vector<CcdShapeConstructionInfo*> m_shapeArray; // for compound shapes
bool m_useGimpact; //use gimpact for concave dynamic/moving collision detection
- float m_weldingThreshold; //welding closeby vertices together can improve softbody stability etc.
+ float m_weldingThreshold1; //welding closeby vertices together can improve softbody stability etc.
CcdShapeConstructionInfo* m_shapeProxy; // only used for PHY_SHAPE_PROXY, pointer to actual shape info
};
@@ -211,6 +214,8 @@ struct CcdConstructionInfo
m_gravity(0,0,0),
m_scaling(1.f,1.f,1.f),
m_mass(0.f),
+ m_clamp_vel_min(-1.f),
+ m_clamp_vel_max(-1.f),
m_restitution(0.1f),
m_friction(0.5f),
m_linearDamping(0.1f),
@@ -236,6 +241,8 @@ struct CcdConstructionInfo
btVector3 m_gravity;
btVector3 m_scaling;
btScalar m_mass;
+ btScalar m_clamp_vel_min;
+ btScalar m_clamp_vel_max;
btScalar m_restitution;
btScalar m_friction;
btScalar m_linearDamping;
@@ -476,7 +483,24 @@ class CcdPhysicsController : public PHY_IPhysicsController
}
m_cci.m_radius = margin;
}
-
+
+ // velocity clamping
+ virtual void SetLinVelocityMin(float val)
+ {
+ m_cci.m_clamp_vel_min= val;
+ }
+ virtual float GetLinVelocityMin() const
+ {
+ return m_cci.m_clamp_vel_min;
+ }
+ virtual void SetLinVelocityMax(float val)
+ {
+ m_cci.m_clamp_vel_max= val;
+ }
+ virtual float GetLinVelocityMax() const
+ {
+ return m_cci.m_clamp_vel_max;
+ }
bool wantsSleeping();
@@ -541,6 +565,7 @@ class DefaultMotionState : public PHY_IMotionState
virtual void setWorldPosition(float posX,float posY,float posZ);
virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal);
+ virtual void getWorldOrientation(float* ori);
virtual void calculateWorldTransformations();
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index dd21e58bd68..3e1e0294321 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -18,6 +18,7 @@ subject to the following restrictions:
#include "CcdPhysicsEnvironment.h"
#include "CcdPhysicsController.h"
+#include "CcdGraphicController.h"
#include <algorithm>
#include "btBulletDynamicsCommon.h"
@@ -32,6 +33,10 @@ subject to the following restrictions:
#include "PHY_IMotionState.h"
+#include "KX_GameObject.h"
+#include "RAS_MeshObject.h"
+#include "RAS_Polygon.h"
+#include "RAS_TexVert.h"
#define CCD_CONSTRAINT_DISABLE_LINKED_COLLISION 0x80
@@ -46,7 +51,9 @@ btRaycastVehicle::btVehicleTuning gTuning;
#endif //NEW_BULLET_VEHICLE_SUPPORT
#include "LinearMath/btAabbUtil2.h"
-
+#include "MT_Matrix4x4.h"
+#include "MT_Vector3.h"
+#include "GL/glew.h"
#ifdef WIN32
void DrawRasterizerLine(const float* from,const float* to,int color);
@@ -316,8 +323,10 @@ static void DrawAabb(btIDebugDraw* debugDrawer,const btVector3& from,const btVec
-CcdPhysicsEnvironment::CcdPhysicsEnvironment(btDispatcher* dispatcher,btOverlappingPairCache* pairCache)
-:m_numIterations(10),
+CcdPhysicsEnvironment::CcdPhysicsEnvironment(bool useDbvtCulling,btDispatcher* dispatcher,btOverlappingPairCache* pairCache)
+:m_cullingCache(NULL),
+m_cullingTree(NULL),
+m_numIterations(10),
m_scalingPropagated(false),
m_numTimeSubSteps(1),
m_ccdMode(0),
@@ -350,6 +359,11 @@ m_ownDispatcher(NULL)
//m_broadphase = new btAxisSweep3(btVector3(-1000,-1000,-1000),btVector3(1000,1000,1000));
//m_broadphase = new btSimpleBroadphase();
m_broadphase = new btDbvtBroadphase();
+ // avoid any collision in the culling tree
+ if (useDbvtCulling) {
+ m_cullingCache = new btNullPairCache();
+ m_cullingTree = new btDbvtBroadphase(m_cullingCache);
+ }
m_filterCallback = new CcdOverlapFilterCallBack(this);
m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback);
@@ -364,7 +378,6 @@ m_ownDispatcher(NULL)
m_gravity = btVector3(0.f,-10.f,0.f);
m_dynamicsWorld->setGravity(m_gravity);
-
}
void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl)
@@ -558,6 +571,41 @@ void CcdPhysicsEnvironment::refreshCcdPhysicsController(CcdPhysicsController* ct
}
}
+void CcdPhysicsEnvironment::addCcdGraphicController(CcdGraphicController* ctrl)
+{
+ if (m_cullingTree)
+ {
+ btVector3 minAabb;
+ btVector3 maxAabb;
+ ctrl->getAabb(minAabb, maxAabb);
+
+ ctrl->setBroadphaseHandle(m_cullingTree->createProxy(
+ minAabb,
+ maxAabb,
+ INVALID_SHAPE_PROXYTYPE, // this parameter is not used
+ ctrl,
+ 0, // this object does not collision with anything
+ 0,
+ NULL, // dispatcher => this parameter is not used
+ 0));
+
+ assert(ctrl->getBroadphaseHandle());
+ }
+}
+
+void CcdPhysicsEnvironment::removeCcdGraphicController(CcdGraphicController* ctrl)
+{
+ if (m_cullingTree)
+ {
+ btBroadphaseProxy* bp = ctrl->getBroadphaseHandle();
+ if (bp)
+ {
+ m_cullingTree->destroyProxy(bp,NULL);
+ ctrl->setBroadphaseHandle(0);
+ }
+ }
+}
+
void CcdPhysicsEnvironment::beginFrame()
{
@@ -593,10 +641,10 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep)
(*it)->SynchronizeMotionStates(timeStep);
}
- for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
- {
- (*it)->SynchronizeMotionStates(timeStep);
- }
+ //for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
+ //{
+ // (*it)->SynchronizeMotionStates(timeStep);
+ //}
for (i=0;i<m_wrapperVehicles.size();i++)
{
@@ -618,9 +666,10 @@ class ClosestRayResultCallbackNotMe : public btCollisionWorld::ClosestRayResultC
public:
ClosestRayResultCallbackNotMe(const btVector3& rayFromWorld,const btVector3& rayToWorld,btCollisionObject* owner,btCollisionObject* parent)
:btCollisionWorld::ClosestRayResultCallback(rayFromWorld,rayToWorld),
- m_owner(owner)
+ m_owner(owner),
+ m_parent(parent)
{
-
+
}
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
@@ -668,7 +717,7 @@ void CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep)
//btVector3 rayToWorld = rayFromWorld + body->getCenterOfMassTransform().getBasis() * rayDirLocal;
//ray always points down the z axis in world space...
btVector3 rayToWorld = rayFromWorld + rayDirLocal;
-
+
ClosestRayResultCallbackNotMe resultCallback(rayFromWorld,rayToWorld,body,parentBody);
m_dynamicsWorld->rayTest(rayFromWorld,rayToWorld,resultCallback);
@@ -1146,7 +1195,578 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac
return result.m_controller;
}
+// Handles occlusion culling.
+// The implementation is based on the CDTestFramework
+struct OcclusionBuffer
+{
+ struct WriteOCL
+ {
+ static inline bool Process(btScalar& q,btScalar v) { if(q<v) q=v;return(false); }
+ static inline void Occlusion(bool& flag) { flag = true; }
+ };
+ struct QueryOCL
+ {
+ static inline bool Process(btScalar& q,btScalar v) { return(q<=v); }
+ static inline void Occlusion(bool& flag) { }
+ };
+ btScalar* m_buffer;
+ size_t m_bufferSize;
+ bool m_initialized;
+ bool m_occlusion;
+ int m_sizes[2];
+ btScalar m_scales[2];
+ btScalar m_offsets[2];
+ btScalar m_wtc[16]; // world to clip transform
+ btScalar m_mtc[16]; // model to clip transform
+ // constructor: size=largest dimension of the buffer.
+ // Buffer size depends on aspect ratio
+ OcclusionBuffer()
+ {
+ m_initialized=false;
+ m_occlusion = false;
+ m_buffer == NULL;
+ m_bufferSize = 0;
+ }
+ // multiplication of column major matrices: m=m1*m2
+ template<typename T1, typename T2>
+ void CMmat4mul(btScalar* m, const T1* m1, const T2* m2)
+ {
+ m[ 0] = btScalar(m1[ 0]*m2[ 0]+m1[ 4]*m2[ 1]+m1[ 8]*m2[ 2]+m1[12]*m2[ 3]);
+ m[ 1] = btScalar(m1[ 1]*m2[ 0]+m1[ 5]*m2[ 1]+m1[ 9]*m2[ 2]+m1[13]*m2[ 3]);
+ m[ 2] = btScalar(m1[ 2]*m2[ 0]+m1[ 6]*m2[ 1]+m1[10]*m2[ 2]+m1[14]*m2[ 3]);
+ m[ 3] = btScalar(m1[ 3]*m2[ 0]+m1[ 7]*m2[ 1]+m1[11]*m2[ 2]+m1[15]*m2[ 3]);
+
+ m[ 4] = btScalar(m1[ 0]*m2[ 4]+m1[ 4]*m2[ 5]+m1[ 8]*m2[ 6]+m1[12]*m2[ 7]);
+ m[ 5] = btScalar(m1[ 1]*m2[ 4]+m1[ 5]*m2[ 5]+m1[ 9]*m2[ 6]+m1[13]*m2[ 7]);
+ m[ 6] = btScalar(m1[ 2]*m2[ 4]+m1[ 6]*m2[ 5]+m1[10]*m2[ 6]+m1[14]*m2[ 7]);
+ m[ 7] = btScalar(m1[ 3]*m2[ 4]+m1[ 7]*m2[ 5]+m1[11]*m2[ 6]+m1[15]*m2[ 7]);
+
+ m[ 8] = btScalar(m1[ 0]*m2[ 8]+m1[ 4]*m2[ 9]+m1[ 8]*m2[10]+m1[12]*m2[11]);
+ m[ 9] = btScalar(m1[ 1]*m2[ 8]+m1[ 5]*m2[ 9]+m1[ 9]*m2[10]+m1[13]*m2[11]);
+ m[10] = btScalar(m1[ 2]*m2[ 8]+m1[ 6]*m2[ 9]+m1[10]*m2[10]+m1[14]*m2[11]);
+ m[11] = btScalar(m1[ 3]*m2[ 8]+m1[ 7]*m2[ 9]+m1[11]*m2[10]+m1[15]*m2[11]);
+
+ m[12] = btScalar(m1[ 0]*m2[12]+m1[ 4]*m2[13]+m1[ 8]*m2[14]+m1[12]*m2[15]);
+ m[13] = btScalar(m1[ 1]*m2[12]+m1[ 5]*m2[13]+m1[ 9]*m2[14]+m1[13]*m2[15]);
+ m[14] = btScalar(m1[ 2]*m2[12]+m1[ 6]*m2[13]+m1[10]*m2[14]+m1[14]*m2[15]);
+ m[15] = btScalar(m1[ 3]*m2[12]+m1[ 7]*m2[13]+m1[11]*m2[14]+m1[15]*m2[15]);
+ }
+ void setup(int size)
+ {
+ m_initialized=false;
+ m_occlusion=false;
+ // compute the size of the buffer
+ GLint v[4];
+ GLdouble m[16],p[16];
+ int maxsize;
+ double ratio;
+ glGetIntegerv(GL_VIEWPORT,v);
+ maxsize = (v[2] > v[3]) ? v[2] : v[3];
+ assert(maxsize > 0);
+ ratio = 1.0/(2*maxsize);
+ // ensure even number
+ m_sizes[0] = 2*((int)(size*v[2]*ratio+0.5));
+ m_sizes[1] = 2*((int)(size*v[3]*ratio+0.5));
+ m_scales[0]=btScalar(m_sizes[0]/2);
+ m_scales[1]=btScalar(m_sizes[1]/2);
+ m_offsets[0]=m_scales[0]+0.5f;
+ m_offsets[1]=m_scales[1]+0.5f;
+ // prepare matrix
+ // at this time of the rendering, the modelview matrix is the
+ // world to camera transformation and the projection matrix is
+ // camera to clip transformation. combine both so that
+ glGetDoublev(GL_MODELVIEW_MATRIX,m);
+ glGetDoublev(GL_PROJECTION_MATRIX,p);
+ CMmat4mul(m_wtc,p,m);
+ }
+ void initialize()
+ {
+ size_t newsize = (m_sizes[0]*m_sizes[1])*sizeof(btScalar);
+ if (m_buffer)
+ {
+ // see if we can reuse
+ if (newsize > m_bufferSize)
+ {
+ free(m_buffer);
+ m_buffer = NULL;
+ m_bufferSize = 0;
+ }
+ }
+ if (!m_buffer)
+ {
+ m_buffer = (btScalar*)calloc(1, newsize);
+ m_bufferSize = newsize;
+ } else
+ {
+ // buffer exists already, just clears it
+ memset(m_buffer, 0, newsize);
+ }
+ // memory allocate must succeed
+ assert(m_buffer != NULL);
+ m_initialized = true;
+ m_occlusion = false;
+ }
+ void SetModelMatrix(double *fl)
+ {
+ CMmat4mul(m_mtc,m_wtc,fl);
+ if (!m_initialized)
+ initialize();
+ }
+
+ // transform a segment in world coordinate to clip coordinate
+ void transformW(const btVector3& x, btVector4& t)
+ {
+ t[0] = x[0]*m_wtc[0]+x[1]*m_wtc[4]+x[2]*m_wtc[8]+m_wtc[12];
+ t[1] = x[0]*m_wtc[1]+x[1]*m_wtc[5]+x[2]*m_wtc[9]+m_wtc[13];
+ t[2] = x[0]*m_wtc[2]+x[1]*m_wtc[6]+x[2]*m_wtc[10]+m_wtc[14];
+ t[3] = x[0]*m_wtc[3]+x[1]*m_wtc[7]+x[2]*m_wtc[11]+m_wtc[15];
+ }
+ void transformM(const float* x, btVector4& t)
+ {
+ t[0] = x[0]*m_mtc[0]+x[1]*m_mtc[4]+x[2]*m_mtc[8]+m_mtc[12];
+ t[1] = x[0]*m_mtc[1]+x[1]*m_mtc[5]+x[2]*m_mtc[9]+m_mtc[13];
+ t[2] = x[0]*m_mtc[2]+x[1]*m_mtc[6]+x[2]*m_mtc[10]+m_mtc[14];
+ t[3] = x[0]*m_mtc[3]+x[1]*m_mtc[7]+x[2]*m_mtc[11]+m_mtc[15];
+ }
+ // convert polygon to device coordinates
+ static bool project(btVector4* p,int n)
+ {
+ for(int i=0;i<n;++i)
+ {
+ const btScalar iw=1/p[i][3];
+ p[i][2]=1/p[i][3];
+ p[i][0]*=p[i][2];
+ p[i][1]*=p[i][2];
+ }
+ return(true);
+ }
+ // pi: closed polygon in clip coordinate, NP = number of segments
+ // po: same polygon with clipped segments removed
+ template <const int NP>
+ static int clip(const btVector4* pi,btVector4* po)
+ {
+ btScalar s[2*NP];
+ btVector4 pn[2*NP];
+ int i, j, m, n, ni;
+ // deal with near clipping
+ for(i=0, m=0;i<NP;++i)
+ {
+ s[i]=pi[i][2]+pi[i][3];
+ if(s[i]<0) m+=1<<i;
+ }
+ if(m==((1<<NP)-1))
+ return(0);
+ if(m!=0)
+ {
+ for(i=NP-1,j=0,n=0;j<NP;i=j++)
+ {
+ const btVector4& a=pi[i];
+ const btVector4& b=pi[j];
+ const btScalar t=s[i]/(a[3]+a[2]-b[3]-b[2]);
+ if((t>0)&&(t<1))
+ {
+ pn[n][0] = a[0]+(b[0]-a[0])*t;
+ pn[n][1] = a[1]+(b[1]-a[1])*t;
+ pn[n][2] = a[2]+(b[2]-a[2])*t;
+ pn[n][3] = a[3]+(b[3]-a[3])*t;
+ ++n;
+ }
+ if(s[j]>0) pn[n++]=b;
+ }
+ // ready to test far clipping, start from the modified polygon
+ pi = pn;
+ ni = n;
+ } else
+ {
+ // no clipping on the near plane, keep same vector
+ ni = NP;
+ }
+ // now deal with far clipping
+ for(i=0, m=0;i<ni;++i)
+ {
+ s[i]=pi[i][2]-pi[i][3];
+ if(s[i]>0) m+=1<<i;
+ }
+ if(m==((1<<ni)-1))
+ return(0);
+ if(m!=0)
+ {
+ for(i=ni-1,j=0,n=0;j<ni;i=j++)
+ {
+ const btVector4& a=pi[i];
+ const btVector4& b=pi[j];
+ const btScalar t=s[i]/(a[2]-a[3]-b[2]+b[3]);
+ if((t>0)&&(t<1))
+ {
+ po[n][0] = a[0]+(b[0]-a[0])*t;
+ po[n][1] = a[1]+(b[1]-a[1])*t;
+ po[n][2] = a[2]+(b[2]-a[2])*t;
+ po[n][3] = a[3]+(b[3]-a[3])*t;
+ ++n;
+ }
+ if(s[j]<0) po[n++]=b;
+ }
+ return(n);
+ }
+ for(int i=0;i<ni;++i) po[i]=pi[i];
+ return(ni);
+ }
+ // write or check a triangle to buffer. a,b,c in device coordinates (-1,+1)
+ template <typename POLICY>
+ inline bool draw( const btVector4& a,
+ const btVector4& b,
+ const btVector4& c,
+ const float face,
+ const btScalar minarea)
+ {
+ const btScalar a2=cross(b-a,c-a)[2];
+ if((face*a2)<0.f || btFabs(a2)<minarea)
+ return false;
+ // further down we are normally going to write to the Zbuffer, mark it so
+ POLICY::Occlusion(m_occlusion);
+
+ int x[3], y[3], ib=1, ic=2;
+ btScalar z[3];
+ x[0]=(int)(a.x()*m_scales[0]+m_offsets[0]);
+ y[0]=(int)(a.y()*m_scales[1]+m_offsets[1]);
+ z[0]=a.z();
+ if (a2 < 0.f)
+ {
+ // negative aire is possible with double face => must
+ // change the order of b and c otherwise the algorithm doesn't work
+ ib=2;
+ ic=1;
+ }
+ x[ib]=(int)(b.x()*m_scales[0]+m_offsets[0]);
+ x[ic]=(int)(c.x()*m_scales[0]+m_offsets[0]);
+ y[ib]=(int)(b.y()*m_scales[1]+m_offsets[1]);
+ y[ic]=(int)(c.y()*m_scales[1]+m_offsets[1]);
+ z[ib]=b.z();
+ z[ic]=c.z();
+ const int mix=btMax(0,btMin(x[0],btMin(x[1],x[2])));
+ const int mxx=btMin(m_sizes[0],1+btMax(x[0],btMax(x[1],x[2])));
+ const int miy=btMax(0,btMin(y[0],btMin(y[1],y[2])));
+ const int mxy=btMin(m_sizes[1],1+btMax(y[0],btMax(y[1],y[2])));
+ const int width=mxx-mix;
+ const int height=mxy-miy;
+ if ((width*height) <= 1)
+ {
+ // degenerated in at most one single pixel
+ btScalar* scan=&m_buffer[miy*m_sizes[0]+mix];
+ // use for loop to detect the case where width or height == 0
+ for(int iy=miy;iy<mxy;++iy)
+ {
+ for(int ix=mix;ix<mxx;++ix)
+ {
+ if(POLICY::Process(*scan,z[0]))
+ return(true);
+ if(POLICY::Process(*scan,z[1]))
+ return(true);
+ if(POLICY::Process(*scan,z[2]))
+ return(true);
+ }
+ }
+ } else if (width == 1)
+ {
+ // Degenerated in at least 2 vertical lines
+ // The algorithm below doesn't work when face has a single pixel width
+ // We cannot use general formulas because the plane is degenerated.
+ // We have to interpolate along the 3 edges that overlaps and process each pixel.
+ // sort the y coord to make formula simpler
+ int ytmp;
+ btScalar ztmp;
+ if (y[0] > y[1]) { ytmp=y[1];y[1]=y[0];y[0]=ytmp;ztmp=z[1];z[1]=z[0];z[0]=ztmp; }
+ if (y[0] > y[2]) { ytmp=y[2];y[2]=y[0];y[0]=ytmp;ztmp=z[2];z[2]=z[0];z[0]=ztmp; }
+ if (y[1] > y[2]) { ytmp=y[2];y[2]=y[1];y[1]=ytmp;ztmp=z[2];z[2]=z[1];z[1]=ztmp; }
+ int dy[]={ y[0]-y[1],
+ y[1]-y[2],
+ y[2]-y[0]};
+ btScalar dzy[3];
+ dzy[0] = (dy[0]) ? (z[0]-z[1])/dy[0] : btScalar(0.f);
+ dzy[1] = (dy[1]) ? (z[1]-z[2])/dy[1] : btScalar(0.f);
+ dzy[2] = (dy[2]) ? (z[2]-z[0])/dy[2] : btScalar(0.f);
+ btScalar v[3] = { dzy[0]*(miy-y[0])+z[0],
+ dzy[1]*(miy-y[1])+z[1],
+ dzy[2]*(miy-y[2])+z[2] };
+ dy[0] = y[1]-y[0];
+ dy[1] = y[0]-y[1];
+ dy[2] = y[2]-y[0];
+ btScalar* scan=&m_buffer[miy*m_sizes[0]+mix];
+ for(int iy=miy;iy<mxy;++iy)
+ {
+ if(dy[0] >= 0 && POLICY::Process(*scan,v[0]))
+ return(true);
+ if(dy[1] >= 0 && POLICY::Process(*scan,v[1]))
+ return(true);
+ if(dy[2] >= 0 && POLICY::Process(*scan,v[2]))
+ return(true);
+ scan+=m_sizes[0];
+ v[0] += dzy[0]; v[1] += dzy[1]; v[2] += dzy[2];
+ dy[0]--; dy[1]++, dy[2]--;
+ }
+ } else if (height == 1)
+ {
+ // Degenerated in at least 2 horizontal lines
+ // The algorithm below doesn't work when face has a single pixel width
+ // We cannot use general formulas because the plane is degenerated.
+ // We have to interpolate along the 3 edges that overlaps and process each pixel.
+ int xtmp;
+ btScalar ztmp;
+ if (x[0] > x[1]) { xtmp=x[1];x[1]=x[0];x[0]=xtmp;ztmp=z[1];z[1]=z[0];z[0]=ztmp; }
+ if (x[0] > x[2]) { xtmp=x[2];x[2]=x[0];x[0]=xtmp;ztmp=z[2];z[2]=z[0];z[0]=ztmp; }
+ if (x[1] > x[2]) { xtmp=x[2];x[2]=x[1];x[1]=xtmp;ztmp=z[2];z[2]=z[1];z[1]=ztmp; }
+ int dx[]={ x[0]-x[1],
+ x[1]-x[2],
+ x[2]-x[0]};
+ btScalar dzx[3];
+ dzx[0] = (dx[0]) ? (z[0]-z[1])/dx[0] : btScalar(0.f);
+ dzx[1] = (dx[1]) ? (z[1]-z[2])/dx[1] : btScalar(0.f);
+ dzx[2] = (dx[2]) ? (z[2]-z[0])/dx[2] : btScalar(0.f);
+ btScalar v[3] = { dzx[0]*(mix-x[0])+z[0],
+ dzx[1]*(mix-x[1])+z[1],
+ dzx[2]*(mix-x[2])+z[2] };
+ dx[0] = x[1]-x[0];
+ dx[1] = x[0]-x[1];
+ dx[2] = x[2]-x[0];
+ btScalar* scan=&m_buffer[miy*m_sizes[0]+mix];
+ for(int ix=mix;ix<mxx;++ix)
+ {
+ if(dx[0] >= 0 && POLICY::Process(*scan,v[0]))
+ return(true);
+ if(dx[1] >= 0 && POLICY::Process(*scan,v[1]))
+ return(true);
+ if(dx[2] >= 0 && POLICY::Process(*scan,v[2]))
+ return(true);
+ scan++;
+ v[0] += dzx[0]; v[1] += dzx[1]; v[2] += dzx[2];
+ dx[0]--; dx[1]++, dx[2]--;
+ }
+ } else
+ {
+ // general case
+ const int dx[]={ y[0]-y[1],
+ y[1]-y[2],
+ y[2]-y[0]};
+ const int dy[]={ x[1]-x[0]-dx[0]*width,
+ x[2]-x[1]-dx[1]*width,
+ x[0]-x[2]-dx[2]*width};
+ const int a=x[2]*y[0]+x[0]*y[1]-x[2]*y[1]-x[0]*y[2]+x[1]*y[2]-x[1]*y[0];
+ const btScalar ia=1/(btScalar)a;
+ const btScalar dzx=ia*(y[2]*(z[1]-z[0])+y[1]*(z[0]-z[2])+y[0]*(z[2]-z[1]));
+ const btScalar dzy=ia*(x[2]*(z[0]-z[1])+x[0]*(z[1]-z[2])+x[1]*(z[2]-z[0]))-(dzx*width);
+ int c[]={ miy*x[1]+mix*y[0]-x[1]*y[0]-mix*y[1]+x[0]*y[1]-miy*x[0],
+ miy*x[2]+mix*y[1]-x[2]*y[1]-mix*y[2]+x[1]*y[2]-miy*x[1],
+ miy*x[0]+mix*y[2]-x[0]*y[2]-mix*y[0]+x[2]*y[0]-miy*x[2]};
+ btScalar v=ia*((z[2]*c[0])+(z[0]*c[1])+(z[1]*c[2]));
+ btScalar* scan=&m_buffer[miy*m_sizes[0]];
+ for(int iy=miy;iy<mxy;++iy)
+ {
+ for(int ix=mix;ix<mxx;++ix)
+ {
+ if((c[0]>=0)&&(c[1]>=0)&&(c[2]>=0))
+ {
+ if(POLICY::Process(scan[ix],v))
+ return(true);
+ }
+ c[0]+=dx[0];c[1]+=dx[1];c[2]+=dx[2];v+=dzx;
+ }
+ c[0]+=dy[0];c[1]+=dy[1];c[2]+=dy[2];v+=dzy;
+ scan+=m_sizes[0];
+ }
+ }
+ return(false);
+ }
+ // clip than write or check a polygon
+ template <const int NP,typename POLICY>
+ inline bool clipDraw( const btVector4* p,
+ const float face,
+ btScalar minarea)
+ {
+ btVector4 o[NP*2];
+ int n=clip<NP>(p,o);
+ bool earlyexit=false;
+ if (n)
+ {
+ project(o,n);
+ for(int i=2;i<n && !earlyexit;++i)
+ {
+ earlyexit|=draw<POLICY>(o[0],o[i-1],o[i],face,minarea);
+ }
+ }
+ return(earlyexit);
+ }
+ // add a triangle (in model coordinate)
+ // face = 0.f if face is double side,
+ // = 1.f if face is single sided and scale is positive
+ // = -1.f if face is single sided and scale is negative
+ void appendOccluderM(const float* a,
+ const float* b,
+ const float* c,
+ const float face)
+ {
+ btVector4 p[3];
+ transformM(a,p[0]);
+ transformM(b,p[1]);
+ transformM(c,p[2]);
+ clipDraw<3,WriteOCL>(p,face,btScalar(0.f));
+ }
+ // add a quad (in model coordinate)
+ void appendOccluderM(const float* a,
+ const float* b,
+ const float* c,
+ const float* d,
+ const float face)
+ {
+ btVector4 p[4];
+ transformM(a,p[0]);
+ transformM(b,p[1]);
+ transformM(c,p[2]);
+ transformM(d,p[3]);
+ clipDraw<4,WriteOCL>(p,face,btScalar(0.f));
+ }
+ // query occluder for a box (c=center, e=extend) in world coordinate
+ inline bool queryOccluderW( const btVector3& c,
+ const btVector3& e)
+ {
+ if (!m_occlusion)
+ // no occlusion yet, no need to check
+ return true;
+ btVector4 x[8];
+ transformW(btVector3(c[0]-e[0],c[1]-e[1],c[2]-e[2]),x[0]);
+ transformW(btVector3(c[0]+e[0],c[1]-e[1],c[2]-e[2]),x[1]);
+ transformW(btVector3(c[0]+e[0],c[1]+e[1],c[2]-e[2]),x[2]);
+ transformW(btVector3(c[0]-e[0],c[1]+e[1],c[2]-e[2]),x[3]);
+ transformW(btVector3(c[0]-e[0],c[1]-e[1],c[2]+e[2]),x[4]);
+ transformW(btVector3(c[0]+e[0],c[1]-e[1],c[2]+e[2]),x[5]);
+ transformW(btVector3(c[0]+e[0],c[1]+e[1],c[2]+e[2]),x[6]);
+ transformW(btVector3(c[0]-e[0],c[1]+e[1],c[2]+e[2]),x[7]);
+ for(int i=0;i<8;++i)
+ {
+ // the box is clipped, it's probably a large box, don't waste our time to check
+ if((x[i][2]+x[i][3])<=0) return(true);
+ }
+ static const int d[]={ 1,0,3,2,
+ 4,5,6,7,
+ 4,7,3,0,
+ 6,5,1,2,
+ 7,6,2,3,
+ 5,4,0,1};
+ for(int i=0;i<(sizeof(d)/sizeof(d[0]));)
+ {
+ const btVector4 p[]={ x[d[i++]],
+ x[d[i++]],
+ x[d[i++]],
+ x[d[i++]]};
+ if(clipDraw<4,QueryOCL>(p,1.f,0.f))
+ return(true);
+ }
+ return(false);
+ }
+};
+
+
+struct DbvtCullingCallback : btDbvt::ICollide
+{
+ PHY_CullingCallback m_clientCallback;
+ void* m_userData;
+ OcclusionBuffer *m_ocb;
+
+ DbvtCullingCallback(PHY_CullingCallback clientCallback, void* userData)
+ {
+ m_clientCallback = clientCallback;
+ m_userData = userData;
+ m_ocb = NULL;
+ }
+ bool Descent(const btDbvtNode* node)
+ {
+ return(m_ocb->queryOccluderW(node->volume.Center(),node->volume.Extents()));
+ }
+ void Process(const btDbvtNode* node,btScalar depth)
+ {
+ Process(node);
+ }
+ void Process(const btDbvtNode* leaf)
+ {
+ btBroadphaseProxy* proxy=(btBroadphaseProxy*)leaf->data;
+ // the client object is a graphic controller
+ CcdGraphicController* ctrl = static_cast<CcdGraphicController*>(proxy->m_clientObject);
+ KX_ClientObjectInfo* info = (KX_ClientObjectInfo*)ctrl->getNewClientInfo();
+ if (m_ocb)
+ {
+ // means we are doing occlusion culling. Check if this object is an occluders
+ KX_GameObject* gameobj = KX_GameObject::GetClientObject(info);
+ if (gameobj && gameobj->GetOccluder())
+ {
+ double* fl = gameobj->GetOpenGLMatrixPtr()->getPointer();
+ // this will create the occlusion buffer if not already done
+ // and compute the transformation from model local space to clip space
+ m_ocb->SetModelMatrix(fl);
+ float face = (gameobj->IsNegativeScaling()) ? -1.0f : 1.0f;
+ // walk through the meshes and for each add to buffer
+ for (int i=0; i<gameobj->GetMeshCount(); i++)
+ {
+ RAS_MeshObject* meshobj = gameobj->GetMesh(i);
+ const float *v1, *v2, *v3, *v4;
+ int polycount = meshobj->NumPolygons();
+ for (int j=0; j<polycount; j++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(j);
+ switch (poly->VertexCount())
+ {
+ case 3:
+ v1 = poly->GetVertex(0)->getXYZ();
+ v2 = poly->GetVertex(1)->getXYZ();
+ v3 = poly->GetVertex(2)->getXYZ();
+ m_ocb->appendOccluderM(v1,v2,v3,((poly->IsTwoside())?0.f:face));
+ break;
+ case 4:
+ v1 = poly->GetVertex(0)->getXYZ();
+ v2 = poly->GetVertex(1)->getXYZ();
+ v3 = poly->GetVertex(2)->getXYZ();
+ v4 = poly->GetVertex(3)->getXYZ();
+ m_ocb->appendOccluderM(v1,v2,v3,v4,((poly->IsTwoside())?0.f:face));
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (info)
+ (*m_clientCallback)(info, m_userData);
+ }
+};
+
+static OcclusionBuffer gOcb;
+bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes)
+{
+ if (!m_cullingTree)
+ return false;
+ DbvtCullingCallback dispatcher(callback, userData);
+ btVector3 planes_n[6];
+ btScalar planes_o[6];
+ if (nplanes > 6)
+ nplanes = 6;
+ for (int i=0; i<nplanes; i++)
+ {
+ planes_n[i].setValue(planes[i][0], planes[i][1], planes[i][2]);
+ planes_o[i] = planes[i][3];
+ }
+ // if occlusionRes != 0 => occlusion culling
+ if (occlusionRes)
+ {
+ gOcb.setup(occlusionRes);
+ dispatcher.m_ocb = &gOcb;
+ // occlusion culling, the direction of the view is taken from the first plan which MUST be the near plane
+ btDbvt::collideOCL(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher);
+ btDbvt::collideOCL(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher);
+ }else
+ {
+ btDbvt::collideKDOP(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,nplanes,dispatcher);
+ btDbvt::collideKDOP(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,nplanes,dispatcher);
+ }
+ return true;
+}
int CcdPhysicsEnvironment::getNumContactPoints()
{
@@ -1211,6 +1831,13 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
if (NULL != m_broadphase)
delete m_broadphase;
+
+ if (NULL != m_cullingTree)
+ delete m_cullingTree;
+
+ if (NULL != m_cullingCache)
+ delete m_cullingCache;
+
}
@@ -1465,8 +2092,8 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radi
{
CcdConstructionInfo cinfo;
- // memory leak! The shape is not deleted by Bullet and we cannot add it to the KX_Scene.m_shapes list
- cinfo.m_collisionShape = new btSphereShape(radius);
+ memset(&cinfo, 0, sizeof(cinfo)); /* avoid uninitialized values */
+ cinfo.m_collisionShape = new btSphereShape(radius); // memory leak! The shape is not deleted by Bullet and we cannot add it to the KX_Scene.m_shapes list
cinfo.m_MotionState = 0;
cinfo.m_physicsEnv = this;
// declare this object as Dyamic rather then static!!
@@ -1925,7 +2552,7 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl
PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight)
{
CcdConstructionInfo cinfo;
-
+ memset(&cinfo, 0, sizeof(cinfo)); /* avoid uninitialized values */
// we don't need a CcdShapeConstructionInfo for this shape:
// it is simple enough for the standard copy constructor (see CcdPhysicsController::GetReplica)
cinfo.m_collisionShape = new btConeShape(coneradius,coneheight);
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index 2f1f0bb254b..f861621ae37 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -20,6 +20,7 @@ subject to the following restrictions:
#include <vector>
#include <set>
class CcdPhysicsController;
+class CcdGraphicController;
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
@@ -40,6 +41,7 @@ class btDispatcher;
class WrapperVehicle;
class btPersistentManifold;
class btBroadphaseInterface;
+struct btDbvtBroadphase;
class btOverlappingPairCache;
class btIDebugDraw;
class PHY_IVehicle;
@@ -58,7 +60,10 @@ protected:
btIDebugDraw* m_debugDrawer;
class btDefaultCollisionConfiguration* m_collisionConfiguration;
- class btBroadphaseInterface* m_broadphase;
+ class btBroadphaseInterface* m_broadphase; // broadphase for dynamic world
+ // for culling only
+ btOverlappingPairCache* m_cullingCache;
+ struct btDbvtBroadphase* m_cullingTree; // broadphase for culling
//solver iterations
int m_numIterations;
@@ -77,7 +82,7 @@ protected:
void processFhSprings(double curTime,float timeStep);
public:
- CcdPhysicsEnvironment(btDispatcher* dispatcher=0, btOverlappingPairCache* pairCache=0);
+ CcdPhysicsEnvironment(bool useDbvtCulling, btDispatcher* dispatcher=0, btOverlappingPairCache* pairCache=0);
virtual ~CcdPhysicsEnvironment();
@@ -167,6 +172,7 @@ protected:
btTypedConstraint* getConstraintById(int constraintId);
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes);
//Methods for gamelogic collision/physics callbacks
@@ -200,7 +206,12 @@ protected:
void refreshCcdPhysicsController(CcdPhysicsController* ctrl);
+ void addCcdGraphicController(CcdGraphicController* ctrl);
+
+ void removeCcdGraphicController(CcdGraphicController* ctrl);
+
btBroadphaseInterface* getBroadphase();
+ btDbvtBroadphase* getCullingTree() { return m_cullingTree; }
btDispatcher* getDispatcher();
diff --git a/source/gameengine/Physics/Bullet/Makefile b/source/gameengine/Physics/Bullet/Makefile
index d5570e75833..48e537bb6a3 100644
--- a/source/gameengine/Physics/Bullet/Makefile
+++ b/source/gameengine/Physics/Bullet/Makefile
@@ -39,8 +39,16 @@ CPPFLAGS += -I$(NAN_BULLET2)/include
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include
CPPFLAGS += -I../../../kernel/gen_system
CPPFLAGS += -I../../Physics/common
CPPFLAGS += -I../../Physics/Dummy
CPPFLAGS += -I../../Rasterizer
+CPPFLAGS += -I../../Ketsji
+CPPFLAGS += -I../../Expressions
+CPPFLAGS += -I../../GameLogic
+CPPFLAGS += -I../../SceneGraph
+CPPFLAGS += -I../../../../source/blender/makesdna
diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript
index db9f3387bfe..ab2c68ddfd5 100644
--- a/source/gameengine/Physics/Bullet/SConscript
+++ b/source/gameengine/Physics/Bullet/SConscript
@@ -1,11 +1,23 @@
#!/usr/bin/python
Import ('env')
-sources = 'CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp'
+sources = 'CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp CcdGraphicController.cpp'
-incs = '. ../common #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer'
+incs = '. ../common'
+incs += ' #source/kernel/gen_system'
+incs += ' #intern/string'
+incs += ' #intern/moto/include'
+incs += ' #extern/glew/include'
+incs += ' #source/gameengine/Rasterizer'
+incs += ' #source/gameengine/Ketsji'
+incs += ' #source/gameengine/Expressions'
+incs += ' #source/gameengine/GameLogic'
+incs += ' #source/gameengine/SceneGraph'
+incs += ' #source/blender/makesdna'
+incs += ' #intern/SoundSystem'
incs += ' ' + env['BF_BULLET_INC']
+incs += ' ' + env['BF_PYTHON_INC']
cxxflags = []
if env['OURPLATFORM']=='win32-vc':
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
index a92b1e7f4a6..4e15e6ec130 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
@@ -70,6 +70,7 @@ public:
}
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes) { return false; }
//gamelogic callbacks
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.h b/source/gameengine/Physics/Sumo/SumoPhysicsController.h
index d8ee54935d7..415bc1e3982 100644
--- a/source/gameengine/Physics/Sumo/SumoPhysicsController.h
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsController.h
@@ -144,6 +144,11 @@ public:
void GetWorldPosition(MT_Point3& pos);
void GetWorldScaling(MT_Vector3& scale);
+ float GetLinVelocityMin() const { return 0.f; }
+ void SetLinVelocityMin(float val) { }
+ float GetLinVelocityMax() const { return 0.f; }
+ void SetLinVelocityMax(float val) { }
+
// void SetSumoObject(class SM_Object* sumoObj) {
// m_sumoObj = sumoObj;
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
index 65b07a7a0be..418a361a065 100644
--- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
@@ -76,6 +76,7 @@ public:
}
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes) { return false; }
//gamelogic callbacks
diff --git a/source/gameengine/Physics/common/CMakeLists.txt b/source/gameengine/Physics/common/CMakeLists.txt
index a28fabe0c3a..41b2687fe38 100644
--- a/source/gameengine/Physics/common/CMakeLists.txt
+++ b/source/gameengine/Physics/common/CMakeLists.txt
@@ -24,7 +24,7 @@
#
# ***** END GPL LICENSE BLOCK *****
-SET(SRC PHY_IMotionState.cpp PHY_IPhysicsController.cpp PHY_IPhysicsEnvironment.cpp PHY_IVehicle.cpp)
+SET(SRC PHY_IMotionState.cpp PHY_IController.cpp PHY_IPhysicsController.cpp PHY_IGraphicController.cpp PHY_IPhysicsEnvironment.cpp PHY_IVehicle.cpp)
SET(INC
.
diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h
index c5cf92b553a..7ce40001af7 100644
--- a/source/gameengine/Physics/common/PHY_DynamicTypes.h
+++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h
@@ -19,12 +19,42 @@ subject to the following restrictions:
-
+struct KX_ClientObjectInfo;
class PHY_Shape;
struct PHY__Vector3
{
float m_vec[4];
+
+ operator const float* () const
+ {
+ return &m_vec[0];
+ }
+ operator float* ()
+ {
+ return &m_vec[0];
+ }
+};
+
+struct PHY__Vector4
+{
+ float m_vec[4];
+ PHY__Vector4() {}
+ void setValue(const float *value)
+ {
+ m_vec[0] = *value++;
+ m_vec[1] = *value++;
+ m_vec[2] = *value++;
+ m_vec[3] = *value++;
+ }
+ void setValue(const double *value)
+ {
+ m_vec[0] = (float)(*value++);
+ m_vec[1] = (float)(*value++);
+ m_vec[2] = (float)(*value++);
+ m_vec[3] = (float)(*value++);
+ }
+
operator const float* () const
{
return &m_vec[0];
@@ -34,6 +64,7 @@ struct PHY__Vector3
return &m_vec[0];
}
};
+
//typedef float PHY__Vector3[4];
enum
@@ -59,7 +90,7 @@ enum
void *client_object1,
void *client_object2,
const PHY_CollData *coll_data);
-
+ typedef void (*PHY_CullingCallback)(KX_ClientObjectInfo* info, void* param);
/// PHY_PhysicsType enumerates all possible Physics Entities.
diff --git a/source/gameengine/Physics/common/PHY_IController.cpp b/source/gameengine/Physics/common/PHY_IController.cpp
new file mode 100644
index 00000000000..47fe9a9eea8
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IController.cpp
@@ -0,0 +1,39 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "PHY_IController.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+PHY_IController::~PHY_IController()
+{
+
+}
+
diff --git a/source/gameengine/Physics/common/PHY_IController.h b/source/gameengine/Physics/common/PHY_IController.h
new file mode 100644
index 00000000000..45e93f9d24e
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IController.h
@@ -0,0 +1,53 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef PHY_ICONTROLLER_H
+#define PHY_ICONTROLLER_H
+
+#include "PHY_DynamicTypes.h"
+
+
+
+/**
+ PHY_IController is the abstract simplified Interface to objects
+ controlled by the physics engine. This includes the physics objects
+ and the graphics object for view frustrum and occlusion culling.
+*/
+class PHY_IController
+{
+ public:
+
+ virtual ~PHY_IController();
+ // clientinfo for raycasts for example
+ virtual void* getNewClientInfo()=0;
+ virtual void setNewClientInfo(void* clientinfo)=0;
+
+};
+
+#endif //PHY_ICONTROLLER_H
+
diff --git a/source/gameengine/Physics/common/PHY_IGraphicController.cpp b/source/gameengine/Physics/common/PHY_IGraphicController.cpp
new file mode 100644
index 00000000000..4dccecd3d29
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IGraphicController.cpp
@@ -0,0 +1,39 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "PHY_IGraphicController.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+PHY_IGraphicController::~PHY_IGraphicController()
+{
+
+}
+
diff --git a/source/gameengine/Physics/common/PHY_IGraphicController.h b/source/gameengine/Physics/common/PHY_IGraphicController.h
new file mode 100644
index 00000000000..36b8a978e87
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IGraphicController.h
@@ -0,0 +1,56 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef PHY_IGRAPHICCONTROLLER_H
+#define PHY_IGRAPHICCONTROLLER_H
+
+#include "PHY_IController.h"
+
+
+
+/**
+ PHY_IPhysicsController is the abstract simplified Interface to a physical object.
+ It contains the IMotionState and IDeformableMesh Interfaces.
+*/
+class PHY_IGraphicController : public PHY_IController
+{
+
+ public:
+
+ virtual ~PHY_IGraphicController();
+ /**
+ SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
+ virtual bool SetGraphicTransform()=0;
+
+ virtual PHY_IGraphicController* GetReplica(class PHY_IMotionState* motionstate) {return 0;}
+
+};
+
+#endif //PHY_IGRAPHICCONTROLLER_H
+
diff --git a/source/gameengine/Physics/common/PHY_IMotionState.h b/source/gameengine/Physics/common/PHY_IMotionState.h
index d759b0aeff4..64bb810ee7c 100644
--- a/source/gameengine/Physics/common/PHY_IMotionState.h
+++ b/source/gameengine/Physics/common/PHY_IMotionState.h
@@ -43,6 +43,8 @@ class PHY_IMotionState
virtual void getWorldPosition(float& posX,float& posY,float& posZ)=0;
virtual void getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)=0;
virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)=0;
+ // ori = array 12 floats, [0..3] = first column + 0, [4..7] = second colum, [8..11] = third column
+ virtual void getWorldOrientation(float* ori)=0;
virtual void setWorldPosition(float posX,float posY,float posZ)=0;
virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)=0;
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h
index 884e14cfb5a..770426b48db 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsController.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h
@@ -29,7 +29,7 @@
#ifndef PHY_IPHYSICSCONTROLLER_H
#define PHY_IPHYSICSCONTROLLER_H
-#include "PHY_DynamicTypes.h"
+#include "PHY_IController.h"
@@ -37,7 +37,7 @@
PHY_IPhysicsController is the abstract simplified Interface to a physical object.
It contains the IMotionState and IDeformableMesh Interfaces.
*/
-class PHY_IPhysicsController
+class PHY_IPhysicsController : public PHY_IController
{
public:
@@ -82,9 +82,7 @@ class PHY_IPhysicsController
// dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted
virtual void setRigidBody(bool rigid)=0;
- // clientinfo for raycasts for example
- virtual void* getNewClientInfo()=0;
- virtual void setNewClientInfo(void* clientinfo)=0;
+
virtual PHY_IPhysicsController* GetReplica() {return 0;}
virtual void calcXform() =0;
@@ -92,6 +90,12 @@ class PHY_IPhysicsController
virtual float GetMargin() const=0;
virtual float GetRadius() const=0;
virtual void SetRadius(float margin) = 0;
+
+ virtual float GetLinVelocityMin() const=0;
+ virtual void SetLinVelocityMin(float val) = 0;
+ virtual float GetLinVelocityMax() const=0;
+ virtual void SetLinVelocityMax(float val) = 0;
+
PHY__Vector3 GetWorldPosition(PHY__Vector3& localpos);
};
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
index 226ba3a7e74..9a4500c3214 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -142,6 +142,10 @@ class PHY_IPhysicsEnvironment
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)=0;
+ //culling based on physical broad phase
+ // the plane number must be set as follow: near, far, left, right, top, botton
+ // the near plane must be the first one and must always be present, it is used to get the direction of the view
+ virtual bool cullingTest(PHY_CullingCallback callback, void *userData, PHY__Vector4* planeNormals, int planeNumber, int occlusionRes) = 0;
//Methods for gamelogic collision/physics callbacks
//todo:
diff --git a/source/gameengine/Physics/common/PHY_Pro.h b/source/gameengine/Physics/common/PHY_Pro.h
index 32e63ac2f6d..0249fc3118a 100644
--- a/source/gameengine/Physics/common/PHY_Pro.h
+++ b/source/gameengine/Physics/common/PHY_Pro.h
@@ -35,9 +35,11 @@
struct PHY_ShapeProps {
MT_Scalar m_mass; // Total mass
MT_Scalar m_inertia; // Inertia, should be a tensor some time
- MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum
- MT_Scalar m_ang_drag; // Angular drag
+ MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum, inverted and called dampening in blenders UI
+ MT_Scalar m_ang_drag; // Angular drag, inverted and called dampening in blenders UI
MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
+ MT_Scalar m_clamp_vel_min; // Clamp the minimum velocity, this ensures an object moves at a minimum speed unless its stationary
+ MT_Scalar m_clamp_vel_max; // Clamp max velocity
bool m_do_anisotropic; // Should I do anisotropic friction?
bool m_do_fh; // Should the object have a linear Fh spring?
bool m_do_rot_fh; // Should the object have an angular Fh spring?
diff --git a/source/gameengine/Physics/common/SConscript b/source/gameengine/Physics/common/SConscript
index 4d7c808f49b..2713143f50d 100644
--- a/source/gameengine/Physics/common/SConscript
+++ b/source/gameengine/Physics/common/SConscript
@@ -1,7 +1,7 @@
#!/usr/bin/python
Import ('env')
-sources = 'PHY_IMotionState.cpp PHY_IPhysicsController.cpp PHY_IPhysicsEnvironment.cpp PHY_IVehicle.cpp'
+sources = 'PHY_IMotionState.cpp PHY_IController.cpp PHY_IPhysicsController.cpp PHY_IGraphicController.cpp PHY_IPhysicsEnvironment.cpp PHY_IVehicle.cpp'
incs = '. ../Dummy #intern/moto/include'