[Bf-blender-cvs] [7bb8099] hair_system: Avoid adding all the hair point rigid bodies to the CollisionWorld.

Lukas Tönne noreply at git.blender.org
Tue Aug 5 15:21:33 CEST 2014


Commit: 7bb8099e9cd7718c7a7e696d6081fb6d852c4a5e
Author: Lukas Tönne
Date:   Tue Aug 5 15:18:40 2014 +0200
Branches: hair_system
https://developer.blender.org/rB7bb8099e9cd7718c7a7e696d6081fb6d852c4a5e

Avoid adding all the hair point rigid bodies to the CollisionWorld.

Instead we now use a single box-shaped collision object for the whole
hair system, and then do direct contact tests for the point objects
when there is a potential contact. This avoids O(n^2) issues when
inserting lots of collision objects into a DbvtBroadphase.

The points now have a radius property of their own as well.

===================================================================

M	intern/rigidbody/rb_bullet_api.cpp
M	source/blender/hair/intern/HAIR_curve.cpp
M	source/blender/hair/intern/HAIR_curve.h
M	source/blender/hair/intern/HAIR_scene.cpp
M	source/blender/hair/intern/HAIR_solver.cpp
M	source/blender/hair/intern/HAIR_solver.h

===================================================================

diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp
index 5adc167..07ffe20 100644
--- a/intern/rigidbody/rb_bullet_api.cpp
+++ b/intern/rigidbody/rb_bullet_api.cpp
@@ -289,7 +289,7 @@ void RB_dworld_add_ghost(rbDynamicsWorld *world, rbGhostObject *object, int col_
 	btGhostObject *ghost = &object->ghost;
 	object->col_groups = col_groups;
 	
-	world->dynamicsWorld->addCollisionObject(ghost, btBroadphaseProxy::DefaultFilter, 0);
+	world->dynamicsWorld->addCollisionObject(ghost, btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::DefaultFilter);
 }
 
 void RB_dworld_remove_ghost(rbDynamicsWorld *world, rbGhostObject *object)
diff --git a/source/blender/hair/intern/HAIR_curve.cpp b/source/blender/hair/intern/HAIR_curve.cpp
index 39f44ad..4ce0038 100644
--- a/source/blender/hair/intern/HAIR_curve.cpp
+++ b/source/blender/hair/intern/HAIR_curve.cpp
@@ -39,6 +39,7 @@ Point::Point() :
 
 Point::Point(const float3 &rest_co) :
     rest_co(rest_co),
