Restructured many collision things again, GUI cleanup
This commit is contained in:
@@ -129,38 +129,39 @@ void implicit_set_positions ( ClothModifierData *clmd );
|
||||
void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float ( *vertexCos ) [3], int numverts );
|
||||
|
||||
// used in collision.c
|
||||
typedef struct Tree
|
||||
typedef struct CollisionTree
|
||||
{
|
||||
struct Tree *nodes[4]; // 4 children --> quad-tree
|
||||
struct Tree *parent;
|
||||
struct Tree *nextLeaf;
|
||||
struct Tree *prevLeaf;
|
||||
struct CollisionTree *nodes[4]; // 4 children --> quad-tree
|
||||
struct CollisionTree *parent;
|
||||
struct CollisionTree *nextLeaf;
|
||||
struct CollisionTree *prevLeaf;
|
||||
float bv[26]; // Bounding volume of all nodes / we have 7 axes on a 14-DOP
|
||||
unsigned int tri_index; // this saves the index of the face
|
||||
// int point_index[4]; // supports up to 4 points in a leaf
|
||||
int count_nodes; // how many nodes are used
|
||||
int traversed; // how many nodes already traversed until this level?
|
||||
int isleaf;
|
||||
}
|
||||
Tree;
|
||||
|
||||
typedef struct Tree TreeNode;
|
||||
CollisionTree;
|
||||
|
||||
typedef struct BVH
|
||||
{
|
||||
unsigned int numfaces;
|
||||
unsigned int numverts;
|
||||
ClothVertex *verts; // just a pointer to the original datastructure
|
||||
// ClothVertex *verts; // just a pointer to the original datastructure
|
||||
MVert *current_x; // e.g. txold in clothvertex
|
||||
MVert *current_xold; // e.g. tx in clothvertex
|
||||
MFace *mfaces; // just a pointer to the original datastructure
|
||||
struct LinkNode *tree;
|
||||
TreeNode *root; // TODO: saving the root --> is this really needed? YES!
|
||||
TreeNode *leaf_tree; /* Tail of the leaf linked list. */
|
||||
TreeNode *leaf_root; /* Head of the leaf linked list. */
|
||||
CollisionTree *root; // TODO: saving the root --> is this really needed? YES!
|
||||
CollisionTree *leaf_tree; /* Tail of the leaf linked list. */
|
||||
CollisionTree *leaf_root; /* Head of the leaf linked list. */
|
||||
float epsilon; /* epslion is used for inflation of the k-dop */
|
||||
int flags; /* bvhFlags */
|
||||
}
|
||||
BVH;
|
||||
|
||||
typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 );
|
||||
typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree * tree1, CollisionTree * tree2 );
|
||||
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
@@ -168,9 +169,15 @@ typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, ClothModifier
|
||||
////////////////////////////////////////////////
|
||||
|
||||
// needed for implicit.c
|
||||
void bvh_collision_response ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 );
|
||||
void bvh_collision_response ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree * tree1, CollisionTree * tree2 );
|
||||
int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt );
|
||||
|
||||
// needed for modifier.c
|
||||
BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon);
|
||||
|
||||
// needed for collision.c
|
||||
void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving);
|
||||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -180,13 +187,12 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt );
|
||||
|
||||
// needed for cloth.c
|
||||
void bvh_free ( BVH * bvh );
|
||||
BVH *bvh_build ( ClothModifierData *clmd, float epsilon );
|
||||
void bvh_build (BVH *bvh);
|
||||
LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr );
|
||||
|
||||
// needed for collision.c
|
||||
int bvh_traverse ( ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response );
|
||||
void bvh_update ( ClothModifierData * clmd, BVH * bvh, int moving );
|
||||
|
||||
int bvh_traverse ( ClothModifierData * clmd, ClothModifierData * coll_clmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response );
|
||||
void bvh_update(BVH * bvh, int moving);
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -199,6 +205,9 @@ void cloth_init ( ClothModifierData *clmd );
|
||||
void cloth_deform_verts ( struct Object *ob, float framenr, float ( *vertexCos ) [3], int numVerts, void *derivedData, ClothModifierData *clmd );
|
||||
void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int totface );
|
||||
|
||||
// needed for collision.c
|
||||
void bvh_update_from_cloth(ClothModifierData *clmd, int moving);
|
||||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ typedef struct BVH
|
||||
}
|
||||
BVH;
|
||||
|
||||
|
||||
/* used for collisions in kdop.c and also collision.c*/
|
||||
typedef struct CollisionPair
|
||||
{
|
||||
|
||||
@@ -160,6 +160,7 @@ void cloth_init ( ClothModifierData *clmd )
|
||||
clmd->sim_parms.maxspringlen = 10;
|
||||
clmd->sim_parms.firstframe = 1;
|
||||
clmd->sim_parms.lastframe = 250;
|
||||
clmd->sim_parms.vgroup_mass = 0;
|
||||
clmd->coll_parms.self_friction = 5.0;
|
||||
clmd->coll_parms.friction = 10.0;
|
||||
clmd->coll_parms.loop_count = 1;
|
||||
@@ -175,13 +176,91 @@ void cloth_init ( ClothModifierData *clmd )
|
||||
// also from softbodies
|
||||
clmd->sim_parms.maxgoal = 1.0f;
|
||||
clmd->sim_parms.mingoal = 0.0f;
|
||||
clmd->sim_parms.defgoal = 0.7f;
|
||||
clmd->sim_parms.defgoal = 0.0f;
|
||||
clmd->sim_parms.goalspring = 100.0f;
|
||||
clmd->sim_parms.goalfrict = 0.0f;
|
||||
|
||||
clmd->sim_parms.cache = NULL;
|
||||
}
|
||||
|
||||
|
||||
BVH *bvh_build_from_cloth (ClothModifierData *clmd, float epsilon)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
BVH *bvh=NULL;
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
ClothVertex *verts = NULL;
|
||||
|
||||
if(!clmd)
|
||||
return NULL;
|
||||
|
||||
cloth = clmd->clothObject;
|
||||
|
||||
if(!cloth)
|
||||
return NULL;
|
||||
|
||||
verts = cloth->verts;
|
||||
|
||||
bvh = MEM_callocN(sizeof(BVH), "BVH");
|
||||
if (bvh == NULL)
|
||||
{
|
||||
printf("bvh: Out of memory.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// springs = cloth->springs;
|
||||
// numsprings = cloth->numsprings;
|
||||
|
||||
bvh->flags = 0;
|
||||
bvh->leaf_tree = NULL;
|
||||
bvh->leaf_root = NULL;
|
||||
bvh->tree = NULL;
|
||||
|
||||
bvh->epsilon = epsilon;
|
||||
bvh->numfaces = cloth->numfaces;
|
||||
bvh->mfaces = cloth->mfaces;
|
||||
|
||||
bvh->numverts = cloth->numverts;
|
||||
|
||||
bvh->current_x = MEM_callocN ( sizeof ( MVert ) * bvh->numverts, "bvh->current_x" );
|
||||
bvh->current_xold = MEM_callocN ( sizeof ( MVert ) * bvh->numverts, "bvh->current_xold" );
|
||||
|
||||
for(i = 0; i < bvh->numverts; i++)
|
||||
{
|
||||
VECCOPY(bvh->current_x[i].co, verts[i].tx);
|
||||
VECCOPY(bvh->current_xold[i].co, verts[i].txold);
|
||||
}
|
||||
|
||||
bvh_build (bvh);
|
||||
|
||||
return bvh;
|
||||
}
|
||||
|
||||
void bvh_update_from_cloth(ClothModifierData *clmd, int moving)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
BVH *bvh = cloth->tree;
|
||||
ClothVertex *verts = cloth->verts;
|
||||
|
||||
if(!bvh)
|
||||
return;
|
||||
|
||||
if(cloth->numverts!=bvh->numverts)
|
||||
return;
|
||||
|
||||
if(cloth->verts)
|
||||
{
|
||||
for(i = 0; i < bvh->numverts; i++)
|
||||
{
|
||||
VECCOPY(bvh->current_x[i].co, verts[i].tx);
|
||||
VECCOPY(bvh->current_xold[i].co, verts[i].txold);
|
||||
}
|
||||
}
|
||||
|
||||
bvh_update(bvh, moving);
|
||||
}
|
||||
|
||||
// unused in the moment, cloth needs quads from mesh
|
||||
DerivedMesh *CDDM_convert_to_triangle ( DerivedMesh *dm )
|
||||
{
|
||||
@@ -433,9 +512,9 @@ static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr
|
||||
|
||||
for(a = 0; a < cloth->numverts; a++)
|
||||
{
|
||||
fwrite(&cloth->verts[a].x, sizeof(float),4,fp);
|
||||
fwrite(&cloth->verts[a].xconst, sizeof(float),4,fp);
|
||||
fwrite(&cloth->verts[a].v, sizeof(float),4,fp);
|
||||
fwrite(&cloth->verts[a].x, sizeof(float),3,fp);
|
||||
fwrite(&cloth->verts[a].xconst, sizeof(float),3,fp);
|
||||
fwrite(&cloth->verts[a].v, sizeof(float),3,fp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
@@ -458,17 +537,17 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr)
|
||||
else {
|
||||
for(a = 0; a < cloth->numverts; a++)
|
||||
{
|
||||
if(fread(&cloth->verts[a].x, sizeof(float), 4, fp) != 4)
|
||||
if(fread(&cloth->verts[a].x, sizeof(float), 3, fp) != 3)
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
if(fread(&cloth->verts[a].xconst, sizeof(float), 4, fp) != 4)
|
||||
if(fread(&cloth->verts[a].xconst, sizeof(float), 3, fp) != 3)
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
if(fread(&cloth->verts[a].v, sizeof(float), 4, fp) != 4)
|
||||
if(fread(&cloth->verts[a].v, sizeof(float), 3, fp) != 3)
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -656,7 +735,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
|
||||
solvers [clmd->sim_parms.solver_type].solver ( ob, framenr, clmd, effectors );
|
||||
|
||||
tend();
|
||||
printf ( "Cloth simulation time: %f\n", ( float ) tval() );
|
||||
// printf ( "Cloth simulation time: %f\n", ( float ) tval() );
|
||||
|
||||
cloth_write_cache(ob, clmd, framenr);
|
||||
|
||||
@@ -830,7 +909,13 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short
|
||||
{
|
||||
verts->goal = dvert->dw [j].weight;
|
||||
|
||||
goalfac= ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal );
|
||||
goalfac= 1.0f;
|
||||
|
||||
/*
|
||||
// Kicking goal factor to simplify things...who uses that anyway?
|
||||
// ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal );
|
||||
*/
|
||||
|
||||
verts->goal = ( float ) pow ( verts->goal , 4.0f );
|
||||
|
||||
if ( dvert->dw [j].weight >=SOFTGOALSNAP )
|
||||
@@ -905,7 +990,7 @@ static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMes
|
||||
verts->impulse_count = 0;
|
||||
VECCOPY ( verts->impulse, tnull );
|
||||
}
|
||||
clmd->clothObject->tree = bvh_build ( clmd,clmd->coll_parms.epsilon );
|
||||
clmd->clothObject->tree = bvh_build_from_cloth ( clmd,clmd->coll_parms.epsilon );
|
||||
|
||||
}
|
||||
|
||||
@@ -1012,7 +1097,7 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh
|
||||
if ( solvers [clmd->sim_parms.solver_type].init )
|
||||
solvers [clmd->sim_parms.solver_type].init ( ob, clmd );
|
||||
|
||||
clmd->clothObject->tree = bvh_build ( clmd, clmd->coll_parms.epsilon );
|
||||
clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms.epsilon );
|
||||
|
||||
cloth_write_cache(ob, clmd, framenr-1);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,72 @@
|
||||
|
||||
#include "Bullet-C-Api.h"
|
||||
|
||||
// step is limited from 0 (frame start position) to 1 (frame end position)
|
||||
void collision_move_object(CollisionModifierData *collmd, float step, float prevstep)
|
||||
{
|
||||
float tv[3] = {0,0,0};
|
||||
unsigned int i = 0;
|
||||
|
||||
for ( i = 0; i < collmd->numverts; i++ )
|
||||
{
|
||||
VECSUB(tv, collmd->xnew[i].co, collmd->x[i].co);
|
||||
VECADDS(collmd->current_x[i].co, collmd->x[i].co, tv, prevstep);
|
||||
VECADDS(collmd->current_xnew[i].co, collmd->x[i].co, tv, step);
|
||||
VECSUB(collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co);
|
||||
}
|
||||
}
|
||||
|
||||
BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon)
|
||||
{
|
||||
BVH *bvh=NULL;
|
||||
|
||||
bvh = MEM_callocN(sizeof(BVH), "BVH");
|
||||
if (bvh == NULL)
|
||||
{
|
||||
printf("bvh: Out of memory.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bvh->flags = 0;
|
||||
bvh->leaf_tree = NULL;
|
||||
bvh->leaf_root = NULL;
|
||||
bvh->tree = NULL;
|
||||
|
||||
bvh->epsilon = epsilon;
|
||||
bvh->numfaces = numfaces;
|
||||
bvh->mfaces = mfaces;
|
||||
|
||||
// we have no faces, we save seperate points
|
||||
if(!mfaces)
|
||||
{
|
||||
bvh->numfaces = numverts;
|
||||
}
|
||||
|
||||
bvh->numverts = numverts;
|
||||
bvh->current_x = MEM_dupallocN(x);
|
||||
bvh->current_xold = MEM_dupallocN(x);
|
||||
|
||||
bvh_build(bvh);
|
||||
|
||||
return bvh;
|
||||
}
|
||||
|
||||
void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving)
|
||||
{
|
||||
if(!bvh)
|
||||
return;
|
||||
|
||||
if(numverts!=bvh->numverts)
|
||||
return;
|
||||
|
||||
if(x)
|
||||
memcpy(bvh->current_xold, x, sizeof(MVert) * numverts);
|
||||
|
||||
if(xnew)
|
||||
memcpy(bvh->current_x, xnew, sizeof(MVert) * numverts);
|
||||
|
||||
bvh_update(bvh, moving);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsl_poly_solve_cubic -
|
||||
@@ -519,7 +584,7 @@ int cloth_collision_response_moving_edges(ClothModifierData *clmd, ClothModifier
|
||||
|
||||
}
|
||||
|
||||
void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2)
|
||||
void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
|
||||
{
|
||||
CollPair *collpair = NULL;
|
||||
Cloth *cloth1=NULL, *cloth2=NULL;
|
||||
@@ -667,7 +732,7 @@ int cloth_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_cl
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2)
|
||||
void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
|
||||
{
|
||||
EdgeCollPair edgecollpair;
|
||||
Cloth *cloth1=NULL, *cloth2=NULL;
|
||||
@@ -802,7 +867,7 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co
|
||||
}
|
||||
}
|
||||
|
||||
void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2)
|
||||
void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
|
||||
{
|
||||
CollPair collpair;
|
||||
Cloth *cloth1=NULL, *cloth2=NULL;
|
||||
@@ -896,7 +961,7 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col
|
||||
}
|
||||
}
|
||||
|
||||
void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2)
|
||||
void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
|
||||
{
|
||||
// TODO: check for adjacent
|
||||
cloth_collision_moving_edges(clmd, coll_clmd, tree1, tree2);
|
||||
@@ -943,7 +1008,7 @@ void cloth_update_collision_objects(float step)
|
||||
}
|
||||
|
||||
// update BVH of collision object
|
||||
bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING
|
||||
bvh_update_from_cloth(coll_clmd, 0); // 0 means STATIC, 1 means MOVING
|
||||
}
|
||||
else
|
||||
printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
|
||||
@@ -972,6 +1037,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cloth = clmd->clothObject;
|
||||
verts = cloth->verts;
|
||||
cloth_bvh = (BVH *) cloth->tree;
|
||||
@@ -983,7 +1049,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt)
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// update cloth bvh
|
||||
bvh_update(clmd, cloth_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function)
|
||||
bvh_update_from_cloth(clmd, 0); // 0 means STATIC, 1 means MOVING (see later in this function)
|
||||
|
||||
// update collision objects
|
||||
cloth_update_collision_objects(step);
|
||||
@@ -1075,12 +1141,12 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt)
|
||||
clmd->coll_parms.collision_list = NULL;
|
||||
}
|
||||
|
||||
printf("ic: %d\n", ic);
|
||||
// printf("ic: %d\n", ic);
|
||||
rounds++;
|
||||
}
|
||||
while(result && (CLOTH_MAX_THRESHOLD>rounds));
|
||||
|
||||
printf("\n");
|
||||
// printf("\n");
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// update positions
|
||||
@@ -1100,7 +1166,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt)
|
||||
|
||||
|
||||
// update cloth bvh
|
||||
bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING
|
||||
bvh_update_from_cloth(clmd, 1); // 0 means STATIC, 1 means MOVING
|
||||
|
||||
// update moving bvh for collision object once
|
||||
for (base = G.scene->base.first; base; base = base->next)
|
||||
@@ -1119,7 +1185,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt)
|
||||
{
|
||||
BVH *coll_bvh = coll_clmd->clothObject->tree;
|
||||
|
||||
bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING
|
||||
bvh_update_from_cloth(coll_clmd, 1); // 0 means STATIC, 1 means MOVING
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1204,7 +1270,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt)
|
||||
}
|
||||
|
||||
// update cloth bvh
|
||||
bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING
|
||||
bvh_update_from_cloth(clmd, 1); // 0 means STATIC, 1 means MOVING
|
||||
|
||||
|
||||
// free collision list
|
||||
@@ -1223,7 +1289,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt)
|
||||
clmd->coll_parms.collision_list = NULL;
|
||||
}
|
||||
|
||||
printf("ic: %d\n", ic);
|
||||
// printf("ic: %d\n", ic);
|
||||
rounds++;
|
||||
}
|
||||
while(result && (CLOTH_MAX_THRESHOLD>rounds));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* collision.c
|
||||
/* kdop.c
|
||||
*
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_cloth_types.h"
|
||||
#include "DNA_key_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
@@ -58,7 +59,7 @@
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_collisions.h"
|
||||
#include "BKE_cloth.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
@@ -164,13 +165,13 @@ static int size_threshold = 16;
|
||||
/*
|
||||
* Common methods for all algorithms
|
||||
*/
|
||||
void bvh_exchange(CollisionTree **a, int i, int j)
|
||||
DO_INLINE void bvh_exchange(CollisionTree **a, int i, int j)
|
||||
{
|
||||
CollisionTree *t=a[i];
|
||||
a[i]=a[j];
|
||||
a[j]=t;
|
||||
}
|
||||
int floor_lg(int a)
|
||||
DO_INLINE int floor_lg(int a)
|
||||
{
|
||||
return (int)(floor(log(a)/log(2)));
|
||||
}
|
||||
@@ -195,7 +196,7 @@ static void bvh_insertionsort(CollisionTree **a, int lo, int hi, int axis)
|
||||
}
|
||||
}
|
||||
|
||||
static int bvh_partition(CollisionTree **a, int lo, int hi, CollisionTree *x, int axis)
|
||||
static int bvh_partition(CollisionTree **a, int lo, int hi, CollisionTree * x, int axis)
|
||||
{
|
||||
int i=lo, j=hi;
|
||||
while (1)
|
||||
@@ -215,7 +216,7 @@ static int bvh_partition(CollisionTree **a, int lo, int hi, CollisionTree *x, in
|
||||
*/
|
||||
static void bvh_downheap(CollisionTree **a, int i, int n, int lo, int axis)
|
||||
{
|
||||
CollisionTree *d = a[lo+i-1];
|
||||
CollisionTree * d = a[lo+i-1];
|
||||
int child;
|
||||
while (i<=n/2)
|
||||
{
|
||||
@@ -293,7 +294,7 @@ static void bvh_introsort_loop (CollisionTree **a, int lo, int hi, int depth_lim
|
||||
}
|
||||
}
|
||||
|
||||
void bvh_sort(CollisionTree **a0, int begin, int end, int axis)
|
||||
DO_INLINE void bvh_sort(CollisionTree **a0, int begin, int end, int axis)
|
||||
{
|
||||
if (begin < end)
|
||||
{
|
||||
@@ -302,7 +303,7 @@ void bvh_sort(CollisionTree **a0, int begin, int end, int axis)
|
||||
bvh_insertionsort(a, begin, end, axis);
|
||||
}
|
||||
}
|
||||
void bvh_sort_along_axis(CollisionTree **face_list, int start, int end, int axis)
|
||||
DO_INLINE void bvh_sort_along_axis(CollisionTree **face_list, int start, int end, int axis)
|
||||
{
|
||||
bvh_sort(face_list, start, end, axis);
|
||||
}
|
||||
@@ -330,11 +331,11 @@ void bvh_free(BVH * bvh)
|
||||
BLI_linklist_free(bvh->tree,NULL);
|
||||
bvh->tree = NULL;
|
||||
|
||||
if(bvh->x)
|
||||
MEM_freeN(bvh->x);
|
||||
if(bvh->xnew)
|
||||
MEM_freeN(bvh->xnew);
|
||||
|
||||
if(bvh->current_x)
|
||||
MEM_freeN(bvh->current_x);
|
||||
if(bvh->current_xold)
|
||||
MEM_freeN(bvh->current_xold);
|
||||
|
||||
MEM_freeN(bvh);
|
||||
bvh = NULL;
|
||||
}
|
||||
@@ -342,7 +343,7 @@ void bvh_free(BVH * bvh)
|
||||
|
||||
// only supports x,y,z axis in the moment
|
||||
// but we should use a plain and simple function here for speed sake
|
||||
int bvh_largest_axis(float *bv)
|
||||
DO_INLINE int bvh_largest_axis(float *bv)
|
||||
{
|
||||
float middle_point[3];
|
||||
|
||||
@@ -366,7 +367,7 @@ int bvh_largest_axis(float *bv)
|
||||
}
|
||||
|
||||
// depends on the fact that the BVH's for each face is already build
|
||||
void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
|
||||
DO_INLINE void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
|
||||
{
|
||||
float newmin,newmax;
|
||||
int i, j;
|
||||
@@ -390,62 +391,35 @@ void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces,
|
||||
}
|
||||
}
|
||||
|
||||
void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
|
||||
DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
|
||||
{
|
||||
MVert *tempMVert = bvh->x;
|
||||
float *tempBV = bv;
|
||||
float newminmax;
|
||||
int i, j, k;
|
||||
for (j = 0; j < numfaces; j++)
|
||||
{
|
||||
// 1 up to 4 vertices per leaf.
|
||||
for (k = 0; k < 4; k++)
|
||||
{
|
||||
int temp = tri[j]->point_index[k];
|
||||
|
||||
if(temp < 0)
|
||||
continue;
|
||||
|
||||
// for all Axes.
|
||||
for (i = KDOP_START; i < KDOP_END; i++)
|
||||
{
|
||||
newminmax = INPR(tempMVert[temp].co, KDOP_AXES[i]);
|
||||
if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
|
||||
tempBV[(2 * i)] = newminmax;
|
||||
if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
|
||||
tempBV[(2 * i) + 1] = newminmax;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
|
||||
{
|
||||
MVert *tempMVert = bvh->x;
|
||||
MVert *tempMVert2 = bvh->xnew;
|
||||
MFace *tempMFace = bvh->mfaces;
|
||||
float *tempBV = bv;
|
||||
float newminmax;
|
||||
int i, j, k;
|
||||
for (j = 0; j < numfaces; j++)
|
||||
{
|
||||
tempMFace = bvh->mfaces + (tri [j])->tri_index;
|
||||
// 3 or 4 vertices per face.
|
||||
for (k = 0; k < 4; k++)
|
||||
{
|
||||
int temp = tri[j]->point_index[k];
|
||||
|
||||
if(temp < 0)
|
||||
int temp = 0;
|
||||
// If this is a triangle.
|
||||
if (k == 3 && !tempMFace->v4)
|
||||
continue;
|
||||
|
||||
// TODO: other name for "temp" this gets all vertices of a face
|
||||
if (k == 0)
|
||||
temp = tempMFace->v1;
|
||||
else if (k == 1)
|
||||
temp = tempMFace->v2;
|
||||
else if (k == 2)
|
||||
temp = tempMFace->v3;
|
||||
else if (k == 3)
|
||||
temp = tempMFace->v4;
|
||||
// for all Axes.
|
||||
for (i = KDOP_START; i < KDOP_END; i++)
|
||||
{
|
||||
newminmax = INPR(tempMVert[temp].co, KDOP_AXES[i]);
|
||||
if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
|
||||
tempBV[(2 * i)] = newminmax;
|
||||
if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
|
||||
tempBV[(2 * i) + 1] = newminmax;
|
||||
|
||||
newminmax = INPR(tempMVert2[temp].co, KDOP_AXES[i]);
|
||||
newminmax = INPR(bvh->current_xold[temp].co, KDOP_AXES[i]);
|
||||
if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
|
||||
tempBV[(2 * i)] = newminmax;
|
||||
if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
|
||||
@@ -455,7 +429,51 @@ void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, floa
|
||||
}
|
||||
}
|
||||
|
||||
static void bvh_div_env_node(BVH * bvh, TreeNode *tree, CollisionTree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink)
|
||||
DO_INLINE void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
|
||||
{
|
||||
MFace *tempMFace = bvh->mfaces;
|
||||
float *tempBV = bv;
|
||||
float newminmax;
|
||||
int i, j, k;
|
||||
for (j = 0; j < numfaces; j++)
|
||||
{
|
||||
tempMFace = bvh->mfaces + (tri [j])->tri_index;
|
||||
// 3 or 4 vertices per face.
|
||||
for (k = 0; k < 4; k++)
|
||||
{
|
||||
int temp = 0;
|
||||
// If this is a triangle.
|
||||
if (k == 3 && !tempMFace->v4)
|
||||
continue;
|
||||
// TODO: other name for "temp" this gets all vertices of a face
|
||||
if (k == 0)
|
||||
temp = tempMFace->v1;
|
||||
else if (k == 1)
|
||||
temp = tempMFace->v2;
|
||||
else if (k == 2)
|
||||
temp = tempMFace->v3;
|
||||
else if (k == 3)
|
||||
temp = tempMFace->v4;
|
||||
// for all Axes.
|
||||
for (i = KDOP_START; i < KDOP_END; i++)
|
||||
{
|
||||
newminmax = INPR(bvh->current_xold[temp].co, KDOP_AXES[i]);
|
||||
if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
|
||||
tempBV[(2 * i)] = newminmax;
|
||||
if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
|
||||
tempBV[(2 * i) + 1] = newminmax;
|
||||
|
||||
newminmax = INPR(bvh->current_x[temp].co, KDOP_AXES[i]);
|
||||
if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
|
||||
tempBV[(2 * i)] = newminmax;
|
||||
if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
|
||||
tempBV[(2 * i) + 1] = newminmax;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bvh_div_env_node(BVH *bvh, CollisionTree *tree, CollisionTree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink)
|
||||
{
|
||||
int i = 0;
|
||||
CollisionTree *newtree = NULL;
|
||||
@@ -523,17 +541,26 @@ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, CollisionTree **face_lis
|
||||
return;
|
||||
}
|
||||
|
||||
// mfaces is allowed to be null
|
||||
// just vertexes are used if mfaces=NULL
|
||||
BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces)
|
||||
/* function cannot be directly called - needs alloced bvh */
|
||||
void bvh_build (BVH *bvh)
|
||||
{
|
||||
unsigned int i = 0, j = 0;
|
||||
unsigned int i = 0, j = 0, k = 0;
|
||||
CollisionTree **face_list=NULL;
|
||||
CollisionTree *tree=NULL;
|
||||
LinkNode *nlink = NULL;
|
||||
|
||||
tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
|
||||
// TODO: check succesfull alloc
|
||||
BLI_linklist_append(&bvh->tree, tree);
|
||||
|
||||
nlink = bvh->tree;
|
||||
|
||||
if (tree == NULL)
|
||||
{
|
||||
printf("bvh_build: Out of memory for nodes.\n");
|
||||
bvh_free(bvh);
|
||||
return;
|
||||
}
|
||||
bvh->root = bvh->tree->link;
|
||||
bvh->root->isleaf = 0;
|
||||
bvh->root->parent = NULL;
|
||||
@@ -541,25 +568,7 @@ BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces)
|
||||
|
||||
if(bvh->numfaces<=1)
|
||||
{
|
||||
// Why that? --> only one face there
|
||||
if(bvh->mfaces)
|
||||
{
|
||||
bvh->root->point_index[0] = mfaces[0].v1;
|
||||
bvh->root->point_index[1] = mfaces[0].v2;
|
||||
bvh->root->point_index[2] = mfaces[0].v3;
|
||||
if(mfaces[0].v4)
|
||||
bvh->root->point_index[3] = mfaces[0].v4;
|
||||
else
|
||||
bvh->root->point_index[3] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bvh->root->point_index[0] = 0;
|
||||
bvh->root->point_index[1] = -1;
|
||||
bvh->root->point_index[2] = -1;
|
||||
bvh->root->point_index[3] = -1;
|
||||
}
|
||||
|
||||
bvh->root->tri_index = 0; // Why that? --> only one face there
|
||||
bvh->root->isleaf = 1;
|
||||
bvh->root->traversed = 0;
|
||||
bvh->root->count_nodes = 0;
|
||||
@@ -569,46 +578,28 @@ BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces)
|
||||
bvh->root->prevLeaf = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// create face boxes
|
||||
face_list = MEM_callocN (bvh->numfaces * sizeof (CollisionTree *), "CollisionTree");
|
||||
if (face_list == NULL)
|
||||
{
|
||||
printf("bvh_build: Out of memory for face_list.\n");
|
||||
bvh_free(bvh);
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// create face boxes
|
||||
for(i = 0; i < bvh->numfaces; i++)
|
||||
for(i = 0, k = 0; i < bvh->numfaces; i++)
|
||||
{
|
||||
LinkNode *tnlink = NULL;
|
||||
|
||||
LinkNode *tnlink;
|
||||
|
||||
tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
|
||||
// TODO: check succesfull alloc
|
||||
|
||||
tnlink = BLI_linklist_append_fast(&nlink->next, tree);
|
||||
|
||||
face_list[i] = tree;
|
||||
|
||||
if(bvh->mfaces)
|
||||
{
|
||||
tree->point_index[0] = mfaces[i].v1;
|
||||
tree->point_index[1] = mfaces[i].v2;
|
||||
tree->point_index[2] = mfaces[i].v3;
|
||||
if(mfaces[i].v4)
|
||||
tree->point_index[3] = mfaces[i].v4;
|
||||
else
|
||||
tree->point_index[3] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree->point_index[0] = i;
|
||||
tree->point_index[1] = -1;
|
||||
tree->point_index[2] = -1;
|
||||
tree->point_index[3] = -1;
|
||||
}
|
||||
|
||||
tree->tri_index = i;
|
||||
tree->isleaf = 1;
|
||||
tree->nextLeaf = NULL;
|
||||
tree->prevLeaf = bvh->leaf_tree;
|
||||
@@ -641,170 +632,18 @@ BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces)
|
||||
|
||||
// build root bvh
|
||||
bvh_calc_DOP_hull_from_faces(bvh, face_list, bvh->numfaces, bvh->root->bv);
|
||||
|
||||
|
||||
// This is the traversal function.
|
||||
bvh_div_env_node(bvh, bvh->root, face_list, 0, bvh->numfaces-1, 0, nlink);
|
||||
if (face_list)
|
||||
MEM_freeN(face_list);
|
||||
|
||||
// BLI_edgehash_free(edgehash, NULL);
|
||||
}
|
||||
|
||||
|
||||
return bvh;
|
||||
}
|
||||
|
||||
BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon)
|
||||
{
|
||||
BVH *bvh=NULL;
|
||||
CollisionTree *tree=NULL;
|
||||
|
||||
bvh = MEM_callocN(sizeof(BVH), "BVH");
|
||||
if (bvh == NULL)
|
||||
{
|
||||
printf("bvh: Out of memory.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bvh->flags = 0;
|
||||
bvh->leaf_tree = NULL;
|
||||
bvh->leaf_root = NULL;
|
||||
bvh->tree = NULL;
|
||||
|
||||
bvh->epsilon = epsilon;
|
||||
bvh->numfaces = numfaces;
|
||||
bvh->mfaces = mfaces;
|
||||
|
||||
// we have no faces, we save seperate points
|
||||
if(!mfaces)
|
||||
{
|
||||
bvh->numfaces = numverts;
|
||||
}
|
||||
|
||||
bvh->numverts = numverts;
|
||||
bvh->xnew = MEM_dupallocN(x);
|
||||
bvh->x = MEM_dupallocN(x);
|
||||
tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
|
||||
|
||||
if (tree == NULL)
|
||||
{
|
||||
printf("bvh_build: Out of memory for nodes.\n");
|
||||
bvh_free(bvh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLI_linklist_append(&bvh->tree, tree);
|
||||
|
||||
return bvh_build(bvh, mfaces, numfaces);
|
||||
}
|
||||
|
||||
|
||||
BVH *bvh_build_from_float3 (MFace *mfaces, unsigned int numfaces, float (*x)[3], unsigned int numverts, float epsilon)
|
||||
{
|
||||
BVH *bvh=NULL;
|
||||
CollisionTree *tree=NULL;
|
||||
unsigned int i = 0;
|
||||
|
||||
bvh = MEM_callocN(sizeof(BVH), "BVH");
|
||||
if (bvh == NULL)
|
||||
{
|
||||
printf("bvh: Out of memory.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bvh->flags = 0;
|
||||
bvh->leaf_tree = NULL;
|
||||
bvh->leaf_root = NULL;
|
||||
bvh->tree = NULL;
|
||||
|
||||
bvh->epsilon = epsilon;
|
||||
bvh->numfaces = numfaces;
|
||||
bvh->mfaces = mfaces;
|
||||
|
||||
// we have no faces, we save seperate points
|
||||
if(!mfaces)
|
||||
{
|
||||
bvh->numfaces = numverts;
|
||||
}
|
||||
|
||||
bvh->numverts = numverts;
|
||||
bvh->xnew = (MVert *)MEM_callocN(sizeof(MVert)*numverts, "BVH MVert");
|
||||
|
||||
for(i = 0; i < numverts; i++)
|
||||
{
|
||||
VECCOPY(bvh->xnew[i].co, x[i]);
|
||||
}
|
||||
|
||||
bvh->x = MEM_dupallocN(bvh->xnew);
|
||||
|
||||
tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
|
||||
|
||||
if (tree == NULL)
|
||||
{
|
||||
printf("bvh_build: Out of memory for nodes.\n");
|
||||
bvh_free(bvh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLI_linklist_append(&bvh->tree, tree);
|
||||
|
||||
return bvh_build(bvh, mfaces, numfaces);
|
||||
}
|
||||
|
||||
BVH *bvh_build_from_float4 (MFace *mfaces, unsigned int numfaces, float (*x)[4], unsigned int numverts, float epsilon)
|
||||
{
|
||||
BVH *bvh=NULL;
|
||||
CollisionTree *tree=NULL;
|
||||
unsigned int i = 0;
|
||||
|
||||
bvh = MEM_callocN(sizeof(BVH), "BVH");
|
||||
if (bvh == NULL)
|
||||
{
|
||||
printf("bvh: Out of memory.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bvh->flags = 0;
|
||||
bvh->leaf_tree = NULL;
|
||||
bvh->leaf_root = NULL;
|
||||
bvh->tree = NULL;
|
||||
|
||||
bvh->epsilon = epsilon;
|
||||
bvh->numfaces = numfaces;
|
||||
bvh->mfaces = mfaces;
|
||||
|
||||
// we have no faces, we save seperate points
|
||||
if(!mfaces)
|
||||
{
|
||||
bvh->numfaces = numverts;
|
||||
}
|
||||
|
||||
bvh->numverts = numverts;
|
||||
bvh->xnew = (MVert *)MEM_callocN(sizeof(MVert)*numverts, "BVH MVert");
|
||||
|
||||
for(i = 0; i < numverts; i++)
|
||||
{
|
||||
VECCOPY(bvh->xnew[i].co, x[i]);
|
||||
}
|
||||
|
||||
bvh->x = MEM_dupallocN(bvh->xnew);
|
||||
|
||||
tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
|
||||
|
||||
if (tree == NULL)
|
||||
{
|
||||
printf("bvh_build: Out of memory for nodes.\n");
|
||||
bvh_free(bvh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLI_linklist_append(&bvh->tree, tree);
|
||||
|
||||
return bvh_build(bvh, mfaces, numfaces);
|
||||
}
|
||||
|
||||
// bvh_overlap - is it possbile for 2 bv's to collide ?
|
||||
int bvh_overlap(float *bv1, float *bv2)
|
||||
DO_INLINE int bvh_overlap(float *bv1, float *bv2)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = KDOP_START; i < KDOP_END; i++)
|
||||
@@ -823,6 +662,7 @@ int bvh_overlap(float *bv1, float *bv2)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* bvh_traverse - traverse two bvh trees looking for potential collisions.
|
||||
*
|
||||
@@ -830,9 +670,18 @@ int bvh_overlap(float *bv1, float *bv2)
|
||||
* every other triangle that doesn't require any realloc, but uses
|
||||
* much memory
|
||||
*/
|
||||
int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collision_list)
|
||||
int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response)
|
||||
{
|
||||
int i = 0, ret = 0;
|
||||
int i = 0, ret=0;
|
||||
|
||||
/*
|
||||
// Shouldn't be possible
|
||||
if(!tree1 || !tree2)
|
||||
{
|
||||
printf("Error: no tree there\n");
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
if (bvh_overlap(tree1->bv, tree2->bv))
|
||||
{
|
||||
// Check if this node in the first tree is a leaf
|
||||
@@ -841,85 +690,11 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio
|
||||
// Check if this node in the second tree a leaf
|
||||
if (tree2->isleaf)
|
||||
{
|
||||
//////////////////////////////////
|
||||
// TODO: check for 3rd point if zero (triangle)!!!
|
||||
//////////////////////////////////
|
||||
// Provide the collision response.
|
||||
|
||||
CollisionPair *collpair = NULL;
|
||||
|
||||
if(tree1 != tree2) // do not collide same points
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// FIRST FACE
|
||||
////////////////////////////////////////
|
||||
|
||||
// save potential colliding triangles
|
||||
collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair");
|
||||
|
||||
VECCOPY(collpair->point_indexA, tree1->point_index);
|
||||
VECCOPY(collpair->point_indexB, tree2->point_index);
|
||||
|
||||
// we use prepend because lots of insertions at end
|
||||
// of list are horrible slow!
|
||||
BLI_linklist_prepend(&collision_list[0], collpair);
|
||||
|
||||
////////////////////////////////////////
|
||||
// SECOND FACE
|
||||
////////////////////////////////////////
|
||||
if(tree1->point_index[3]) // check for quad face
|
||||
{
|
||||
// save potential colliding triangles
|
||||
collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair");
|
||||
|
||||
VECCOPY(collpair->point_indexA, tree1->point_index);
|
||||
collpair->point_indexA[2] = tree1->point_index[3];
|
||||
|
||||
VECCOPY(collpair->point_indexB, tree2->point_index);
|
||||
|
||||
// we use prepend because lots of insertions at end
|
||||
// of list are horrible slow!
|
||||
BLI_linklist_prepend(&collision_list[0], collpair);
|
||||
}
|
||||
////////////////////////////////////////
|
||||
// THIRD FACE
|
||||
////////////////////////////////////////
|
||||
if(tree2->point_index[3]) // check for quad face
|
||||
{
|
||||
// save potential colliding triangles
|
||||
collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair");
|
||||
|
||||
VECCOPY(collpair->point_indexA, tree1->point_index);
|
||||
|
||||
VECCOPY(collpair->point_indexB, tree2->point_index);
|
||||
collpair->point_indexB[2] = tree2->point_index[3];
|
||||
|
||||
// we use prepend because lots of insertions at end
|
||||
// of list are horrible slow!
|
||||
BLI_linklist_prepend(&collision_list[0], collpair);
|
||||
}
|
||||
////////////////////////////////////////
|
||||
// FOURTH FACE
|
||||
////////////////////////////////////////
|
||||
if(tree1->point_index[3] && tree1->point_index[3]) // check for quad face
|
||||
{
|
||||
// save potential colliding triangles
|
||||
collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair");
|
||||
|
||||
VECCOPY(collpair->point_indexA, tree1->point_index);
|
||||
collpair->point_indexA[2] = tree1->point_index[3];
|
||||
|
||||
VECCOPY(collpair->point_indexB, tree2->point_index);
|
||||
collpair->point_indexB[2] = tree2->point_index[3];
|
||||
|
||||
// we use prepend because lots of insertions at end
|
||||
// of list are horrible slow!
|
||||
BLI_linklist_prepend(&collision_list[0], collpair);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
if(collision_response)
|
||||
collision_response (clmd, coll_clmd, tree1, tree2);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -927,7 +702,7 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
// Only traverse nodes that exist.
|
||||
if (tree2->nodes[i] && (bvh_traverse (tree1, tree2->nodes[i], collision_list)))
|
||||
if (tree2->nodes[i] && bvh_traverse (clmd, coll_clmd, tree1, tree2->nodes[i], step, collision_response))
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
@@ -938,7 +713,7 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
// Only traverse nodes that exist.
|
||||
if (tree1->nodes [i] && (bvh_traverse (tree1->nodes[i], tree2, collision_list)))
|
||||
if (tree1->nodes [i] && bvh_traverse (clmd, coll_clmd, tree1->nodes[i], tree2, step, collision_response))
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
@@ -949,7 +724,7 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio
|
||||
|
||||
// bottom up update of bvh tree:
|
||||
// join the 4 children here
|
||||
void bvh_join(CollisionTree *tree)
|
||||
void bvh_join(CollisionTree * tree)
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
if (!tree)
|
||||
@@ -979,10 +754,10 @@ void bvh_join(CollisionTree *tree)
|
||||
}
|
||||
|
||||
// update static bvh
|
||||
// needs new positions in bvh->x, bvh->xnew
|
||||
/* you have to update the bvh position before calling this function */
|
||||
void bvh_update(BVH * bvh, int moving)
|
||||
{
|
||||
TreeNode *leaf, *parent;
|
||||
CollisionTree *leaf, *parent;
|
||||
int traversecheck = 1; // if this is zero we don't go further
|
||||
unsigned int j = 0;
|
||||
|
||||
@@ -993,7 +768,6 @@ void bvh_update(BVH * bvh, int moving)
|
||||
{
|
||||
leaf->parent->traversed = 0;
|
||||
}
|
||||
|
||||
if(!moving)
|
||||
bvh_calc_DOP_hull_static(bvh, &leaf, 1, leaf->bv);
|
||||
else
|
||||
@@ -1034,70 +808,3 @@ void bvh_update(BVH * bvh, int moving)
|
||||
}
|
||||
}
|
||||
|
||||
void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving)
|
||||
{
|
||||
if(!bvh)
|
||||
return;
|
||||
|
||||
if(numverts!=bvh->numverts)
|
||||
return;
|
||||
|
||||
if(x)
|
||||
memcpy(bvh->x, x, sizeof(MVert) * numverts);
|
||||
|
||||
if(xnew)
|
||||
memcpy(bvh->xnew, xnew, sizeof(MVert) * numverts);
|
||||
|
||||
bvh_update(bvh, moving);
|
||||
}
|
||||
|
||||
void bvh_update_from_float3(BVH * bvh, float (*x)[3], unsigned int numverts, float (*xnew)[3], int moving)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
if(!bvh)
|
||||
return;
|
||||
|
||||
if(numverts!=bvh->numverts)
|
||||
return;
|
||||
|
||||
if(x)
|
||||
{
|
||||
for(i = 0; i < numverts; i++)
|
||||
VECCOPY(bvh->x[i].co, x[i]);
|
||||
}
|
||||
|
||||
if(xnew)
|
||||
{
|
||||
for(i = 0; i < numverts; i++)
|
||||
VECCOPY(bvh->xnew[i].co, xnew[i]);
|
||||
}
|
||||
|
||||
bvh_update(bvh, moving);
|
||||
}
|
||||
|
||||
void bvh_update_from_float4(BVH * bvh, float (*x)[4], unsigned int numverts, float (*xnew)[4], int moving)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
if(!bvh)
|
||||
return;
|
||||
|
||||
if(numverts!=bvh->numverts)
|
||||
return;
|
||||
|
||||
if(x)
|
||||
{
|
||||
for(i = 0; i < numverts; i++)
|
||||
VECCOPY(bvh->x[i].co, x[i]);
|
||||
}
|
||||
|
||||
if(xnew)
|
||||
{
|
||||
for(i = 0; i < numverts; i++)
|
||||
VECCOPY(bvh->xnew[i].co, xnew[i]);
|
||||
}
|
||||
|
||||
bvh_update(bvh, moving);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_anim.h"
|
||||
#include "BKE_bad_level_calls.h"
|
||||
#include "BKE_cloth.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_global.h"
|
||||
@@ -5031,6 +5032,145 @@ static void clothModifier_freeData(ModifierData *md)
|
||||
}
|
||||
}
|
||||
|
||||
/* Collision */
|
||||
|
||||
static void collisionModifier_initData(ModifierData *md)
|
||||
{
|
||||
CollisionModifierData *collmd = (CollisionModifierData*) md;
|
||||
|
||||
collmd->x = NULL;
|
||||
collmd->xnew = NULL;
|
||||
collmd->current_x = NULL;
|
||||
collmd->current_xnew = NULL;
|
||||
collmd->current_v = NULL;
|
||||
collmd->time = -1;
|
||||
collmd->numverts = 0;
|
||||
collmd->tree = NULL;
|
||||
}
|
||||
|
||||
static void collisionModifier_freeData(ModifierData *md)
|
||||
{
|
||||
CollisionModifierData *collmd = (CollisionModifierData*) md;
|
||||
|
||||
if (collmd)
|
||||
{
|
||||
if(collmd->tree)
|
||||
bvh_free(collmd->tree);
|
||||
if(collmd->x)
|
||||
MEM_freeN(collmd->x);
|
||||
if(collmd->xnew)
|
||||
MEM_freeN(collmd->xnew);
|
||||
if(collmd->current_x)
|
||||
MEM_freeN(collmd->current_x);
|
||||
if(collmd->current_xnew)
|
||||
MEM_freeN(collmd->current_xnew);
|
||||
if(collmd->current_v)
|
||||
MEM_freeN(collmd->current_v);
|
||||
|
||||
collmd->x = NULL;
|
||||
collmd->xnew = NULL;
|
||||
collmd->current_x = NULL;
|
||||
collmd->current_xnew = NULL;
|
||||
collmd->current_v = NULL;
|
||||
collmd->time = -1;
|
||||
collmd->numverts = 0;
|
||||
collmd->tree = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int collisionModifier_dependsOnTime(ModifierData *md)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void collisionModifier_deformVerts(
|
||||
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
||||
float (*vertexCos)[3], int numVerts)
|
||||
{
|
||||
CollisionModifierData *collmd = (CollisionModifierData*) md;
|
||||
DerivedMesh *dm = NULL;
|
||||
float current_time = 0;
|
||||
unsigned int numverts = 0, i = 0;
|
||||
MVert *tempVert = NULL;
|
||||
|
||||
// if possible use/create DerivedMesh
|
||||
|
||||
if(derivedData) dm = CDDM_copy(derivedData);
|
||||
else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
|
||||
|
||||
if(!ob->pd)
|
||||
{
|
||||
printf("collisionModifier_deformVerts: Should not happen!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(dm)
|
||||
{
|
||||
CDDM_apply_vert_coords(dm, vertexCos);
|
||||
CDDM_calc_normals(dm);
|
||||
|
||||
|
||||
current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 );
|
||||
|
||||
if(current_time > collmd->time)
|
||||
{
|
||||
numverts = dm->getNumVerts ( dm );
|
||||
|
||||
// check if mesh has changed
|
||||
if(collmd->x && (numverts != collmd->numverts))
|
||||
collisionModifier_freeData((ModifierData *)collmd);
|
||||
|
||||
if(collmd->time == -1) // first time
|
||||
{
|
||||
collmd->x = dm->dupVertArray(dm); // frame start position
|
||||
|
||||
for ( i = 0; i < numverts; i++ )
|
||||
{
|
||||
// we save global positions
|
||||
Mat4MulVecfl ( ob->obmat, collmd->x[i].co );
|
||||
}
|
||||
|
||||
collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
|
||||
collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
|
||||
collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
|
||||
collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
|
||||
|
||||
collmd->numverts = numverts;
|
||||
|
||||
// TODO: epsilon
|
||||
// create bounding box hierarchy
|
||||
collmd->tree = bvh_build_from_mvert(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->current_x, numverts, ob->pd->pdef_sbift);
|
||||
}
|
||||
else if(numverts == collmd->numverts)
|
||||
{
|
||||
// put positions to old positions
|
||||
tempVert = collmd->x;
|
||||
collmd->x = collmd->xnew;
|
||||
collmd->xnew = tempVert;
|
||||
|
||||
memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
|
||||
|
||||
for ( i = 0; i < numverts; i++ )
|
||||
{
|
||||
// we save global positions
|
||||
Mat4MulVecfl ( ob->obmat, collmd->xnew[i].co );
|
||||
}
|
||||
|
||||
memcpy(collmd->current_xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
|
||||
memcpy(collmd->current_x, dm->getVertArray(dm), numverts*sizeof(MVert));
|
||||
|
||||
// recalc static bounding boxes
|
||||
bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0);
|
||||
}
|
||||
|
||||
collmd->time = current_time;
|
||||
}
|
||||
}
|
||||
|
||||
if(dm)
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
/* Boolean */
|
||||
|
||||
static void booleanModifier_copyData(ModifierData *md, ModifierData *target)
|
||||
@@ -6855,6 +6995,16 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
|
||||
// mti->copyData = clothModifier_copyData;
|
||||
mti->deformVerts = clothModifier_deformVerts;
|
||||
mti->updateDepgraph = clothModifier_updateDepgraph;
|
||||
|
||||
mti = INIT_TYPE(Collision);
|
||||
mti->type = eModifierTypeType_OnlyDeform;
|
||||
mti->initData = collisionModifier_initData;
|
||||
mti->flags = eModifierTypeFlag_AcceptsMesh
|
||||
| eModifierTypeFlag_RequiresOriginalData;
|
||||
mti->dependsOnTime = collisionModifier_dependsOnTime;
|
||||
mti->freeData = collisionModifier_freeData;
|
||||
mti->deformVerts = collisionModifier_deformVerts;
|
||||
// mti->copyData = collisionModifier_copyData;
|
||||
|
||||
mti = INIT_TYPE(Boolean);
|
||||
mti->type = eModifierTypeType_Nonconstructive;
|
||||
|
||||
@@ -106,7 +106,7 @@ typedef struct SimulationSettings
|
||||
float bending; /* Flexion spring stiffness. */
|
||||
float sim_time;
|
||||
int flags; /* flags, see CSIMSETT_FLAGS enum above. */
|
||||
short solver_type; /* which solver should be used? */
|
||||
short solver_type; /* which solver should be used? txold */
|
||||
short pad2;
|
||||
float maxgoal; /* see SB */
|
||||
float eff_force_scale;/* Scaling of effector forces (see softbody_calc_forces).*/
|
||||
|
||||
@@ -3184,7 +3184,7 @@ static void object_panel_deflection(Object *ob)
|
||||
PartDeflect *pd= ob->pd;
|
||||
|
||||
but = uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
|
||||
// uiButSetFunc(but, object_collision__enabletoggle, ob, NULL);
|
||||
uiButSetFunc(but, object_collision__enabletoggle, ob, NULL);
|
||||
|
||||
if(pd->deflect) {
|
||||
uiDefBut(block, LABEL, 0, "Particles", 160,140,75,20, NULL, 0.0, 0, 0, 0, "");
|
||||
@@ -4928,7 +4928,7 @@ static void object_panel_cloth(Object *ob)
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
int defCount;
|
||||
char *clvg1, *clvg2;
|
||||
char clmvg [] = "Mass Vertex Group%t|None%x0|";
|
||||
char clmvg [] = "Weight Paint Groups%t|";
|
||||
|
||||
val2=0;
|
||||
|
||||
@@ -4938,12 +4938,12 @@ static void object_panel_cloth(Object *ob)
|
||||
uiClearButLock();
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure");
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility");
|
||||
uiDefButI(block, NUM, B_CLOTH_RENEW, "Steps per Frame:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)");
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle coefficient (higher = less smaller but more big wrinkles)");
|
||||
uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)");
|
||||
uiBlockEndAlign(block);
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Spring damping");
|
||||
uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms.Cvi, 0.0, 10.0, 10, 0, "Apply gravitation to point movement");
|
||||
uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms.Cvi, 0.0, 10.0, 10, 0, "Air has normaly some thickness which slows falling things down");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
uiClearButLock();
|
||||
@@ -4959,7 +4959,7 @@ static void object_panel_cloth(Object *ob)
|
||||
|
||||
/* GOAL STUFF */
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Use Goal", 10,70,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position");
|
||||
uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Pinning of cloth", 10,70,150,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position");
|
||||
if (clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL)
|
||||
{
|
||||
if(ob->type==OB_MESH)
|
||||
@@ -4977,26 +4977,15 @@ static void object_panel_cloth(Object *ob)
|
||||
{
|
||||
clmd->sim_parms.vgroup_mass = 0;
|
||||
}
|
||||
else
|
||||
if(!clmd->sim_parms.vgroup_mass)
|
||||
clmd->sim_parms.vgroup_mass = 1;
|
||||
|
||||
sprintf (clvg2, "%s%s", clmvg, clvg1);
|
||||
|
||||
uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups");
|
||||
uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 160,70,150,20, &clmd->sim_parms.vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups");
|
||||
MEM_freeN (clvg1);
|
||||
MEM_freeN (clvg2);
|
||||
|
||||
if(clmd->sim_parms.vgroup_mass)
|
||||
{
|
||||
bDeformGroup *defGroup = BLI_findlink(&ob->defbase, clmd->sim_parms.vgroup_mass-1);
|
||||
if(defGroup)
|
||||
uiDefBut(block, BUT, B_DIFF, defGroup->name, 160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group");
|
||||
else
|
||||
uiDefBut(block, BUT, B_DIFF, "(no group)", 160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Vertex Group doesn't exist anymore");
|
||||
|
||||
uiDefIconBut(block, BUT, B_CLOTH_DEL_VG, ICON_X, 290,70,20,20, 0, 0, 0, 0, 0, "Disable use of vertex group");
|
||||
|
||||
}
|
||||
else
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5004,10 +4993,13 @@ static void object_panel_cloth(Object *ob)
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used");
|
||||
}
|
||||
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "G Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness");
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "Pin Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Pin (vertex target position) spring stiffness");
|
||||
/*
|
||||
// nobody is changing these ones anyway
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "G Damp:", 160,50,150,20, &clmd->sim_parms.goalfrict , 0.0, 50.0, 10, 0, "Goal (vertex target position) friction");
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "G Min:", 10,30,150,20, &clmd->sim_parms.mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range");
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "G Max:", 160,30,150,20, &clmd->sim_parms.maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range");
|
||||
*/
|
||||
}
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user