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:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/blenkernel/intern/softbody.c
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/blenkernel/intern/softbody.c')
-rw-r--r--source/blender/blenkernel/intern/softbody.c5860
1 files changed, 2960 insertions, 2900 deletions
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 2e0d4719339..ba7e26e817a 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -21,12 +21,11 @@
* \ingroup bke
*/
-
/**
* variables on the UI for now
* <pre>
* float mediafrict; friction to env
- * float nodemass; softbody mass of *vertex*
+ * float nodemass; softbody mass of *vertex*
* float grav; softbody amount of gravitation to apply
*
* float goalspring; softbody goal springs
@@ -34,12 +33,11 @@
* float mingoal; quick limits for goal
* float maxgoal;
*
- * float inspring; softbody inner springs
+ * float inspring; softbody inner springs
* float infrict; softbody inner springs friction
* </pre>
*/
-
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -79,90 +77,86 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "PIL_time.h"
+#include "PIL_time.h"
static CLG_LogRef LOG = {"bke.softbody"};
/* callbacks for errors and interrupts and some goo */
static int (*SB_localInterruptCallBack)(void) = NULL;
-
/* ********** soft body engine ******* */
-typedef enum {SB_EDGE=1, SB_BEND=2, SB_STIFFQUAD=3, SB_HANDLE=4} type_spring;
+typedef enum { SB_EDGE = 1, SB_BEND = 2, SB_STIFFQUAD = 3, SB_HANDLE = 4 } type_spring;
typedef struct BodySpring {
- int v1, v2;
- float len, cf, load;
- float ext_force[3]; /* edges colliding and sailing */
- type_spring springtype;
- short flag;
+ int v1, v2;
+ float len, cf, load;
+ float ext_force[3]; /* edges colliding and sailing */
+ type_spring springtype;
+ short flag;
} BodySpring;
typedef struct BodyFace {
- int v1, v2, v3;
- float ext_force[3]; /* faces colliding */
- short flag;
+ int v1, v2, v3;
+ float ext_force[3]; /* faces colliding */
+ short flag;
} BodyFace;
typedef struct ReferenceVert {
- float pos[3]; /* position relative to com */
- float mass; /* node mass */
+ float pos[3]; /* position relative to com */
+ float mass; /* node mass */
} ReferenceVert;
typedef struct ReferenceState {
- float com[3]; /* center of mass*/
- ReferenceVert *ivert; /* list of initial values */
+ float com[3]; /* center of mass*/
+ ReferenceVert *ivert; /* list of initial values */
} ReferenceState;
-
/*private scratch pad for caching and other data only needed when alive*/
typedef struct SBScratch {
- GHash *colliderhash;
- short needstobuildcollider;
- short flag;
- BodyFace *bodyface;
- int totface;
- float aabbmin[3], aabbmax[3];
- ReferenceState Ref;
+ GHash *colliderhash;
+ short needstobuildcollider;
+ short flag;
+ BodyFace *bodyface;
+ int totface;
+ float aabbmin[3], aabbmax[3];
+ ReferenceState Ref;
} SBScratch;
-typedef struct SB_thread_context {
- Scene *scene;
- Object *ob;
- float forcetime;
- float timenow;
- int ifirst;
- int ilast;
- ListBase *effectors;
- int do_deflector;
- float fieldfactor;
- float windfactor;
- int nr;
- int tot;
+typedef struct SB_thread_context {
+ Scene *scene;
+ Object *ob;
+ float forcetime;
+ float timenow;
+ int ifirst;
+ int ilast;
+ ListBase *effectors;
+ int do_deflector;
+ float fieldfactor;
+ float windfactor;
+ int nr;
+ int tot;
} SB_thread_context;
#define MID_PRESERVE 1
-#define SOFTGOALSNAP 0.999f
+#define SOFTGOALSNAP 0.999f
/* if bp-> goal is above make it a *forced follow original* and skip all ODE stuff for this bp
* removes *unnecessary* stiffness from ODE system
*/
#define HEUNWARNLIMIT 1 /* 500 would be fine i think for detecting severe *stiff* stuff */
-
-#define BSF_INTERSECT 1 /* edge intersects collider face */
+#define BSF_INTERSECT 1 /* edge intersects collider face */
/* private definitions for bodypoint states */
-#define SBF_DOFUZZY 1 /* Bodypoint do fuzzy */
-#define SBF_OUTOFCOLLISION 2 /* Bodypoint does not collide */
-
-
-#define BFF_INTERSECT 1 /* collider edge intrudes face */
-#define BFF_CLOSEVERT 2 /* collider vertex repulses face */
+#define SBF_DOFUZZY 1 /* Bodypoint do fuzzy */
+#define SBF_OUTOFCOLLISION 2 /* Bodypoint does not collide */
+#define BFF_INTERSECT 1 /* collider edge intrudes face */
+#define BFF_CLOSEVERT 2 /* collider vertex repulses face */
-static float SoftHeunTol = 1.0f; /* humm .. this should be calculated from sb parameters and sizes */
+static float SoftHeunTol =
+ 1.0f; /* humm .. this should be calculated from sb parameters and sizes */
/* local prototypes */
static void free_softbody_intern(SoftBody *sb);
@@ -176,7 +170,7 @@ static float sb_grav_force_scale(Object *UNUSED(ob))
* put it to a function here, so we can add user options later without touching simulation code
*/
{
- return (0.001f);
+ return (0.001f);
}
static float sb_fric_force_scale(Object *UNUSED(ob))
@@ -184,27 +178,27 @@ static float sb_fric_force_scale(Object *UNUSED(ob))
* put it to a function here, so we can add user options later without touching simulation code
*/
{
- return (0.01f);
+ return (0.01f);
}
static float sb_time_scale(Object *ob)
/* defining the frames to *real* time relation */
{
- SoftBody *sb= ob->soft; /* is supposed to be there */
- if (sb) {
- return(sb->physics_speed);
- /* hrms .. this could be IPO as well :)
- * estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)]
- * 1 approx = a unit 1 pendulum at g = 9.8 [earth conditions] has period 65 frames
- * theory would give a 50 frames period .. so there must be something inaccurate .. looking for that (BM)
- */
- }
- return (1.0f);
- /*
- * this would be frames/sec independent timing assuming 25 fps is default
- * but does not work very well with NLA
- * return (25.0f/scene->r.frs_sec)
- */
+ SoftBody *sb = ob->soft; /* is supposed to be there */
+ if (sb) {
+ return (sb->physics_speed);
+ /* hrms .. this could be IPO as well :)
+ * estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)]
+ * 1 approx = a unit 1 pendulum at g = 9.8 [earth conditions] has period 65 frames
+ * theory would give a 50 frames period .. so there must be something inaccurate .. looking for that (BM)
+ */
+ }
+ return (1.0f);
+ /*
+ * this would be frames/sec independent timing assuming 25 fps is default
+ * but does not work very well with NLA
+ * return (25.0f/scene->r.frs_sec)
+ */
}
/*--- frame based timing ---*/
@@ -218,33 +212,35 @@ static float sb_time_scale(Object *ob)
*/
/* animate sb->maxgoal, sb->mingoal */
-static float _final_goal(Object *ob, BodyPoint *bp)/*jow_go_for2_5 */
-{
- float f = -1999.99f;
- if (ob) {
- SoftBody *sb= ob->soft; /* is supposed to be there */
- if (!(ob->softflag & OB_SB_GOAL)) return (0.0f);
- if (sb&&bp) {
- if (bp->goal < 0.0f) return (0.0f);
- f = sb->mingoal + bp->goal * fabsf(sb->maxgoal - sb->mingoal);
- f = pow(f, 4.0f);
- return (f);
- }
- }
- CLOG_ERROR(&LOG, "sb or bp == NULL");
- return f; /*using crude but spot able values some times helps debuggin */
+static float _final_goal(Object *ob, BodyPoint *bp) /*jow_go_for2_5 */
+{
+ float f = -1999.99f;
+ if (ob) {
+ SoftBody *sb = ob->soft; /* is supposed to be there */
+ if (!(ob->softflag & OB_SB_GOAL))
+ return (0.0f);
+ if (sb && bp) {
+ if (bp->goal < 0.0f)
+ return (0.0f);
+ f = sb->mingoal + bp->goal * fabsf(sb->maxgoal - sb->mingoal);
+ f = pow(f, 4.0f);
+ return (f);
+ }
+ }
+ CLOG_ERROR(&LOG, "sb or bp == NULL");
+ return f; /*using crude but spot able values some times helps debuggin */
}
static float _final_mass(Object *ob, BodyPoint *bp)
{
- if (ob) {
- SoftBody *sb= ob->soft; /* is supposed to be there */
- if (sb&&bp) {
- return(bp->mass*sb->nodemass);
- }
- }
- CLOG_ERROR(&LOG, "sb or bp == NULL");
- return 1.0f;
+ if (ob) {
+ SoftBody *sb = ob->soft; /* is supposed to be there */
+ if (sb && bp) {
+ return (bp->mass * sb->nodemass);
+ }
+ }
+ CLOG_ERROR(&LOG, "sb or bp == NULL");
+ return 1.0f;
}
/* helper functions for everything is animateble jow_go_for2_5 ------*/
@@ -263,466 +259,472 @@ static float _final_mass(Object *ob, BodyPoint *bp)
static const int CCD_SAVETY = 190561;
typedef struct ccdf_minmax {
- float minx, miny, minz, maxx, maxy, maxz;
+ float minx, miny, minz, maxx, maxy, maxz;
} ccdf_minmax;
-
typedef struct ccd_Mesh {
- int mvert_num, tri_num;
- const MVert *mvert;
- const MVert *mprevvert;
- const MVertTri *tri;
- int savety;
- ccdf_minmax *mima;
- /* Axis Aligned Bounding Box AABB */
- float bbmin[3];
- float bbmax[3];
+ int mvert_num, tri_num;
+ const MVert *mvert;
+ const MVert *mprevvert;
+ const MVertTri *tri;
+ int savety;
+ ccdf_minmax *mima;
+ /* Axis Aligned Bounding Box AABB */
+ float bbmin[3];
+ float bbmax[3];
} ccd_Mesh;
-
static ccd_Mesh *ccd_mesh_make(Object *ob)
{
- CollisionModifierData *cmd;
- ccd_Mesh *pccd_M = NULL;
- ccdf_minmax *mima;
- const MVertTri *vt;
- float hull;
- int i;
-
- cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
-
- /* first some paranoia checks */
- if (!cmd) return NULL;
- if (!cmd->mvert_num || !cmd->tri_num) return NULL;
-
- pccd_M = MEM_mallocN(sizeof(ccd_Mesh), "ccd_Mesh");
- pccd_M->mvert_num = cmd->mvert_num;
- pccd_M->tri_num = cmd->tri_num;
- pccd_M->savety = CCD_SAVETY;
- pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f;
- pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f;
- pccd_M->mprevvert=NULL;
-
- /* blow it up with forcefield ranges */
- hull = max_ff(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
-
- /* alloc and copy verts*/
- pccd_M->mvert = MEM_dupallocN(cmd->xnew);
- /* note that xnew coords are already in global space, */
- /* determine the ortho BB */
- for (i = 0; i < pccd_M->mvert_num; i++) {
- const float *v;
-
- /* evaluate limits */
- v = pccd_M->mvert[i].co;
- pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
- pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
- pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
-
- pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
- pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
- pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
-
- }
- /* alloc and copy faces*/
- pccd_M->tri = MEM_dupallocN(cmd->tri);
-
- /* OBBs for idea1 */
- pccd_M->mima = MEM_mallocN(sizeof(ccdf_minmax) * pccd_M->tri_num, "ccd_Mesh_Faces_mima");
-
-
- /* anyhoo we need to walk the list of faces and find OBB they live in */
- for (i = 0, mima = pccd_M->mima, vt = pccd_M->tri; i < pccd_M->tri_num; i++, mima++, vt++) {
- const float *v;
-
- mima->minx=mima->miny=mima->minz=1e30f;
- mima->maxx=mima->maxy=mima->maxz=-1e30f;
-
- v = pccd_M->mvert[vt->tri[0]].co;
- mima->minx = min_ff(mima->minx, v[0] - hull);
- mima->miny = min_ff(mima->miny, v[1] - hull);
- mima->minz = min_ff(mima->minz, v[2] - hull);
- mima->maxx = max_ff(mima->maxx, v[0] + hull);
- mima->maxy = max_ff(mima->maxy, v[1] + hull);
- mima->maxz = max_ff(mima->maxz, v[2] + hull);
-
- v = pccd_M->mvert[vt->tri[1]].co;
- mima->minx = min_ff(mima->minx, v[0] - hull);
- mima->miny = min_ff(mima->miny, v[1] - hull);
- mima->minz = min_ff(mima->minz, v[2] - hull);
- mima->maxx = max_ff(mima->maxx, v[0] + hull);
- mima->maxy = max_ff(mima->maxy, v[1] + hull);
- mima->maxz = max_ff(mima->maxz, v[2] + hull);
-
- v = pccd_M->mvert[vt->tri[2]].co;
- mima->minx = min_ff(mima->minx, v[0] - hull);
- mima->miny = min_ff(mima->miny, v[1] - hull);
- mima->minz = min_ff(mima->minz, v[2] - hull);
- mima->maxx = max_ff(mima->maxx, v[0] + hull);
- mima->maxy = max_ff(mima->maxy, v[1] + hull);
- mima->maxz = max_ff(mima->maxz, v[2] + hull);
- }
-
- return pccd_M;
+ CollisionModifierData *cmd;
+ ccd_Mesh *pccd_M = NULL;
+ ccdf_minmax *mima;
+ const MVertTri *vt;
+ float hull;
+ int i;
+
+ cmd = (CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
+
+ /* first some paranoia checks */
+ if (!cmd)
+ return NULL;
+ if (!cmd->mvert_num || !cmd->tri_num)
+ return NULL;
+
+ pccd_M = MEM_mallocN(sizeof(ccd_Mesh), "ccd_Mesh");
+ pccd_M->mvert_num = cmd->mvert_num;
+ pccd_M->tri_num = cmd->tri_num;
+ pccd_M->savety = CCD_SAVETY;
+ pccd_M->bbmin[0] = pccd_M->bbmin[1] = pccd_M->bbmin[2] = 1e30f;
+ pccd_M->bbmax[0] = pccd_M->bbmax[1] = pccd_M->bbmax[2] = -1e30f;
+ pccd_M->mprevvert = NULL;
+
+ /* blow it up with forcefield ranges */
+ hull = max_ff(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
+
+ /* alloc and copy verts*/
+ pccd_M->mvert = MEM_dupallocN(cmd->xnew);
+ /* note that xnew coords are already in global space, */
+ /* determine the ortho BB */
+ for (i = 0; i < pccd_M->mvert_num; i++) {
+ const float *v;
+
+ /* evaluate limits */
+ v = pccd_M->mvert[i].co;
+ pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
+ pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
+ pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
+
+ pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
+ pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
+ pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
+ }
+ /* alloc and copy faces*/
+ pccd_M->tri = MEM_dupallocN(cmd->tri);
+
+ /* OBBs for idea1 */
+ pccd_M->mima = MEM_mallocN(sizeof(ccdf_minmax) * pccd_M->tri_num, "ccd_Mesh_Faces_mima");
+
+ /* anyhoo we need to walk the list of faces and find OBB they live in */
+ for (i = 0, mima = pccd_M->mima, vt = pccd_M->tri; i < pccd_M->tri_num; i++, mima++, vt++) {
+ const float *v;
+
+ mima->minx = mima->miny = mima->minz = 1e30f;
+ mima->maxx = mima->maxy = mima->maxz = -1e30f;
+
+ v = pccd_M->mvert[vt->tri[0]].co;
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
+
+ v = pccd_M->mvert[vt->tri[1]].co;
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
+
+ v = pccd_M->mvert[vt->tri[2]].co;
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
+ }
+
+ return pccd_M;
}
static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
{
- CollisionModifierData *cmd;
- ccdf_minmax *mima;
- const MVertTri *vt;
- float hull;
- int i;
-
- cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
-
- /* first some paranoia checks */
- if (!cmd) return;
- if (!cmd->mvert_num || !cmd->tri_num) return;
-
- if ((pccd_M->mvert_num != cmd->mvert_num) ||
- (pccd_M->tri_num != cmd->tri_num))
- {
- return;
- }
-
- pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f;
- pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f;
-
-
- /* blow it up with forcefield ranges */
- hull = max_ff(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
-
- /* rotate current to previous */
- if (pccd_M->mprevvert) MEM_freeN((void *)pccd_M->mprevvert);
- pccd_M->mprevvert = pccd_M->mvert;
- /* alloc and copy verts*/
- pccd_M->mvert = MEM_dupallocN(cmd->xnew);
- /* note that xnew coords are already in global space, */
- /* determine the ortho BB */
- for (i=0; i < pccd_M->mvert_num; i++) {
- const float *v;
-
- /* evaluate limits */
- v = pccd_M->mvert[i].co;
- pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
- pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
- pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
-
- pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
- pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
- pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
-
- /* evaluate limits */
- v = pccd_M->mprevvert[i].co;
- pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
- pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
- pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
-
- pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
- pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
- pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
-
- }
-
- /* anyhoo we need to walk the list of faces and find OBB they live in */
- for (i = 0, mima = pccd_M->mima, vt = pccd_M->tri; i < pccd_M->tri_num; i++, mima++, vt++) {
- const float *v;
-
- mima->minx=mima->miny=mima->minz=1e30f;
- mima->maxx=mima->maxy=mima->maxz=-1e30f;
-
- /* mvert */
- v = pccd_M->mvert[vt->tri[0]].co;
- mima->minx = min_ff(mima->minx, v[0] - hull);
- mima->miny = min_ff(mima->miny, v[1] - hull);
- mima->minz = min_ff(mima->minz, v[2] - hull);
- mima->maxx = max_ff(mima->maxx, v[0] + hull);
- mima->maxy = max_ff(mima->maxy, v[1] + hull);
- mima->maxz = max_ff(mima->maxz, v[2] + hull);
-
- v = pccd_M->mvert[vt->tri[1]].co;
- mima->minx = min_ff(mima->minx, v[0] - hull);
- mima->miny = min_ff(mima->miny, v[1] - hull);
- mima->minz = min_ff(mima->minz, v[2] - hull);
- mima->maxx = max_ff(mima->maxx, v[0] + hull);
- mima->maxy = max_ff(mima->maxy, v[1] + hull);
- mima->maxz = max_ff(mima->maxz, v[2] + hull);
-
- v = pccd_M->mvert[vt->tri[2]].co;
- mima->minx = min_ff(mima->minx, v[0] - hull);
- mima->miny = min_ff(mima->miny, v[1] - hull);
- mima->minz = min_ff(mima->minz, v[2] - hull);
- mima->maxx = max_ff(mima->maxx, v[0] + hull);
- mima->maxy = max_ff(mima->maxy, v[1] + hull);
- mima->maxz = max_ff(mima->maxz, v[2] + hull);
-
-
- /* mprevvert */
- v = pccd_M->mprevvert[vt->tri[0]].co;
- mima->minx = min_ff(mima->minx, v[0] - hull);
- mima->miny = min_ff(mima->miny, v[1] - hull);
- mima->minz = min_ff(mima->minz, v[2] - hull);
- mima->maxx = max_ff(mima->maxx, v[0] + hull);
- mima->maxy = max_ff(mima->maxy, v[1] + hull);
- mima->maxz = max_ff(mima->maxz, v[2] + hull);
-
- v = pccd_M->mprevvert[vt->tri[1]].co;
- mima->minx = min_ff(mima->minx, v[0] - hull);
- mima->miny = min_ff(mima->miny, v[1] - hull);
- mima->minz = min_ff(mima->minz, v[2] - hull);
- mima->maxx = max_ff(mima->maxx, v[0] + hull);
- mima->maxy = max_ff(mima->maxy, v[1] + hull);
- mima->maxz = max_ff(mima->maxz, v[2] + hull);
-
- v = pccd_M->mprevvert[vt->tri[2]].co;
- mima->minx = min_ff(mima->minx, v[0] - hull);
- mima->miny = min_ff(mima->miny, v[1] - hull);
- mima->minz = min_ff(mima->minz, v[2] - hull);
- mima->maxx = max_ff(mima->maxx, v[0] + hull);
- mima->maxy = max_ff(mima->maxy, v[1] + hull);
- mima->maxz = max_ff(mima->maxz, v[2] + hull);
- }
- return;
+ CollisionModifierData *cmd;
+ ccdf_minmax *mima;
+ const MVertTri *vt;
+ float hull;
+ int i;
+
+ cmd = (CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
+
+ /* first some paranoia checks */
+ if (!cmd)
+ return;
+ if (!cmd->mvert_num || !cmd->tri_num)
+ return;
+
+ if ((pccd_M->mvert_num != cmd->mvert_num) || (pccd_M->tri_num != cmd->tri_num)) {
+ return;
+ }
+
+ pccd_M->bbmin[0] = pccd_M->bbmin[1] = pccd_M->bbmin[2] = 1e30f;
+ pccd_M->bbmax[0] = pccd_M->bbmax[1] = pccd_M->bbmax[2] = -1e30f;
+
+ /* blow it up with forcefield ranges */
+ hull = max_ff(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
+
+ /* rotate current to previous */
+ if (pccd_M->mprevvert)
+ MEM_freeN((void *)pccd_M->mprevvert);
+ pccd_M->mprevvert = pccd_M->mvert;
+ /* alloc and copy verts*/
+ pccd_M->mvert = MEM_dupallocN(cmd->xnew);
+ /* note that xnew coords are already in global space, */
+ /* determine the ortho BB */
+ for (i = 0; i < pccd_M->mvert_num; i++) {
+ const float *v;
+
+ /* evaluate limits */
+ v = pccd_M->mvert[i].co;
+ pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
+ pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
+ pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
+
+ pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
+ pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
+ pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
+
+ /* evaluate limits */
+ v = pccd_M->mprevvert[i].co;
+ pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
+ pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
+ pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
+
+ pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
+ pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
+ pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
+ }
+
+ /* anyhoo we need to walk the list of faces and find OBB they live in */
+ for (i = 0, mima = pccd_M->mima, vt = pccd_M->tri; i < pccd_M->tri_num; i++, mima++, vt++) {
+ const float *v;
+
+ mima->minx = mima->miny = mima->minz = 1e30f;
+ mima->maxx = mima->maxy = mima->maxz = -1e30f;
+
+ /* mvert */
+ v = pccd_M->mvert[vt->tri[0]].co;
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
+
+ v = pccd_M->mvert[vt->tri[1]].co;
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
+
+ v = pccd_M->mvert[vt->tri[2]].co;
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
+
+ /* mprevvert */
+ v = pccd_M->mprevvert[vt->tri[0]].co;
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
+
+ v = pccd_M->mprevvert[vt->tri[1]].co;
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
+
+ v = pccd_M->mprevvert[vt->tri[2]].co;
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
+ }
+ return;
}
static void ccd_mesh_free(ccd_Mesh *ccdm)
{
- if (ccdm && (ccdm->savety == CCD_SAVETY )) { /*make sure we're not nuking objects we don't know*/
- MEM_freeN((void *)ccdm->mvert);
- MEM_freeN((void *)ccdm->tri);
- if (ccdm->mprevvert) MEM_freeN((void *)ccdm->mprevvert);
- MEM_freeN(ccdm->mima);
- MEM_freeN(ccdm);
- ccdm = NULL;
- }
+ if (ccdm && (ccdm->savety == CCD_SAVETY)) { /*make sure we're not nuking objects we don't know*/
+ MEM_freeN((void *)ccdm->mvert);
+ MEM_freeN((void *)ccdm->tri);
+ if (ccdm->mprevvert)
+ MEM_freeN((void *)ccdm->mprevvert);
+ MEM_freeN(ccdm->mima);
+ MEM_freeN(ccdm);
+ ccdm = NULL;
+ }
}
static void ccd_build_deflector_hash_single(GHash *hash, Object *ob)
{
- /* only with deflecting set */
- if (ob->pd && ob->pd->deflect) {
- void **val_p;
- if (!BLI_ghash_ensure_p(hash, ob, &val_p)) {
- ccd_Mesh *ccdmesh = ccd_mesh_make(ob);
- *val_p = ccdmesh;
- }
- }
+ /* only with deflecting set */
+ if (ob->pd && ob->pd->deflect) {
+ void **val_p;
+ if (!BLI_ghash_ensure_p(hash, ob, &val_p)) {
+ ccd_Mesh *ccdmesh = ccd_mesh_make(ob);
+ *val_p = ccdmesh;
+ }
+ }
}
/**
* \note collection overrides scene when not NULL.
*/
-static void ccd_build_deflector_hash(Depsgraph *depsgraph, Collection *collection, Object *vertexowner, GHash *hash)
+static void ccd_build_deflector_hash(Depsgraph *depsgraph,
+ Collection *collection,
+ Object *vertexowner,
+ GHash *hash)
{
- if (!hash) return;
+ if (!hash)
+ return;
- unsigned int numobjects;
- Object **objects = BKE_collision_objects_create(depsgraph, vertexowner, collection, &numobjects, eModifierType_Collision);
+ unsigned int numobjects;
+ Object **objects = BKE_collision_objects_create(
+ depsgraph, vertexowner, collection, &numobjects, eModifierType_Collision);
- for (int i = 0; i < numobjects; i++) {
- Object *ob = objects[i];
+ for (int i = 0; i < numobjects; i++) {
+ Object *ob = objects[i];
- if (ob->type == OB_MESH) {
- ccd_build_deflector_hash_single(hash, ob);
- }
- }
+ if (ob->type == OB_MESH) {
+ ccd_build_deflector_hash_single(hash, ob);
+ }
+ }
- BKE_collision_objects_free(objects);
+ BKE_collision_objects_free(objects);
}
static void ccd_update_deflector_hash_single(GHash *hash, Object *ob)
{
- if (ob->pd && ob->pd->deflect) {
- ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash, ob);
- if (ccdmesh) {
- ccd_mesh_update(ob, ccdmesh);
- }
- }
+ if (ob->pd && ob->pd->deflect) {
+ ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash, ob);
+ if (ccdmesh) {
+ ccd_mesh_update(ob, ccdmesh);
+ }
+ }
}
/**
* \note collection overrides scene when not NULL.
*/
-static void ccd_update_deflector_hash(Depsgraph *depsgraph, Collection *collection, Object *vertexowner, GHash *hash)
+static void ccd_update_deflector_hash(Depsgraph *depsgraph,
+ Collection *collection,
+ Object *vertexowner,
+ GHash *hash)
{
- if ((!hash) || (!vertexowner)) return;
+ if ((!hash) || (!vertexowner))
+ return;
- unsigned int numobjects;
- Object **objects = BKE_collision_objects_create(depsgraph, vertexowner, collection, &numobjects, eModifierType_Collision);
+ unsigned int numobjects;
+ Object **objects = BKE_collision_objects_create(
+ depsgraph, vertexowner, collection, &numobjects, eModifierType_Collision);
- for (int i = 0; i < numobjects; i++) {
- Object *ob = objects[i];
+ for (int i = 0; i < numobjects; i++) {
+ Object *ob = objects[i];
- if (ob->type == OB_MESH) {
- ccd_update_deflector_hash_single(hash, ob);
- }
- }
+ if (ob->type == OB_MESH) {
+ ccd_update_deflector_hash_single(hash, ob);
+ }
+ }
- BKE_collision_objects_free(objects);
+ BKE_collision_objects_free(objects);
}
/*--- collider caching and dicing ---*/
-
static int count_mesh_quads(Mesh *me)
{
- int a, result = 0;
- const MPoly *mp = me->mpoly;
+ int a, result = 0;
+ const MPoly *mp = me->mpoly;
- if (mp) {
- for (a = me->totpoly; a > 0; a--, mp++) {
- if (mp->totloop == 4) {
- result++;
- }
- }
- }
- return result;
+ if (mp) {
+ for (a = me->totpoly; a > 0; a--, mp++) {
+ if (mp->totloop == 4) {
+ result++;
+ }
+ }
+ }
+ return result;
}
static void add_mesh_quad_diag_springs(Object *ob)
{
- Mesh *me= ob->data;
- /*BodyPoint *bp;*/ /*UNUSED*/
- int a;
-
- if (ob->soft) {
- int nofquads;
- //float s_shear = ob->soft->shearstiff*ob->soft->shearstiff;
-
- nofquads = count_mesh_quads(me);
- if (nofquads) {
- const MLoop *mloop = me->mloop;
- const MPoly *mp = me->mpoly;
- BodySpring *bs;
-
- /* resize spring-array to hold additional quad springs */
- ob->soft->bspring = MEM_recallocN(ob->soft->bspring, sizeof(BodySpring) * (ob->soft->totspring + nofquads * 2));
-
- /* fill the tail */
- a = 0;
- bs = &ob->soft->bspring[ob->soft->totspring];
- /*bp= ob->soft->bpoint; */ /*UNUSED*/
- for (a = me->totpoly; a > 0; a--, mp++) {
- if (mp->totloop == 4) {
- bs->v1 = mloop[mp->loopstart + 0].v;
- bs->v2 = mloop[mp->loopstart + 2].v;
- bs->springtype = SB_STIFFQUAD;
- bs++;
- bs->v1 = mloop[mp->loopstart + 1].v;
- bs->v2 = mloop[mp->loopstart + 3].v;
- bs->springtype = SB_STIFFQUAD;
- bs++;
- }
- }
-
- /* now we can announce new springs */
- ob->soft->totspring += nofquads * 2;
- }
- }
+ Mesh *me = ob->data;
+ /*BodyPoint *bp;*/ /*UNUSED*/
+ int a;
+
+ if (ob->soft) {
+ int nofquads;
+ //float s_shear = ob->soft->shearstiff*ob->soft->shearstiff;
+
+ nofquads = count_mesh_quads(me);
+ if (nofquads) {
+ const MLoop *mloop = me->mloop;
+ const MPoly *mp = me->mpoly;
+ BodySpring *bs;
+
+ /* resize spring-array to hold additional quad springs */
+ ob->soft->bspring = MEM_recallocN(ob->soft->bspring,
+ sizeof(BodySpring) * (ob->soft->totspring + nofquads * 2));
+
+ /* fill the tail */
+ a = 0;
+ bs = &ob->soft->bspring[ob->soft->totspring];
+ /*bp= ob->soft->bpoint; */ /*UNUSED*/
+ for (a = me->totpoly; a > 0; a--, mp++) {
+ if (mp->totloop == 4) {
+ bs->v1 = mloop[mp->loopstart + 0].v;
+ bs->v2 = mloop[mp->loopstart + 2].v;
+ bs->springtype = SB_STIFFQUAD;
+ bs++;
+ bs->v1 = mloop[mp->loopstart + 1].v;
+ bs->v2 = mloop[mp->loopstart + 3].v;
+ bs->springtype = SB_STIFFQUAD;
+ bs++;
+ }
+ }
+
+ /* now we can announce new springs */
+ ob->soft->totspring += nofquads * 2;
+ }
+ }
}
static void add_2nd_order_roller(Object *ob, float UNUSED(stiffness), int *counter, int addsprings)
{
- /*assume we have a softbody*/
- SoftBody *sb= ob->soft; /* is supposed to be there */
- BodyPoint *bp, *bpo;
- BodySpring *bs, *bs2, *bs3= NULL;
- int a, b, c, notthis= 0, v0;
- if (!sb->bspring) {return;} /* we are 2nd order here so 1rst should have been build :) */
- /* first run counting second run adding */
- *counter = 0;
- if (addsprings) bs3 = ob->soft->bspring+ob->soft->totspring;
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- /*scan for neighborhood*/
- bpo = NULL;
- v0 = (sb->totpoint-a);
- for (b=bp->nofsprings;b>0;b--) {
- bs = sb->bspring + bp->springs[b-1];
- /*nasty thing here that springs have two ends
- so here we have to make sure we examine the other */
- if (v0 == bs->v1) {
- bpo = sb->bpoint+bs->v2;
- notthis = bs->v2;
- }
- else {
- if (v0 == bs->v2) {
- bpo = sb->bpoint+bs->v1;
- notthis = bs->v1;
- }
- else {
- CLOG_ERROR(&LOG, "oops we should not get here");
- }
- }
- if (bpo) {/* so now we have a 2nd order humpdidump */
- for (c=bpo->nofsprings;c>0;c--) {
- bs2 = sb->bspring + bpo->springs[c-1];
- if ((bs2->v1 != notthis) && (bs2->v1 > v0)) {
- (*counter)++;/*hit */
- if (addsprings) {
- bs3->v1= v0;
- bs3->v2= bs2->v1;
- bs3->springtype = SB_BEND;
- bs3++;
- }
- }
- if ((bs2->v2 !=notthis)&&(bs2->v2 > v0)) {
- (*counter)++; /* hit */
- if (addsprings) {
- bs3->v1= v0;
- bs3->v2= bs2->v2;
- bs3->springtype = SB_BEND;
- bs3++;
- }
-
- }
- }
-
- }
-
- }
- /*scan for neighborhood done*/
- }
+ /*assume we have a softbody*/
+ SoftBody *sb = ob->soft; /* is supposed to be there */
+ BodyPoint *bp, *bpo;
+ BodySpring *bs, *bs2, *bs3 = NULL;
+ int a, b, c, notthis = 0, v0;
+ if (!sb->bspring) {
+ return;
+ } /* we are 2nd order here so 1rst should have been build :) */
+ /* first run counting second run adding */
+ *counter = 0;
+ if (addsprings)
+ bs3 = ob->soft->bspring + ob->soft->totspring;
+ for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
+ /*scan for neighborhood*/
+ bpo = NULL;
+ v0 = (sb->totpoint - a);
+ for (b = bp->nofsprings; b > 0; b--) {
+ bs = sb->bspring + bp->springs[b - 1];
+ /*nasty thing here that springs have two ends
+ so here we have to make sure we examine the other */
+ if (v0 == bs->v1) {
+ bpo = sb->bpoint + bs->v2;
+ notthis = bs->v2;
+ }
+ else {
+ if (v0 == bs->v2) {
+ bpo = sb->bpoint + bs->v1;
+ notthis = bs->v1;
+ }
+ else {
+ CLOG_ERROR(&LOG, "oops we should not get here");
+ }
+ }
+ if (bpo) { /* so now we have a 2nd order humpdidump */
+ for (c = bpo->nofsprings; c > 0; c--) {
+ bs2 = sb->bspring + bpo->springs[c - 1];
+ if ((bs2->v1 != notthis) && (bs2->v1 > v0)) {
+ (*counter)++; /*hit */
+ if (addsprings) {
+ bs3->v1 = v0;
+ bs3->v2 = bs2->v1;
+ bs3->springtype = SB_BEND;
+ bs3++;
+ }
+ }
+ if ((bs2->v2 != notthis) && (bs2->v2 > v0)) {
+ (*counter)++; /* hit */
+ if (addsprings) {
+ bs3->v1 = v0;
+ bs3->v2 = bs2->v2;
+ bs3->springtype = SB_BEND;
+ bs3++;
+ }
+ }
+ }
+ }
+ }
+ /*scan for neighborhood done*/
+ }
}
-
static void add_2nd_order_springs(Object *ob, float stiffness)
{
- int counter = 0;
- BodySpring *bs_new;
- stiffness *=stiffness;
+ int counter = 0;
+ BodySpring *bs_new;
+ stiffness *= stiffness;
- add_2nd_order_roller(ob, stiffness, &counter, 0); /* counting */
- if (counter) {
- /* resize spring-array to hold additional springs */
- bs_new= MEM_callocN((ob->soft->totspring + counter )*sizeof(BodySpring), "bodyspring");
- memcpy(bs_new, ob->soft->bspring, (ob->soft->totspring )*sizeof(BodySpring));
+ add_2nd_order_roller(ob, stiffness, &counter, 0); /* counting */
+ if (counter) {
+ /* resize spring-array to hold additional springs */
+ bs_new = MEM_callocN((ob->soft->totspring + counter) * sizeof(BodySpring), "bodyspring");
+ memcpy(bs_new, ob->soft->bspring, (ob->soft->totspring) * sizeof(BodySpring));
- if (ob->soft->bspring)
- MEM_freeN(ob->soft->bspring);
- ob->soft->bspring = bs_new;
+ if (ob->soft->bspring)
+ MEM_freeN(ob->soft->bspring);
+ ob->soft->bspring = bs_new;
- add_2nd_order_roller(ob, stiffness, &counter, 1); /* adding */
- ob->soft->totspring += counter;
- }
+ add_2nd_order_roller(ob, stiffness, &counter, 1); /* adding */
+ ob->soft->totspring += counter;
+ }
}
static void add_bp_springlist(BodyPoint *bp, int springID)
{
- int *newlist;
+ int *newlist;
- if (bp->springs == NULL) {
- bp->springs = MEM_callocN(sizeof(int), "bpsprings");
- bp->springs[0] = springID;
- bp->nofsprings = 1;
- }
- else {
- bp->nofsprings++;
- newlist = MEM_callocN(bp->nofsprings * sizeof(int), "bpsprings");
- memcpy(newlist, bp->springs, (bp->nofsprings-1)* sizeof(int));
- MEM_freeN(bp->springs);
- bp->springs = newlist;
- bp->springs[bp->nofsprings-1] = springID;
- }
+ if (bp->springs == NULL) {
+ bp->springs = MEM_callocN(sizeof(int), "bpsprings");
+ bp->springs[0] = springID;
+ bp->nofsprings = 1;
+ }
+ else {
+ bp->nofsprings++;
+ newlist = MEM_callocN(bp->nofsprings * sizeof(int), "bpsprings");
+ memcpy(newlist, bp->springs, (bp->nofsprings - 1) * sizeof(int));
+ MEM_freeN(bp->springs);
+ bp->springs = newlist;
+ bp->springs[bp->nofsprings - 1] = springID;
+ }
}
/**
@@ -731,193 +733,197 @@ static void add_bp_springlist(BodyPoint *bp, int springID)
*/
static void build_bps_springlist(Object *ob)
{
- SoftBody *sb= ob->soft; /* is supposed to be there */
- BodyPoint *bp;
- BodySpring *bs;
- int a, b;
-
- if (sb==NULL) return; /* paranoya check */
-
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- /* throw away old list */
- if (bp->springs) {
- MEM_freeN(bp->springs);
- bp->springs=NULL;
- }
- /* scan for attached inner springs */
- for (b=sb->totspring, bs= sb->bspring; b>0; b--, bs++) {
- if (( (sb->totpoint-a) == bs->v1) ) {
- add_bp_springlist(bp, sb->totspring -b);
- }
- if (( (sb->totpoint-a) == bs->v2) ) {
- add_bp_springlist(bp, sb->totspring -b);
- }
- }/*for springs*/
- }/*for bp*/
+ SoftBody *sb = ob->soft; /* is supposed to be there */
+ BodyPoint *bp;
+ BodySpring *bs;
+ int a, b;
+
+ if (sb == NULL)
+ return; /* paranoya check */
+
+ for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
+ /* throw away old list */
+ if (bp->springs) {
+ MEM_freeN(bp->springs);
+ bp->springs = NULL;
+ }
+ /* scan for attached inner springs */
+ for (b = sb->totspring, bs = sb->bspring; b > 0; b--, bs++) {
+ if (((sb->totpoint - a) == bs->v1)) {
+ add_bp_springlist(bp, sb->totspring - b);
+ }
+ if (((sb->totpoint - a) == bs->v2)) {
+ add_bp_springlist(bp, sb->totspring - b);
+ }
+ } /*for springs*/
+ } /*for bp*/
}
static void calculate_collision_balls(Object *ob)
{
- SoftBody *sb= ob->soft; /* is supposed to be there */
- BodyPoint *bp;
- BodySpring *bs;
- int a, b, akku_count;
- float min, max, akku;
-
- if (sb==NULL) return; /* paranoya check */
-
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- bp->colball=0;
- akku =0.0f;
- akku_count=0;
- min = 1e22f;
- max = -1e22f;
- /* first estimation based on attached */
- for (b=bp->nofsprings;b>0;b--) {
- bs = sb->bspring + bp->springs[b-1];
- if (bs->springtype == SB_EDGE) {
- akku += bs->len;
- akku_count++;
- min = min_ff(bs->len, min);
- max = max_ff(bs->len, max);
- }
- }
-
- if (akku_count > 0) {
- if (sb->sbc_mode == SBC_MODE_MANUAL) {
- bp->colball=sb->colball;
- }
- if (sb->sbc_mode == SBC_MODE_AVG) {
- bp->colball = akku/(float)akku_count*sb->colball;
- }
- if (sb->sbc_mode == SBC_MODE_MIN) {
- bp->colball=min*sb->colball;
- }
- if (sb->sbc_mode == SBC_MODE_MAX) {
- bp->colball=max*sb->colball;
- }
- if (sb->sbc_mode == SBC_MODE_AVGMINMAX) {
- bp->colball = (min + max)/2.0f*sb->colball;
- }
- }
- else bp->colball=0;
- }/*for bp*/
+ SoftBody *sb = ob->soft; /* is supposed to be there */
+ BodyPoint *bp;
+ BodySpring *bs;
+ int a, b, akku_count;
+ float min, max, akku;
+
+ if (sb == NULL)
+ return; /* paranoya check */
+
+ for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
+ bp->colball = 0;
+ akku = 0.0f;
+ akku_count = 0;
+ min = 1e22f;
+ max = -1e22f;
+ /* first estimation based on attached */
+ for (b = bp->nofsprings; b > 0; b--) {
+ bs = sb->bspring + bp->springs[b - 1];
+ if (bs->springtype == SB_EDGE) {
+ akku += bs->len;
+ akku_count++;
+ min = min_ff(bs->len, min);
+ max = max_ff(bs->len, max);
+ }
+ }
+
+ if (akku_count > 0) {
+ if (sb->sbc_mode == SBC_MODE_MANUAL) {
+ bp->colball = sb->colball;
+ }
+ if (sb->sbc_mode == SBC_MODE_AVG) {
+ bp->colball = akku / (float)akku_count * sb->colball;
+ }
+ if (sb->sbc_mode == SBC_MODE_MIN) {
+ bp->colball = min * sb->colball;
+ }
+ if (sb->sbc_mode == SBC_MODE_MAX) {
+ bp->colball = max * sb->colball;
+ }
+ if (sb->sbc_mode == SBC_MODE_AVGMINMAX) {
+ bp->colball = (min + max) / 2.0f * sb->colball;
+ }
+ }
+ else
+ bp->colball = 0;
+ } /*for bp*/
}
-
/* creates new softbody if didn't exist yet, makes new points and springs arrays */
static void renew_softbody(Scene *scene, Object *ob, int totpoint, int totspring)
{
- SoftBody *sb;
- int i;
- short softflag;
- if (ob->soft==NULL) ob->soft= sbNew(scene);
- else free_softbody_intern(ob->soft);
- sb= ob->soft;
- softflag=ob->softflag;
-
- if (totpoint) {
- sb->totpoint= totpoint;
- sb->totspring= totspring;
-
- sb->bpoint= MEM_mallocN(totpoint*sizeof(BodyPoint), "bodypoint");
- if (totspring)
- sb->bspring= MEM_mallocN(totspring*sizeof(BodySpring), "bodyspring");
-
- /* initialize BodyPoint array */
- for (i=0; i<totpoint; i++) {
- BodyPoint *bp = &sb->bpoint[i];
-
-
- /* hum as far as i see this is overridden by _final_goal() now jow_go_for2_5 */
- /* sadly breaks compatibility with older versions */
- /* but makes goals behave the same for meshes, lattices and curves */
- if (softflag & OB_SB_GOAL) {
- bp->goal= sb->defgoal;
- }
- else {
- bp->goal= 0.0f;
- /* so this will definily be below SOFTGOALSNAP */
- }
-
- bp->nofsprings= 0;
- bp->springs= NULL;
- bp->choke = 0.0f;
- bp->choke2 = 0.0f;
- bp->frozen = 1.0f;
- bp->colball = 0.0f;
- bp->loc_flag = 0;
- bp->springweight = 1.0f;
- bp->mass = 1.0f;
- }
- }
+ SoftBody *sb;
+ int i;
+ short softflag;
+ if (ob->soft == NULL)
+ ob->soft = sbNew(scene);
+ else
+ free_softbody_intern(ob->soft);
+ sb = ob->soft;
+ softflag = ob->softflag;
+
+ if (totpoint) {
+ sb->totpoint = totpoint;
+ sb->totspring = totspring;
+
+ sb->bpoint = MEM_mallocN(totpoint * sizeof(BodyPoint), "bodypoint");
+ if (totspring)
+ sb->bspring = MEM_mallocN(totspring * sizeof(BodySpring), "bodyspring");
+
+ /* initialize BodyPoint array */
+ for (i = 0; i < totpoint; i++) {
+ BodyPoint *bp = &sb->bpoint[i];
+
+ /* hum as far as i see this is overridden by _final_goal() now jow_go_for2_5 */
+ /* sadly breaks compatibility with older versions */
+ /* but makes goals behave the same for meshes, lattices and curves */
+ if (softflag & OB_SB_GOAL) {
+ bp->goal = sb->defgoal;
+ }
+ else {
+ bp->goal = 0.0f;
+ /* so this will definily be below SOFTGOALSNAP */
+ }
+
+ bp->nofsprings = 0;
+ bp->springs = NULL;
+ bp->choke = 0.0f;
+ bp->choke2 = 0.0f;
+ bp->frozen = 1.0f;
+ bp->colball = 0.0f;
+ bp->loc_flag = 0;
+ bp->springweight = 1.0f;
+ bp->mass = 1.0f;
+ }
+ }
}
static void free_softbody_baked(SoftBody *sb)
{
- SBVertex *key;
- int k;
+ SBVertex *key;
+ int k;
- for (k=0; k<sb->totkey; k++) {
- key= *(sb->keys + k);
- if (key) MEM_freeN(key);
- }
- if (sb->keys) MEM_freeN(sb->keys);
+ for (k = 0; k < sb->totkey; k++) {
+ key = *(sb->keys + k);
+ if (key)
+ MEM_freeN(key);
+ }
+ if (sb->keys)
+ MEM_freeN(sb->keys);
- sb->keys= NULL;
- sb->totkey= 0;
+ sb->keys = NULL;
+ sb->totkey = 0;
}
static void free_scratch(SoftBody *sb)
{
- if (sb->scratch) {
- /* todo make sure everything is cleaned up nicly */
- if (sb->scratch->colliderhash) {
- BLI_ghash_free(
- sb->scratch->colliderhash, NULL,
- (GHashValFreeFP) ccd_mesh_free); /*this hoepfully will free all caches*/
- sb->scratch->colliderhash = NULL;
- }
- if (sb->scratch->bodyface) {
- MEM_freeN(sb->scratch->bodyface);
- }
- if (sb->scratch->Ref.ivert) {
- MEM_freeN(sb->scratch->Ref.ivert);
- }
- MEM_freeN(sb->scratch);
- sb->scratch = NULL;
- }
-
+ if (sb->scratch) {
+ /* todo make sure everything is cleaned up nicly */
+ if (sb->scratch->colliderhash) {
+ BLI_ghash_free(sb->scratch->colliderhash,
+ NULL,
+ (GHashValFreeFP)ccd_mesh_free); /*this hoepfully will free all caches*/
+ sb->scratch->colliderhash = NULL;
+ }
+ if (sb->scratch->bodyface) {
+ MEM_freeN(sb->scratch->bodyface);
+ }
+ if (sb->scratch->Ref.ivert) {
+ MEM_freeN(sb->scratch->Ref.ivert);
+ }
+ MEM_freeN(sb->scratch);
+ sb->scratch = NULL;
+ }
}
/* only frees internal data */
static void free_softbody_intern(SoftBody *sb)
{
- if (sb) {
- int a;
- BodyPoint *bp;
+ if (sb) {
+ int a;
+ BodyPoint *bp;
- if (sb->bpoint) {
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- /* free spring list */
- if (bp->springs != NULL) {
- MEM_freeN(bp->springs);
- }
- }
- MEM_freeN(sb->bpoint);
- }
+ if (sb->bpoint) {
+ for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
+ /* free spring list */
+ if (bp->springs != NULL) {
+ MEM_freeN(bp->springs);
+ }
+ }
+ MEM_freeN(sb->bpoint);
+ }
- if (sb->bspring) MEM_freeN(sb->bspring);
+ if (sb->bspring)
+ MEM_freeN(sb->bspring);
- sb->totpoint= sb->totspring= 0;
- sb->bpoint= NULL;
- sb->bspring= NULL;
+ sb->totpoint = sb->totspring = 0;
+ sb->bpoint = NULL;
+ sb->bspring = NULL;
- free_scratch(sb);
- free_softbody_baked(sb);
- }
+ free_scratch(sb);
+ free_softbody_baked(sb);
+ }
}
-
/* ************ dynamics ********** */
/* the most general (micro physics correct) way to do collision
@@ -952,1491 +958,1536 @@ static void free_softbody_intern(SoftBody *sb)
*/
static int query_external_colliders(Depsgraph *depsgraph, Collection *collection)
{
- unsigned int numobjects;
- Object **objects = BKE_collision_objects_create(depsgraph, NULL, collection, &numobjects, eModifierType_Collision);
- BKE_collision_objects_free(objects);
+ unsigned int numobjects;
+ Object **objects = BKE_collision_objects_create(
+ depsgraph, NULL, collection, &numobjects, eModifierType_Collision);
+ BKE_collision_objects_free(objects);
- return (numobjects != 0);
+ return (numobjects != 0);
}
/* --- dependency information functions*/
-
/* +++ the aabb "force" section*/
-static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), struct Object *vertexowner, float UNUSED(time))
-{
- Object *ob;
- SoftBody *sb=vertexowner->soft;
- GHash *hash;
- GHashIterator *ihash;
- float aabbmin[3], aabbmax[3];
- int deflected=0;
+static int sb_detect_aabb_collisionCached(float UNUSED(force[3]),
+ struct Object *vertexowner,
+ float UNUSED(time))
+{
+ Object *ob;
+ SoftBody *sb = vertexowner->soft;
+ GHash *hash;
+ GHashIterator *ihash;
+ float aabbmin[3], aabbmax[3];
+ int deflected = 0;
#if 0
- int a;
+ int a;
#endif
- if ((sb == NULL) || (sb->scratch ==NULL)) return 0;
- copy_v3_v3(aabbmin, sb->scratch->aabbmin);
- copy_v3_v3(aabbmax, sb->scratch->aabbmax);
-
- hash = vertexowner->soft->scratch->colliderhash;
- ihash = BLI_ghashIterator_new(hash);
- while (!BLI_ghashIterator_done(ihash)) {
-
- ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
- ob = BLI_ghashIterator_getKey (ihash);
- {
- /* only with deflecting set */
- if (ob->pd && ob->pd->deflect) {
- if (ccdm) {
- if ((aabbmax[0] < ccdm->bbmin[0]) ||
- (aabbmax[1] < ccdm->bbmin[1]) ||
- (aabbmax[2] < ccdm->bbmin[2]) ||
- (aabbmin[0] > ccdm->bbmax[0]) ||
- (aabbmin[1] > ccdm->bbmax[1]) ||
- (aabbmin[2] > ccdm->bbmax[2]) )
- {
- /* boxes don't intersect */
- BLI_ghashIterator_step(ihash);
- continue;
- }
-
- /* so now we have the 2 boxes overlapping */
- /* forces actually not used */
- deflected = 2;
-
- }
- else {
- /*aye that should be cached*/
- CLOG_ERROR(&LOG, "missing cache error");
- BLI_ghashIterator_step(ihash);
- continue;
- }
- } /* if (ob->pd && ob->pd->deflect) */
- BLI_ghashIterator_step(ihash);
- }
- } /* while () */
- BLI_ghashIterator_free(ihash);
- return deflected;
+ if ((sb == NULL) || (sb->scratch == NULL))
+ return 0;
+ copy_v3_v3(aabbmin, sb->scratch->aabbmin);
+ copy_v3_v3(aabbmax, sb->scratch->aabbmax);
+
+ hash = vertexowner->soft->scratch->colliderhash;
+ ihash = BLI_ghashIterator_new(hash);
+ while (!BLI_ghashIterator_done(ihash)) {
+
+ ccd_Mesh *ccdm = BLI_ghashIterator_getValue(ihash);
+ ob = BLI_ghashIterator_getKey(ihash);
+ {
+ /* only with deflecting set */
+ if (ob->pd && ob->pd->deflect) {
+ if (ccdm) {
+ if ((aabbmax[0] < ccdm->bbmin[0]) || (aabbmax[1] < ccdm->bbmin[1]) ||
+ (aabbmax[2] < ccdm->bbmin[2]) || (aabbmin[0] > ccdm->bbmax[0]) ||
+ (aabbmin[1] > ccdm->bbmax[1]) || (aabbmin[2] > ccdm->bbmax[2])) {
+ /* boxes don't intersect */
+ BLI_ghashIterator_step(ihash);
+ continue;
+ }
+
+ /* so now we have the 2 boxes overlapping */
+ /* forces actually not used */
+ deflected = 2;
+ }
+ else {
+ /*aye that should be cached*/
+ CLOG_ERROR(&LOG, "missing cache error");
+ BLI_ghashIterator_step(ihash);
+ continue;
+ }
+ } /* if (ob->pd && ob->pd->deflect) */
+ BLI_ghashIterator_step(ihash);
+ }
+ } /* while () */
+ BLI_ghashIterator_free(ihash);
+ return deflected;
}
/* --- the aabb section*/
-
/* +++ the face external section*/
-static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float face_v3[3], float *damp,
- float force[3], struct Object *vertexowner, float time)
-{
- Object *ob;
- GHash *hash;
- GHashIterator *ihash;
- float nv1[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
- float facedist, outerfacethickness, tune = 10.f;
- int a, deflected=0;
-
- aabbmin[0] = min_fff(face_v1[0], face_v2[0], face_v3[0]);
- aabbmin[1] = min_fff(face_v1[1], face_v2[1], face_v3[1]);
- aabbmin[2] = min_fff(face_v1[2], face_v2[2], face_v3[2]);
- aabbmax[0] = max_fff(face_v1[0], face_v2[0], face_v3[0]);
- aabbmax[1] = max_fff(face_v1[1], face_v2[1], face_v3[1]);
- aabbmax[2] = max_fff(face_v1[2], face_v2[2], face_v3[2]);
-
- /* calculate face normal once again SIGH */
- sub_v3_v3v3(edge1, face_v1, face_v2);
- sub_v3_v3v3(edge2, face_v3, face_v2);
- cross_v3_v3v3(d_nvect, edge2, edge1);
- normalize_v3(d_nvect);
-
-
- hash = vertexowner->soft->scratch->colliderhash;
- ihash = BLI_ghashIterator_new(hash);
- while (!BLI_ghashIterator_done(ihash)) {
-
- ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
- ob = BLI_ghashIterator_getKey (ihash);
- {
- /* only with deflecting set */
- if (ob->pd && ob->pd->deflect) {
- const MVert *mvert= NULL;
- const MVert *mprevvert= NULL;
- if (ccdm) {
- mvert = ccdm->mvert;
- a = ccdm->mvert_num;
- mprevvert= ccdm->mprevvert;
- outerfacethickness = ob->pd->pdef_sboft;
- if ((aabbmax[0] < ccdm->bbmin[0]) ||
- (aabbmax[1] < ccdm->bbmin[1]) ||
- (aabbmax[2] < ccdm->bbmin[2]) ||
- (aabbmin[0] > ccdm->bbmax[0]) ||
- (aabbmin[1] > ccdm->bbmax[1]) ||
- (aabbmin[2] > ccdm->bbmax[2]) )
- {
- /* boxes don't intersect */
- BLI_ghashIterator_step(ihash);
- continue;
- }
-
- }
- else {
- /*aye that should be cached*/
- CLOG_ERROR(&LOG, "missing cache error");
- BLI_ghashIterator_step(ihash);
- continue;
- }
-
-
- /* use mesh*/
- if (mvert) {
- while (a) {
- copy_v3_v3(nv1, mvert[a-1].co);
- if (mprevvert) {
- mul_v3_fl(nv1, time);
- madd_v3_v3fl(nv1, mprevvert[a - 1].co, 1.0f - time);
- }
- /* origin to face_v2*/
- sub_v3_v3(nv1, face_v2);
- facedist = dot_v3v3(nv1, d_nvect);
- if (ABS(facedist)<outerfacethickness) {
- if (isect_point_tri_prism_v3(nv1, face_v1, face_v2, face_v3) ) {
- float df;
- if (facedist > 0) {
- df = (outerfacethickness-facedist)/outerfacethickness;
- }
- else {
- df = (outerfacethickness+facedist)/outerfacethickness;
- }
-
- *damp=df*tune*ob->pd->pdef_sbdamp;
-
- df = 0.01f * expf(-100.0f * df);
- madd_v3_v3fl(force, d_nvect, -df);
- deflected = 3;
- }
- }
- a--;
- }/* while (a)*/
- } /* if (mvert) */
- } /* if (ob->pd && ob->pd->deflect) */
- BLI_ghashIterator_step(ihash);
- }
- } /* while () */
- BLI_ghashIterator_free(ihash);
- return deflected;
-}
-
-
-static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], float face_v3[3], float *damp,
- float force[3], struct Object *vertexowner, float time)
-{
- Object *ob;
- GHash *hash;
- GHashIterator *ihash;
- float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
- float t, tune = 10.0f;
- int a, deflected=0;
-
- aabbmin[0] = min_fff(face_v1[0], face_v2[0], face_v3[0]);
- aabbmin[1] = min_fff(face_v1[1], face_v2[1], face_v3[1]);
- aabbmin[2] = min_fff(face_v1[2], face_v2[2], face_v3[2]);
- aabbmax[0] = max_fff(face_v1[0], face_v2[0], face_v3[0]);
- aabbmax[1] = max_fff(face_v1[1], face_v2[1], face_v3[1]);
- aabbmax[2] = max_fff(face_v1[2], face_v2[2], face_v3[2]);
-
- hash = vertexowner->soft->scratch->colliderhash;
- ihash = BLI_ghashIterator_new(hash);
- while (!BLI_ghashIterator_done(ihash)) {
-
- ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
- ob = BLI_ghashIterator_getKey (ihash);
- {
- /* only with deflecting set */
- if (ob->pd && ob->pd->deflect) {
- const MVert *mvert = NULL;
- const MVert *mprevvert = NULL;
- const MVertTri *vt = NULL;
- const ccdf_minmax *mima = NULL;
-
- if (ccdm) {
- mvert = ccdm->mvert;
- vt = ccdm->tri;
- mprevvert = ccdm->mprevvert;
- mima = ccdm->mima;
- a = ccdm->tri_num;
-
- if ((aabbmax[0] < ccdm->bbmin[0]) ||
- (aabbmax[1] < ccdm->bbmin[1]) ||
- (aabbmax[2] < ccdm->bbmin[2]) ||
- (aabbmin[0] > ccdm->bbmax[0]) ||
- (aabbmin[1] > ccdm->bbmax[1]) ||
- (aabbmin[2] > ccdm->bbmax[2]) )
- {
- /* boxes don't intersect */
- BLI_ghashIterator_step(ihash);
- continue;
- }
-
- }
- else {
- /*aye that should be cached*/
- CLOG_ERROR(&LOG, "missing cache error");
- BLI_ghashIterator_step(ihash);
- continue;
- }
-
-
- /* use mesh*/
- while (a--) {
- if ((aabbmax[0] < mima->minx) ||
- (aabbmin[0] > mima->maxx) ||
- (aabbmax[1] < mima->miny) ||
- (aabbmin[1] > mima->maxy) ||
- (aabbmax[2] < mima->minz) ||
- (aabbmin[2] > mima->maxz))
- {
- mima++;
- vt++;
- continue;
- }
-
-
- if (mvert) {
-
- copy_v3_v3(nv1, mvert[vt->tri[0]].co);
- copy_v3_v3(nv2, mvert[vt->tri[1]].co);
- copy_v3_v3(nv3, mvert[vt->tri[2]].co);
-
- if (mprevvert) {
- mul_v3_fl(nv1, time);
- madd_v3_v3fl(nv1, mprevvert[vt->tri[0]].co, 1.0f - time);
-
- mul_v3_fl(nv2, time);
- madd_v3_v3fl(nv2, mprevvert[vt->tri[1]].co, 1.0f - time);
-
- mul_v3_fl(nv3, time);
- madd_v3_v3fl(nv3, mprevvert[vt->tri[2]].co, 1.0f - time);
- }
- }
-
- /* switch origin to be nv2*/
- sub_v3_v3v3(edge1, nv1, nv2);
- sub_v3_v3v3(edge2, nv3, nv2);
- cross_v3_v3v3(d_nvect, edge2, edge1);
- normalize_v3(d_nvect);
- if (isect_line_segment_tri_v3(nv1, nv2, face_v1, face_v2, face_v3, &t, NULL) ||
- isect_line_segment_tri_v3(nv2, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
- isect_line_segment_tri_v3(nv3, nv1, face_v1, face_v2, face_v3, &t, NULL) )
- {
- madd_v3_v3fl(force, d_nvect, -0.5f);
- *damp=tune*ob->pd->pdef_sbdamp;
- deflected = 2;
- }
- mima++;
- vt++;
- }/* while a */
- } /* if (ob->pd && ob->pd->deflect) */
- BLI_ghashIterator_step(ihash);
- }
- } /* while () */
- BLI_ghashIterator_free(ihash);
- return deflected;
+static int sb_detect_face_pointCached(float face_v1[3],
+ float face_v2[3],
+ float face_v3[3],
+ float *damp,
+ float force[3],
+ struct Object *vertexowner,
+ float time)
+{
+ Object *ob;
+ GHash *hash;
+ GHashIterator *ihash;
+ float nv1[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
+ float facedist, outerfacethickness, tune = 10.f;
+ int a, deflected = 0;
+
+ aabbmin[0] = min_fff(face_v1[0], face_v2[0], face_v3[0]);
+ aabbmin[1] = min_fff(face_v1[1], face_v2[1], face_v3[1]);
+ aabbmin[2] = min_fff(face_v1[2], face_v2[2], face_v3[2]);
+ aabbmax[0] = max_fff(face_v1[0], face_v2[0], face_v3[0]);
+ aabbmax[1] = max_fff(face_v1[1], face_v2[1], face_v3[1]);
+ aabbmax[2] = max_fff(face_v1[2], face_v2[2], face_v3[2]);
+
+ /* calculate face normal once again SIGH */
+ sub_v3_v3v3(edge1, face_v1, face_v2);
+ sub_v3_v3v3(edge2, face_v3, face_v2);
+ cross_v3_v3v3(d_nvect, edge2, edge1);
+ normalize_v3(d_nvect);
+
+ hash = vertexowner->soft->scratch->colliderhash;
+ ihash = BLI_ghashIterator_new(hash);
+ while (!BLI_ghashIterator_done(ihash)) {
+
+ ccd_Mesh *ccdm = BLI_ghashIterator_getValue(ihash);
+ ob = BLI_ghashIterator_getKey(ihash);
+ {
+ /* only with deflecting set */
+ if (ob->pd && ob->pd->deflect) {
+ const MVert *mvert = NULL;
+ const MVert *mprevvert = NULL;
+ if (ccdm) {
+ mvert = ccdm->mvert;
+ a = ccdm->mvert_num;
+ mprevvert = ccdm->mprevvert;
+ outerfacethickness = ob->pd->pdef_sboft;
+ if ((aabbmax[0] < ccdm->bbmin[0]) || (aabbmax[1] < ccdm->bbmin[1]) ||
+ (aabbmax[2] < ccdm->bbmin[2]) || (aabbmin[0] > ccdm->bbmax[0]) ||
+ (aabbmin[1] > ccdm->bbmax[1]) || (aabbmin[2] > ccdm->bbmax[2])) {
+ /* boxes don't intersect */
+ BLI_ghashIterator_step(ihash);
+ continue;
+ }
+ }
+ else {
+ /*aye that should be cached*/
+ CLOG_ERROR(&LOG, "missing cache error");
+ BLI_ghashIterator_step(ihash);
+ continue;
+ }
+
+ /* use mesh*/
+ if (mvert) {
+ while (a) {
+ copy_v3_v3(nv1, mvert[a - 1].co);
+ if (mprevvert) {
+ mul_v3_fl(nv1, time);
+ madd_v3_v3fl(nv1, mprevvert[a - 1].co, 1.0f - time);
+ }
+ /* origin to face_v2*/
+ sub_v3_v3(nv1, face_v2);
+ facedist = dot_v3v3(nv1, d_nvect);
+ if (ABS(facedist) < outerfacethickness) {
+ if (isect_point_tri_prism_v3(nv1, face_v1, face_v2, face_v3)) {
+ float df;
+ if (facedist > 0) {
+ df = (outerfacethickness - facedist) / outerfacethickness;
+ }
+ else {
+ df = (outerfacethickness + facedist) / outerfacethickness;
+ }
+
+ *damp = df * tune * ob->pd->pdef_sbdamp;
+
+ df = 0.01f * expf(-100.0f * df);
+ madd_v3_v3fl(force, d_nvect, -df);
+ deflected = 3;
+ }
+ }
+ a--;
+ } /* while (a)*/
+ } /* if (mvert) */
+ } /* if (ob->pd && ob->pd->deflect) */
+ BLI_ghashIterator_step(ihash);
+ }
+ } /* while () */
+ BLI_ghashIterator_free(ihash);
+ return deflected;
+}
+
+static int sb_detect_face_collisionCached(float face_v1[3],
+ float face_v2[3],
+ float face_v3[3],
+ float *damp,
+ float force[3],
+ struct Object *vertexowner,
+ float time)
+{
+ Object *ob;
+ GHash *hash;
+ GHashIterator *ihash;
+ float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
+ float t, tune = 10.0f;
+ int a, deflected = 0;
+
+ aabbmin[0] = min_fff(face_v1[0], face_v2[0], face_v3[0]);
+ aabbmin[1] = min_fff(face_v1[1], face_v2[1], face_v3[1]);
+ aabbmin[2] = min_fff(face_v1[2], face_v2[2], face_v3[2]);
+ aabbmax[0] = max_fff(face_v1[0], face_v2[0], face_v3[0]);
+ aabbmax[1] = max_fff(face_v1[1], face_v2[1], face_v3[1]);
+ aabbmax[2] = max_fff(face_v1[2], face_v2[2], face_v3[2]);
+
+ hash = vertexowner->soft->scratch->colliderhash;
+ ihash = BLI_ghashIterator_new(hash);
+ while (!BLI_ghashIterator_done(ihash)) {
+
+ ccd_Mesh *ccdm = BLI_ghashIterator_getValue(ihash);
+ ob = BLI_ghashIterator_getKey(ihash);
+ {
+ /* only with deflecting set */
+ if (ob->pd && ob->pd->deflect) {
+ const MVert *mvert = NULL;
+ const MVert *mprevvert = NULL;
+ const MVertTri *vt = NULL;
+ const ccdf_minmax *mima = NULL;
+
+ if (ccdm) {
+ mvert = ccdm->mvert;
+ vt = ccdm->tri;
+ mprevvert = ccdm->mprevvert;
+ mima = ccdm->mima;
+ a = ccdm->tri_num;
+
+ if ((aabbmax[0] < ccdm->bbmin[0]) || (aabbmax[1] < ccdm->bbmin[1]) ||
+ (aabbmax[2] < ccdm->bbmin[2]) || (aabbmin[0] > ccdm->bbmax[0]) ||
+ (aabbmin[1] > ccdm->bbmax[1]) || (aabbmin[2] > ccdm->bbmax[2])) {
+ /* boxes don't intersect */
+ BLI_ghashIterator_step(ihash);
+ continue;
+ }
+ }
+ else {
+ /*aye that should be cached*/
+ CLOG_ERROR(&LOG, "missing cache error");
+ BLI_ghashIterator_step(ihash);
+ continue;
+ }
+
+ /* use mesh*/
+ while (a--) {
+ if ((aabbmax[0] < mima->minx) || (aabbmin[0] > mima->maxx) ||
+ (aabbmax[1] < mima->miny) || (aabbmin[1] > mima->maxy) ||
+ (aabbmax[2] < mima->minz) || (aabbmin[2] > mima->maxz)) {
+ mima++;
+ vt++;
+ continue;
+ }
+
+ if (mvert) {
+
+ copy_v3_v3(nv1, mvert[vt->tri[0]].co);
+ copy_v3_v3(nv2, mvert[vt->tri[1]].co);
+ copy_v3_v3(nv3, mvert[vt->tri[2]].co);
+
+ if (mprevvert) {
+ mul_v3_fl(nv1, time);
+ madd_v3_v3fl(nv1, mprevvert[vt->tri[0]].co, 1.0f - time);
+
+ mul_v3_fl(nv2, time);
+ madd_v3_v3fl(nv2, mprevvert[vt->tri[1]].co, 1.0f - time);
+
+ mul_v3_fl(nv3, time);
+ madd_v3_v3fl(nv3, mprevvert[vt->tri[2]].co, 1.0f - time);
+ }
+ }
+
+ /* switch origin to be nv2*/
+ sub_v3_v3v3(edge1, nv1, nv2);
+ sub_v3_v3v3(edge2, nv3, nv2);
+ cross_v3_v3v3(d_nvect, edge2, edge1);
+ normalize_v3(d_nvect);
+ if (isect_line_segment_tri_v3(nv1, nv2, face_v1, face_v2, face_v3, &t, NULL) ||
+ isect_line_segment_tri_v3(nv2, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
+ isect_line_segment_tri_v3(nv3, nv1, face_v1, face_v2, face_v3, &t, NULL)) {
+ madd_v3_v3fl(force, d_nvect, -0.5f);
+ *damp = tune * ob->pd->pdef_sbdamp;
+ deflected = 2;
+ }
+ mima++;
+ vt++;
+ } /* while a */
+ } /* if (ob->pd && ob->pd->deflect) */
+ BLI_ghashIterator_step(ihash);
+ }
+ } /* while () */
+ BLI_ghashIterator_free(ihash);
+ return deflected;
}
-
-
static void scan_for_ext_face_forces(Object *ob, float timenow)
{
- SoftBody *sb = ob->soft;
- BodyFace *bf;
- int a;
- float damp=0.0f, choke=1.0f;
- float tune = -10.0f;
- float feedback[3];
-
- if (sb && sb->scratch->totface) {
-
-
- bf = sb->scratch->bodyface;
- for (a=0; a<sb->scratch->totface; a++, bf++) {
- bf->ext_force[0]=bf->ext_force[1]=bf->ext_force[2]=0.0f;
-/*+++edges intruding*/
- bf->flag &= ~BFF_INTERSECT;
- zero_v3(feedback);
- if (sb_detect_face_collisionCached(
- sb->bpoint[bf->v1].pos, sb->bpoint[bf->v2].pos, sb->bpoint[bf->v3].pos,
- &damp, feedback, ob, timenow))
- {
- madd_v3_v3fl(sb->bpoint[bf->v1].force, feedback, tune);
- madd_v3_v3fl(sb->bpoint[bf->v2].force, feedback, tune);
- madd_v3_v3fl(sb->bpoint[bf->v3].force, feedback, tune);
-// madd_v3_v3fl(bf->ext_force, feedback, tune);
- bf->flag |= BFF_INTERSECT;
- choke = min_ff(max_ff(damp, choke), 1.0f);
- }
-/*---edges intruding*/
-
-/*+++ close vertices*/
- if (( bf->flag & BFF_INTERSECT)==0) {
- bf->flag &= ~BFF_CLOSEVERT;
- tune = -1.0f;
- zero_v3(feedback);
- if (sb_detect_face_pointCached(
- sb->bpoint[bf->v1].pos, sb->bpoint[bf->v2].pos, sb->bpoint[bf->v3].pos,
- &damp, feedback, ob, timenow))
- {
- madd_v3_v3fl(sb->bpoint[bf->v1].force, feedback, tune);
- madd_v3_v3fl(sb->bpoint[bf->v2].force, feedback, tune);
- madd_v3_v3fl(sb->bpoint[bf->v3].force, feedback, tune);
-// madd_v3_v3fl(bf->ext_force, feedback, tune);
- bf->flag |= BFF_CLOSEVERT;
- choke = min_ff(max_ff(damp, choke), 1.0f);
- }
- }
-/*--- close vertices*/
- }
- bf = sb->scratch->bodyface;
- for (a=0; a<sb->scratch->totface; a++, bf++) {
- if (( bf->flag & BFF_INTERSECT) || ( bf->flag & BFF_CLOSEVERT)) {
- sb->bpoint[bf->v1].choke2 = max_ff(sb->bpoint[bf->v1].choke2, choke);
- sb->bpoint[bf->v2].choke2 = max_ff(sb->bpoint[bf->v2].choke2, choke);
- sb->bpoint[bf->v3].choke2 = max_ff(sb->bpoint[bf->v3].choke2, choke);
- }
- }
- }
+ SoftBody *sb = ob->soft;
+ BodyFace *bf;
+ int a;
+ float damp = 0.0f, choke = 1.0f;
+ float tune = -10.0f;
+ float feedback[3];
+
+ if (sb && sb->scratch->totface) {
+
+ bf = sb->scratch->bodyface;
+ for (a = 0; a < sb->scratch->totface; a++, bf++) {
+ bf->ext_force[0] = bf->ext_force[1] = bf->ext_force[2] = 0.0f;
+ /*+++edges intruding*/
+ bf->flag &= ~BFF_INTERSECT;
+ zero_v3(feedback);
+ if (sb_detect_face_collisionCached(sb->bpoint[bf->v1].pos,
+ sb->bpoint[bf->v2].pos,
+ sb->bpoint[bf->v3].pos,
+ &damp,
+ feedback,
+ ob,
+ timenow)) {
+ madd_v3_v3fl(sb->bpoint[bf->v1].force, feedback, tune);
+ madd_v3_v3fl(sb->bpoint[bf->v2].force, feedback, tune);
+ madd_v3_v3fl(sb->bpoint[bf->v3].force, feedback, tune);
+ // madd_v3_v3fl(bf->ext_force, feedback, tune);
+ bf->flag |= BFF_INTERSECT;
+ choke = min_ff(max_ff(damp, choke), 1.0f);
+ }
+ /*---edges intruding*/
+
+ /*+++ close vertices*/
+ if ((bf->flag & BFF_INTERSECT) == 0) {
+ bf->flag &= ~BFF_CLOSEVERT;
+ tune = -1.0f;
+ zero_v3(feedback);
+ if (sb_detect_face_pointCached(sb->bpoint[bf->v1].pos,
+ sb->bpoint[bf->v2].pos,
+ sb->bpoint[bf->v3].pos,
+ &damp,
+ feedback,
+ ob,
+ timenow)) {
+ madd_v3_v3fl(sb->bpoint[bf->v1].force, feedback, tune);
+ madd_v3_v3fl(sb->bpoint[bf->v2].force, feedback, tune);
+ madd_v3_v3fl(sb->bpoint[bf->v3].force, feedback, tune);
+ // madd_v3_v3fl(bf->ext_force, feedback, tune);
+ bf->flag |= BFF_CLOSEVERT;
+ choke = min_ff(max_ff(damp, choke), 1.0f);
+ }
+ }
+ /*--- close vertices*/
+ }
+ bf = sb->scratch->bodyface;
+ for (a = 0; a < sb->scratch->totface; a++, bf++) {
+ if ((bf->flag & BFF_INTERSECT) || (bf->flag & BFF_CLOSEVERT)) {
+ sb->bpoint[bf->v1].choke2 = max_ff(sb->bpoint[bf->v1].choke2, choke);
+ sb->bpoint[bf->v2].choke2 = max_ff(sb->bpoint[bf->v2].choke2, choke);
+ sb->bpoint[bf->v3].choke2 = max_ff(sb->bpoint[bf->v3].choke2, choke);
+ }
+ }
+ }
}
/* --- the face external section*/
-
/* +++ the spring external section*/
-static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], float *damp,
- float force[3], struct Object *vertexowner, float time)
-{
- Object *ob;
- GHash *hash;
- GHashIterator *ihash;
- float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
- float t, el;
- int a, deflected=0;
-
- minmax_v3v3_v3(aabbmin, aabbmax, edge_v1);
- minmax_v3v3_v3(aabbmin, aabbmax, edge_v2);
-
- el = len_v3v3(edge_v1, edge_v2);
-
- hash = vertexowner->soft->scratch->colliderhash;
- ihash = BLI_ghashIterator_new(hash);
- while (!BLI_ghashIterator_done(ihash)) {
-
- ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
- ob = BLI_ghashIterator_getKey (ihash);
- {
- /* only with deflecting set */
- if (ob->pd && ob->pd->deflect) {
- const MVert *mvert = NULL;
- const MVert *mprevvert = NULL;
- const MVertTri *vt = NULL;
- const ccdf_minmax *mima = NULL;
-
- if (ccdm) {
- mvert = ccdm->mvert;
- mprevvert = ccdm->mprevvert;
- vt = ccdm->tri;
- mima = ccdm->mima;
- a = ccdm->tri_num;
-
- if ((aabbmax[0] < ccdm->bbmin[0]) ||
- (aabbmax[1] < ccdm->bbmin[1]) ||
- (aabbmax[2] < ccdm->bbmin[2]) ||
- (aabbmin[0] > ccdm->bbmax[0]) ||
- (aabbmin[1] > ccdm->bbmax[1]) ||
- (aabbmin[2] > ccdm->bbmax[2]) )
- {
- /* boxes don't intersect */
- BLI_ghashIterator_step(ihash);
- continue;
- }
-
- }
- else {
- /*aye that should be cached*/
- CLOG_ERROR(&LOG, "missing cache error");
- BLI_ghashIterator_step(ihash);
- continue;
- }
-
-
- /* use mesh*/
- while (a--) {
- if ((aabbmax[0] < mima->minx) ||
- (aabbmin[0] > mima->maxx) ||
- (aabbmax[1] < mima->miny) ||
- (aabbmin[1] > mima->maxy) ||
- (aabbmax[2] < mima->minz) ||
- (aabbmin[2] > mima->maxz))
- {
- mima++;
- vt++;
- continue;
- }
-
-
- if (mvert) {
-
- copy_v3_v3(nv1, mvert[vt->tri[0]].co);
- copy_v3_v3(nv2, mvert[vt->tri[1]].co);
- copy_v3_v3(nv3, mvert[vt->tri[2]].co);
-
- if (mprevvert) {
- mul_v3_fl(nv1, time);
- madd_v3_v3fl(nv1, mprevvert[vt->tri[0]].co, 1.0f - time);
-
- mul_v3_fl(nv2, time);
- madd_v3_v3fl(nv2, mprevvert[vt->tri[1]].co, 1.0f - time);
-
- mul_v3_fl(nv3, time);
- madd_v3_v3fl(nv3, mprevvert[vt->tri[2]].co, 1.0f - time);
- }
- }
-
- /* switch origin to be nv2*/
- sub_v3_v3v3(edge1, nv1, nv2);
- sub_v3_v3v3(edge2, nv3, nv2);
-
- cross_v3_v3v3(d_nvect, edge2, edge1);
- normalize_v3(d_nvect);
- if (isect_line_segment_tri_v3(edge_v1, edge_v2, nv1, nv2, nv3, &t, NULL)) {
- float v1[3], v2[3];
- float intrusiondepth, i1, i2;
- sub_v3_v3v3(v1, edge_v1, nv2);
- sub_v3_v3v3(v2, edge_v2, nv2);
- i1 = dot_v3v3(v1, d_nvect);
- i2 = dot_v3v3(v2, d_nvect);
- intrusiondepth = -min_ff(i1, i2) / el;
- madd_v3_v3fl(force, d_nvect, intrusiondepth);
- *damp=ob->pd->pdef_sbdamp;
- deflected = 2;
- }
-
- mima++;
- vt++;
- }/* while a */
- } /* if (ob->pd && ob->pd->deflect) */
- BLI_ghashIterator_step(ihash);
- }
- } /* while () */
- BLI_ghashIterator_free(ihash);
- return deflected;
-}
-
-static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow, int ifirst, int ilast, struct ListBase *effectors)
-{
- SoftBody *sb = ob->soft;
- int a;
- float damp;
- float feedback[3];
-
- if (sb && sb->totspring) {
- for (a=ifirst; a<ilast; a++) {
- BodySpring *bs = &sb->bspring[a];
- bs->ext_force[0]=bs->ext_force[1]=bs->ext_force[2]=0.0f;
- feedback[0]=feedback[1]=feedback[2]=0.0f;
- bs->flag &= ~BSF_INTERSECT;
-
- if (bs->springtype == SB_EDGE) {
- /* +++ springs colliding */
- if (ob->softflag & OB_SB_EDGECOLL) {
- if (sb_detect_edge_collisionCached(
- sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos,
- &damp, feedback, ob, timenow))
- {
- add_v3_v3(bs->ext_force, feedback);
- bs->flag |= BSF_INTERSECT;
- //bs->cf=damp;
- bs->cf=sb->choke*0.01f;
- }
- }
- /* ---- springs colliding */
-
- /* +++ springs seeing wind ... n stuff depending on their orientation*/
- /* note we don't use sb->mediafrict but use sb->aeroedge for magnitude of effect*/
- if (sb->aeroedge) {
- float vel[3], sp[3], pr[3], force[3];
- float f, windfactor = 0.25f;
- /*see if we have wind*/
- if (effectors) {
- EffectedPoint epoint;
- float speed[3] = {0.0f, 0.0f, 0.0f};
- float pos[3];
- mid_v3_v3v3(pos, sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos);
- mid_v3_v3v3(vel, sb->bpoint[bs->v1].vec, sb->bpoint[bs->v2].vec);
- pd_point_from_soft(scene, pos, vel, -1, &epoint);
- BKE_effectors_apply(effectors, NULL, sb->effector_weights, &epoint, force, speed);
-
- mul_v3_fl(speed, windfactor);
- add_v3_v3(vel, speed);
- }
- /* media in rest */
- else {
- add_v3_v3v3(vel, sb->bpoint[bs->v1].vec, sb->bpoint[bs->v2].vec);
- }
- f = normalize_v3(vel);
- f = -0.0001f*f*f*sb->aeroedge;
- /* (todo) add a nice angle dependent function done for now BUT */
- /* still there could be some nice drag/lift function, but who needs it */
-
- sub_v3_v3v3(sp, sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos);
- project_v3_v3v3(pr, vel, sp);
- sub_v3_v3(vel, pr);
- normalize_v3(vel);
- if (ob->softflag & OB_SB_AERO_ANGLE) {
- normalize_v3(sp);
- madd_v3_v3fl(bs->ext_force, vel, f * (1.0f - fabsf(dot_v3v3(vel, sp))));
- }
- else {
- madd_v3_v3fl(bs->ext_force, vel, f); // to keep compatible with 2.45 release files
- }
- }
- /* --- springs seeing wind */
- }
- }
- }
+static int sb_detect_edge_collisionCached(float edge_v1[3],
+ float edge_v2[3],
+ float *damp,
+ float force[3],
+ struct Object *vertexowner,
+ float time)
+{
+ Object *ob;
+ GHash *hash;
+ GHashIterator *ihash;
+ float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
+ float t, el;
+ int a, deflected = 0;
+
+ minmax_v3v3_v3(aabbmin, aabbmax, edge_v1);
+ minmax_v3v3_v3(aabbmin, aabbmax, edge_v2);
+
+ el = len_v3v3(edge_v1, edge_v2);
+
+ hash = vertexowner->soft->scratch->colliderhash;
+ ihash = BLI_ghashIterator_new(hash);
+ while (!BLI_ghashIterator_done(ihash)) {
+
+ ccd_Mesh *ccdm = BLI_ghashIterator_getValue(ihash);
+ ob = BLI_ghashIterator_getKey(ihash);
+ {
+ /* only with deflecting set */
+ if (ob->pd && ob->pd->deflect) {
+ const MVert *mvert = NULL;
+ const MVert *mprevvert = NULL;
+ const MVertTri *vt = NULL;
+ const ccdf_minmax *mima = NULL;
+
+ if (ccdm) {
+ mvert = ccdm->mvert;
+ mprevvert = ccdm->mprevvert;
+ vt = ccdm->tri;
+ mima = ccdm->mima;
+ a = ccdm->tri_num;
+
+ if ((aabbmax[0] < ccdm->bbmin[0]) || (aabbmax[1] < ccdm->bbmin[1]) ||
+ (aabbmax[2] < ccdm->bbmin[2]) || (aabbmin[0] > ccdm->bbmax[0]) ||
+ (aabbmin[1] > ccdm->bbmax[1]) || (aabbmin[2] > ccdm->bbmax[2])) {
+ /* boxes don't intersect */
+ BLI_ghashIterator_step(ihash);
+ continue;
+ }
+ }
+ else {
+ /*aye that should be cached*/
+ CLOG_ERROR(&LOG, "missing cache error");
+ BLI_ghashIterator_step(ihash);
+ continue;
+ }
+
+ /* use mesh*/
+ while (a--) {
+ if ((aabbmax[0] < mima->minx) || (aabbmin[0] > mima->maxx) ||
+ (aabbmax[1] < mima->miny) || (aabbmin[1] > mima->maxy) ||
+ (aabbmax[2] < mima->minz) || (aabbmin[2] > mima->maxz)) {
+ mima++;
+ vt++;
+ continue;
+ }
+
+ if (mvert) {
+
+ copy_v3_v3(nv1, mvert[vt->tri[0]].co);
+ copy_v3_v3(nv2, mvert[vt->tri[1]].co);
+ copy_v3_v3(nv3, mvert[vt->tri[2]].co);
+
+ if (mprevvert) {
+ mul_v3_fl(nv1, time);
+ madd_v3_v3fl(nv1, mprevvert[vt->tri[0]].co, 1.0f - time);
+
+ mul_v3_fl(nv2, time);
+ madd_v3_v3fl(nv2, mprevvert[vt->tri[1]].co, 1.0f - time);
+
+ mul_v3_fl(nv3, time);
+ madd_v3_v3fl(nv3, mprevvert[vt->tri[2]].co, 1.0f - time);
+ }
+ }
+
+ /* switch origin to be nv2*/
+ sub_v3_v3v3(edge1, nv1, nv2);
+ sub_v3_v3v3(edge2, nv3, nv2);
+
+ cross_v3_v3v3(d_nvect, edge2, edge1);
+ normalize_v3(d_nvect);
+ if (isect_line_segment_tri_v3(edge_v1, edge_v2, nv1, nv2, nv3, &t, NULL)) {
+ float v1[3], v2[3];
+ float intrusiondepth, i1, i2;
+ sub_v3_v3v3(v1, edge_v1, nv2);
+ sub_v3_v3v3(v2, edge_v2, nv2);
+ i1 = dot_v3v3(v1, d_nvect);
+ i2 = dot_v3v3(v2, d_nvect);
+ intrusiondepth = -min_ff(i1, i2) / el;
+ madd_v3_v3fl(force, d_nvect, intrusiondepth);
+ *damp = ob->pd->pdef_sbdamp;
+ deflected = 2;
+ }
+
+ mima++;
+ vt++;
+ } /* while a */
+ } /* if (ob->pd && ob->pd->deflect) */
+ BLI_ghashIterator_step(ihash);
+ }
+ } /* while () */
+ BLI_ghashIterator_free(ihash);
+ return deflected;
+}
+
+static void _scan_for_ext_spring_forces(
+ Scene *scene, Object *ob, float timenow, int ifirst, int ilast, struct ListBase *effectors)
+{
+ SoftBody *sb = ob->soft;
+ int a;
+ float damp;
+ float feedback[3];
+
+ if (sb && sb->totspring) {
+ for (a = ifirst; a < ilast; a++) {
+ BodySpring *bs = &sb->bspring[a];
+ bs->ext_force[0] = bs->ext_force[1] = bs->ext_force[2] = 0.0f;
+ feedback[0] = feedback[1] = feedback[2] = 0.0f;
+ bs->flag &= ~BSF_INTERSECT;
+
+ if (bs->springtype == SB_EDGE) {
+ /* +++ springs colliding */
+ if (ob->softflag & OB_SB_EDGECOLL) {
+ if (sb_detect_edge_collisionCached(
+ sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos, &damp, feedback, ob, timenow)) {
+ add_v3_v3(bs->ext_force, feedback);
+ bs->flag |= BSF_INTERSECT;
+ //bs->cf=damp;
+ bs->cf = sb->choke * 0.01f;
+ }
+ }
+ /* ---- springs colliding */
+
+ /* +++ springs seeing wind ... n stuff depending on their orientation*/
+ /* note we don't use sb->mediafrict but use sb->aeroedge for magnitude of effect*/
+ if (sb->aeroedge) {
+ float vel[3], sp[3], pr[3], force[3];
+ float f, windfactor = 0.25f;
+ /*see if we have wind*/
+ if (effectors) {
+ EffectedPoint epoint;
+ float speed[3] = {0.0f, 0.0f, 0.0f};
+ float pos[3];
+ mid_v3_v3v3(pos, sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos);
+ mid_v3_v3v3(vel, sb->bpoint[bs->v1].vec, sb->bpoint[bs->v2].vec);
+ pd_point_from_soft(scene, pos, vel, -1, &epoint);
+ BKE_effectors_apply(effectors, NULL, sb->effector_weights, &epoint, force, speed);
+
+ mul_v3_fl(speed, windfactor);
+ add_v3_v3(vel, speed);
+ }
+ /* media in rest */
+ else {
+ add_v3_v3v3(vel, sb->bpoint[bs->v1].vec, sb->bpoint[bs->v2].vec);
+ }
+ f = normalize_v3(vel);
+ f = -0.0001f * f * f * sb->aeroedge;
+ /* (todo) add a nice angle dependent function done for now BUT */
+ /* still there could be some nice drag/lift function, but who needs it */
+
+ sub_v3_v3v3(sp, sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos);
+ project_v3_v3v3(pr, vel, sp);
+ sub_v3_v3(vel, pr);
+ normalize_v3(vel);
+ if (ob->softflag & OB_SB_AERO_ANGLE) {
+ normalize_v3(sp);
+ madd_v3_v3fl(bs->ext_force, vel, f * (1.0f - fabsf(dot_v3v3(vel, sp))));
+ }
+ else {
+ madd_v3_v3fl(bs->ext_force, vel, f); // to keep compatible with 2.45 release files
+ }
+ }
+ /* --- springs seeing wind */
+ }
+ }
+ }
}
static void *exec_scan_for_ext_spring_forces(void *data)
{
- SB_thread_context *pctx = (SB_thread_context*)data;
- _scan_for_ext_spring_forces(pctx->scene, pctx->ob, pctx->timenow, pctx->ifirst, pctx->ilast, pctx->effectors);
- return NULL;
-}
-
-static void sb_sfesf_threads_run(struct Depsgraph *depsgraph, Scene *scene, struct Object *ob, float timenow, int totsprings, int *UNUSED(ptr_to_break_func(void)))
-{
- ListBase threads;
- SB_thread_context *sb_threads;
- int i, totthread, left, dec;
- int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
-
- ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, ob->soft->effector_weights);
-
- /* figure the number of threads while preventing pretty pointless threading overhead */
- totthread= BKE_scene_num_threads(scene);
- /* what if we got zillions of CPUs running but less to spread*/
- while ((totsprings/totthread < lowsprings) && (totthread > 1)) {
- totthread--;
- }
-
- sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBSpringsThread");
- memset(sb_threads, 0, sizeof(SB_thread_context)*totthread);
- left = totsprings;
- dec = totsprings/totthread +1;
- for (i=0; i<totthread; i++) {
- sb_threads[i].scene = scene;
- sb_threads[i].ob = ob;
- sb_threads[i].forcetime = 0.0; // not used here
- sb_threads[i].timenow = timenow;
- sb_threads[i].ilast = left;
- left = left - dec;
- if (left >0) {
- sb_threads[i].ifirst = left;
- }
- else
- sb_threads[i].ifirst = 0;
- sb_threads[i].effectors = effectors;
- sb_threads[i].do_deflector = false;// not used here
- sb_threads[i].fieldfactor = 0.0f;// not used here
- sb_threads[i].windfactor = 0.0f;// not used here
- sb_threads[i].nr= i;
- sb_threads[i].tot= totthread;
- }
- if (totthread > 1) {
- BLI_threadpool_init(&threads, exec_scan_for_ext_spring_forces, totthread);
-
- for (i=0; i<totthread; i++)
- BLI_threadpool_insert(&threads, &sb_threads[i]);
-
- BLI_threadpool_end(&threads);
- }
- else
- exec_scan_for_ext_spring_forces(&sb_threads[0]);
- /* clean up */
- MEM_freeN(sb_threads);
-
- BKE_effectors_free(effectors);
+ SB_thread_context *pctx = (SB_thread_context *)data;
+ _scan_for_ext_spring_forces(
+ pctx->scene, pctx->ob, pctx->timenow, pctx->ifirst, pctx->ilast, pctx->effectors);
+ return NULL;
+}
+
+static void sb_sfesf_threads_run(struct Depsgraph *depsgraph,
+ Scene *scene,
+ struct Object *ob,
+ float timenow,
+ int totsprings,
+ int *UNUSED(ptr_to_break_func(void)))
+{
+ ListBase threads;
+ SB_thread_context *sb_threads;
+ int i, totthread, left, dec;
+ int lowsprings =
+ 100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
+
+ ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, ob->soft->effector_weights);
+
+ /* figure the number of threads while preventing pretty pointless threading overhead */
+ totthread = BKE_scene_num_threads(scene);
+ /* what if we got zillions of CPUs running but less to spread*/
+ while ((totsprings / totthread < lowsprings) && (totthread > 1)) {
+ totthread--;
+ }
+
+ sb_threads = MEM_callocN(sizeof(SB_thread_context) * totthread, "SBSpringsThread");
+ memset(sb_threads, 0, sizeof(SB_thread_context) * totthread);
+ left = totsprings;
+ dec = totsprings / totthread + 1;
+ for (i = 0; i < totthread; i++) {
+ sb_threads[i].scene = scene;
+ sb_threads[i].ob = ob;
+ sb_threads[i].forcetime = 0.0; // not used here
+ sb_threads[i].timenow = timenow;
+ sb_threads[i].ilast = left;
+ left = left - dec;
+ if (left > 0) {
+ sb_threads[i].ifirst = left;
+ }
+ else
+ sb_threads[i].ifirst = 0;
+ sb_threads[i].effectors = effectors;
+ sb_threads[i].do_deflector = false; // not used here
+ sb_threads[i].fieldfactor = 0.0f; // not used here
+ sb_threads[i].windfactor = 0.0f; // not used here
+ sb_threads[i].nr = i;
+ sb_threads[i].tot = totthread;
+ }
+ if (totthread > 1) {
+ BLI_threadpool_init(&threads, exec_scan_for_ext_spring_forces, totthread);
+
+ for (i = 0; i < totthread; i++)
+ BLI_threadpool_insert(&threads, &sb_threads[i]);
+
+ BLI_threadpool_end(&threads);
+ }
+ else
+ exec_scan_for_ext_spring_forces(&sb_threads[0]);
+ /* clean up */
+ MEM_freeN(sb_threads);
+
+ BKE_effectors_free(effectors);
}
-
/* --- the spring external section*/
-static int choose_winner(float *w, float *pos, float *a, float *b, float *c, float *ca, float *cb, float *cc)
-{
- float mindist, cp;
- int winner =1;
- mindist = fabsf(dot_v3v3(pos, a));
-
- cp = fabsf(dot_v3v3(pos, b));
- if ( mindist < cp ) {
- mindist = cp;
- winner =2;
- }
-
- cp = fabsf(dot_v3v3(pos, c));
- if (mindist < cp ) {
- mindist = cp;
- winner =3;
- }
- switch (winner) {
- case 1: copy_v3_v3(w, ca); break;
- case 2: copy_v3_v3(w, cb); break;
- case 3: copy_v3_v3(w, cc);
- }
- return(winner);
-}
-
-
-
-static int sb_detect_vertex_collisionCached(
- float opco[3], float facenormal[3], float *damp,
- float force[3], struct Object *vertexowner,
- float time, float vel[3], float *intrusion)
-{
- Object *ob= NULL;
- GHash *hash;
- GHashIterator *ihash;
- float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], dv1[3], ve[3], avel[3] = {0.0, 0.0, 0.0},
- vv1[3], vv2[3], vv3[3], coledge[3] = {0.0f, 0.0f, 0.0f}, mindistedge = 1000.0f,
- outerforceaccu[3], innerforceaccu[3],
- facedist, /* n_mag, */ /* UNUSED */ force_mag_norm, minx, miny, minz, maxx, maxy, maxz,
- innerfacethickness = -0.5f, outerfacethickness = 0.2f,
- ee = 5.0f, ff = 0.1f, fa=1;
- int a, deflected=0, cavel=0, ci=0;
-/* init */
- *intrusion = 0.0f;
- hash = vertexowner->soft->scratch->colliderhash;
- ihash = BLI_ghashIterator_new(hash);
- outerforceaccu[0]=outerforceaccu[1]=outerforceaccu[2]=0.0f;
- innerforceaccu[0]=innerforceaccu[1]=innerforceaccu[2]=0.0f;
-/* go */
- while (!BLI_ghashIterator_done(ihash)) {
-
- ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
- ob = BLI_ghashIterator_getKey (ihash);
- {
- /* only with deflecting set */
- if (ob->pd && ob->pd->deflect) {
- const MVert *mvert = NULL;
- const MVert *mprevvert = NULL;
- const MVertTri *vt = NULL;
- const ccdf_minmax *mima = NULL;
-
- if (ccdm) {
- mvert = ccdm->mvert;
- mprevvert = ccdm->mprevvert;
- vt = ccdm->tri;
- mima = ccdm->mima;
- a = ccdm->tri_num;
-
- minx = ccdm->bbmin[0];
- miny = ccdm->bbmin[1];
- minz = ccdm->bbmin[2];
-
- maxx = ccdm->bbmax[0];
- maxy = ccdm->bbmax[1];
- maxz = ccdm->bbmax[2];
-
- if ((opco[0] < minx) ||
- (opco[1] < miny) ||
- (opco[2] < minz) ||
- (opco[0] > maxx) ||
- (opco[1] > maxy) ||
- (opco[2] > maxz) )
- {
- /* outside the padded boundbox --> collision object is too far away */
- BLI_ghashIterator_step(ihash);
- continue;
- }
- }
- else {
- /*aye that should be cached*/
- CLOG_ERROR(&LOG, "missing cache error");
- BLI_ghashIterator_step(ihash);
- continue;
- }
-
- /* do object level stuff */
- /* need to have user control for that since it depends on model scale */
- innerfacethickness = -ob->pd->pdef_sbift;
- outerfacethickness = ob->pd->pdef_sboft;
- fa = (ff*outerfacethickness-outerfacethickness);
- fa *= fa;
- fa = 1.0f/fa;
- avel[0]=avel[1]=avel[2]=0.0f;
- /* use mesh*/
- while (a--) {
- if ((opco[0] < mima->minx) ||
- (opco[0] > mima->maxx) ||
- (opco[1] < mima->miny) ||
- (opco[1] > mima->maxy) ||
- (opco[2] < mima->minz) ||
- (opco[2] > mima->maxz))
- {
- mima++;
- vt++;
- continue;
- }
-
- if (mvert) {
-
- copy_v3_v3(nv1, mvert[vt->tri[0]].co);
- copy_v3_v3(nv2, mvert[vt->tri[1]].co);
- copy_v3_v3(nv3, mvert[vt->tri[2]].co);
-
- if (mprevvert) {
- /* grab the average speed of the collider vertices
- * before we spoil nvX
- * humm could be done once a SB steps but then we' need to store that too
- * since the AABB reduced propabitlty to get here drasticallly
- * it might be a nice tradeof CPU <--> memory
- */
- sub_v3_v3v3(vv1, nv1, mprevvert[vt->tri[0]].co);
- sub_v3_v3v3(vv2, nv2, mprevvert[vt->tri[1]].co);
- sub_v3_v3v3(vv3, nv3, mprevvert[vt->tri[2]].co);
-
- mul_v3_fl(nv1, time);
- madd_v3_v3fl(nv1, mprevvert[vt->tri[0]].co, 1.0f - time);
-
- mul_v3_fl(nv2, time);
- madd_v3_v3fl(nv2, mprevvert[vt->tri[1]].co, 1.0f - time);
-
- mul_v3_fl(nv3, time);
- madd_v3_v3fl(nv3, mprevvert[vt->tri[2]].co, 1.0f - time);
- }
- }
-
- /* switch origin to be nv2*/
- sub_v3_v3v3(edge1, nv1, nv2);
- sub_v3_v3v3(edge2, nv3, nv2);
- sub_v3_v3v3(dv1, opco, nv2); /* abuse dv1 to have vertex in question at *origin* of triangle */
-
- cross_v3_v3v3(d_nvect, edge2, edge1);
- /* n_mag = */ /* UNUSED */ normalize_v3(d_nvect);
- facedist = dot_v3v3(dv1, d_nvect);
- // so rules are
- //
-
- if ((facedist > innerfacethickness) && (facedist < outerfacethickness)) {
- if (isect_point_tri_prism_v3(opco, nv1, nv2, nv3) ) {
- force_mag_norm =(float)exp(-ee*facedist);
- if (facedist > outerfacethickness*ff)
- force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
- *damp=ob->pd->pdef_sbdamp;
- if (facedist > 0.0f) {
- *damp *= (1.0f - facedist/outerfacethickness);
- madd_v3_v3fl(outerforceaccu, d_nvect, force_mag_norm);
- deflected = 3;
-
- }
- else {
- madd_v3_v3fl(innerforceaccu, d_nvect, force_mag_norm);
- if (deflected < 2) deflected = 2;
- }
- if ((mprevvert) && (*damp > 0.0f)) {
- choose_winner(ve, opco, nv1, nv2, nv3, vv1, vv2, vv3);
- add_v3_v3(avel, ve);
- cavel ++;
- }
- *intrusion += facedist;
- ci++;
- }
- }
-
- mima++;
- vt++;
- }/* while a */
- } /* if (ob->pd && ob->pd->deflect) */
- BLI_ghashIterator_step(ihash);
- }
- } /* while () */
-
- if (deflected == 1) { // no face but 'outer' edge cylinder sees vert
- force_mag_norm =(float)exp(-ee*mindistedge);
- if (mindistedge > outerfacethickness*ff)
- force_mag_norm =(float)force_mag_norm*fa*(mindistedge - outerfacethickness)*(mindistedge - outerfacethickness);
- madd_v3_v3fl(force, coledge, force_mag_norm);
- *damp=ob->pd->pdef_sbdamp;
- if (mindistedge > 0.0f) {
- *damp *= (1.0f - mindistedge/outerfacethickness);
- }
-
- }
- if (deflected == 2) { // face inner detected
- add_v3_v3(force, innerforceaccu);
- }
- if (deflected == 3) { // face outer detected
- add_v3_v3(force, outerforceaccu);
- }
-
- BLI_ghashIterator_free(ihash);
- if (cavel) mul_v3_fl(avel, 1.0f/(float)cavel);
- copy_v3_v3(vel, avel);
- if (ci) *intrusion /= ci;
- if (deflected) {
- normalize_v3_v3(facenormal, force);
- }
- return deflected;
+static int choose_winner(
+ float *w, float *pos, float *a, float *b, float *c, float *ca, float *cb, float *cc)
+{
+ float mindist, cp;
+ int winner = 1;
+ mindist = fabsf(dot_v3v3(pos, a));
+
+ cp = fabsf(dot_v3v3(pos, b));
+ if (mindist < cp) {
+ mindist = cp;
+ winner = 2;
+ }
+
+ cp = fabsf(dot_v3v3(pos, c));
+ if (mindist < cp) {
+ mindist = cp;
+ winner = 3;
+ }
+ switch (winner) {
+ case 1:
+ copy_v3_v3(w, ca);
+ break;
+ case 2:
+ copy_v3_v3(w, cb);
+ break;
+ case 3:
+ copy_v3_v3(w, cc);
+ }
+ return (winner);
+}
+
+static int sb_detect_vertex_collisionCached(float opco[3],
+ float facenormal[3],
+ float *damp,
+ float force[3],
+ struct Object *vertexowner,
+ float time,
+ float vel[3],
+ float *intrusion)
+{
+ Object *ob = NULL;
+ GHash *hash;
+ GHashIterator *ihash;
+ float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], dv1[3], ve[3],
+ avel[3] = {0.0, 0.0, 0.0}, vv1[3], vv2[3], vv3[3], coledge[3] = {0.0f, 0.0f, 0.0f},
+ mindistedge = 1000.0f, outerforceaccu[3], innerforceaccu[3], facedist,
+ /* n_mag, */ /* UNUSED */ force_mag_norm, minx, miny, minz, maxx, maxy, maxz,
+ innerfacethickness = -0.5f, outerfacethickness = 0.2f, ee = 5.0f, ff = 0.1f, fa = 1;
+ int a, deflected = 0, cavel = 0, ci = 0;
+ /* init */
+ *intrusion = 0.0f;
+ hash = vertexowner->soft->scratch->colliderhash;
+ ihash = BLI_ghashIterator_new(hash);
+ outerforceaccu[0] = outerforceaccu[1] = outerforceaccu[2] = 0.0f;
+ innerforceaccu[0] = innerforceaccu[1] = innerforceaccu[2] = 0.0f;
+ /* go */
+ while (!BLI_ghashIterator_done(ihash)) {
+
+ ccd_Mesh *ccdm = BLI_ghashIterator_getValue(ihash);
+ ob = BLI_ghashIterator_getKey(ihash);
+ {
+ /* only with deflecting set */
+ if (ob->pd && ob->pd->deflect) {
+ const MVert *mvert = NULL;
+ const MVert *mprevvert = NULL;
+ const MVertTri *vt = NULL;
+ const ccdf_minmax *mima = NULL;
+
+ if (ccdm) {
+ mvert = ccdm->mvert;
+ mprevvert = ccdm->mprevvert;
+ vt = ccdm->tri;
+ mima = ccdm->mima;
+ a = ccdm->tri_num;
+
+ minx = ccdm->bbmin[0];
+ miny = ccdm->bbmin[1];
+ minz = ccdm->bbmin[2];
+
+ maxx = ccdm->bbmax[0];
+ maxy = ccdm->bbmax[1];
+ maxz = ccdm->bbmax[2];
+
+ if ((opco[0] < minx) || (opco[1] < miny) || (opco[2] < minz) || (opco[0] > maxx) ||
+ (opco[1] > maxy) || (opco[2] > maxz)) {
+ /* outside the padded boundbox --> collision object is too far away */
+ BLI_ghashIterator_step(ihash);
+ continue;
+ }
+ }
+ else {
+ /*aye that should be cached*/
+ CLOG_ERROR(&LOG, "missing cache error");
+ BLI_ghashIterator_step(ihash);
+ continue;
+ }
+
+ /* do object level stuff */
+ /* need to have user control for that since it depends on model scale */
+ innerfacethickness = -ob->pd->pdef_sbift;
+ outerfacethickness = ob->pd->pdef_sboft;
+ fa = (ff * outerfacethickness - outerfacethickness);
+ fa *= fa;
+ fa = 1.0f / fa;
+ avel[0] = avel[1] = avel[2] = 0.0f;
+ /* use mesh*/
+ while (a--) {
+ if ((opco[0] < mima->minx) || (opco[0] > mima->maxx) || (opco[1] < mima->miny) ||
+ (opco[1] > mima->maxy) || (opco[2] < mima->minz) || (opco[2] > mima->maxz)) {
+ mima++;
+ vt++;
+ continue;
+ }
+
+ if (mvert) {
+
+ copy_v3_v3(nv1, mvert[vt->tri[0]].co);
+ copy_v3_v3(nv2, mvert[vt->tri[1]].co);
+ copy_v3_v3(nv3, mvert[vt->tri[2]].co);
+
+ if (mprevvert) {
+ /* grab the average speed of the collider vertices
+ * before we spoil nvX
+ * humm could be done once a SB steps but then we' need to store that too
+ * since the AABB reduced propabitlty to get here drasticallly
+ * it might be a nice tradeof CPU <--> memory
+ */
+ sub_v3_v3v3(vv1, nv1, mprevvert[vt->tri[0]].co);
+ sub_v3_v3v3(vv2, nv2, mprevvert[vt->tri[1]].co);
+ sub_v3_v3v3(vv3, nv3, mprevvert[vt->tri[2]].co);
+
+ mul_v3_fl(nv1, time);
+ madd_v3_v3fl(nv1, mprevvert[vt->tri[0]].co, 1.0f - time);
+
+ mul_v3_fl(nv2, time);
+ madd_v3_v3fl(nv2, mprevvert[vt->tri[1]].co, 1.0f - time);
+
+ mul_v3_fl(nv3, time);
+ madd_v3_v3fl(nv3, mprevvert[vt->tri[2]].co, 1.0f - time);
+ }
+ }
+
+ /* switch origin to be nv2*/
+ sub_v3_v3v3(edge1, nv1, nv2);
+ sub_v3_v3v3(edge2, nv3, nv2);
+ sub_v3_v3v3(
+ dv1, opco, nv2); /* abuse dv1 to have vertex in question at *origin* of triangle */
+
+ cross_v3_v3v3(d_nvect, edge2, edge1);
+ /* n_mag = */ /* UNUSED */ normalize_v3(d_nvect);
+ facedist = dot_v3v3(dv1, d_nvect);
+ // so rules are
+ //
+
+ if ((facedist > innerfacethickness) && (facedist < outerfacethickness)) {
+ if (isect_point_tri_prism_v3(opco, nv1, nv2, nv3)) {
+ force_mag_norm = (float)exp(-ee * facedist);
+ if (facedist > outerfacethickness * ff)
+ force_mag_norm = (float)force_mag_norm * fa * (facedist - outerfacethickness) *
+ (facedist - outerfacethickness);
+ *damp = ob->pd->pdef_sbdamp;
+ if (facedist > 0.0f) {
+ *damp *= (1.0f - facedist / outerfacethickness);
+ madd_v3_v3fl(outerforceaccu, d_nvect, force_mag_norm);
+ deflected = 3;
+ }
+ else {
+ madd_v3_v3fl(innerforceaccu, d_nvect, force_mag_norm);
+ if (deflected < 2)
+ deflected = 2;
+ }
+ if ((mprevvert) && (*damp > 0.0f)) {
+ choose_winner(ve, opco, nv1, nv2, nv3, vv1, vv2, vv3);
+ add_v3_v3(avel, ve);
+ cavel++;
+ }
+ *intrusion += facedist;
+ ci++;
+ }
+ }
+
+ mima++;
+ vt++;
+ } /* while a */
+ } /* if (ob->pd && ob->pd->deflect) */
+ BLI_ghashIterator_step(ihash);
+ }
+ } /* while () */
+
+ if (deflected == 1) { // no face but 'outer' edge cylinder sees vert
+ force_mag_norm = (float)exp(-ee * mindistedge);
+ if (mindistedge > outerfacethickness * ff)
+ force_mag_norm = (float)force_mag_norm * fa * (mindistedge - outerfacethickness) *
+ (mindistedge - outerfacethickness);
+ madd_v3_v3fl(force, coledge, force_mag_norm);
+ *damp = ob->pd->pdef_sbdamp;
+ if (mindistedge > 0.0f) {
+ *damp *= (1.0f - mindistedge / outerfacethickness);
+ }
+ }
+ if (deflected == 2) { // face inner detected
+ add_v3_v3(force, innerforceaccu);
+ }
+ if (deflected == 3) { // face outer detected
+ add_v3_v3(force, outerforceaccu);
+ }
+
+ BLI_ghashIterator_free(ihash);
+ if (cavel)
+ mul_v3_fl(avel, 1.0f / (float)cavel);
+ copy_v3_v3(vel, avel);
+ if (ci)
+ *intrusion /= ci;
+ if (deflected) {
+ normalize_v3_v3(facenormal, force);
+ }
+ return deflected;
}
-
/* sandbox to plug in various deflection algos */
-static int sb_deflect_face(Object *ob, float *actpos, float *facenormal, float *force, float *cf, float time, float *vel, float *intrusion)
-{
- float s_actpos[3];
- int deflected;
- copy_v3_v3(s_actpos, actpos);
- deflected= sb_detect_vertex_collisionCached(s_actpos, facenormal, cf, force, ob, time, vel, intrusion);
- //deflected= sb_detect_vertex_collisionCachedEx(s_actpos, facenormal, cf, force, ob, time, vel, intrusion);
- return(deflected);
+static int sb_deflect_face(Object *ob,
+ float *actpos,
+ float *facenormal,
+ float *force,
+ float *cf,
+ float time,
+ float *vel,
+ float *intrusion)
+{
+ float s_actpos[3];
+ int deflected;
+ copy_v3_v3(s_actpos, actpos);
+ deflected = sb_detect_vertex_collisionCached(
+ s_actpos, facenormal, cf, force, ob, time, vel, intrusion);
+ //deflected= sb_detect_vertex_collisionCachedEx(s_actpos, facenormal, cf, force, ob, time, vel, intrusion);
+ return (deflected);
}
/* hiding this for now .. but the jacobian may pop up on other tasks .. so i'd like to keep it */
#if 0
static void dfdx_spring(int ia, int ic, int op, float dir[3], float L, float len, float factor)
{
- float m, delta_ij;
- int i, j;
- if (L < len) {
- for (i=0;i<3;i++) {
- for (j=0;j<3;j++) {
- delta_ij = (i==j ? (1.0f): (0.0f));
- m=factor*(dir[i]*dir[j] + (1-L/len)*(delta_ij - dir[i]*dir[j]));
- EIG_linear_solver_matrix_add(ia+i, op+ic+j, m);
- }
- }
- }
- else {
- for (i=0;i<3;i++) {
- for (j=0;j<3;j++) {
- m=factor*dir[i]*dir[j];
- EIG_linear_solver_matrix_add(ia+i, op+ic+j, m);
- }
- }
- }
+ float m, delta_ij;
+ int i, j;
+ if (L < len) {
+ for (i=0;i<3;i++) {
+ for (j=0;j<3;j++) {
+ delta_ij = (i==j ? (1.0f): (0.0f));
+ m=factor*(dir[i]*dir[j] + (1-L/len)*(delta_ij - dir[i]*dir[j]));
+ EIG_linear_solver_matrix_add(ia+i, op+ic+j, m);
+ }
+ }
+ }
+ else {
+ for (i=0;i<3;i++) {
+ for (j=0;j<3;j++) {
+ m=factor*dir[i]*dir[j];
+ EIG_linear_solver_matrix_add(ia+i, op+ic+j, m);
+ }
+ }
+ }
}
static void dfdx_goal(int ia, int ic, int op, float factor)
{
- int i;
- for (i=0;i<3;i++) EIG_linear_solver_matrix_add(ia+i, op+ic+i, factor);
+ int i;
+ for (i=0;i<3;i++) EIG_linear_solver_matrix_add(ia+i, op+ic+i, factor);
}
static void dfdv_goal(int ia, int ic, float factor)
{
- int i;
- for (i=0;i<3;i++) EIG_linear_solver_matrix_add(ia+i, ic+i, factor);
+ int i;
+ for (i=0;i<3;i++) EIG_linear_solver_matrix_add(ia+i, ic+i, factor);
}
-#endif /* if 0 */
+#endif /* if 0 */
-static void sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, float UNUSED(forcetime))
+static void sb_spring_force(
+ Object *ob, int bpi, BodySpring *bs, float iks, float UNUSED(forcetime))
{
- SoftBody *sb= ob->soft; /* is supposed to be there */
- BodyPoint *bp1, *bp2;
+ SoftBody *sb = ob->soft; /* is supposed to be there */
+ BodyPoint *bp1, *bp2;
- float dir[3], dvel[3];
- float distance, forcefactor, kd, absvel, projvel, kw;
-#if 0 /* UNUSED */
- int ia, ic;
+ float dir[3], dvel[3];
+ float distance, forcefactor, kd, absvel, projvel, kw;
+#if 0 /* UNUSED */
+ int ia, ic;
#endif
- /* prepare depending on which side of the spring we are on */
- if (bpi == bs->v1) {
- bp1 = &sb->bpoint[bs->v1];
- bp2 = &sb->bpoint[bs->v2];
-#if 0 /* UNUSED */
- ia =3*bs->v1;
- ic =3*bs->v2;
+ /* prepare depending on which side of the spring we are on */
+ if (bpi == bs->v1) {
+ bp1 = &sb->bpoint[bs->v1];
+ bp2 = &sb->bpoint[bs->v2];
+#if 0 /* UNUSED */
+ ia =3*bs->v1;
+ ic =3*bs->v2;
#endif
- }
- else if (bpi == bs->v2) {
- bp1 = &sb->bpoint[bs->v2];
- bp2 = &sb->bpoint[bs->v1];
-#if 0 /* UNUSED */
- ia =3*bs->v2;
- ic =3*bs->v1;
+ }
+ else if (bpi == bs->v2) {
+ bp1 = &sb->bpoint[bs->v2];
+ bp2 = &sb->bpoint[bs->v1];
+#if 0 /* UNUSED */
+ ia =3*bs->v2;
+ ic =3*bs->v1;
#endif
- }
- else {
- /* TODO make this debug option */
- CLOG_WARN(&LOG, "bodypoint <bpi> is not attached to spring <*bs>");
- return;
- }
-
- /* do bp1 <--> bp2 elastic */
- sub_v3_v3v3(dir, bp1->pos, bp2->pos);
- distance = normalize_v3(dir);
- if (bs->len < distance)
- iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
- else
- iks = 1.0f/(1.0f-sb->inpush)-1.0f ;/* inner spring constants function */
-
- if (bs->len > 0.0f) /* check for degenerated springs */
- forcefactor = iks/bs->len;
- else
- forcefactor = iks;
- kw = (bp1->springweight+bp2->springweight)/2.0f;
- kw = kw * kw;
- kw = kw * kw;
- switch (bs->springtype) {
- case SB_EDGE:
- case SB_HANDLE:
- forcefactor *= kw;
- break;
- case SB_BEND:
- forcefactor *= sb->secondspring * kw;
- break;
- case SB_STIFFQUAD:
- forcefactor *= sb->shearstiff * sb->shearstiff * kw;
- break;
- default:
- break;
- }
-
-
- madd_v3_v3fl(bp1->force, dir, (bs->len - distance) * forcefactor);
-
- /* do bp1 <--> bp2 viscous */
- sub_v3_v3v3(dvel, bp1->vec, bp2->vec);
- kd = sb->infrict * sb_fric_force_scale(ob);
- absvel = normalize_v3(dvel);
- projvel = dot_v3v3(dir, dvel);
- kd *= absvel * projvel;
- madd_v3_v3fl(bp1->force, dir, -kd);
+ }
+ else {
+ /* TODO make this debug option */
+ CLOG_WARN(&LOG, "bodypoint <bpi> is not attached to spring <*bs>");
+ return;
+ }
+
+ /* do bp1 <--> bp2 elastic */
+ sub_v3_v3v3(dir, bp1->pos, bp2->pos);
+ distance = normalize_v3(dir);
+ if (bs->len < distance)
+ iks = 1.0f / (1.0f - sb->inspring) - 1.0f; /* inner spring constants function */
+ else
+ iks = 1.0f / (1.0f - sb->inpush) - 1.0f; /* inner spring constants function */
+
+ if (bs->len > 0.0f) /* check for degenerated springs */
+ forcefactor = iks / bs->len;
+ else
+ forcefactor = iks;
+ kw = (bp1->springweight + bp2->springweight) / 2.0f;
+ kw = kw * kw;
+ kw = kw * kw;
+ switch (bs->springtype) {
+ case SB_EDGE:
+ case SB_HANDLE:
+ forcefactor *= kw;
+ break;
+ case SB_BEND:
+ forcefactor *= sb->secondspring * kw;
+ break;
+ case SB_STIFFQUAD:
+ forcefactor *= sb->shearstiff * sb->shearstiff * kw;
+ break;
+ default:
+ break;
+ }
+
+ madd_v3_v3fl(bp1->force, dir, (bs->len - distance) * forcefactor);
+
+ /* do bp1 <--> bp2 viscous */
+ sub_v3_v3v3(dvel, bp1->vec, bp2->vec);
+ kd = sb->infrict * sb_fric_force_scale(ob);
+ absvel = normalize_v3(dvel);
+ projvel = dot_v3v3(dir, dvel);
+ kd *= absvel * projvel;
+ madd_v3_v3fl(bp1->force, dir, -kd);
}
-
/* since this is definitely the most CPU consuming task here .. try to spread it */
/* core function _softbody_calc_forces_slice_in_a_thread */
/* result is int to be able to flag user break */
-static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, float forcetime, float timenow, int ifirst, int ilast, int *UNUSED(ptr_to_break_func(void)), ListBase *effectors, int do_deflector, float fieldfactor, float windfactor)
-{
- float iks;
- int bb, do_selfcollision, do_springcollision, do_aero;
- int number_of_points_here = ilast - ifirst;
- SoftBody *sb = ob->soft; /* is supposed to be there */
- BodyPoint *bp;
-
- /* initialize */
- if (sb) {
- /* check conditions for various options */
- /* +++ could be done on object level to squeeze out the last bits of it */
- do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
- do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
- do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
- /* --- could be done on object level to squeeze out the last bits of it */
- }
- else {
- CLOG_ERROR(&LOG, "expected a SB here");
- return (999);
- }
-
-/* debugerin */
- if (sb->totpoint < ifirst) {
- printf("Aye 998");
- return (998);
- }
-/* debugerin */
-
-
- bp = &sb->bpoint[ifirst];
- for (bb=number_of_points_here; bb>0; bb--, bp++) {
- /* clear forces accumulator */
- bp->force[0] = bp->force[1] = bp->force[2] = 0.0;
- /* naive ball self collision */
- /* needs to be done if goal snaps or not */
- if (do_selfcollision) {
- int attached;
- BodyPoint *obp;
- BodySpring *bs;
- int c, b;
- float velcenter[3], dvel[3], def[3];
- float distance;
- float compare;
- float bstune = sb->ballstiff;
-
- /* running in a slice we must not assume anything done with obp neither alter the data of obp */
- for (c=sb->totpoint, obp= sb->bpoint; c>0; c--, obp++) {
- compare = (obp->colball + bp->colball);
- sub_v3_v3v3(def, bp->pos, obp->pos);
- /* rather check the AABBoxes before ever calculating the real distance */
- /* mathematically it is completely nuts, but performance is pretty much (3) times faster */
- if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
- distance = normalize_v3(def);
- if (distance < compare ) {
- /* exclude body points attached with a spring */
- attached = 0;
- for (b=obp->nofsprings;b>0;b--) {
- bs = sb->bspring + obp->springs[b-1];
- if (( ilast-bb == bs->v2) || ( ilast-bb == bs->v1)) {
- attached=1;
- continue;
- }
- }
- if (!attached) {
- float f = bstune / (distance) + bstune / (compare * compare) * distance - 2.0f * bstune / compare;
-
- mid_v3_v3v3(velcenter, bp->vec, obp->vec);
- sub_v3_v3v3(dvel, velcenter, bp->vec);
- mul_v3_fl(dvel, _final_mass(ob, bp));
-
- madd_v3_v3fl(bp->force, def, f * (1.0f - sb->balldamp));
- madd_v3_v3fl(bp->force, dvel, sb->balldamp);
- }
- }
- }
- }
- /* naive ball self collision done */
-
- if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* omit this bp when it snaps */
- float auxvect[3];
- float velgoal[3];
-
- /* do goal stuff */
- if (ob->softflag & OB_SB_GOAL) {
- /* true elastic goal */
- float ks, kd;
- sub_v3_v3v3(auxvect, bp->pos, bp->origT);
- ks = 1.0f / (1.0f - _final_goal(ob, bp) * sb->goalspring) - 1.0f;
- bp->force[0]+= -ks*(auxvect[0]);
- bp->force[1]+= -ks*(auxvect[1]);
- bp->force[2]+= -ks*(auxvect[2]);
-
- /* calculate damping forces generated by goals*/
- sub_v3_v3v3(velgoal, bp->origS, bp->origE);
- kd = sb->goalfrict * sb_fric_force_scale(ob);
- add_v3_v3v3(auxvect, velgoal, bp->vec);
-
- if (forcetime > 0.0f) { /* make sure friction does not become rocket motor on time reversal */
- bp->force[0]-= kd * (auxvect[0]);
- bp->force[1]-= kd * (auxvect[1]);
- bp->force[2]-= kd * (auxvect[2]);
- }
- else {
- bp->force[0]-= kd * (velgoal[0] - bp->vec[0]);
- bp->force[1]-= kd * (velgoal[1] - bp->vec[1]);
- bp->force[2]-= kd * (velgoal[2] - bp->vec[2]);
- }
- }
- /* done goal stuff */
-
- /* gravitation */
- if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
- float gravity[3];
- copy_v3_v3(gravity, scene->physics_settings.gravity);
- mul_v3_fl(gravity, sb_grav_force_scale(ob)*_final_mass(ob, bp)*sb->effector_weights->global_gravity); /* individual mass of node here */
- add_v3_v3(bp->force, gravity);
- }
-
- /* particle field & vortex */
- if (effectors) {
- EffectedPoint epoint;
- float kd;
- float force[3] = {0.0f, 0.0f, 0.0f};
- float speed[3] = {0.0f, 0.0f, 0.0f};
- float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */
- pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint-bp, &epoint);
- BKE_effectors_apply(effectors, NULL, sb->effector_weights, &epoint, force, speed);
-
- /* apply forcefield*/
- mul_v3_fl(force, fieldfactor * eval_sb_fric_force_scale);
- add_v3_v3(bp->force, force);
-
- /* BP friction in moving media */
- kd= sb->mediafrict * eval_sb_fric_force_scale;
- bp->force[0] -= kd * (bp->vec[0] + windfactor*speed[0]/eval_sb_fric_force_scale);
- bp->force[1] -= kd * (bp->vec[1] + windfactor*speed[1]/eval_sb_fric_force_scale);
- bp->force[2] -= kd * (bp->vec[2] + windfactor*speed[2]/eval_sb_fric_force_scale);
- /* now we'll have nice centrifugal effect for vortex */
-
- }
- else {
- /* BP friction in media (not) moving*/
- float kd = sb->mediafrict * sb_fric_force_scale(ob);
- /* assume it to be proportional to actual velocity */
- bp->force[0]-= bp->vec[0]*kd;
- bp->force[1]-= bp->vec[1]*kd;
- bp->force[2]-= bp->vec[2]*kd;
- /* friction in media done */
- }
- /* +++cached collision targets */
- bp->choke = 0.0f;
- bp->choke2 = 0.0f;
- bp->loc_flag &= ~SBF_DOFUZZY;
- if (do_deflector && !(bp->loc_flag & SBF_OUTOFCOLLISION) ) {
- float cfforce[3], defforce[3] ={0.0f, 0.0f, 0.0f}, vel[3] = {0.0f, 0.0f, 0.0f}, facenormal[3], cf = 1.0f, intrusion;
- float kd = 1.0f;
-
- if (sb_deflect_face(ob, bp->pos, facenormal, defforce, &cf, timenow, vel, &intrusion)) {
- if (intrusion < 0.0f) {
- sb->scratch->flag |= SBF_DOFUZZY;
- bp->loc_flag |= SBF_DOFUZZY;
- bp->choke = sb->choke*0.01f;
- }
-
- sub_v3_v3v3(cfforce, bp->vec, vel);
- madd_v3_v3fl(bp->force, cfforce, -cf * 50.0f);
-
- madd_v3_v3fl(bp->force, defforce, kd);
- }
-
- }
- /* ---cached collision targets */
-
- /* +++springs */
- iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
- if (ob->softflag & OB_SB_EDGES) {
- if (sb->bspring) { /* spring list exists at all ? */
- int b;
- BodySpring *bs;
- for (b=bp->nofsprings;b>0;b--) {
- bs = sb->bspring + bp->springs[b-1];
- if (do_springcollision || do_aero) {
- add_v3_v3(bp->force, bs->ext_force);
- if (bs->flag & BSF_INTERSECT)
- bp->choke = bs->cf;
-
- }
- // sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, float forcetime)
- sb_spring_force(ob, ilast-bb, bs, iks, forcetime);
- }/* loop springs */
- }/* existing spring list */
- }/*any edges*/
- /* ---springs */
- }/*omit on snap */
- }/*loop all bp's*/
- return 0; /*done fine*/
+static int _softbody_calc_forces_slice_in_a_thread(Scene *scene,
+ Object *ob,
+ float forcetime,
+ float timenow,
+ int ifirst,
+ int ilast,
+ int *UNUSED(ptr_to_break_func(void)),
+ ListBase *effectors,
+ int do_deflector,
+ float fieldfactor,
+ float windfactor)
+{
+ float iks;
+ int bb, do_selfcollision, do_springcollision, do_aero;
+ int number_of_points_here = ilast - ifirst;
+ SoftBody *sb = ob->soft; /* is supposed to be there */
+ BodyPoint *bp;
+
+ /* initialize */
+ if (sb) {
+ /* check conditions for various options */
+ /* +++ could be done on object level to squeeze out the last bits of it */
+ do_selfcollision = ((ob->softflag & OB_SB_EDGES) && (sb->bspring) &&
+ (ob->softflag & OB_SB_SELF));
+ do_springcollision = do_deflector && (ob->softflag & OB_SB_EDGES) &&
+ (ob->softflag & OB_SB_EDGECOLL);
+ do_aero = ((sb->aeroedge) && (ob->softflag & OB_SB_EDGES));
+ /* --- could be done on object level to squeeze out the last bits of it */
+ }
+ else {
+ CLOG_ERROR(&LOG, "expected a SB here");
+ return (999);
+ }
+
+ /* debugerin */
+ if (sb->totpoint < ifirst) {
+ printf("Aye 998");
+ return (998);
+ }
+ /* debugerin */
+
+ bp = &sb->bpoint[ifirst];
+ for (bb = number_of_points_here; bb > 0; bb--, bp++) {
+ /* clear forces accumulator */
+ bp->force[0] = bp->force[1] = bp->force[2] = 0.0;
+ /* naive ball self collision */
+ /* needs to be done if goal snaps or not */
+ if (do_selfcollision) {
+ int attached;
+ BodyPoint *obp;
+ BodySpring *bs;
+ int c, b;
+ float velcenter[3], dvel[3], def[3];
+ float distance;
+ float compare;
+ float bstune = sb->ballstiff;
+
+ /* running in a slice we must not assume anything done with obp neither alter the data of obp */
+ for (c = sb->totpoint, obp = sb->bpoint; c > 0; c--, obp++) {
+ compare = (obp->colball + bp->colball);
+ sub_v3_v3v3(def, bp->pos, obp->pos);
+ /* rather check the AABBoxes before ever calculating the real distance */
+ /* mathematically it is completely nuts, but performance is pretty much (3) times faster */
+ if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare))
+ continue;
+ distance = normalize_v3(def);
+ if (distance < compare) {
+ /* exclude body points attached with a spring */
+ attached = 0;
+ for (b = obp->nofsprings; b > 0; b--) {
+ bs = sb->bspring + obp->springs[b - 1];
+ if ((ilast - bb == bs->v2) || (ilast - bb == bs->v1)) {
+ attached = 1;
+ continue;
+ }
+ }
+ if (!attached) {
+ float f = bstune / (distance) + bstune / (compare * compare) * distance -
+ 2.0f * bstune / compare;
+
+ mid_v3_v3v3(velcenter, bp->vec, obp->vec);
+ sub_v3_v3v3(dvel, velcenter, bp->vec);
+ mul_v3_fl(dvel, _final_mass(ob, bp));
+
+ madd_v3_v3fl(bp->force, def, f * (1.0f - sb->balldamp));
+ madd_v3_v3fl(bp->force, dvel, sb->balldamp);
+ }
+ }
+ }
+ }
+ /* naive ball self collision done */
+
+ if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* omit this bp when it snaps */
+ float auxvect[3];
+ float velgoal[3];
+
+ /* do goal stuff */
+ if (ob->softflag & OB_SB_GOAL) {
+ /* true elastic goal */
+ float ks, kd;
+ sub_v3_v3v3(auxvect, bp->pos, bp->origT);
+ ks = 1.0f / (1.0f - _final_goal(ob, bp) * sb->goalspring) - 1.0f;
+ bp->force[0] += -ks * (auxvect[0]);
+ bp->force[1] += -ks * (auxvect[1]);
+ bp->force[2] += -ks * (auxvect[2]);
+
+ /* calculate damping forces generated by goals*/
+ sub_v3_v3v3(velgoal, bp->origS, bp->origE);
+ kd = sb->goalfrict * sb_fric_force_scale(ob);
+ add_v3_v3v3(auxvect, velgoal, bp->vec);
+
+ if (forcetime >
+ 0.0f) { /* make sure friction does not become rocket motor on time reversal */
+ bp->force[0] -= kd * (auxvect[0]);
+ bp->force[1] -= kd * (auxvect[1]);
+ bp->force[2] -= kd * (auxvect[2]);
+ }
+ else {
+ bp->force[0] -= kd * (velgoal[0] - bp->vec[0]);
+ bp->force[1] -= kd * (velgoal[1] - bp->vec[1]);
+ bp->force[2] -= kd * (velgoal[2] - bp->vec[2]);
+ }
+ }
+ /* done goal stuff */
+
+ /* gravitation */
+ if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
+ float gravity[3];
+ copy_v3_v3(gravity, scene->physics_settings.gravity);
+ mul_v3_fl(gravity,
+ sb_grav_force_scale(ob) * _final_mass(ob, bp) *
+ sb->effector_weights->global_gravity); /* individual mass of node here */
+ add_v3_v3(bp->force, gravity);
+ }
+
+ /* particle field & vortex */
+ if (effectors) {
+ EffectedPoint epoint;
+ float kd;
+ float force[3] = {0.0f, 0.0f, 0.0f};
+ float speed[3] = {0.0f, 0.0f, 0.0f};
+ float eval_sb_fric_force_scale = sb_fric_force_scale(
+ ob); /* just for calling function once */
+ pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint - bp, &epoint);
+ BKE_effectors_apply(effectors, NULL, sb->effector_weights, &epoint, force, speed);
+
+ /* apply forcefield*/
+ mul_v3_fl(force, fieldfactor * eval_sb_fric_force_scale);
+ add_v3_v3(bp->force, force);
+
+ /* BP friction in moving media */
+ kd = sb->mediafrict * eval_sb_fric_force_scale;
+ bp->force[0] -= kd * (bp->vec[0] + windfactor * speed[0] / eval_sb_fric_force_scale);
+ bp->force[1] -= kd * (bp->vec[1] + windfactor * speed[1] / eval_sb_fric_force_scale);
+ bp->force[2] -= kd * (bp->vec[2] + windfactor * speed[2] / eval_sb_fric_force_scale);
+ /* now we'll have nice centrifugal effect for vortex */
+ }
+ else {
+ /* BP friction in media (not) moving*/
+ float kd = sb->mediafrict * sb_fric_force_scale(ob);
+ /* assume it to be proportional to actual velocity */
+ bp->force[0] -= bp->vec[0] * kd;
+ bp->force[1] -= bp->vec[1] * kd;
+ bp->force[2] -= bp->vec[2] * kd;
+ /* friction in media done */
+ }
+ /* +++cached collision targets */
+ bp->choke = 0.0f;
+ bp->choke2 = 0.0f;
+ bp->loc_flag &= ~SBF_DOFUZZY;
+ if (do_deflector && !(bp->loc_flag & SBF_OUTOFCOLLISION)) {
+ float cfforce[3], defforce[3] = {0.0f, 0.0f, 0.0f}, vel[3] = {0.0f, 0.0f, 0.0f},
+ facenormal[3], cf = 1.0f, intrusion;
+ float kd = 1.0f;
+
+ if (sb_deflect_face(ob, bp->pos, facenormal, defforce, &cf, timenow, vel, &intrusion)) {
+ if (intrusion < 0.0f) {
+ sb->scratch->flag |= SBF_DOFUZZY;
+ bp->loc_flag |= SBF_DOFUZZY;
+ bp->choke = sb->choke * 0.01f;
+ }
+
+ sub_v3_v3v3(cfforce, bp->vec, vel);
+ madd_v3_v3fl(bp->force, cfforce, -cf * 50.0f);
+
+ madd_v3_v3fl(bp->force, defforce, kd);
+ }
+ }
+ /* ---cached collision targets */
+
+ /* +++springs */
+ iks = 1.0f / (1.0f - sb->inspring) - 1.0f; /* inner spring constants function */
+ if (ob->softflag & OB_SB_EDGES) {
+ if (sb->bspring) { /* spring list exists at all ? */
+ int b;
+ BodySpring *bs;
+ for (b = bp->nofsprings; b > 0; b--) {
+ bs = sb->bspring + bp->springs[b - 1];
+ if (do_springcollision || do_aero) {
+ add_v3_v3(bp->force, bs->ext_force);
+ if (bs->flag & BSF_INTERSECT)
+ bp->choke = bs->cf;
+ }
+ // sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, float forcetime)
+ sb_spring_force(ob, ilast - bb, bs, iks, forcetime);
+ } /* loop springs */
+ } /* existing spring list */
+ } /*any edges*/
+ /* ---springs */
+ } /*omit on snap */
+ } /*loop all bp's*/
+ return 0; /*done fine*/
}
static void *exec_softbody_calc_forces(void *data)
{
- SB_thread_context *pctx = (SB_thread_context*)data;
- _softbody_calc_forces_slice_in_a_thread(pctx->scene, pctx->ob, pctx->forcetime, pctx->timenow, pctx->ifirst, pctx->ilast, NULL, pctx->effectors, pctx->do_deflector, pctx->fieldfactor, pctx->windfactor);
- return NULL;
-}
-
-static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float timenow, int totpoint, int *UNUSED(ptr_to_break_func(void)), struct ListBase *effectors, int do_deflector, float fieldfactor, float windfactor)
-{
- ListBase threads;
- SB_thread_context *sb_threads;
- int i, totthread, left, dec;
- int lowpoints =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
-
- /* figure the number of threads while preventing pretty pointless threading overhead */
- totthread= BKE_scene_num_threads(scene);
- /* what if we got zillions of CPUs running but less to spread*/
- while ((totpoint/totthread < lowpoints) && (totthread > 1)) {
- totthread--;
- }
-
- /* printf("sb_cf_threads_run spawning %d threads\n", totthread); */
-
- sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBThread");
- memset(sb_threads, 0, sizeof(SB_thread_context)*totthread);
- left = totpoint;
- dec = totpoint/totthread +1;
- for (i=0; i<totthread; i++) {
- sb_threads[i].scene = scene;
- sb_threads[i].ob = ob;
- sb_threads[i].forcetime = forcetime;
- sb_threads[i].timenow = timenow;
- sb_threads[i].ilast = left;
- left = left - dec;
- if (left >0) {
- sb_threads[i].ifirst = left;
- }
- else
- sb_threads[i].ifirst = 0;
- sb_threads[i].effectors = effectors;
- sb_threads[i].do_deflector = do_deflector;
- sb_threads[i].fieldfactor = fieldfactor;
- sb_threads[i].windfactor = windfactor;
- sb_threads[i].nr= i;
- sb_threads[i].tot= totthread;
- }
-
-
- if (totthread > 1) {
- BLI_threadpool_init(&threads, exec_softbody_calc_forces, totthread);
-
- for (i=0; i<totthread; i++)
- BLI_threadpool_insert(&threads, &sb_threads[i]);
-
- BLI_threadpool_end(&threads);
- }
- else
- exec_softbody_calc_forces(&sb_threads[0]);
- /* clean up */
- MEM_freeN(sb_threads);
-}
-
-static void softbody_calc_forces(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float forcetime, float timenow)
-{
- /* rule we never alter free variables :bp->vec bp->pos in here !
- * this will ruin adaptive stepsize AKA heun! (BM)
- */
- SoftBody *sb= ob->soft; /* is supposed to be there */
- /*BodyPoint *bproot;*/ /* UNUSED */
- /* float gravity; */ /* UNUSED */
- /* float iks; */
- float fieldfactor = -1.0f, windfactor = 0.25;
- int do_deflector /*, do_selfcollision*/, do_springcollision, do_aero;
-
- /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */
-
- /* check conditions for various options */
- do_deflector= query_external_colliders(depsgraph, sb->collision_group);
- /* do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); */ /* UNUSED */
- do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
- do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
-
- /* iks = 1.0f/(1.0f-sb->inspring)-1.0f; */ /* inner spring constants function */ /* UNUSED */
- /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */
-
- if (do_springcollision || do_aero)
- sb_sfesf_threads_run(depsgraph, scene, ob, timenow, sb->totspring, NULL);
-
- /* after spring scan because it uses Effoctors too */
- ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, sb->effector_weights);
-
- if (do_deflector) {
- float defforce[3];
- do_deflector = sb_detect_aabb_collisionCached(defforce, ob, timenow);
- }
-
- sb_cf_threads_run(scene, ob, forcetime, timenow, sb->totpoint, NULL, effectors, do_deflector, fieldfactor, windfactor);
-
- /* finally add forces caused by face collision */
- if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob, timenow);
-
- /* finish matrix and solve */
- BKE_effectors_free(effectors);
+ SB_thread_context *pctx = (SB_thread_context *)data;
+ _softbody_calc_forces_slice_in_a_thread(pctx->scene,
+ pctx->ob,
+ pctx->forcetime,
+ pctx->timenow,
+ pctx->ifirst,
+ pctx->ilast,
+ NULL,
+ pctx->effectors,
+ pctx->do_deflector,
+ pctx->fieldfactor,
+ pctx->windfactor);
+ return NULL;
+}
+
+static void sb_cf_threads_run(Scene *scene,
+ Object *ob,
+ float forcetime,
+ float timenow,
+ int totpoint,
+ int *UNUSED(ptr_to_break_func(void)),
+ struct ListBase *effectors,
+ int do_deflector,
+ float fieldfactor,
+ float windfactor)
+{
+ ListBase threads;
+ SB_thread_context *sb_threads;
+ int i, totthread, left, dec;
+ int lowpoints =
+ 100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
+
+ /* figure the number of threads while preventing pretty pointless threading overhead */
+ totthread = BKE_scene_num_threads(scene);
+ /* what if we got zillions of CPUs running but less to spread*/
+ while ((totpoint / totthread < lowpoints) && (totthread > 1)) {
+ totthread--;
+ }
+
+ /* printf("sb_cf_threads_run spawning %d threads\n", totthread); */
+
+ sb_threads = MEM_callocN(sizeof(SB_thread_context) * totthread, "SBThread");
+ memset(sb_threads, 0, sizeof(SB_thread_context) * totthread);
+ left = totpoint;
+ dec = totpoint / totthread + 1;
+ for (i = 0; i < totthread; i++) {
+ sb_threads[i].scene = scene;
+ sb_threads[i].ob = ob;
+ sb_threads[i].forcetime = forcetime;
+ sb_threads[i].timenow = timenow;
+ sb_threads[i].ilast = left;
+ left = left - dec;
+ if (left > 0) {
+ sb_threads[i].ifirst = left;
+ }
+ else
+ sb_threads[i].ifirst = 0;
+ sb_threads[i].effectors = effectors;
+ sb_threads[i].do_deflector = do_deflector;
+ sb_threads[i].fieldfactor = fieldfactor;
+ sb_threads[i].windfactor = windfactor;
+ sb_threads[i].nr = i;
+ sb_threads[i].tot = totthread;
+ }
+
+ if (totthread > 1) {
+ BLI_threadpool_init(&threads, exec_softbody_calc_forces, totthread);
+
+ for (i = 0; i < totthread; i++)
+ BLI_threadpool_insert(&threads, &sb_threads[i]);
+
+ BLI_threadpool_end(&threads);
+ }
+ else
+ exec_softbody_calc_forces(&sb_threads[0]);
+ /* clean up */
+ MEM_freeN(sb_threads);
+}
+
+static void softbody_calc_forces(
+ struct Depsgraph *depsgraph, Scene *scene, Object *ob, float forcetime, float timenow)
+{
+ /* rule we never alter free variables :bp->vec bp->pos in here !
+ * this will ruin adaptive stepsize AKA heun! (BM)
+ */
+ SoftBody *sb = ob->soft; /* is supposed to be there */
+ /*BodyPoint *bproot;*/ /* UNUSED */
+ /* float gravity; */ /* UNUSED */
+ /* float iks; */
+ float fieldfactor = -1.0f, windfactor = 0.25;
+ int do_deflector /*, do_selfcollision*/, do_springcollision, do_aero;
+
+ /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */
+
+ /* check conditions for various options */
+ do_deflector = query_external_colliders(depsgraph, sb->collision_group);
+ /* do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); */ /* UNUSED */
+ do_springcollision = do_deflector && (ob->softflag & OB_SB_EDGES) &&
+ (ob->softflag & OB_SB_EDGECOLL);
+ do_aero = ((sb->aeroedge) && (ob->softflag & OB_SB_EDGES));
+
+ /* iks = 1.0f/(1.0f-sb->inspring)-1.0f; */ /* inner spring constants function */ /* UNUSED */
+ /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */
+
+ if (do_springcollision || do_aero)
+ sb_sfesf_threads_run(depsgraph, scene, ob, timenow, sb->totspring, NULL);
+
+ /* after spring scan because it uses Effoctors too */
+ ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, sb->effector_weights);
+
+ if (do_deflector) {
+ float defforce[3];
+ do_deflector = sb_detect_aabb_collisionCached(defforce, ob, timenow);
+ }
+
+ sb_cf_threads_run(scene,
+ ob,
+ forcetime,
+ timenow,
+ sb->totpoint,
+ NULL,
+ effectors,
+ do_deflector,
+ fieldfactor,
+ windfactor);
+
+ /* finally add forces caused by face collision */
+ if (ob->softflag & OB_SB_FACECOLL)
+ scan_for_ext_face_forces(ob, timenow);
+
+ /* finish matrix and solve */
+ BKE_effectors_free(effectors);
}
static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err, int mid_flags)
{
- /* time evolution */
- /* actually does an explicit euler step mode == 0 */
- /* or heun ~ 2nd order runge-kutta steps, mode 1, 2 */
- SoftBody *sb= ob->soft; /* is supposed to be there */
- BodyPoint *bp;
- float dx[3] = {0}, dv[3], aabbmin[3], aabbmax[3], cm[3] = {0.0f, 0.0f, 0.0f};
- float timeovermass/*, freezeloc=0.00001f, freezeforce=0.00000000001f*/;
- float maxerrpos= 0.0f, maxerrvel = 0.0f;
- int a, fuzzy=0;
+ /* time evolution */
+ /* actually does an explicit euler step mode == 0 */
+ /* or heun ~ 2nd order runge-kutta steps, mode 1, 2 */
+ SoftBody *sb = ob->soft; /* is supposed to be there */
+ BodyPoint *bp;
+ float dx[3] = {0}, dv[3], aabbmin[3], aabbmax[3], cm[3] = {0.0f, 0.0f, 0.0f};
+ float timeovermass /*, freezeloc=0.00001f, freezeforce=0.00000000001f*/;
+ float maxerrpos = 0.0f, maxerrvel = 0.0f;
+ int a, fuzzy = 0;
- forcetime *= sb_time_scale(ob);
+ forcetime *= sb_time_scale(ob);
- aabbmin[0]=aabbmin[1]=aabbmin[2] = 1e20f;
- aabbmax[0]=aabbmax[1]=aabbmax[2] = -1e20f;
+ aabbmin[0] = aabbmin[1] = aabbmin[2] = 1e20f;
+ aabbmax[0] = aabbmax[1] = aabbmax[2] = -1e20f;
- /* old one with homogeneous masses */
- /* claim a minimum mass for vertex */
+ /* old one with homogeneous masses */
+ /* claim a minimum mass for vertex */
#if 0
- if (sb->nodemass > 0.009999f) timeovermass = forcetime / sb->nodemass;
- else timeovermass = forcetime / 0.009999f;
+ if (sb->nodemass > 0.009999f) timeovermass = forcetime / sb->nodemass;
+ else timeovermass = forcetime / 0.009999f;
#endif
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
-/* now we have individual masses */
-/* claim a minimum mass for vertex */
- if (_final_mass(ob, bp) > 0.009999f) timeovermass = forcetime/_final_mass(ob, bp);
- else timeovermass = forcetime/0.009999f;
-
-
- if (_final_goal(ob, bp) < SOFTGOALSNAP) {
- /* this makes t~ = t */
- if (mid_flags & MID_PRESERVE) copy_v3_v3(dx, bp->vec);
-
- /* so here is (v)' = a(cceleration) = sum(F_springs)/m + gravitation + some friction forces + more forces*/
- /* the ( ... )' operator denotes derivate respective time */
- /* the euler step for velocity then becomes */
- /* v(t + dt) = v(t) + a(t) * dt */
- mul_v3_fl(bp->force, timeovermass);/* individual mass of node here */
- /* some nasty if's to have heun in here too */
- copy_v3_v3(dv, bp->force);
-
- if (mode == 1) {
- copy_v3_v3(bp->prevvec, bp->vec);
- copy_v3_v3(bp->prevdv, dv);
- }
-
- if (mode ==2) {
- /* be optimistic and execute step */
- bp->vec[0] = bp->prevvec[0] + 0.5f * (dv[0] + bp->prevdv[0]);
- bp->vec[1] = bp->prevvec[1] + 0.5f * (dv[1] + bp->prevdv[1]);
- bp->vec[2] = bp->prevvec[2] + 0.5f * (dv[2] + bp->prevdv[2]);
- /* compare euler to heun to estimate error for step sizing */
- maxerrvel = max_ff(maxerrvel, fabsf(dv[0] - bp->prevdv[0]));
- maxerrvel = max_ff(maxerrvel, fabsf(dv[1] - bp->prevdv[1]));
- maxerrvel = max_ff(maxerrvel, fabsf(dv[2] - bp->prevdv[2]));
- }
- else { add_v3_v3(bp->vec, bp->force); }
-
- /* this makes t~ = t+dt */
- if (!(mid_flags & MID_PRESERVE)) copy_v3_v3(dx, bp->vec);
-
- /* so here is (x)'= v(elocity) */
- /* the euler step for location then becomes */
- /* x(t + dt) = x(t) + v(t~) * dt */
- mul_v3_fl(dx, forcetime);
-
- /* the freezer coming sooner or later */
+ for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
+ /* now we have individual masses */
+ /* claim a minimum mass for vertex */
+ if (_final_mass(ob, bp) > 0.009999f)
+ timeovermass = forcetime / _final_mass(ob, bp);
+ else
+ timeovermass = forcetime / 0.009999f;
+
+ if (_final_goal(ob, bp) < SOFTGOALSNAP) {
+ /* this makes t~ = t */
+ if (mid_flags & MID_PRESERVE)
+ copy_v3_v3(dx, bp->vec);
+
+ /* so here is (v)' = a(cceleration) = sum(F_springs)/m + gravitation + some friction forces + more forces*/
+ /* the ( ... )' operator denotes derivate respective time */
+ /* the euler step for velocity then becomes */
+ /* v(t + dt) = v(t) + a(t) * dt */
+ mul_v3_fl(bp->force, timeovermass); /* individual mass of node here */
+ /* some nasty if's to have heun in here too */
+ copy_v3_v3(dv, bp->force);
+
+ if (mode == 1) {
+ copy_v3_v3(bp->prevvec, bp->vec);
+ copy_v3_v3(bp->prevdv, dv);
+ }
+
+ if (mode == 2) {
+ /* be optimistic and execute step */
+ bp->vec[0] = bp->prevvec[0] + 0.5f * (dv[0] + bp->prevdv[0]);
+ bp->vec[1] = bp->prevvec[1] + 0.5f * (dv[1] + bp->prevdv[1]);
+ bp->vec[2] = bp->prevvec[2] + 0.5f * (dv[2] + bp->prevdv[2]);
+ /* compare euler to heun to estimate error for step sizing */
+ maxerrvel = max_ff(maxerrvel, fabsf(dv[0] - bp->prevdv[0]));
+ maxerrvel = max_ff(maxerrvel, fabsf(dv[1] - bp->prevdv[1]));
+ maxerrvel = max_ff(maxerrvel, fabsf(dv[2] - bp->prevdv[2]));
+ }
+ else {
+ add_v3_v3(bp->vec, bp->force);
+ }
+
+ /* this makes t~ = t+dt */
+ if (!(mid_flags & MID_PRESERVE))
+ copy_v3_v3(dx, bp->vec);
+
+ /* so here is (x)'= v(elocity) */
+ /* the euler step for location then becomes */
+ /* x(t + dt) = x(t) + v(t~) * dt */
+ mul_v3_fl(dx, forcetime);
+
+ /* the freezer coming sooner or later */
#if 0
- if ((dot_v3v3(dx, dx)<freezeloc )&&(dot_v3v3(bp->force, bp->force)<freezeforce )) {
- bp->frozen /=2;
- }
- else {
- bp->frozen = min_ff(bp->frozen*1.05f, 1.0f);
- }
- mul_v3_fl(dx, bp->frozen);
+ if ((dot_v3v3(dx, dx)<freezeloc )&&(dot_v3v3(bp->force, bp->force)<freezeforce )) {
+ bp->frozen /=2;
+ }
+ else {
+ bp->frozen = min_ff(bp->frozen*1.05f, 1.0f);
+ }
+ mul_v3_fl(dx, bp->frozen);
#endif
- /* again some nasty if's to have heun in here too */
- if (mode ==1) {
- copy_v3_v3(bp->prevpos, bp->pos);
- copy_v3_v3(bp->prevdx, dx);
- }
-
- if (mode ==2) {
- bp->pos[0] = bp->prevpos[0] + 0.5f * ( dx[0] + bp->prevdx[0]);
- bp->pos[1] = bp->prevpos[1] + 0.5f * ( dx[1] + bp->prevdx[1]);
- bp->pos[2] = bp->prevpos[2] + 0.5f * ( dx[2] + bp->prevdx[2]);
- maxerrpos = max_ff(maxerrpos, fabsf(dx[0] - bp->prevdx[0]));
- maxerrpos = max_ff(maxerrpos, fabsf(dx[1] - bp->prevdx[1]));
- maxerrpos = max_ff(maxerrpos, fabsf(dx[2] - bp->prevdx[2]));
-
- /* bp->choke is set when we need to pull a vertex or edge out of the collider.
- * the collider object signals to get out by pushing hard. on the other hand
- * we don't want to end up in deep space so we add some <viscosity>
- * to balance that out */
- if (bp->choke2 > 0.0f) {
- mul_v3_fl(bp->vec, (1.0f - bp->choke2));
- }
- if (bp->choke > 0.0f) {
- mul_v3_fl(bp->vec, (1.0f - bp->choke));
- }
-
- }
- else {
- add_v3_v3(bp->pos, dx);
- }
- }/*snap*/
- /* so while we are looping BPs anyway do statistics on the fly */
- minmax_v3v3_v3(aabbmin, aabbmax, bp->pos);
- if (bp->loc_flag & SBF_DOFUZZY) fuzzy =1;
- } /*for*/
-
- if (sb->totpoint) mul_v3_fl(cm, 1.0f/sb->totpoint);
- if (sb->scratch) {
- copy_v3_v3(sb->scratch->aabbmin, aabbmin);
- copy_v3_v3(sb->scratch->aabbmax, aabbmax);
- }
-
- if (err) { /* so step size will be controlled by biggest difference in slope */
- if (sb->solverflags & SBSO_OLDERR)
- *err = max_ff(maxerrpos, maxerrvel);
- else
- *err = maxerrpos;
- //printf("EP %f EV %f\n", maxerrpos, maxerrvel);
- if (fuzzy) {
- *err /= sb->fuzzyness;
- }
- }
+ /* again some nasty if's to have heun in here too */
+ if (mode == 1) {
+ copy_v3_v3(bp->prevpos, bp->pos);
+ copy_v3_v3(bp->prevdx, dx);
+ }
+
+ if (mode == 2) {
+ bp->pos[0] = bp->prevpos[0] + 0.5f * (dx[0] + bp->prevdx[0]);
+ bp->pos[1] = bp->prevpos[1] + 0.5f * (dx[1] + bp->prevdx[1]);
+ bp->pos[2] = bp->prevpos[2] + 0.5f * (dx[2] + bp->prevdx[2]);
+ maxerrpos = max_ff(maxerrpos, fabsf(dx[0] - bp->prevdx[0]));
+ maxerrpos = max_ff(maxerrpos, fabsf(dx[1] - bp->prevdx[1]));
+ maxerrpos = max_ff(maxerrpos, fabsf(dx[2] - bp->prevdx[2]));
+
+ /* bp->choke is set when we need to pull a vertex or edge out of the collider.
+ * the collider object signals to get out by pushing hard. on the other hand
+ * we don't want to end up in deep space so we add some <viscosity>
+ * to balance that out */
+ if (bp->choke2 > 0.0f) {
+ mul_v3_fl(bp->vec, (1.0f - bp->choke2));
+ }
+ if (bp->choke > 0.0f) {
+ mul_v3_fl(bp->vec, (1.0f - bp->choke));
+ }
+ }
+ else {
+ add_v3_v3(bp->pos, dx);
+ }
+ } /*snap*/
+ /* so while we are looping BPs anyway do statistics on the fly */
+ minmax_v3v3_v3(aabbmin, aabbmax, bp->pos);
+ if (bp->loc_flag & SBF_DOFUZZY)
+ fuzzy = 1;
+ } /*for*/
+
+ if (sb->totpoint)
+ mul_v3_fl(cm, 1.0f / sb->totpoint);
+ if (sb->scratch) {
+ copy_v3_v3(sb->scratch->aabbmin, aabbmin);
+ copy_v3_v3(sb->scratch->aabbmax, aabbmax);
+ }
+
+ if (err) { /* so step size will be controlled by biggest difference in slope */
+ if (sb->solverflags & SBSO_OLDERR)
+ *err = max_ff(maxerrpos, maxerrvel);
+ else
+ *err = maxerrpos;
+ //printf("EP %f EV %f\n", maxerrpos, maxerrvel);
+ if (fuzzy) {
+ *err /= sb->fuzzyness;
+ }
+ }
}
/* used by heun when it overshoots */
static void softbody_restore_prev_step(Object *ob)
{
- SoftBody *sb= ob->soft; /* is supposed to be there*/
- BodyPoint *bp;
- int a;
+ SoftBody *sb = ob->soft; /* is supposed to be there*/
+ BodyPoint *bp;
+ int a;
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- copy_v3_v3(bp->vec, bp->prevvec);
- copy_v3_v3(bp->pos, bp->prevpos);
- }
+ for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
+ copy_v3_v3(bp->vec, bp->prevvec);
+ copy_v3_v3(bp->pos, bp->prevpos);
+ }
}
#if 0
static void softbody_store_step(Object *ob)
{
- SoftBody *sb= ob->soft; /* is supposed to be there*/
- BodyPoint *bp;
- int a;
+ SoftBody *sb= ob->soft; /* is supposed to be there*/
+ BodyPoint *bp;
+ int a;
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- copy_v3_v3(bp->prevvec, bp->vec);
- copy_v3_v3(bp->prevpos, bp->pos);
- }
+ for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
+ copy_v3_v3(bp->prevvec, bp->vec);
+ copy_v3_v3(bp->prevpos, bp->pos);
+ }
}
/* used by predictors and correctors */
static void softbody_store_state(Object *ob, float *ppos, float *pvel)
{
- SoftBody *sb= ob->soft; /* is supposed to be there*/
- BodyPoint *bp;
- int a;
- float *pp=ppos, *pv=pvel;
+ SoftBody *sb= ob->soft; /* is supposed to be there*/
+ BodyPoint *bp;
+ int a;
+ float *pp=ppos, *pv=pvel;
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
+ for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- copy_v3_v3(pv, bp->vec);
- pv+=3;
+ copy_v3_v3(pv, bp->vec);
+ pv+=3;
- copy_v3_v3(pp, bp->pos);
- pp+=3;
- }
+ copy_v3_v3(pp, bp->pos);
+ pp+=3;
+ }
}
/* used by predictors and correctors */
static void softbody_retrieve_state(Object *ob, float *ppos, float *pvel)
{
- SoftBody *sb= ob->soft; /* is supposed to be there*/
- BodyPoint *bp;
- int a;
- float *pp=ppos, *pv=pvel;
+ SoftBody *sb= ob->soft; /* is supposed to be there*/
+ BodyPoint *bp;
+ int a;
+ float *pp=ppos, *pv=pvel;
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
+ for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- copy_v3_v3(bp->vec, pv);
- pv+=3;
+ copy_v3_v3(bp->vec, pv);
+ pv+=3;
- copy_v3_v3(bp->pos, pp);
- pp+=3;
- }
+ copy_v3_v3(bp->pos, pp);
+ pp+=3;
+ }
}
/* used by predictors and correctors */
static void softbody_swap_state(Object *ob, float *ppos, float *pvel)
{
- SoftBody *sb= ob->soft; /* is supposed to be there*/
- BodyPoint *bp;
- int a;
- float *pp=ppos, *pv=pvel;
- float temp[3];
+ SoftBody *sb= ob->soft; /* is supposed to be there*/
+ BodyPoint *bp;
+ int a;
+ float *pp=ppos, *pv=pvel;
+ float temp[3];
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
+ for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- copy_v3_v3(temp, bp->vec);
- copy_v3_v3(bp->vec, pv);
- copy_v3_v3(pv, temp);
- pv+=3;
+ copy_v3_v3(temp, bp->vec);
+ copy_v3_v3(bp->vec, pv);
+ copy_v3_v3(pv, temp);
+ pv+=3;
- copy_v3_v3(temp, bp->pos);
- copy_v3_v3(bp->pos, pp);
- copy_v3_v3(pp, temp);
- pp+=3;
- }
+ copy_v3_v3(temp, bp->pos);
+ copy_v3_v3(bp->pos, pp);
+ copy_v3_v3(pp, temp);
+ pp+=3;
+ }
}
#endif
-
/* care for bodypoints taken out of the 'ordinary' solver step
* because they are screwed to goal by bolts
* they just need to move along with the goal in time
@@ -2445,66 +2496,63 @@ static void softbody_swap_state(Object *ob, float *ppos, float *pvel)
*/
static void softbody_apply_goalsnap(Object *ob)
{
- SoftBody *sb= ob->soft; /* is supposed to be there */
- BodyPoint *bp;
- int a;
+ SoftBody *sb = ob->soft; /* is supposed to be there */
+ BodyPoint *bp;
+ int a;
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- if (_final_goal(ob, bp) >= SOFTGOALSNAP) {
- copy_v3_v3(bp->prevpos, bp->pos);
- copy_v3_v3(bp->pos, bp->origT);
- }
- }
+ for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
+ if (_final_goal(ob, bp) >= SOFTGOALSNAP) {
+ copy_v3_v3(bp->prevpos, bp->pos);
+ copy_v3_v3(bp->pos, bp->origT);
+ }
+ }
}
-
static void apply_spring_memory(Object *ob)
{
- SoftBody *sb = ob->soft;
- BodySpring *bs;
- BodyPoint *bp1, *bp2;
- int a;
- float b, l, r;
-
- if (sb && sb->totspring) {
- b = sb->plastic;
- for (a=0; a<sb->totspring; a++) {
- bs = &sb->bspring[a];
- bp1 =&sb->bpoint[bs->v1];
- bp2 =&sb->bpoint[bs->v2];
- l = len_v3v3(bp1->pos, bp2->pos);
- r = bs->len/l;
- if (( r > 1.05f) || (r < 0.95f)) {
- bs->len = ((100.0f - b) * bs->len + b*l)/100.0f;
- }
- }
- }
+ SoftBody *sb = ob->soft;
+ BodySpring *bs;
+ BodyPoint *bp1, *bp2;
+ int a;
+ float b, l, r;
+
+ if (sb && sb->totspring) {
+ b = sb->plastic;
+ for (a = 0; a < sb->totspring; a++) {
+ bs = &sb->bspring[a];
+ bp1 = &sb->bpoint[bs->v1];
+ bp2 = &sb->bpoint[bs->v2];
+ l = len_v3v3(bp1->pos, bp2->pos);
+ r = bs->len / l;
+ if ((r > 1.05f) || (r < 0.95f)) {
+ bs->len = ((100.0f - b) * bs->len + b * l) / 100.0f;
+ }
+ }
+ }
}
/* expects full initialized softbody */
static void interpolate_exciter(Object *ob, int timescale, int time)
{
- SoftBody *sb= ob->soft;
- BodyPoint *bp;
- float f;
- int a;
-
- f = (float)time/(float)timescale;
+ SoftBody *sb = ob->soft;
+ BodyPoint *bp;
+ float f;
+ int a;
- for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
- bp->origT[0] = bp->origS[0] + f*(bp->origE[0] - bp->origS[0]);
- bp->origT[1] = bp->origS[1] + f*(bp->origE[1] - bp->origS[1]);
- bp->origT[2] = bp->origS[2] + f*(bp->origE[2] - bp->origS[2]);
- if (_final_goal(ob, bp) >= SOFTGOALSNAP) {
- bp->vec[0] = bp->origE[0] - bp->origS[0];
- bp->vec[1] = bp->origE[1] - bp->origS[1];
- bp->vec[2] = bp->origE[2] - bp->origS[2];
- }
- }
+ f = (float)time / (float)timescale;
+ for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
+ bp->origT[0] = bp->origS[0] + f * (bp->origE[0] - bp->origS[0]);
+ bp->origT[1] = bp->origS[1] + f * (bp->origE[1] - bp->origS[1]);
+ bp->origT[2] = bp->origS[2] + f * (bp->origE[2] - bp->origS[2]);
+ if (_final_goal(ob, bp) >= SOFTGOALSNAP) {
+ bp->vec[0] = bp->origE[0] - bp->origS[0];
+ bp->vec[1] = bp->origE[1] - bp->origS[1];
+ bp->vec[2] = bp->origE[2] - bp->origS[2];
+ }
+ }
}
-
/* ************ convertors ********** */
/* for each object type we need;
@@ -2515,174 +2563,168 @@ static void interpolate_exciter(Object *ob, int timescale, int time)
/* Spring length are caculted from'raw' mesh vertices that are NOT altered by modifier stack. */
static void springs_from_mesh(Object *ob)
{
- SoftBody *sb;
- Mesh *me= ob->data;
- BodyPoint *bp;
- int a;
- float scale =1.0f;
-
- sb= ob->soft;
- if (me && sb) {
- /* using bp->origS as a container for spring calculations here
- * will be overwritten sbObjectStep() to receive
- * actual modifier stack positions
- */
- if (me->totvert) {
- bp= ob->soft->bpoint;
- for (a=0; a<me->totvert; a++, bp++) {
- copy_v3_v3(bp->origS, me->mvert[a].co);
- mul_m4_v3(ob->obmat, bp->origS);
- }
-
- }
- /* recalculate spring length for meshes here */
- /* public version shrink to fit */
- if (sb->springpreload != 0 ) {
- scale = sb->springpreload / 100.0f;
- }
- for (a=0; a<sb->totspring; a++) {
- BodySpring *bs = &sb->bspring[a];
- bs->len= scale*len_v3v3(sb->bpoint[bs->v1].origS, sb->bpoint[bs->v2].origS);
- }
- }
+ SoftBody *sb;
+ Mesh *me = ob->data;
+ BodyPoint *bp;
+ int a;
+ float scale = 1.0f;
+
+ sb = ob->soft;
+ if (me && sb) {
+ /* using bp->origS as a container for spring calculations here
+ * will be overwritten sbObjectStep() to receive
+ * actual modifier stack positions
+ */
+ if (me->totvert) {
+ bp = ob->soft->bpoint;
+ for (a = 0; a < me->totvert; a++, bp++) {
+ copy_v3_v3(bp->origS, me->mvert[a].co);
+ mul_m4_v3(ob->obmat, bp->origS);
+ }
+ }
+ /* recalculate spring length for meshes here */
+ /* public version shrink to fit */
+ if (sb->springpreload != 0) {
+ scale = sb->springpreload / 100.0f;
+ }
+ for (a = 0; a < sb->totspring; a++) {
+ BodySpring *bs = &sb->bspring[a];
+ bs->len = scale * len_v3v3(sb->bpoint[bs->v1].origS, sb->bpoint[bs->v2].origS);
+ }
+ }
}
-
-
-
/* makes totally fresh start situation */
static void mesh_to_softbody(Scene *scene, Object *ob)
{
- SoftBody *sb;
- Mesh *me= ob->data;
- MEdge *medge= me->medge;
- BodyPoint *bp;
- BodySpring *bs;
- int a, totedge;
- int defgroup_index, defgroup_index_mass, defgroup_index_spring;
-
- if (ob->softflag & OB_SB_EDGES) totedge= me->totedge;
- else totedge= 0;
-
- /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
- renew_softbody(scene, ob, me->totvert, totedge);
-
- /* we always make body points */
- sb = ob->soft;
- bp= sb->bpoint;
-
- defgroup_index = me->dvert ? (sb->vertgroup - 1) : -1;
- defgroup_index_mass = me->dvert ? defgroup_name_index(ob, sb->namedVG_Mass) : -1;
- defgroup_index_spring = me->dvert ? defgroup_name_index(ob, sb->namedVG_Spring_K) : -1;
-
- for (a=0; a<me->totvert; a++, bp++) {
- /* get scalar values needed *per vertex* from vertex group functions,
- * so we can *paint* them nicly ..
- * they are normalized [0.0..1.0] so may be we need amplitude for scale
- * which can be done by caller but still .. i'd like it to go this way
- */
-
- if (ob->softflag & OB_SB_GOAL) {
- BLI_assert(bp->goal == sb->defgoal);
- }
- if ((ob->softflag & OB_SB_GOAL) && (defgroup_index != -1)) {
- bp->goal *= defvert_find_weight(&me->dvert[a], defgroup_index);
- }
-
- /* to proof the concept
- * this enables per vertex *mass painting*
- */
-
- if (defgroup_index_mass != -1) {
- bp->mass *= defvert_find_weight(&me->dvert[a], defgroup_index_mass);
- }
-
- if (defgroup_index_spring != -1) {
- bp->springweight *= defvert_find_weight(&me->dvert[a], defgroup_index_spring);
- }
- }
-
- /* but we only optionally add body edge springs */
- if (ob->softflag & OB_SB_EDGES) {
- if (medge) {
- bs= sb->bspring;
- for (a=me->totedge; a>0; a--, medge++, bs++) {
- bs->v1= medge->v1;
- bs->v2= medge->v2;
- bs->springtype=SB_EDGE;
- }
-
-
- /* insert *diagonal* springs in quads if desired */
- if (ob->softflag & OB_SB_QUADS) {
- add_mesh_quad_diag_springs(ob);
- }
-
- build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */
- /* insert *other second order* springs if desired */
- if (sb->secondspring > 0.0000001f) {
- add_2nd_order_springs(ob, sb->secondspring); /* exploits the first run of build_bps_springlist(ob);*/
- build_bps_springlist(ob); /* yes we need to do it again*/
- }
- springs_from_mesh(ob); /* write the 'rest'-length of the springs */
- if (ob->softflag & OB_SB_SELF) { calculate_collision_balls(ob); }
-
- }
-
- }
-
+ SoftBody *sb;
+ Mesh *me = ob->data;
+ MEdge *medge = me->medge;
+ BodyPoint *bp;
+ BodySpring *bs;
+ int a, totedge;
+ int defgroup_index, defgroup_index_mass, defgroup_index_spring;
+
+ if (ob->softflag & OB_SB_EDGES)
+ totedge = me->totedge;
+ else
+ totedge = 0;
+
+ /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
+ renew_softbody(scene, ob, me->totvert, totedge);
+
+ /* we always make body points */
+ sb = ob->soft;
+ bp = sb->bpoint;
+
+ defgroup_index = me->dvert ? (sb->vertgroup - 1) : -1;
+ defgroup_index_mass = me->dvert ? defgroup_name_index(ob, sb->namedVG_Mass) : -1;
+ defgroup_index_spring = me->dvert ? defgroup_name_index(ob, sb->namedVG_Spring_K) : -1;
+
+ for (a = 0; a < me->totvert; a++, bp++) {
+ /* get scalar values needed *per vertex* from vertex group functions,
+ * so we can *paint* them nicly ..
+ * they are normalized [0.0..1.0] so may be we need amplitude for scale
+ * which can be done by caller but still .. i'd like it to go this way
+ */
+
+ if (ob->softflag & OB_SB_GOAL) {
+ BLI_assert(bp->goal == sb->defgoal);
+ }
+ if ((ob->softflag & OB_SB_GOAL) && (defgroup_index != -1)) {
+ bp->goal *= defvert_find_weight(&me->dvert[a], defgroup_index);
+ }
+
+ /* to proof the concept
+ * this enables per vertex *mass painting*
+ */
+
+ if (defgroup_index_mass != -1) {
+ bp->mass *= defvert_find_weight(&me->dvert[a], defgroup_index_mass);
+ }
+
+ if (defgroup_index_spring != -1) {
+ bp->springweight *= defvert_find_weight(&me->dvert[a], defgroup_index_spring);
+ }
+ }
+
+ /* but we only optionally add body edge springs */
+ if (ob->softflag & OB_SB_EDGES) {
+ if (medge) {
+ bs = sb->bspring;
+ for (a = me->totedge; a > 0; a--, medge++, bs++) {
+ bs->v1 = medge->v1;
+ bs->v2 = medge->v2;
+ bs->springtype = SB_EDGE;
+ }
+
+ /* insert *diagonal* springs in quads if desired */
+ if (ob->softflag & OB_SB_QUADS) {
+ add_mesh_quad_diag_springs(ob);
+ }
+
+ build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */
+ /* insert *other second order* springs if desired */
+ if (sb->secondspring > 0.0000001f) {
+ add_2nd_order_springs(
+ ob, sb->secondspring); /* exploits the first run of build_bps_springlist(ob);*/
+ build_bps_springlist(ob); /* yes we need to do it again*/
+ }
+ springs_from_mesh(ob); /* write the 'rest'-length of the springs */
+ if (ob->softflag & OB_SB_SELF) {
+ calculate_collision_balls(ob);
+ }
+ }
+ }
}
static void mesh_faces_to_scratch(Object *ob)
{
- SoftBody *sb= ob->soft;
- const Mesh *me = ob->data;
- MLoopTri *looptri, *lt;
- BodyFace *bodyface;
- int a;
- /* alloc and copy faces*/
-
- sb->scratch->totface = poly_to_tri_count(me->totpoly, me->totloop);
- looptri = lt = MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__);
- BKE_mesh_recalc_looptri(
- me->mloop, me->mpoly,
- me->mvert,
- me->totloop, me->totpoly,
- looptri);
-
- bodyface = sb->scratch->bodyface = MEM_mallocN(sizeof(BodyFace) * sb->scratch->totface, "SB_body_Faces");
-
- for (a = 0; a < sb->scratch->totface; a++, lt++, bodyface++) {
- bodyface->v1 = me->mloop[lt->tri[0]].v;
- bodyface->v2 = me->mloop[lt->tri[1]].v;
- bodyface->v3 = me->mloop[lt->tri[2]].v;
- zero_v3(bodyface->ext_force);
- bodyface->ext_force[0] = bodyface->ext_force[1] = bodyface->ext_force[2] = 0.0f;
- bodyface->flag = 0;
- }
-
- MEM_freeN(looptri);
+ SoftBody *sb = ob->soft;
+ const Mesh *me = ob->data;
+ MLoopTri *looptri, *lt;
+ BodyFace *bodyface;
+ int a;
+ /* alloc and copy faces*/
+
+ sb->scratch->totface = poly_to_tri_count(me->totpoly, me->totloop);
+ looptri = lt = MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__);
+ BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
+
+ bodyface = sb->scratch->bodyface = MEM_mallocN(sizeof(BodyFace) * sb->scratch->totface,
+ "SB_body_Faces");
+
+ for (a = 0; a < sb->scratch->totface; a++, lt++, bodyface++) {
+ bodyface->v1 = me->mloop[lt->tri[0]].v;
+ bodyface->v2 = me->mloop[lt->tri[1]].v;
+ bodyface->v3 = me->mloop[lt->tri[2]].v;
+ zero_v3(bodyface->ext_force);
+ bodyface->ext_force[0] = bodyface->ext_force[1] = bodyface->ext_force[2] = 0.0f;
+ bodyface->flag = 0;
+ }
+
+ MEM_freeN(looptri);
}
static void reference_to_scratch(Object *ob)
{
- SoftBody *sb= ob->soft;
- ReferenceVert *rp;
- BodyPoint *bp;
- float accu_pos[3] ={0.f, 0.f, 0.f};
- float accu_mass = 0.f;
- int a;
-
- sb->scratch->Ref.ivert = MEM_mallocN(sizeof(ReferenceVert)*sb->totpoint, "SB_Reference");
- bp= ob->soft->bpoint;
- rp= sb->scratch->Ref.ivert;
- for (a=0; a<sb->totpoint; a++, rp++, bp++) {
- copy_v3_v3(rp->pos, bp->pos);
- add_v3_v3(accu_pos, bp->pos);
- accu_mass += _final_mass(ob, bp);
- }
- mul_v3_fl(accu_pos, 1.0f/accu_mass);
- copy_v3_v3(sb->scratch->Ref.com, accu_pos);
- /* printf("reference_to_scratch\n"); */
+ SoftBody *sb = ob->soft;
+ ReferenceVert *rp;
+ BodyPoint *bp;
+ float accu_pos[3] = {0.f, 0.f, 0.f};
+ float accu_mass = 0.f;
+ int a;
+
+ sb->scratch->Ref.ivert = MEM_mallocN(sizeof(ReferenceVert) * sb->totpoint, "SB_Reference");
+ bp = ob->soft->bpoint;
+ rp = sb->scratch->Ref.ivert;
+ for (a = 0; a < sb->totpoint; a++, rp++, bp++) {
+ copy_v3_v3(rp->pos, bp->pos);
+ add_v3_v3(accu_pos, bp->pos);
+ accu_mass += _final_mass(ob, bp);
+ }
+ mul_v3_fl(accu_pos, 1.0f / accu_mass);
+ copy_v3_v3(sb->scratch->Ref.com, accu_pos);
+ /* printf("reference_to_scratch\n"); */
}
/*
@@ -2691,284 +2733,284 @@ static void reference_to_scratch(Object *ob)
*/
static float globallen(float *v1, float *v2, Object *ob)
{
- float p1[3], p2[3];
- copy_v3_v3(p1, v1);
- mul_m4_v3(ob->obmat, p1);
- copy_v3_v3(p2, v2);
- mul_m4_v3(ob->obmat, p2);
- return len_v3v3(p1, p2);
-}
-
-static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff, Object *ob)
-{
- BPoint *bp=lt->def, *bpu;
- int u, v, w, dv, dw, bpc=0, bpuc;
-
- dv= lt->pntsu;
- dw= dv*lt->pntsv;
-
- for (w=0; w<lt->pntsw; w++) {
-
- for (v=0; v<lt->pntsv; v++) {
-
- for (u=0, bpuc=0, bpu=NULL; u<lt->pntsu; u++, bp++, bpc++) {
-
- if (w) {
- bs->v1 = bpc;
- bs->v2 = bpc-dw;
- bs->springtype=SB_EDGE;
- bs->len= globallen((bp-dw)->vec, bp->vec, ob);
- bs++;
- }
- if (v) {
- bs->v1 = bpc;
- bs->v2 = bpc-dv;
- bs->springtype=SB_EDGE;
- bs->len= globallen((bp-dv)->vec, bp->vec, ob);
- bs++;
- }
- if (u) {
- bs->v1 = bpuc;
- bs->v2 = bpc;
- bs->springtype=SB_EDGE;
- bs->len= globallen((bpu)->vec, bp->vec, ob);
- bs++;
- }
-
- if (dostiff) {
-
- if (w) {
- if ( v && u ) {
- bs->v1 = bpc;
- bs->v2 = bpc-dw-dv-1;
- bs->springtype=SB_BEND;
- bs->len= globallen((bp-dw-dv-1)->vec, bp->vec, ob);
- bs++;
- }
- if ( (v < lt->pntsv-1) && (u != 0) ) {
- bs->v1 = bpc;
- bs->v2 = bpc-dw+dv-1;
- bs->springtype=SB_BEND;
- bs->len= globallen((bp-dw+dv-1)->vec, bp->vec, ob);
- bs++;
- }
- }
-
- if (w < lt->pntsw -1) {
- if ( v && u ) {
- bs->v1 = bpc;
- bs->v2 = bpc+dw-dv-1;
- bs->springtype=SB_BEND;
- bs->len= globallen((bp+dw-dv-1)->vec, bp->vec, ob);
- bs++;
- }
- if ( (v < lt->pntsv-1) && (u != 0) ) {
- bs->v1 = bpc;
- bs->v2 = bpc+dw+dv-1;
- bs->springtype=SB_BEND;
- bs->len= globallen((bp+dw+dv-1)->vec, bp->vec, ob);
- bs++;
- }
- }
- }
- bpu = bp;
- bpuc = bpc;
- }
- }
- }
+ float p1[3], p2[3];
+ copy_v3_v3(p1, v1);
+ mul_m4_v3(ob->obmat, p1);
+ copy_v3_v3(p2, v2);
+ mul_m4_v3(ob->obmat, p2);
+ return len_v3v3(p1, p2);
+}
+
+static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff, Object *ob)
+{
+ BPoint *bp = lt->def, *bpu;
+ int u, v, w, dv, dw, bpc = 0, bpuc;
+
+ dv = lt->pntsu;
+ dw = dv * lt->pntsv;
+
+ for (w = 0; w < lt->pntsw; w++) {
+
+ for (v = 0; v < lt->pntsv; v++) {
+
+ for (u = 0, bpuc = 0, bpu = NULL; u < lt->pntsu; u++, bp++, bpc++) {
+
+ if (w) {
+ bs->v1 = bpc;
+ bs->v2 = bpc - dw;
+ bs->springtype = SB_EDGE;
+ bs->len = globallen((bp - dw)->vec, bp->vec, ob);
+ bs++;
+ }
+ if (v) {
+ bs->v1 = bpc;
+ bs->v2 = bpc - dv;
+ bs->springtype = SB_EDGE;
+ bs->len = globallen((bp - dv)->vec, bp->vec, ob);
+ bs++;
+ }
+ if (u) {
+ bs->v1 = bpuc;
+ bs->v2 = bpc;
+ bs->springtype = SB_EDGE;
+ bs->len = globallen((bpu)->vec, bp->vec, ob);
+ bs++;
+ }
+
+ if (dostiff) {
+
+ if (w) {
+ if (v && u) {
+ bs->v1 = bpc;
+ bs->v2 = bpc - dw - dv - 1;
+ bs->springtype = SB_BEND;
+ bs->len = globallen((bp - dw - dv - 1)->vec, bp->vec, ob);
+ bs++;
+ }
+ if ((v < lt->pntsv - 1) && (u != 0)) {
+ bs->v1 = bpc;
+ bs->v2 = bpc - dw + dv - 1;
+ bs->springtype = SB_BEND;
+ bs->len = globallen((bp - dw + dv - 1)->vec, bp->vec, ob);
+ bs++;
+ }
+ }
+
+ if (w < lt->pntsw - 1) {
+ if (v && u) {
+ bs->v1 = bpc;
+ bs->v2 = bpc + dw - dv - 1;
+ bs->springtype = SB_BEND;
+ bs->len = globallen((bp + dw - dv - 1)->vec, bp->vec, ob);
+ bs++;
+ }
+ if ((v < lt->pntsv - 1) && (u != 0)) {
+ bs->v1 = bpc;
+ bs->v2 = bpc + dw + dv - 1;
+ bs->springtype = SB_BEND;
+ bs->len = globallen((bp + dw + dv - 1)->vec, bp->vec, ob);
+ bs++;
+ }
+ }
+ }
+ bpu = bp;
+ bpuc = bpc;
+ }
+ }
+ }
}
-
/* makes totally fresh start situation */
static void lattice_to_softbody(Scene *scene, Object *ob)
{
- Lattice *lt= ob->data;
- SoftBody *sb;
- int totvert, totspring = 0, a;
- BodyPoint *bp;
- BPoint *bpnt = lt->def;
- int defgroup_index, defgroup_index_mass, defgroup_index_spring;
-
- totvert= lt->pntsu*lt->pntsv*lt->pntsw;
-
- if (ob->softflag & OB_SB_EDGES) {
- totspring = ((lt->pntsu - 1) * lt->pntsv +
- (lt->pntsv - 1) * lt->pntsu) * lt->pntsw +
- lt->pntsu*lt->pntsv * (lt->pntsw - 1);
- if (ob->softflag & OB_SB_QUADS) {
- totspring += 4 * (lt->pntsu - 1) * (lt->pntsv -1) * (lt->pntsw - 1);
- }
- }
-
-
- /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
- renew_softbody(scene, ob, totvert, totspring);
- sb= ob->soft; /* can be created in renew_softbody() */
- bp = sb->bpoint;
-
- defgroup_index = lt->dvert ? (sb->vertgroup - 1) : -1;
- defgroup_index_mass = lt->dvert ? defgroup_name_index(ob, sb->namedVG_Mass) : -1;
- defgroup_index_spring = lt->dvert ? defgroup_name_index(ob, sb->namedVG_Spring_K) : -1;
-
- /* same code used as for mesh vertices */
- for (a = 0; a < totvert; a++, bp++, bpnt++) {
-
- if (ob->softflag & OB_SB_GOAL) {
- BLI_assert(bp->goal == sb->defgoal);
- }
-
- if ((ob->softflag & OB_SB_GOAL) && (defgroup_index != -1)) {
- bp->goal *= defvert_find_weight(&lt->dvert[a], defgroup_index);
- }
- else {
- bp->goal *= bpnt->weight;
- }
-
- if (defgroup_index_mass != -1) {
- bp->mass *= defvert_find_weight(&lt->dvert[a], defgroup_index_mass);
- }
-
- if (defgroup_index_spring != -1) {
- bp->springweight *= defvert_find_weight(&lt->dvert[a], defgroup_index_spring);
- }
- }
-
-
- /* create some helper edges to enable SB lattice to be useful at all */
- if (ob->softflag & OB_SB_EDGES) {
- makelatticesprings(lt, ob->soft->bspring, ob->softflag & OB_SB_QUADS, ob);
- build_bps_springlist(ob); /* link bps to springs */
- }
+ Lattice *lt = ob->data;
+ SoftBody *sb;
+ int totvert, totspring = 0, a;
+ BodyPoint *bp;
+ BPoint *bpnt = lt->def;
+ int defgroup_index, defgroup_index_mass, defgroup_index_spring;
+
+ totvert = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ if (ob->softflag & OB_SB_EDGES) {
+ totspring = ((lt->pntsu - 1) * lt->pntsv + (lt->pntsv - 1) * lt->pntsu) * lt->pntsw +
+ lt->pntsu * lt->pntsv * (lt->pntsw - 1);
+ if (ob->softflag & OB_SB_QUADS) {
+ totspring += 4 * (lt->pntsu - 1) * (lt->pntsv - 1) * (lt->pntsw - 1);
+ }
+ }
+
+ /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
+ renew_softbody(scene, ob, totvert, totspring);
+ sb = ob->soft; /* can be created in renew_softbody() */
+ bp = sb->bpoint;
+
+ defgroup_index = lt->dvert ? (sb->vertgroup - 1) : -1;
+ defgroup_index_mass = lt->dvert ? defgroup_name_index(ob, sb->namedVG_Mass) : -1;
+ defgroup_index_spring = lt->dvert ? defgroup_name_index(ob, sb->namedVG_Spring_K) : -1;
+
+ /* same code used as for mesh vertices */
+ for (a = 0; a < totvert; a++, bp++, bpnt++) {
+
+ if (ob->softflag & OB_SB_GOAL) {
+ BLI_assert(bp->goal == sb->defgoal);
+ }
+
+ if ((ob->softflag & OB_SB_GOAL) && (defgroup_index != -1)) {
+ bp->goal *= defvert_find_weight(&lt->dvert[a], defgroup_index);
+ }
+ else {
+ bp->goal *= bpnt->weight;
+ }
+
+ if (defgroup_index_mass != -1) {
+ bp->mass *= defvert_find_weight(&lt->dvert[a], defgroup_index_mass);
+ }
+
+ if (defgroup_index_spring != -1) {
+ bp->springweight *= defvert_find_weight(&lt->dvert[a], defgroup_index_spring);
+ }
+ }
+
+ /* create some helper edges to enable SB lattice to be useful at all */
+ if (ob->softflag & OB_SB_EDGES) {
+ makelatticesprings(lt, ob->soft->bspring, ob->softflag & OB_SB_QUADS, ob);
+ build_bps_springlist(ob); /* link bps to springs */
+ }
}
/* makes totally fresh start situation */
static void curve_surf_to_softbody(Scene *scene, Object *ob)
{
- Curve *cu= ob->data;
- SoftBody *sb;
- BodyPoint *bp;
- BodySpring *bs;
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bpnt;
- int a, curindex=0;
- int totvert, totspring = 0, setgoal=0;
-
- totvert= BKE_nurbList_verts_count(&cu->nurb);
-
- if (ob->softflag & OB_SB_EDGES) {
- if (ob->type==OB_CURVE) {
- totspring = totvert - BLI_listbase_count(&cu->nurb);
- }
- }
-
- /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
- renew_softbody(scene, ob, totvert, totspring);
- sb= ob->soft; /* can be created in renew_softbody() */
-
- /* set vars now */
- bp= sb->bpoint;
- bs= sb->bspring;
-
- /* weights from bpoints, same code used as for mesh vertices */
- /* if ((ob->softflag & OB_SB_GOAL) && sb->vertgroup) 2.4x hack*/
- /* new! take the weights from curve vertex anyhow */
- if (ob->softflag & OB_SB_GOAL)
- setgoal= 1;
-
- for (nu= cu->nurb.first; nu; nu= nu->next) {
- if (nu->bezt) {
- /* bezier case ; this is nicly said naive; who ever wrote this part, it was not me (JOW) :) */
- /* a: never ever make tangent handles (sub) and or (ob)ject to collision */
- /* b: rather calculate them using some C2 (C2= continuous in second derivate -> no jump in bending ) condition */
- /* not too hard to do, but needs some more code to care for; some one may want look at it JOW 2010/06/12*/
- for (bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++, bp+=3, curindex+=3) {
- if (setgoal) {
- bp->goal *= bezt->weight;
-
- /* all three triples */
- (bp+1)->goal= bp->goal;
- (bp+2)->goal= bp->goal;
- /*do not collide handles */
- (bp+1)->loc_flag |= SBF_OUTOFCOLLISION;
- (bp+2)->loc_flag |= SBF_OUTOFCOLLISION;
- }
-
- if (totspring) {
- if (a>0) {
- bs->v1= curindex-3;
- bs->v2= curindex;
- bs->springtype=SB_HANDLE;
- bs->len = globallen((bezt-1)->vec[0], bezt->vec[0], ob);
- bs++;
- }
- bs->v1= curindex;
- bs->v2= curindex+1;
- bs->springtype=SB_HANDLE;
- bs->len = globallen(bezt->vec[0], bezt->vec[1], ob);
- bs++;
-
- bs->v1= curindex+1;
- bs->v2= curindex+2;
- bs->springtype=SB_HANDLE;
- bs->len = globallen(bezt->vec[1], bezt->vec[2], ob);
- bs++;
- }
- }
- }
- else {
- for (bpnt=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bpnt++, bp++, curindex++) {
- if (setgoal) {
- bp->goal *= bpnt->weight;
- }
- if (totspring && a>0) {
- bs->v1= curindex-1;
- bs->v2= curindex;
- bs->springtype=SB_EDGE;
- bs->len= globallen( (bpnt-1)->vec, bpnt->vec, ob );
- bs++;
- }
- }
- }
- }
-
- if (totspring) {
- build_bps_springlist(ob); /* link bps to springs */
- if (ob->softflag & OB_SB_SELF) { calculate_collision_balls(ob); }
- }
+ Curve *cu = ob->data;
+ SoftBody *sb;
+ BodyPoint *bp;
+ BodySpring *bs;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bpnt;
+ int a, curindex = 0;
+ int totvert, totspring = 0, setgoal = 0;
+
+ totvert = BKE_nurbList_verts_count(&cu->nurb);
+
+ if (ob->softflag & OB_SB_EDGES) {
+ if (ob->type == OB_CURVE) {
+ totspring = totvert - BLI_listbase_count(&cu->nurb);
+ }
+ }
+
+ /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
+ renew_softbody(scene, ob, totvert, totspring);
+ sb = ob->soft; /* can be created in renew_softbody() */
+
+ /* set vars now */
+ bp = sb->bpoint;
+ bs = sb->bspring;
+
+ /* weights from bpoints, same code used as for mesh vertices */
+ /* if ((ob->softflag & OB_SB_GOAL) && sb->vertgroup) 2.4x hack*/
+ /* new! take the weights from curve vertex anyhow */
+ if (ob->softflag & OB_SB_GOAL)
+ setgoal = 1;
+
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ /* bezier case ; this is nicly said naive; who ever wrote this part, it was not me (JOW) :) */
+ /* a: never ever make tangent handles (sub) and or (ob)ject to collision */
+ /* b: rather calculate them using some C2 (C2= continuous in second derivate -> no jump in bending ) condition */
+ /* not too hard to do, but needs some more code to care for; some one may want look at it JOW 2010/06/12*/
+ for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++, bp += 3, curindex += 3) {
+ if (setgoal) {
+ bp->goal *= bezt->weight;
+
+ /* all three triples */
+ (bp + 1)->goal = bp->goal;
+ (bp + 2)->goal = bp->goal;
+ /*do not collide handles */
+ (bp + 1)->loc_flag |= SBF_OUTOFCOLLISION;
+ (bp + 2)->loc_flag |= SBF_OUTOFCOLLISION;
+ }
+
+ if (totspring) {
+ if (a > 0) {
+ bs->v1 = curindex - 3;
+ bs->v2 = curindex;
+ bs->springtype = SB_HANDLE;
+ bs->len = globallen((bezt - 1)->vec[0], bezt->vec[0], ob);
+ bs++;
+ }
+ bs->v1 = curindex;
+ bs->v2 = curindex + 1;
+ bs->springtype = SB_HANDLE;
+ bs->len = globallen(bezt->vec[0], bezt->vec[1], ob);
+ bs++;
+
+ bs->v1 = curindex + 1;
+ bs->v2 = curindex + 2;
+ bs->springtype = SB_HANDLE;
+ bs->len = globallen(bezt->vec[1], bezt->vec[2], ob);
+ bs++;
+ }
+ }
+ }
+ else {
+ for (bpnt = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bpnt++, bp++, curindex++) {
+ if (setgoal) {
+ bp->goal *= bpnt->weight;
+ }
+ if (totspring && a > 0) {
+ bs->v1 = curindex - 1;
+ bs->v2 = curindex;
+ bs->springtype = SB_EDGE;
+ bs->len = globallen((bpnt - 1)->vec, bpnt->vec, ob);
+ bs++;
+ }
+ }
+ }
+ }
+
+ if (totspring) {
+ build_bps_springlist(ob); /* link bps to springs */
+ if (ob->softflag & OB_SB_SELF) {
+ calculate_collision_balls(ob);
+ }
+ }
}
/* copies softbody result back in object */
static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, int local)
{
- SoftBody *sb= ob->soft;
- if (sb) {
- BodyPoint *bp= sb->bpoint;
- int a;
- if (sb->solverflags & SBSO_ESTIMATEIPO) {SB_estimate_transform(ob, sb->lcom, sb->lrot, sb->lscale);}
- /* inverse matrix is not uptodate... */
- invert_m4_m4(ob->imat, ob->obmat);
+ SoftBody *sb = ob->soft;
+ if (sb) {
+ BodyPoint *bp = sb->bpoint;
+ int a;
+ if (sb->solverflags & SBSO_ESTIMATEIPO) {
+ SB_estimate_transform(ob, sb->lcom, sb->lrot, sb->lscale);
+ }
+ /* inverse matrix is not uptodate... */
+ invert_m4_m4(ob->imat, ob->obmat);
- for (a=0; a<numVerts; a++, bp++) {
- copy_v3_v3(vertexCos[a], bp->pos);
- if (local==0)
- mul_m4_v3(ob->imat, vertexCos[a]); /* softbody is in global coords, baked optionally not */
- }
- }
+ for (a = 0; a < numVerts; a++, bp++) {
+ copy_v3_v3(vertexCos[a], bp->pos);
+ if (local == 0)
+ mul_m4_v3(ob->imat, vertexCos[a]); /* softbody is in global coords, baked optionally not */
+ }
+ }
}
/* +++ ************ maintaining scratch *************** */
static void sb_new_scratch(SoftBody *sb)
{
- if (!sb) return;
- sb->scratch = MEM_callocN(sizeof(SBScratch), "SBScratch");
- sb->scratch->colliderhash = BLI_ghash_ptr_new("sb_new_scratch gh");
- sb->scratch->bodyface = NULL;
- sb->scratch->totface = 0;
- sb->scratch->aabbmax[0]=sb->scratch->aabbmax[1]=sb->scratch->aabbmax[2] = 1.0e30f;
- sb->scratch->aabbmin[0]=sb->scratch->aabbmin[1]=sb->scratch->aabbmin[2] = -1.0e30f;
- sb->scratch->Ref.ivert = NULL;
-
+ if (!sb)
+ return;
+ sb->scratch = MEM_callocN(sizeof(SBScratch), "SBScratch");
+ sb->scratch->colliderhash = BLI_ghash_ptr_new("sb_new_scratch gh");
+ sb->scratch->bodyface = NULL;
+ sb->scratch->totface = 0;
+ sb->scratch->aabbmax[0] = sb->scratch->aabbmax[1] = sb->scratch->aabbmax[2] = 1.0e30f;
+ sb->scratch->aabbmin[0] = sb->scratch->aabbmin[1] = sb->scratch->aabbmin[2] = -1.0e30f;
+ sb->scratch->Ref.ivert = NULL;
}
/* --- ************ maintaining scratch *************** */
@@ -2977,134 +3019,135 @@ static void sb_new_scratch(SoftBody *sb)
/* allocates and initializes general main data */
SoftBody *sbNew(Scene *scene)
{
- SoftBody *sb;
-
- sb= MEM_callocN(sizeof(SoftBody), "softbody");
+ SoftBody *sb;
- sb->mediafrict= 0.5f;
- sb->nodemass= 1.0f;
- sb->grav= 9.8f;
- sb->physics_speed= 1.0f;
- sb->rklimit= 0.1f;
+ sb = MEM_callocN(sizeof(SoftBody), "softbody");
- sb->goalspring= 0.5f;
- sb->goalfrict= 0.0f;
- sb->mingoal= 0.0f;
- sb->maxgoal= 1.0f;
- sb->defgoal= 0.7f;
+ sb->mediafrict = 0.5f;
+ sb->nodemass = 1.0f;
+ sb->grav = 9.8f;
+ sb->physics_speed = 1.0f;
+ sb->rklimit = 0.1f;
- sb->inspring= 0.5f;
- sb->infrict= 0.5f;
- /*todo backward file compat should copy inspring to inpush while reading old files*/
- sb->inpush = 0.5f;
+ sb->goalspring = 0.5f;
+ sb->goalfrict = 0.0f;
+ sb->mingoal = 0.0f;
+ sb->maxgoal = 1.0f;
+ sb->defgoal = 0.7f;
- sb->interval= 10;
- sb->sfra= scene->r.sfra;
- sb->efra= scene->r.efra;
+ sb->inspring = 0.5f;
+ sb->infrict = 0.5f;
+ /*todo backward file compat should copy inspring to inpush while reading old files*/
+ sb->inpush = 0.5f;
- sb->colball = 0.49f;
- sb->balldamp = 0.50f;
- sb->ballstiff= 1.0f;
- sb->sbc_mode = 1;
+ sb->interval = 10;
+ sb->sfra = scene->r.sfra;
+ sb->efra = scene->r.efra;
+ sb->colball = 0.49f;
+ sb->balldamp = 0.50f;
+ sb->ballstiff = 1.0f;
+ sb->sbc_mode = 1;
- sb->minloops = 10;
- sb->maxloops = 300;
+ sb->minloops = 10;
+ sb->maxloops = 300;
- sb->choke = 3;
- sb_new_scratch(sb);
- /*todo backward file compat should set sb->shearstiff = 1.0f while reading old files*/
- sb->shearstiff = 1.0f;
- sb->solverflags |= SBSO_OLDERR;
+ sb->choke = 3;
+ sb_new_scratch(sb);
+ /*todo backward file compat should set sb->shearstiff = 1.0f while reading old files*/
+ sb->shearstiff = 1.0f;
+ sb->solverflags |= SBSO_OLDERR;
- sb->shared = MEM_callocN(sizeof(*sb->shared), "SoftBody_Shared");
- sb->shared->pointcache = BKE_ptcache_add(&sb->shared->ptcaches);
+ sb->shared = MEM_callocN(sizeof(*sb->shared), "SoftBody_Shared");
+ sb->shared->pointcache = BKE_ptcache_add(&sb->shared->ptcaches);
- if (!sb->effector_weights)
- sb->effector_weights = BKE_effector_add_weights(NULL);
+ if (!sb->effector_weights)
+ sb->effector_weights = BKE_effector_add_weights(NULL);
- sb->last_frame= MINFRAME-1;
+ sb->last_frame = MINFRAME - 1;
- return sb;
+ return sb;
}
/* frees all */
void sbFree(Object *ob)
{
- SoftBody *sb = ob->soft;
- if (sb == NULL) {
- return;
- }
+ SoftBody *sb = ob->soft;
+ if (sb == NULL) {
+ return;
+ }
- free_softbody_intern(sb);
+ free_softbody_intern(sb);
- if ((ob->id.tag & LIB_TAG_NO_MAIN) == 0) {
- /* Only free shared data on non-CoW copies */
- BKE_ptcache_free_list(&sb->shared->ptcaches);
- sb->shared->pointcache = NULL;
- MEM_freeN(sb->shared);
- }
- if (sb->effector_weights)
- MEM_freeN(sb->effector_weights);
- MEM_freeN(sb);
+ if ((ob->id.tag & LIB_TAG_NO_MAIN) == 0) {
+ /* Only free shared data on non-CoW copies */
+ BKE_ptcache_free_list(&sb->shared->ptcaches);
+ sb->shared->pointcache = NULL;
+ MEM_freeN(sb->shared);
+ }
+ if (sb->effector_weights)
+ MEM_freeN(sb->effector_weights);
+ MEM_freeN(sb);
- ob->soft = NULL;
+ ob->soft = NULL;
}
void sbFreeSimulation(SoftBody *sb)
{
- free_softbody_intern(sb);
+ free_softbody_intern(sb);
}
/* makes totally fresh start situation */
void sbObjectToSoftbody(Object *ob)
{
- //ob->softflag |= OB_SB_REDO;
+ //ob->softflag |= OB_SB_REDO;
- free_softbody_intern(ob->soft);
+ free_softbody_intern(ob->soft);
}
static int object_has_edges(Object *ob)
{
- if (ob->type==OB_MESH) {
- return ((Mesh*) ob->data)->totedge;
- }
- else if (ob->type==OB_LATTICE) {
- return 1;
- }
- else {
- return 0;
- }
+ if (ob->type == OB_MESH) {
+ return ((Mesh *)ob->data)->totedge;
+ }
+ else if (ob->type == OB_LATTICE) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
/* SB global visible functions */
void sbSetInterruptCallBack(int (*f)(void))
{
- SB_localInterruptCallBack = f;
+ SB_localInterruptCallBack = f;
}
-static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts)
+static void softbody_update_positions(Object *ob,
+ SoftBody *sb,
+ float (*vertexCos)[3],
+ int numVerts)
{
- BodyPoint *bp;
- int a;
+ BodyPoint *bp;
+ int a;
- if (!sb || !sb->bpoint)
- return;
+ if (!sb || !sb->bpoint)
+ return;
- for (a=0, bp=sb->bpoint; a<numVerts; a++, bp++) {
- /* store where goals are now */
- copy_v3_v3(bp->origS, bp->origE);
- /* copy the position of the goals at desired end time */
- copy_v3_v3(bp->origE, vertexCos[a]);
- /* vertexCos came from local world, go global */
- mul_m4_v3(ob->obmat, bp->origE);
- /* just to be save give bp->origT a defined value
- * will be calculated in interpolate_exciter() */
- copy_v3_v3(bp->origT, bp->origE);
- }
+ for (a = 0, bp = sb->bpoint; a < numVerts; a++, bp++) {
+ /* store where goals are now */
+ copy_v3_v3(bp->origS, bp->origE);
+ /* copy the position of the goals at desired end time */
+ copy_v3_v3(bp->origE, vertexCos[a]);
+ /* vertexCos came from local world, go global */
+ mul_m4_v3(ob->obmat, bp->origE);
+ /* just to be save give bp->origT a defined value
+ * will be calculated in interpolate_exciter() */
+ copy_v3_v3(bp->origT, bp->origE);
+ }
}
-
/* void SB_estimate_transform */
/* input Object *ob out (says any object that can do SB like mesh, lattice, curve )
* output float lloc[3], float lrot[3][3], float lscale[3][3]
@@ -3122,366 +3165,383 @@ static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCo
void SB_estimate_transform(Object *ob, float lloc[3], float lrot[3][3], float lscale[3][3])
{
- BodyPoint *bp;
- ReferenceVert *rp;
- SoftBody *sb = NULL;
- float (*opos)[3];
- float (*rpos)[3];
- float com[3], rcom[3];
- int a;
-
- if (!ob ||!ob->soft) return; /* why did we get here ? */
- sb= ob->soft;
- if (!sb || !sb->bpoint) return;
- opos= MEM_callocN((sb->totpoint)*3*sizeof(float), "SB_OPOS");
- rpos= MEM_callocN((sb->totpoint)*3*sizeof(float), "SB_RPOS");
- /* might filter vertex selection with a vertex group */
- for (a=0, bp=sb->bpoint, rp=sb->scratch->Ref.ivert; a<sb->totpoint; a++, bp++, rp++) {
- copy_v3_v3(rpos[a], rp->pos);
- copy_v3_v3(opos[a], bp->pos);
- }
-
- vcloud_estimate_transform_v3(sb->totpoint, opos, NULL, rpos, NULL, com, rcom, lrot, lscale);
- //sub_v3_v3(com, rcom);
- if (lloc) copy_v3_v3(lloc, com);
- copy_v3_v3(sb->lcom, com);
- if (lscale) copy_m3_m3(sb->lscale, lscale);
- if (lrot) copy_m3_m3(sb->lrot, lrot);
-
-
- MEM_freeN(opos);
- MEM_freeN(rpos);
+ BodyPoint *bp;
+ ReferenceVert *rp;
+ SoftBody *sb = NULL;
+ float(*opos)[3];
+ float(*rpos)[3];
+ float com[3], rcom[3];
+ int a;
+
+ if (!ob || !ob->soft)
+ return; /* why did we get here ? */
+ sb = ob->soft;
+ if (!sb || !sb->bpoint)
+ return;
+ opos = MEM_callocN((sb->totpoint) * 3 * sizeof(float), "SB_OPOS");
+ rpos = MEM_callocN((sb->totpoint) * 3 * sizeof(float), "SB_RPOS");
+ /* might filter vertex selection with a vertex group */
+ for (a = 0, bp = sb->bpoint, rp = sb->scratch->Ref.ivert; a < sb->totpoint; a++, bp++, rp++) {
+ copy_v3_v3(rpos[a], rp->pos);
+ copy_v3_v3(opos[a], bp->pos);
+ }
+
+ vcloud_estimate_transform_v3(sb->totpoint, opos, NULL, rpos, NULL, com, rcom, lrot, lscale);
+ //sub_v3_v3(com, rcom);
+ if (lloc)
+ copy_v3_v3(lloc, com);
+ copy_v3_v3(sb->lcom, com);
+ if (lscale)
+ copy_m3_m3(sb->lscale, lscale);
+ if (lrot)
+ copy_m3_m3(sb->lrot, lrot);
+
+ MEM_freeN(opos);
+ MEM_freeN(rpos);
}
static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts)
{
- BodyPoint *bp;
- int a;
-
- for (a=0, bp=sb->bpoint; a<numVerts; a++, bp++) {
- copy_v3_v3(bp->pos, vertexCos[a]);
- mul_m4_v3(ob->obmat, bp->pos); /* yep, sofbody is global coords*/
- copy_v3_v3(bp->origS, bp->pos);
- copy_v3_v3(bp->origE, bp->pos);
- copy_v3_v3(bp->origT, bp->pos);
- bp->vec[0] = bp->vec[1] = bp->vec[2] = 0.0f;
-
- /* the bp->prev*'s are for rolling back from a canceled try to propagate in time
- * adaptive step size algo in a nutshell:
- * 1. set scheduled time step to new dtime
- * 2. try to advance the scheduled time step, being optimistic execute it
- * 3. check for success
- * 3.a we 're fine continue, may be we can increase scheduled time again ?? if so, do so!
- * 3.b we did exceed error limit --> roll back, shorten the scheduled time and try again at 2.
- * 4. check if we did reach dtime
- * 4.a nope we need to do some more at 2.
- * 4.b yup we're done
- */
-
- copy_v3_v3(bp->prevpos, bp->pos);
- copy_v3_v3(bp->prevvec, bp->vec);
- copy_v3_v3(bp->prevdx, bp->vec);
- copy_v3_v3(bp->prevdv, bp->vec);
- }
-
- /* make a nice clean scratch struc */
- free_scratch(sb); /* clear if any */
- sb_new_scratch(sb); /* make a new */
- sb->scratch->needstobuildcollider=1;
- zero_v3(sb->lcom);
- unit_m3(sb->lrot);
- unit_m3(sb->lscale);
-
-
-
- /* copy some info to scratch */
- /* we only need that if we want to reconstruct IPO */
- if (1) {
- reference_to_scratch(ob);
- SB_estimate_transform(ob, NULL, NULL, NULL);
- SB_estimate_transform(ob, NULL, NULL, NULL);
- }
- switch (ob->type) {
- case OB_MESH:
- if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob);
- break;
- case OB_LATTICE:
- break;
- case OB_CURVE:
- case OB_SURF:
- break;
- default:
- break;
- }
-}
-
-static void softbody_step(struct Depsgraph *depsgraph, Scene *scene, Object *ob, SoftBody *sb, float dtime)
-{
- /* the simulator */
- float forcetime;
- double sct, sst;
-
-
- sst=PIL_check_seconds_timer();
- /* Integration back in time is possible in theory, but pretty useless here.
- * So we refuse to do so. Since we do not know anything about 'outside' changes
- * especially colliders we refuse to go more than 10 frames.
- */
- if (dtime < 0 || dtime > 10.5f) return;
-
- ccd_update_deflector_hash(depsgraph, sb->collision_group, ob, sb->scratch->colliderhash);
-
- if (sb->scratch->needstobuildcollider) {
- ccd_build_deflector_hash(depsgraph, sb->collision_group, ob, sb->scratch->colliderhash);
- sb->scratch->needstobuildcollider=0;
- }
-
- if (sb->solver_ID < 2) {
- /* special case of 2nd order Runge-Kutta type AKA Heun */
- int mid_flags=0;
- float err = 0;
- float forcetimemax = 1.0f; /* set defaults guess we shall do one frame */
- float forcetimemin = 0.01f; /* set defaults guess 1/100 is tight enough */
- float timedone =0.0; /* how far did we get without violating error condition */
- /* loops = counter for emergency brake
- * we don't want to lock up the system if physics fail */
- int loops = 0;
-
- SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */
- /* adjust loop limits */
- if (sb->minloops > 0) forcetimemax = dtime / sb->minloops;
- if (sb->maxloops > 0) forcetimemin = dtime / sb->maxloops;
-
- if (sb->solver_ID>0) mid_flags |= MID_PRESERVE;
-
- forcetime = forcetimemax; /* hope for integrating in one step */
- while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) ) {
- /* set goals in time */
- interpolate_exciter(ob, 200, (int)(200.0f*(timedone/dtime)));
-
- sb->scratch->flag &= ~SBF_DOFUZZY;
- /* do predictive euler step */
- softbody_calc_forces(depsgraph, scene, ob, forcetime, timedone/dtime);
-
- softbody_apply_forces(ob, forcetime, 1, NULL, mid_flags);
-
- /* crop new slope values to do averaged slope step */
- softbody_calc_forces(depsgraph, scene, ob, forcetime, timedone/dtime);
-
- softbody_apply_forces(ob, forcetime, 2, &err, mid_flags);
- softbody_apply_goalsnap(ob);
-
- if (err > SoftHeunTol) { /* error needs to be scaled to some quantity */
-
- if (forcetime > forcetimemin) {
- forcetime = max_ff(forcetime / 2.0f, forcetimemin);
- softbody_restore_prev_step(ob);
- //printf("down, ");
- }
- else {
- timedone += forcetime;
- }
- }
- else {
- float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */
-
- if (sb->scratch->flag & SBF_DOFUZZY) {
- //if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) { /* stay with this stepsize unless err really small */
- newtime = forcetime;
- //}
- }
- else {
- if (err > SoftHeunTol/2.0f) { /* stay with this stepsize unless err really small */
- newtime = forcetime;
- }
- }
- timedone += forcetime;
- newtime = min_ff(forcetimemax, max_ff(newtime, forcetimemin));
- //if (newtime > forcetime) printf("up, ");
- if (forcetime > 0.0f)
- forcetime = min_ff(dtime - timedone, newtime);
- else
- forcetime = max_ff(dtime - timedone, newtime);
- }
- loops++;
- if (sb->solverflags & SBSO_MONITOR ) {
- sct = PIL_check_seconds_timer();
- if (sct - sst > 0.5) printf("%3.0f%% \r", 100.0f * timedone / dtime);
- }
- /* ask for user break */
- if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break;
-
- }
- /* move snapped to final position */
- interpolate_exciter(ob, 2, 2);
- softbody_apply_goalsnap(ob);
-
- // if (G.debug & G_DEBUG) {
- if (sb->solverflags & SBSO_MONITOR ) {
- if (loops > HEUNWARNLIMIT) /* monitor high loop counts */
- printf("\r needed %d steps/frame", loops);
- }
-
- }
- else if (sb->solver_ID == 2) {
- /* do semi "fake" implicit euler */
- //removed
- }/*SOLVER SELECT*/
- else if (sb->solver_ID == 4) {
- /* do semi "fake" implicit euler */
- }/*SOLVER SELECT*/
- else if (sb->solver_ID == 3) {
- /* do "stupid" semi "fake" implicit euler */
- //removed
-
- }/*SOLVER SELECT*/
- else {
- CLOG_ERROR(&LOG, "softbody no valid solver ID!");
- }/*SOLVER SELECT*/
- if (sb->plastic) { apply_spring_memory(ob);}
-
- if (sb->solverflags & SBSO_MONITOR ) {
- sct=PIL_check_seconds_timer();
- if ((sct - sst > 0.5) || (G.debug & G_DEBUG)) printf(" solver time %f sec %s\n", sct-sst, ob->id.name);
- }
+ BodyPoint *bp;
+ int a;
+
+ for (a = 0, bp = sb->bpoint; a < numVerts; a++, bp++) {
+ copy_v3_v3(bp->pos, vertexCos[a]);
+ mul_m4_v3(ob->obmat, bp->pos); /* yep, sofbody is global coords*/
+ copy_v3_v3(bp->origS, bp->pos);
+ copy_v3_v3(bp->origE, bp->pos);
+ copy_v3_v3(bp->origT, bp->pos);
+ bp->vec[0] = bp->vec[1] = bp->vec[2] = 0.0f;
+
+ /* the bp->prev*'s are for rolling back from a canceled try to propagate in time
+ * adaptive step size algo in a nutshell:
+ * 1. set scheduled time step to new dtime
+ * 2. try to advance the scheduled time step, being optimistic execute it
+ * 3. check for success
+ * 3.a we 're fine continue, may be we can increase scheduled time again ?? if so, do so!
+ * 3.b we did exceed error limit --> roll back, shorten the scheduled time and try again at 2.
+ * 4. check if we did reach dtime
+ * 4.a nope we need to do some more at 2.
+ * 4.b yup we're done
+ */
+
+ copy_v3_v3(bp->prevpos, bp->pos);
+ copy_v3_v3(bp->prevvec, bp->vec);
+ copy_v3_v3(bp->prevdx, bp->vec);
+ copy_v3_v3(bp->prevdv, bp->vec);
+ }
+
+ /* make a nice clean scratch struc */
+ free_scratch(sb); /* clear if any */
+ sb_new_scratch(sb); /* make a new */
+ sb->scratch->needstobuildcollider = 1;
+ zero_v3(sb->lcom);
+ unit_m3(sb->lrot);
+ unit_m3(sb->lscale);
+
+ /* copy some info to scratch */
+ /* we only need that if we want to reconstruct IPO */
+ if (1) {
+ reference_to_scratch(ob);
+ SB_estimate_transform(ob, NULL, NULL, NULL);
+ SB_estimate_transform(ob, NULL, NULL, NULL);
+ }
+ switch (ob->type) {
+ case OB_MESH:
+ if (ob->softflag & OB_SB_FACECOLL)
+ mesh_faces_to_scratch(ob);
+ break;
+ case OB_LATTICE:
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ break;
+ default:
+ break;
+ }
+}
+
+static void softbody_step(
+ struct Depsgraph *depsgraph, Scene *scene, Object *ob, SoftBody *sb, float dtime)
+{
+ /* the simulator */
+ float forcetime;
+ double sct, sst;
+
+ sst = PIL_check_seconds_timer();
+ /* Integration back in time is possible in theory, but pretty useless here.
+ * So we refuse to do so. Since we do not know anything about 'outside' changes
+ * especially colliders we refuse to go more than 10 frames.
+ */
+ if (dtime < 0 || dtime > 10.5f)
+ return;
+
+ ccd_update_deflector_hash(depsgraph, sb->collision_group, ob, sb->scratch->colliderhash);
+
+ if (sb->scratch->needstobuildcollider) {
+ ccd_build_deflector_hash(depsgraph, sb->collision_group, ob, sb->scratch->colliderhash);
+ sb->scratch->needstobuildcollider = 0;
+ }
+
+ if (sb->solver_ID < 2) {
+ /* special case of 2nd order Runge-Kutta type AKA Heun */
+ int mid_flags = 0;
+ float err = 0;
+ float forcetimemax = 1.0f; /* set defaults guess we shall do one frame */
+ float forcetimemin = 0.01f; /* set defaults guess 1/100 is tight enough */
+ float timedone = 0.0; /* how far did we get without violating error condition */
+ /* loops = counter for emergency brake
+ * we don't want to lock up the system if physics fail */
+ int loops = 0;
+
+ SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */
+ /* adjust loop limits */
+ if (sb->minloops > 0)
+ forcetimemax = dtime / sb->minloops;
+ if (sb->maxloops > 0)
+ forcetimemin = dtime / sb->maxloops;
+
+ if (sb->solver_ID > 0)
+ mid_flags |= MID_PRESERVE;
+
+ forcetime = forcetimemax; /* hope for integrating in one step */
+ while ((ABS(timedone) < ABS(dtime)) && (loops < 2000)) {
+ /* set goals in time */
+ interpolate_exciter(ob, 200, (int)(200.0f * (timedone / dtime)));
+
+ sb->scratch->flag &= ~SBF_DOFUZZY;
+ /* do predictive euler step */
+ softbody_calc_forces(depsgraph, scene, ob, forcetime, timedone / dtime);
+
+ softbody_apply_forces(ob, forcetime, 1, NULL, mid_flags);
+
+ /* crop new slope values to do averaged slope step */
+ softbody_calc_forces(depsgraph, scene, ob, forcetime, timedone / dtime);
+
+ softbody_apply_forces(ob, forcetime, 2, &err, mid_flags);
+ softbody_apply_goalsnap(ob);
+
+ if (err > SoftHeunTol) { /* error needs to be scaled to some quantity */
+
+ if (forcetime > forcetimemin) {
+ forcetime = max_ff(forcetime / 2.0f, forcetimemin);
+ softbody_restore_prev_step(ob);
+ //printf("down, ");
+ }
+ else {
+ timedone += forcetime;
+ }
+ }
+ else {
+ float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */
+
+ if (sb->scratch->flag & SBF_DOFUZZY) {
+ //if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) { /* stay with this stepsize unless err really small */
+ newtime = forcetime;
+ //}
+ }
+ else {
+ if (err > SoftHeunTol / 2.0f) { /* stay with this stepsize unless err really small */
+ newtime = forcetime;
+ }
+ }
+ timedone += forcetime;
+ newtime = min_ff(forcetimemax, max_ff(newtime, forcetimemin));
+ //if (newtime > forcetime) printf("up, ");
+ if (forcetime > 0.0f)
+ forcetime = min_ff(dtime - timedone, newtime);
+ else
+ forcetime = max_ff(dtime - timedone, newtime);
+ }
+ loops++;
+ if (sb->solverflags & SBSO_MONITOR) {
+ sct = PIL_check_seconds_timer();
+ if (sct - sst > 0.5)
+ printf("%3.0f%% \r", 100.0f * timedone / dtime);
+ }
+ /* ask for user break */
+ if (SB_localInterruptCallBack && SB_localInterruptCallBack())
+ break;
+ }
+ /* move snapped to final position */
+ interpolate_exciter(ob, 2, 2);
+ softbody_apply_goalsnap(ob);
+
+ // if (G.debug & G_DEBUG) {
+ if (sb->solverflags & SBSO_MONITOR) {
+ if (loops > HEUNWARNLIMIT) /* monitor high loop counts */
+ printf("\r needed %d steps/frame", loops);
+ }
+ }
+ else if (sb->solver_ID == 2) {
+ /* do semi "fake" implicit euler */
+ //removed
+ } /*SOLVER SELECT*/
+ else if (sb->solver_ID == 4) {
+ /* do semi "fake" implicit euler */
+ } /*SOLVER SELECT*/
+ else if (sb->solver_ID == 3) {
+ /* do "stupid" semi "fake" implicit euler */
+ //removed
+
+ } /*SOLVER SELECT*/
+ else {
+ CLOG_ERROR(&LOG, "softbody no valid solver ID!");
+ } /*SOLVER SELECT*/
+ if (sb->plastic) {
+ apply_spring_memory(ob);
+ }
+
+ if (sb->solverflags & SBSO_MONITOR) {
+ sct = PIL_check_seconds_timer();
+ if ((sct - sst > 0.5) || (G.debug & G_DEBUG))
+ printf(" solver time %f sec %s\n", sct - sst, ob->id.name);
+ }
}
static void sbStoreLastFrame(struct Depsgraph *depsgraph, Object *object, float framenr)
{
- if (!DEG_is_active(depsgraph)) {
- return;
- }
- Object *object_orig = DEG_get_original_object(object);
- object->soft->last_frame = framenr;
- object_orig->soft->last_frame = framenr;
+ if (!DEG_is_active(depsgraph)) {
+ return;
+ }
+ Object *object_orig = DEG_get_original_object(object);
+ object->soft->last_frame = framenr;
+ object_orig->soft->last_frame = framenr;
}
/* simulates one step. framenr is in frames */
-void sbObjectStep(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts)
-{
- SoftBody *sb= ob->soft;
- PointCache *cache;
- PTCacheID pid;
- float dtime, timescale;
- int framedelta, framenr, startframe, endframe;
- int cache_result;
- cache= sb->shared->pointcache;
-
- framenr= (int)cfra;
- framedelta= framenr - cache->simframe;
-
- BKE_ptcache_id_from_softbody(&pid, ob, sb);
- BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
-
- /* check for changes in mesh, should only happen in case the mesh
- * structure changes during an animation */
- if (sb->bpoint && numVerts != sb->totpoint) {
- BKE_ptcache_invalidate(cache);
- return;
- }
-
- /* clamp frame ranges */
- if (framenr < startframe) {
- BKE_ptcache_invalidate(cache);
- return;
- }
- else if (framenr > endframe) {
- framenr = endframe;
- }
-
- /* verify if we need to create the softbody data */
- if (sb->bpoint == NULL ||
- ((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob)))
- {
-
- switch (ob->type) {
- case OB_MESH:
- mesh_to_softbody(scene, ob);
- break;
- case OB_LATTICE:
- lattice_to_softbody(scene, ob);
- break;
- case OB_CURVE:
- case OB_SURF:
- curve_surf_to_softbody(scene, ob);
- break;
- default:
- renew_softbody(scene, ob, numVerts, 0);
- break;
- }
-
- softbody_update_positions(ob, sb, vertexCos, numVerts);
- softbody_reset(ob, sb, vertexCos, numVerts);
- }
-
- /* still no points? go away */
- if (sb->totpoint==0) {
- return;
- }
- if (framenr == startframe) {
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
-
- /* first frame, no simulation to do, just set the positions */
- softbody_update_positions(ob, sb, vertexCos, numVerts);
-
- BKE_ptcache_validate(cache, framenr);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
-
- sbStoreLastFrame(depsgraph, ob, framenr);
-
- return;
- }
-
- /* try to read from cache */
- bool can_write_cache = DEG_is_active(depsgraph);
- bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED) && can_write_cache;
-
- cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate);
-
- if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED ||
- (!can_simulate && cache_result == PTCACHE_READ_OLD))
- {
- softbody_to_object(ob, vertexCos, numVerts, sb->local);
-
- BKE_ptcache_validate(cache, framenr);
-
- if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED && can_write_cache)
- BKE_ptcache_write(&pid, framenr);
-
- sbStoreLastFrame(depsgraph, ob, framenr);
-
- return;
- }
- else if (cache_result==PTCACHE_READ_OLD) {
- ; /* do nothing */
- }
- else if (/*ob->id.lib || */(cache->flag & PTCACHE_BAKED)) { /* "library linking & pointcaches" has to be solved properly at some point */
- /* if baked and nothing in cache, do nothing */
- if (can_write_cache) {
- BKE_ptcache_invalidate(cache);
- }
- return;
- }
-
- if (!can_simulate)
- return;
-
- /* if on second frame, write cache for first frame */
- if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
- BKE_ptcache_write(&pid, startframe);
-
- softbody_update_positions(ob, sb, vertexCos, numVerts);
-
- /* checking time: */
- dtime = framedelta*timescale;
-
- /* do simulation */
- softbody_step(depsgraph, scene, ob, sb, dtime);
-
- softbody_to_object(ob, vertexCos, numVerts, 0);
-
- BKE_ptcache_validate(cache, framenr);
- BKE_ptcache_write(&pid, framenr);
-
- sbStoreLastFrame(depsgraph, ob, framenr);
+void sbObjectStep(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ float cfra,
+ float (*vertexCos)[3],
+ int numVerts)
+{
+ SoftBody *sb = ob->soft;
+ PointCache *cache;
+ PTCacheID pid;
+ float dtime, timescale;
+ int framedelta, framenr, startframe, endframe;
+ int cache_result;
+ cache = sb->shared->pointcache;
+
+ framenr = (int)cfra;
+ framedelta = framenr - cache->simframe;
+
+ BKE_ptcache_id_from_softbody(&pid, ob, sb);
+ BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
+
+ /* check for changes in mesh, should only happen in case the mesh
+ * structure changes during an animation */
+ if (sb->bpoint && numVerts != sb->totpoint) {
+ BKE_ptcache_invalidate(cache);
+ return;
+ }
+
+ /* clamp frame ranges */
+ if (framenr < startframe) {
+ BKE_ptcache_invalidate(cache);
+ return;
+ }
+ else if (framenr > endframe) {
+ framenr = endframe;
+ }
+
+ /* verify if we need to create the softbody data */
+ if (sb->bpoint == NULL ||
+ ((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) {
+
+ switch (ob->type) {
+ case OB_MESH:
+ mesh_to_softbody(scene, ob);
+ break;
+ case OB_LATTICE:
+ lattice_to_softbody(scene, ob);
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ curve_surf_to_softbody(scene, ob);
+ break;
+ default:
+ renew_softbody(scene, ob, numVerts, 0);
+ break;
+ }
+
+ softbody_update_positions(ob, sb, vertexCos, numVerts);
+ softbody_reset(ob, sb, vertexCos, numVerts);
+ }
+
+ /* still no points? go away */
+ if (sb->totpoint == 0) {
+ return;
+ }
+ if (framenr == startframe) {
+ BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
+
+ /* first frame, no simulation to do, just set the positions */
+ softbody_update_positions(ob, sb, vertexCos, numVerts);
+
+ BKE_ptcache_validate(cache, framenr);
+ cache->flag &= ~PTCACHE_REDO_NEEDED;
+
+ sbStoreLastFrame(depsgraph, ob, framenr);
+
+ return;
+ }
+
+ /* try to read from cache */
+ bool can_write_cache = DEG_is_active(depsgraph);
+ bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED) &&
+ can_write_cache;
+
+ cache_result = BKE_ptcache_read(&pid, (float)framenr + scene->r.subframe, can_simulate);
+
+ if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED ||
+ (!can_simulate && cache_result == PTCACHE_READ_OLD)) {
+ softbody_to_object(ob, vertexCos, numVerts, sb->local);
+
+ BKE_ptcache_validate(cache, framenr);
+
+ if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED &&
+ can_write_cache)
+ BKE_ptcache_write(&pid, framenr);
+
+ sbStoreLastFrame(depsgraph, ob, framenr);
+
+ return;
+ }
+ else if (cache_result == PTCACHE_READ_OLD) {
+ ; /* do nothing */
+ }
+ else if (/*ob->id.lib || */ (
+ cache->flag &
+ PTCACHE_BAKED)) { /* "library linking & pointcaches" has to be solved properly at some point */
+ /* if baked and nothing in cache, do nothing */
+ if (can_write_cache) {
+ BKE_ptcache_invalidate(cache);
+ }
+ return;
+ }
+
+ if (!can_simulate)
+ return;
+
+ /* if on second frame, write cache for first frame */
+ if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0))
+ BKE_ptcache_write(&pid, startframe);
+
+ softbody_update_positions(ob, sb, vertexCos, numVerts);
+
+ /* checking time: */
+ dtime = framedelta * timescale;
+
+ /* do simulation */
+ softbody_step(depsgraph, scene, ob, sb, dtime);
+
+ softbody_to_object(ob, vertexCos, numVerts, 0);
+
+ BKE_ptcache_validate(cache, framenr);
+ BKE_ptcache_write(&pid, framenr);
+
+ sbStoreLastFrame(depsgraph, ob, framenr);
}