+    radius(0.0f),
     rb_ghost(),
     bt_shape(1.0f)
 {
diff --git a/source/blender/hair/intern/HAIR_curve.h b/source/blender/hair/intern/HAIR_curve.h
index 95d0b68..c84d304 100644
--- a/source/blender/hair/intern/HAIR_curve.h
+++ b/source/blender/hair/intern/HAIR_curve.h
@@ -56,6 +56,8 @@ struct Point {
 	float3 rest_co;
 	float3 rest_bend;
 	
+	float radius;
+	
 	rbGhostObject rb_ghost;
 	btSphereShape bt_shape;
 	
diff --git a/source/blender/hair/intern/HAIR_scene.cpp b/source/blender/hair/intern/HAIR_scene.cpp
index 3171ff2..48c543b 100644
--- a/source/blender/hair/intern/HAIR_scene.cpp
+++ b/source/blender/hair/intern/HAIR_scene.cpp
@@ -94,6 +94,8 @@ SolverData *SceneConverter::build_solver_data(Scene *scene, Object *ob, DerivedM
 			HairPoint *hair_pt = hair->points + k;
 			
 			point->rest_co = transform_point(mat, hair_pt->rest_co);
+			point->radius = 0.0f;
+			
 			point->cur.co = transform_point(mat, hair_pt->co);
 			point->cur.vel = transform_direction(mat, hair_pt->vel);
 		}
@@ -158,16 +160,41 @@ void SceneConverter::sync_rigidbody_data(SolverData *data)
 	/* sync settings */
 	Curve *solver_curves = data->curves;
 	int totcurves = data->totcurves;
+	btTransform trans;
+	btVector3 halfsize;
 	
-	for (int i = 0; i < totcurves && i < totcurves; ++i) {
-		Curve *curve = solver_curves + i;
+	if (data->totpoints == 0) {
+		trans.setIdentity();
+		halfsize = btVector3(0.5f, 0.5f, 0.5f);
+	}
+	else {
+		float3 co_min(FLT_MAX, FLT_MAX, FLT_MAX);
+		float3 co_max(-FLT_MAX, -FLT_MAX, -FLT_MAX);
 		
-		for (int k = 0; k < curve->totpoints; ++k) {
-			Point *point = curve->points + k;
+		for (int i = 0; i < totcurves && i < totcurves; ++i) {
+			Curve *curve = solver_curves + i;
 			
-			RB_ghost_set_loc_rot(&point->rb_ghost, point->cur.co.data(), unit_qt.data());
+			for (int k = 0; k < curve->totpoints; ++k) {
+				Point *point = curve->points + k;
+				
+				co_min[0] = min_ff(co_min[0], point->cur.co.x - point->radius);
+				co_min[1] = min_ff(co_min[1], point->cur.co.y - point->radius);
+				co_min[2] = min_ff(co_min[2], point->cur.co.z - point->radius);
+				co_max[0] = max_ff(co_max[0], point->cur.co.x + point->radius);
+				co_max[1] = max_ff(co_max[1], point->cur.co.y + point->radius);
+				co_max[2] = max_ff(co_max[2], point->cur.co.z + point->radius);
+				
+				RB_ghost_set_loc_rot(&point->rb_ghost, point->cur.co.data(), unit_qt.data());
+			}
 		}
+		
+		trans.setIdentity();
+		trans.setOrigin(btVector3(0.5f*(co_min[0] + co_max[0]), 0.5f*(co_min[1] + co_max[1]), 0.5f*(co_min[2] + co_max[2])));
+		halfsize = btVector3(0.5f*(co_max[0] - co_min[0]), 0.5f*(co_max[1] - co_min[1]), 0.5f*(co_max[2] - co_min[2]));
 	}
+	
+	data->rb_ghost.ghost.setWorldTransform(trans);
+	data->bt_shape.setLocalScaling(halfsize);
 }
 
 HAIR_NAMESPACE_END
diff --git a/source/blender/hair/intern/HAIR_solver.cpp b/source/blender/hair/intern/HAIR_solver.cpp
index f176a6a..c6dc92f 100644
--- a/source/blender/hair/intern/HAIR_solver.cpp
+++ b/source/blender/hair/intern/HAIR_solver.cpp
@@ -44,24 +44,34 @@ SolverData::SolverData() :
     curves(NULL),
     points(NULL),
     totcurves(0),
-    totpoints(0)
+    totpoints(0),
+    rb_ghost(),
+    bt_shape(btVector3(1.0f, 1.0f, 1.0f))
 {
+	rb_ghost.ghost.setCollisionShape(&bt_shape);
 }
 
 SolverData::SolverData(int totcurves, int totpoints) :
     totcurves(totcurves),
-    totpoints(totpoints)
+    totpoints(totpoints),
+    rb_ghost(),
+    bt_shape(btVector3(1.0f, 1.0f, 1.0f))
 {
 	curves = new Curve[totcurves];
 	points = new Point[totpoints];
+
+	rb_ghost.ghost.setCollisionShape(&bt_shape);
 }
 
 SolverData::SolverData(const SolverData &other) :
     curves(other.curves),
     points(other.points),
     totcurves(other.totcurves),
-    totpoints(other.totpoints)
+    totpoints(other.totpoints),
+    rb_ghost(),
+    bt_shape(btVector3(1.0f, 1.0f, 1.0f))
 {
+	rb_ghost.ghost.setCollisionShape(&bt_shape);
 }
 
 SolverData::~SolverData()
@@ -77,9 +87,7 @@ void SolverData::add_to_world(rbDynamicsWorld *world, int col_groups)
 	if (!world)
 		return;
 	
-	for (int k = 0; k < totpoints; ++k) {
-		RB_dworld_add_ghost(world, &points[k].rb_ghost, col_groups);
-	}
+	RB_dworld_add_ghost(world, &rb_ghost, col_groups);
 }
 
 void SolverData::remove_from_world(rbDynamicsWorld *world)
@@ -87,9 +95,7 @@ void SolverData::remove_from_world(rbDynamicsWorld *world)
 	if (!world)
 		return;
 	
-	for (int k = 0; k < totpoints; ++k) {
-		RB_dworld_remove_ghost(world, &points[k].rb_ghost);
-	}
+	RB_dworld_remove_ghost(world, &rb_ghost);
 }
 
 static float3 calc_bend(const Frame &frame, const float3 &co0, const float3 &co1)
@@ -132,9 +138,29 @@ void SolverData::precompute_rest_bend()
 	}
 }
 
