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);

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to