-static void debug_point_contacts(btDynamicsWorld *dworld, Point *point)
+struct HairContactResultCallback : btCollisionWorld::ContactResultCallback {
+	btScalar addSingleResult(btManifoldPoint &cp,
+	                         const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0,
+	                         const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1)
+	{
+		if (cp.getDistance() < 0.f) {
+			const btVector3 &ptA = cp.getPositionWorldOnA();
+			const btVector3 &ptB = cp.getPositionWorldOnB();
+//			const btVector3 &normalOnB = cp.m_normalWorldOnB;
+			
+			Debug::collision_contact(float3(ptA.x(), ptA.y(), ptA.z()), float3(ptB.x(), ptB.y(), ptB.z()));
+		}
+		
+		/* note: return value is unused
+		 * http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20990#p20990
+		 */
+		return 0.0f;
+	}
+};
+
+static void debug_ghost_contacts(SolverData *data, btDynamicsWorld *dworld, rbGhostObject *object)
 {
-	btPairCachingGhostObject *ghost = &point->rb_ghost.ghost;
+	btPairCachingGhostObject *ghost = &object->ghost;
 	
 	btManifoldArray manifold_array;
 	const btBroadphasePairArray& pairs = ghost->getOverlappingPairCache()->getOverlappingPairArray();
@@ -149,10 +175,25 @@ static void debug_point_contacts(btDynamicsWorld *dworld, Point *point)
 		btBroadphasePair* collision_pair = dworld->getPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
 		if (!collision_pair)
 			continue;
-	
+		
+		btCollisionObject *ob0 = (btCollisionObject *)pair.m_pProxy0->m_clientObject;
+		btCollisionObject *ob1 = (btCollisionObject *)pair.m_pProxy1->m_clientObject;
+		btCollisionObject *other = ob0 == ghost ? ob1 : ob0;
+		
+		HairContactResultCallback cb;
+		
+		Curve *curve = data->curves;
+		for (int i = 0; i < data->totcurves; ++i, ++curve) {
+			Point *pt = curve->points;
+			for (int k = 0; k < curve->totpoints; ++k, ++pt) {
+				dworld->contactPairTest(&pt->rb_ghost.ghost, other, cb);
+			}
+		}
+		
+#if 0
 		if (collision_pair->m_algorithm)
 			collision_pair->m_algorithm->getAllContactManifolds(manifold_array);
-	
+		
 		for (int j = 0; j < manifold_array.size(); j++) {
 			btPersistentManifold* manifold = manifold_array[j];
 			btScalar direction_sign = manifold->getBody0() == ghost ? btScalar(-1.0) : btScalar(1.0);
@@ -167,6 +208,7 @@ static void debug_point_contacts(btDynamicsWorld *dworld, Point *point)
 				}
 			}
 		}
+#endif
 	}
 }
 
@@ -174,11 +216,32 @@ void SolverData::debug_contacts(rbDynamicsWorld *world)
 {
 	btDynamicsWorld *dworld = world->dynamicsWorld;
 	
-	Curve *curve = curves;
-	for (int i = 0; i < totcurves; ++i, ++curve) {
-		Point *pt = curve->points;
-		for (int k = 0; k < curve->totpoints; ++k, ++pt)
-			debug_point_contacts(dworld, pt);
+	debug_ghost_contacts(this, dworld, &rb_ghost);
+
+	if (rb_ghost.ghost.getBroadphaseHandle()) {
+		float3 c[8];
+		c[0] = float3((float *)rb_ghost.ghost.getBroadphaseHandle()->m_aabbMin.m_floats);
+		c[7] = float3((float *)rb_ghost.ghost.getBroadphaseHandle()->m_aabbMax.m_floats);
+		c[1] = float3(c[7].x, c[0].y, c[0].z);
+		c[2] = float3(c[0].x, c[7].y, c[0].z);
+		c[3] = float3(c[7].x, c[7].y, c[0].z);
+		c[4] = float3(c[0].x, c[0].y, c[7].z);
+		c[5] = float3(c[7].x, c[0].y, c[7].z);
+		c[6] = float3(c[0].x, c[7].y, c[7].z);
+		Debug::collision_contact(c[0], c[1]);
+		Debug::collision_contact(c[1], c[3]);
+		Debug::collision_contact(c[3], c[2]);
+		Debug::collision_contact(c[2], c[0]);
+		
+		Debug::collision_contact(c[0], c[4]);
+		Debug::collision_contact(c[1], c[5]);
+		Debug::collision_contact(c[2], c[6]);
+		Debug::collision_contact(c[3], c[7]);
+		
+		Debug::collision_contact(c[4], c[5]);
+		Debug::collision_contact(c[5], c[7]);
+		Debug::collision_contact(c[7], c[6]);
+		Debug::collision_contact(c[6], c[4]);
 	}
 }
 
diff --git a/source/blender/hair/intern/HAIR_solver.h b/source/blender/hair/intern/HAIR_solver.h
index 794c3ff..d11bf63 100644
--- a/source/blender/hair/intern/HAIR_solver.h
+++ b/source/blender/hair/intern/HAIR_solver.h
@@ -27,6 +27,8 @@
 #ifndef __HAIR_SOLVER_H__
 #define __HAIR_SOLVER_H__
 
+#include <BulletCollision/CollisionShapes/btBoxShape.h>
+
 extern "C" {
 #include "DNA_hair_types.h"
 }
@@ -52,6 +54,9 @@ struct SolverData {
 	
 	float t0, t1;
 	
+	rbGhostObject rb_ghost;
+	btBoxShape bt_shape;
+	
 	void precompute_rest_bend();
 	
 	void add_to_world(rbDynamicsWorld *world, int col_groups);




More information about the Bf-blender-cvs mailing list