WIP commit, (just in case my HD breaks down). Don't expect anything to work. Code crashes and sim doesn't work ;)

This commit is contained in:
Daniel Genrich
2007-10-22 22:50:32 +00:00
parent dfd9c71b56
commit 5a6ffd8441
13 changed files with 1125 additions and 1023 deletions

View File

@@ -122,7 +122,7 @@ void cloth_free_modifier ( ClothModifierData *clmd );
void implicit_set_positions ( ClothModifierData *clmd );
// from cloth.c, needed for modifier.c
void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float ( *vertexCos ) [3], int numverts );
DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm);
////////////////////////////////////////////////
@@ -132,9 +132,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, fl
////////////////////////////////////////////////
void cloth_free_modifier ( ClothModifierData *clmd );
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 );
////////////////////////////////////////////////

View File

@@ -44,21 +44,21 @@
#include "BKE_DerivedMesh.h"
// used in kdop.c and 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;
CollisionTree;
typedef struct Tree TreeNode;
typedef struct CollisionTree TreeNode;
typedef struct BVH
{
@@ -79,7 +79,7 @@ BVH;
/* used for collisions in kdop.c and also collision.c*/
typedef struct CollisionPair
{
unsigned int indexA, indexB;
int point_indexA[4], point_indexB[4];
}
CollisionPair;
@@ -89,18 +89,21 @@ CollisionPair;
/////////////////////////////////////////////////
// builds bounding volume hierarchy
BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xold, unsigned int numverts, float epsilon);
BVH *bvh_build (MFace *mfaces, unsigned int numfaces, MVert *x, MVert *xnew, unsigned int numverts, float epsilon);
// frees the same
void bvh_free ( BVH *bvh );
// checks two bounding volume hierarchies for potential collisions and returns some list with those
int bvh_traverse(Tree *tree1, Tree *tree2, LinkNode *collision_list);
int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision_list);
// update bounding volumes, needs updated positions in bvh->x
void bvh_update(DerivedMesh *dm, BVH * bvh, int moving);
void bvh_update(BVH * bvh, int moving);
LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr );
LinkNode *BLI_linklist_append_fast (LinkNode **listp, void *ptr);
// move Collision modifier object inter-frame with step = [0,1]
// defined in collisions.c
void collision_move_object(CollisionModifierData *collmd, float step);
/////////////////////////////////////////////////

View File

@@ -277,7 +277,7 @@ int modifiers_getCageIndex(struct Object *ob,
int *lastPossibleCageIndex_r);
int modifiers_isSoftbodyEnabled(struct Object *ob);
struct ModifierData *modifiers_isClothEnabled(struct Object *ob);
struct ClothModifierData *modifiers_isClothEnabled(Object *ob);
struct Object *modifiers_isDeformedByArmature(struct Object *ob);
struct Object *modifiers_isDeformedByLattice(struct Object *ob);
int modifiers_usesArmature(struct Object *ob, struct bArmature *arm);

View File

@@ -120,10 +120,9 @@ static CM_SOLVER_DEF solvers [] =
/* ********** cloth engine ******* */
/* Prototypes for internal functions.
*/
static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts );
static void cloth_to_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm );
static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm );
static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts );
static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts );
static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm );
int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm );
static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup );
@@ -603,69 +602,63 @@ void cloth_cache_free ( ClothModifierData *clmd, float time )
* cloth_deform_verts - simulates one step, framenr is in frames.
*
**/
void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
float ( *vertexCos ) [3], int numverts )
DerivedMesh *clothModifier_do(ClothModifierData *clmd,
Object *ob, DerivedMesh *dm)
{
unsigned int i;
unsigned int numedges = -1;
unsigned int numfaces = -1;
MVert *mvert = NULL;
MEdge *medge = NULL;
MFace *mface = NULL;
DerivedMesh *result = NULL, *result2 = NULL;
DerivedMesh *result = NULL;
Cloth *cloth = clmd->clothObject;
unsigned int framenr = ( float ) G.scene->r.cfra;
float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 );
ListBase *effectors = NULL;
ClothVertex *newframe= NULL, *verts;
ListBase *effectors = NULL;
ClothVertex *verts = NULL;
Frame *frame = NULL;
LinkNode *search = NULL;
float deltaTime = current_time - clmd->sim_parms.sim_time;
MVert *mverts = NULL;
result = CDDM_copy(dm);
// only be active during a specific period:
// that's "first frame" and "last frame" on GUI
if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) )
if ( clmd->clothObject )
{
if ( clmd->clothObject )
if ( clmd->sim_parms.cache )
{
if ( clmd->sim_parms.cache )
if ( current_time < clmd->sim_parms.firstframe )
{
if ( current_time < clmd->sim_parms.firstframe )
int frametime = cloth_cache_first_frame ( clmd );
if ( cloth_cache_search_frame ( clmd, frametime ) )
{
int frametime = cloth_cache_first_frame ( clmd );
if ( cloth_cache_search_frame ( clmd, frametime ) )
{
cloth_cache_get_frame ( clmd, frametime );
cloth_to_object ( ob, clmd, vertexCos, numverts );
}
return;
}
else if ( current_time > clmd->sim_parms.lastframe )
{
int frametime = cloth_cache_last_frame ( clmd );
if ( cloth_cache_search_frame ( clmd, frametime ) )
{
cloth_cache_get_frame ( clmd, frametime );
cloth_to_object ( ob, clmd, vertexCos, numverts );
}
return;
}
else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed
{
if ( cloth_cache_search_frame ( clmd, framenr ) )
{
cloth_cache_get_frame ( clmd, framenr );
cloth_to_object ( ob, clmd, vertexCos, numverts );
}
clmd->sim_parms.sim_time = current_time;
return;
cloth_cache_get_frame ( clmd, frametime );
cloth_to_object ( ob, clmd, result );
}
return;
}
else if ( current_time > clmd->sim_parms.lastframe )
{
int frametime = cloth_cache_last_frame ( clmd );
if ( cloth_cache_search_frame ( clmd, frametime ) )
{
cloth_cache_get_frame ( clmd, frametime );
cloth_to_object ( ob, clmd, result );
}
return;
}
else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed
{
if ( cloth_cache_search_frame ( clmd, framenr ) )
{
cloth_cache_get_frame ( clmd, framenr );
cloth_to_object ( ob, clmd, result );
}
clmd->sim_parms.sim_time = current_time;
return;
}
}
}
// unused in the moment, calculated seperately in implicit.c
clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame;
@@ -673,9 +666,9 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
if ( deltaTime == 1.0f )
{
if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) )
if ( ( clmd->clothObject == NULL ) || ( dm->getNumVerts(dm) != clmd->clothObject->numverts ) )
{
if ( !cloth_from_object ( ob, clmd, dm, vertexCos, numverts ) )
if ( !cloth_from_object ( ob, clmd, dm ) )
return;
if ( clmd->clothObject == NULL )
@@ -692,6 +685,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
if ( !cloth_cache_search_frame ( clmd, framenr ) )
{
verts = cloth->verts;
mverts = dm->getVertArray(dm);
// Force any pinned verts to their constrained location.
for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ )
@@ -699,9 +693,8 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
// Save the previous position.
VECCOPY ( verts->xold, verts->xconst );
VECCOPY ( verts->txold, verts->x );
// Get the current position.
VECCOPY ( verts->xconst, vertexCos[i] );
VECCOPY ( verts->xconst, mverts[i].co );
Mat4MulVecfl ( ob->obmat, verts->xconst );
}
@@ -723,7 +716,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
}
// Copy the result back to the object.
cloth_to_object ( ob, clmd, vertexCos, numverts );
cloth_to_object ( ob, clmd, result );
// bvh_free(clmd->clothObject->tree);
// clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon);
@@ -737,11 +730,12 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
if ( cloth_cache_search_frame ( clmd, framenr ) )
{
cloth_cache_get_frame ( clmd, framenr );
cloth_to_object ( ob, clmd, vertexCos, numverts );
cloth_to_object ( ob, clmd, result );
}
}
}
return result;
}
/* frees all */
@@ -771,6 +765,14 @@ void cloth_free_modifier ( ClothModifierData *clmd )
// Free the verts.
if ( cloth->verts != NULL )
MEM_freeN ( cloth->verts );
// Free the verts.
if ( cloth->x != NULL )
MEM_freeN ( cloth->x );
// Free the verts.
if ( cloth->xnew != NULL )
MEM_freeN ( cloth->xnew );
cloth->verts = NULL;
cloth->numverts = 0;
@@ -823,22 +825,24 @@ void cloth_free_modifier ( ClothModifierData *clmd )
*
* This function is a modified version of the softbody.c:softbody_to_object() function.
**/
static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts )
static void cloth_to_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm )
{
ClothVertex *verts = NULL;
unsigned int i = 0;
MVert *mvert = NULL;
if ( clmd->clothObject )
{
verts = clmd->clothObject->verts;
mvert = dm->getVertArray(dm);
/* inverse matrix is not uptodate... */
Mat4Invert ( ob->imat, ob->obmat );
for ( i = 0; i < numverts; i++, verts++ )
for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ )
{
VECCOPY ( vertexCos[i], verts->x );
Mat4MulVecfl ( ob->imat, vertexCos[i] ); /* softbody is in global coords */
VECCOPY ( mvert[i].co, verts->x );
Mat4MulVecfl ( ob->imat, mvert[i].co ); /* softbody is in global coords */
}
}
}
@@ -903,7 +907,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short
}
// only meshes supported at the moment
static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts )
static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm )
{
unsigned int i = 0;
// dm->getNumVerts(dm);
@@ -954,7 +958,7 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh
verts = clmd->clothObject->verts;
/* set initial values */
for ( i = 0; i < numverts; i++, verts++ )
for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ )
{
VECCOPY ( verts->x, mvert[i].co );
Mat4MulVecfl ( ob->obmat, verts->x );
@@ -1021,6 +1025,22 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *
modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." );
return;
}
clmd->clothObject->x = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_x" );
if ( clmd->clothObject->x == NULL )
{
cloth_free_modifier ( clmd );
modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->x." );
return;
}
clmd->clothObject->xnew = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_xnew" );
if ( clmd->clothObject->xnew == NULL )
{
cloth_free_modifier ( clmd );
modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xnew." );
return;
}
// save face information
clmd->clothObject->numfaces = numfaces;
@@ -1067,7 +1087,10 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in
cloth->numsprings++;
BLI_linklist_append ( &cloth->springs, spring );
return 1;
}
return 0;
}
int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm )

View File

@@ -72,6 +72,22 @@
#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 tv[3] = {0,0,0};
unsigned int i = 0;
MVert *tempVert = collmd->current_x;
collmd->current_x = collmd->current_xnew;
collmd->current_xnew = tempVert;
for ( i = 0; i < collmd->numverts; i++ )
{
VECSUB(tv, collmd->xnew[i].co, collmd->x[i].co);
VECADDS(collmd->current_xnew[i].co, collmd->x[i].co, tv, step);
}
}
/**
* gsl_poly_solve_cubic -
@@ -362,846 +378,3 @@ DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], floa
VECADDMUL(to, v3, w3);
}
// unused in the moment, has some bug in
DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal[3], double normalVelocity,
double frictionConstant, double delta_V_n)
{
float vrel_t_pre[3];
float vrel_t[3];
VECSUBS(vrel_t_pre, vrel, normal, normalVelocity);
VECCOPY(to, vrel_t_pre);
VecMulf(to, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f));
}
int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd)
{
/*
unsigned int i = 0;
int result = 0;
LinkNode *search = NULL;
CollPair *collpair = NULL;
Cloth *cloth1, *cloth2;
float w1, w2, w3, u1, u2, u3;
float v1[3], v2[3], relativeVelocity[3];
float magrelVel;
cloth1 = clmd->clothObject;
cloth2 = coll_clmd->clothObject;
// search = clmd->coll_parms.collision_list;
while(search)
{
collpair = search->link;
// compute barycentric coordinates for both collision points
collisions_compute_barycentric(collpair->pa,
cloth1->verts[collpair->ap1].txold,
cloth1->verts[collpair->ap2].txold,
cloth1->verts[collpair->ap3].txold,
&w1, &w2, &w3);
collisions_compute_barycentric(collpair->pb,
cloth2->verts[collpair->bp1].txold,
cloth2->verts[collpair->bp2].txold,
cloth2->verts[collpair->bp3].txold,
&u1, &u2, &u3);
// Calculate relative "velocity".
interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3);
interpolateOnTriangle(v2, cloth2->verts[collpair->bp1].tv, cloth2->verts[collpair->bp2].tv, cloth2->verts[collpair->bp3].tv, u1, u2, u3);
VECSUB(relativeVelocity, v1, v2);
// Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal').
magrelVel = INPR(relativeVelocity, collpair->normal);
// printf("magrelVel: %f\n", magrelVel);
// Calculate masses of points.
// If v_n_mag < 0 the edges are approaching each other.
if(magrelVel < -ALMOST_ZERO)
{
// Calculate Impulse magnitude to stop all motion in normal direction.
// const double I_mag = v_n_mag / (1/m1 + 1/m2);
float magnitude_i = magrelVel / 2.0f; // TODO implement masses
float tangential[3], magtangent, magnormal, collvel[3];
float vrel_t_pre[3];
float vrel_t[3];
double impulse;
float epsilon = clmd->coll_parms.epsilon;
float overlap = (epsilon + ALMOST_ZERO-collpair->distance);
// calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel);
// magtangent = INPR(tangential, tangential);
// Apply friction impulse.
if (magtangent < -ALMOST_ZERO)
{
// printf("friction applied: %f\n", magtangent);
// TODO check original code
}
impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3);
// printf("impulse: %f\n", impulse);
// face A
VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse);
cloth1->verts[collpair->ap1].impulse_count++;
VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse);
cloth1->verts[collpair->ap2].impulse_count++;
VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse);
cloth1->verts[collpair->ap3].impulse_count++;
// face B
VECADDMUL(cloth2->verts[collpair->bp1].impulse, collpair->normal, u1 * impulse);
cloth2->verts[collpair->bp1].impulse_count++;
VECADDMUL(cloth2->verts[collpair->bp2].impulse, collpair->normal, u2 * impulse);
cloth2->verts[collpair->bp2].impulse_count++;
VECADDMUL(cloth2->verts[collpair->bp3].impulse, collpair->normal, u3 * impulse);
cloth2->verts[collpair->bp3].impulse_count++;
result = 1;
// printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case
// Apply the impulse and increase impulse counters.
}
search = search->next;
}
return result;
*/
return 0;
}
int collisions_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd)
{
}
int collisions_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd)
{
}
void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2)
{
/*
CollPair *collpair = NULL;
Cloth *cloth1=NULL, *cloth2=NULL;
MFace *face1=NULL, *face2=NULL;
ClothVertex *verts1=NULL, *verts2=NULL;
double distance = 0;
float epsilon = clmd->coll_parms.epsilon;
unsigned int i = 0;
for(i = 0; i < 4; i++)
{
collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair");
cloth1 = clmd->clothObject;
cloth2 = coll_clmd->clothObject;
verts1 = cloth1->verts;
verts2 = cloth2->verts;
face1 = &(cloth1->mfaces[tree1->tri_index]);
face2 = &(cloth2->mfaces[tree2->tri_index]);
// check all possible pairs of triangles
if(i == 0)
{
collpair->ap1 = face1->v1;
collpair->ap2 = face1->v2;
collpair->ap3 = face1->v3;
collpair->bp1 = face2->v1;
collpair->bp2 = face2->v2;
collpair->bp3 = face2->v3;
}
if(i == 1)
{
if(face1->v4)
{
collpair->ap1 = face1->v3;
collpair->ap2 = face1->v4;
collpair->ap3 = face1->v1;
collpair->bp1 = face2->v1;
collpair->bp2 = face2->v2;
collpair->bp3 = face2->v3;
}
else
i++;
}
if(i == 2)
{
if(face2->v4)
{
collpair->ap1 = face1->v1;
collpair->ap2 = face1->v2;
collpair->ap3 = face1->v3;
collpair->bp1 = face2->v3;
collpair->bp2 = face2->v4;
collpair->bp3 = face2->v1;
}
else
i+=2;
}
if(i == 3)
{
if((face1->v4)&&(face2->v4))
{
collpair->ap1 = face1->v3;
collpair->ap2 = face1->v4;
collpair->ap3 = face1->v1;
collpair->bp1 = face2->v3;
collpair->bp2 = face2->v4;
collpair->bp3 = face2->v1;
}
else
i++;
}
// calc SIPcode (?)
if(i < 4)
{
// calc distance + normal
distance = plNearestPoints(
verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, collpair->pa,collpair->pb,collpair->vector);
if (distance <= (epsilon + ALMOST_ZERO))
{
// printf("dist: %f\n", (float)distance);
// collpair->face1 = tree1->tri_index;
// collpair->face2 = tree2->tri_index;
// VECCOPY(collpair->normal, collpair->vector);
// Normalize(collpair->normal);
// collpair->distance = distance;
}
else
{
MEM_freeN(collpair);
}
}
else
{
MEM_freeN(collpair);
}
}
*/
}
int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair)
{
Cloth *cloth1, *cloth2;
ClothVertex *verts1, *verts2;
float temp[3];
cloth1 = clmd->clothObject;
cloth2 = coll_clmd->clothObject;
verts1 = cloth1->verts;
verts2 = cloth2->verts;
VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold);
if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
return 1;
VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold);
if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
return 1;
VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold);
if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
return 1;
VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold);
if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
return 1;
return 0;
}
void collisions_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2)
{
EdgeCollPair edgecollpair;
Cloth *cloth1=NULL, *cloth2=NULL;
MFace *face1=NULL, *face2=NULL;
ClothVertex *verts1=NULL, *verts2=NULL;
double distance = 0;
float epsilon = clmd->coll_parms.epsilon;
unsigned int i = 0, j = 0, k = 0;
int numsolutions = 0;
float a[3], b[3], c[3], d[3], e[3], f[3], solution[3];
cloth1 = clmd->clothObject;
cloth2 = coll_clmd->clothObject;
verts1 = cloth1->verts;
verts2 = cloth2->verts;
face1 = &(cloth1->mfaces[tree1->tri_index]);
face2 = &(cloth2->mfaces[tree2->tri_index]);
for( i = 0; i < 5; i++)
{
if(i == 0)
{
edgecollpair.p11 = face1->v1;
edgecollpair.p12 = face1->v2;
}
else if(i == 1)
{
edgecollpair.p11 = face1->v2;
edgecollpair.p12 = face1->v3;
}
else if(i == 2)
{
if(face1->v4)
{
edgecollpair.p11 = face1->v3;
edgecollpair.p12 = face1->v4;
}
else
{
edgecollpair.p11 = face1->v3;
edgecollpair.p12 = face1->v1;
i+=5; // get out of here after this edge pair is handled
}
}
else if(i == 3)
{
if(face1->v4)
{
edgecollpair.p11 = face1->v4;
edgecollpair.p12 = face1->v1;
}
else
continue;
}
else
{
edgecollpair.p11 = face1->v3;
edgecollpair.p12 = face1->v1;
}
for( j = 0; j < 5; j++)
{
if(j == 0)
{
edgecollpair.p21 = face2->v1;
edgecollpair.p22 = face2->v2;
}
else if(j == 1)
{
edgecollpair.p21 = face2->v2;
edgecollpair.p22 = face2->v3;
}
else if(j == 2)
{
if(face2->v4)
{
edgecollpair.p21 = face2->v3;
edgecollpair.p22 = face2->v4;
}
else
{
edgecollpair.p21 = face2->v3;
edgecollpair.p22 = face2->v1;
}
}
else if(j == 3)
{
if(face2->v4)
{
edgecollpair.p21 = face2->v4;
edgecollpair.p22 = face2->v1;
}
else
continue;
}
else
{
edgecollpair.p21 = face2->v3;
edgecollpair.p22 = face2->v1;
}
if(!collisions_are_edges_adjacent(clmd, coll_clmd, &edgecollpair))
{
VECSUB(a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold);
VECSUB(b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v);
VECSUB(c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold);
VECSUB(d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v);
VECSUB(e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold);
VECSUB(f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v);
numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution);
for (k = 0; k < numsolutions; k++)
{
if ((solution[k] >= 0.0) && (solution[k] <= 1.0))
{
float out_collisionTime = solution[k];
// TODO: check for collisions
// TODO: put into (edge) collision list
printf("Moving edge found!\n");
}
}
}
}
}
}
void collisions_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2)
{
/*
CollPair collpair;
Cloth *cloth1=NULL, *cloth2=NULL;
MFace *face1=NULL, *face2=NULL;
ClothVertex *verts1=NULL, *verts2=NULL;
double distance = 0;
float epsilon = clmd->coll_parms.epsilon;
unsigned int i = 0, j = 0, k = 0;
int numsolutions = 0;
float a[3], b[3], c[3], d[3], e[3], f[3], solution[3];
for(i = 0; i < 2; i++)
{
cloth1 = clmd->clothObject;
cloth2 = coll_clmd->clothObject;
verts1 = cloth1->verts;
verts2 = cloth2->verts;
face1 = &(cloth1->mfaces[tree1->tri_index]);
face2 = &(cloth2->mfaces[tree2->tri_index]);
// check all possible pairs of triangles
if(i == 0)
{
collpair.ap1 = face1->v1;
collpair.ap2 = face1->v2;
collpair.ap3 = face1->v3;
collpair.pointsb[0] = face2->v1;
collpair.pointsb[1] = face2->v2;
collpair.pointsb[2] = face2->v3;
collpair.pointsb[3] = face2->v4;
}
if(i == 1)
{
if(face1->v4)
{
collpair.ap1 = face1->v3;
collpair.ap2 = face1->v4;
collpair.ap3 = face1->v1;
collpair.pointsb[0] = face2->v1;
collpair.pointsb[1] = face2->v2;
collpair.pointsb[2] = face2->v3;
collpair.pointsb[3] = face2->v4;
}
else
i++;
}
// calc SIPcode (?)
if(i < 2)
{
VECSUB(a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold);
VECSUB(b, verts1[collpair.ap2].v, verts1[collpair.ap1].v);
VECSUB(c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold);
VECSUB(d, verts1[collpair.ap3].v, verts1[collpair.ap1].v);
for(j = 0; j < 4; j++)
{
if((j==3) && !(face2->v4))
break;
VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold);
VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v);
numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution);
for (k = 0; k < numsolutions; k++)
{
if ((solution[k] >= 0.0) && (solution[k] <= 1.0))
{
float out_collisionTime = solution[k];
// TODO: check for collisions
// TODO: put into (point-face) collision list
printf("Moving found!\n");
}
}
// TODO: check borders for collisions
}
}
}
*/
}
void collisions_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2)
{
/*
// TODO: check for adjacent
collisions_collision_moving_edges(clmd, coll_clmd, tree1, tree2);
collisions_collision_moving_tris(clmd, coll_clmd, tree1, tree2);
collisions_collision_moving_tris(coll_clmd, clmd, tree2, tree1);
*/
}
// move collision objects forward in time and update static bounding boxes
void collisions_update_collision_objects(float step)
{
Base *base=NULL;
ClothModifierData *coll_clmd=NULL;
Object *coll_ob=NULL;
unsigned int i=0;
// search all objects for collision object
for (base = G.scene->base.first; base; base = base->next)
{
coll_ob = base->object;
coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
if (!coll_clmd)
continue;
// if collision object go on
if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)
{
if (coll_clmd->clothObject && coll_clmd->clothObject->tree)
{
Cloth *coll_cloth = coll_clmd->clothObject;
BVH *coll_bvh = coll_clmd->clothObject->tree;
unsigned int coll_numverts = coll_cloth->numverts;
// update position of collision object
for(i = 0; i < coll_numverts; i++)
{
VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx);
VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step);
// no dt here because of float rounding errors
VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold);
}
// update BVH of collision object
// bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING
}
else
printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
}
}
}
// collisions_MAX_THRESHOLD defines how much collision rounds/loops should be taken
#define CLOTH_MAX_THRESHOLD 10
// cloth - object collisions
int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt)
{
Base *base=NULL;
ClothModifierData *coll_clmd=NULL;
Cloth *cloth=NULL;
Object *coll_ob=NULL;
BVH *collisions_bvh=NULL;
unsigned int i=0, j = 0, numfaces = 0, numverts = 0;
unsigned int result = 0, ic = 0, rounds = 0; // result counts applied collisions; ic is for debug output;
ClothVertex *verts = NULL;
float tnull[3] = {0,0,0};
int ret = 0;
LinkNode *collision_list = NULL;
if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree))
{
return 0;
}
cloth = clmd->clothObject;
verts = cloth->verts;
collisions_bvh = (BVH *) cloth->tree;
numfaces = clmd->clothObject->numfaces;
numverts = clmd->clothObject->numverts;
////////////////////////////////////////////////////////////
// static collisions
////////////////////////////////////////////////////////////
// update cloth bvh
// bvh_update(clmd, collisions_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function)
// update collision objects
collisions_update_collision_objects(step);
do
{
result = 0;
ic = 0;
// check all collision objects
for (base = G.scene->base.first; base; base = base->next)
{
coll_ob = base->object;
coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
if (!coll_clmd)
continue;
// if collision object go on
if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)
{
if (coll_clmd->clothObject && coll_clmd->clothObject->tree)
{
BVH *coll_bvh = coll_clmd->clothObject->tree;
// fill collision list
bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list);
// process all collisions (calculate impulses, TODO: also repulses if distance too short)
result = 1;
for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence
{
result = 0;
// result += collisions_collision_response_static_tris(clmd, coll_clmd, collision_list, 0);
// result += collisions_collision_response_static_tris(coll_clmd, clmd, collision_list, 1);
// apply impulses in parallel
ic=0;
for(i = 0; i < numverts; i++)
{
// calculate "velocities" (just xnew = xold + v; no dt in v)
if(verts[i].impulse_count)
{
VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count);
VECCOPY(verts[i].impulse, tnull);
verts[i].impulse_count = 0;
ic++;
ret++;
}
}
}
// free collision list
if(collision_list)
{
LinkNode *search = collision_list;
while(search)
{
CollisionPair *coll_pair = search->link;
MEM_freeN(coll_pair);
search = search->next;
}
BLI_linklist_free(collision_list,NULL);
collision_list = NULL;
}
}
else
printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
}
}
printf("ic: %d\n", ic);
rounds++;
}
while(result && (CLOTH_MAX_THRESHOLD>rounds));
printf("\n");
////////////////////////////////////////////////////////////
// update positions
// this is needed for bvh_calc_DOP_hull_moving() [kdop.c]
////////////////////////////////////////////////////////////
// verts come from clmd
for(i = 0; i < numverts; i++)
{
VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// moving collisions
////////////////////////////////////////////////////////////
// update cloth bvh
// bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING
// update moving bvh for collision object once
for (base = G.scene->base.first; base; base = base->next)
{
coll_ob = base->object;
coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
if (!coll_clmd)
continue;
if(!coll_clmd->clothObject)
continue;
// if collision object go on
if (coll_clmd->clothObject && coll_clmd->clothObject->tree)
{
BVH *coll_bvh = coll_clmd->clothObject->tree;
// bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING
}
}
do
{
result = 0;
ic = 0;
// check all collision objects
for (base = G.scene->base.first; base; base = base->next)
{
coll_ob = base->object;
coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
if (!coll_clmd)
continue;
// if collision object go on
if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)
{
if (coll_clmd->clothObject && coll_clmd->clothObject->tree)
{
BVH *coll_bvh = coll_clmd->clothObject->tree;
bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list);
// process all collisions (calculate impulses, TODO: also repulses if distance too short)
result = 1;
for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence
{
result = 0;
// handle all collision objects
/*
if (coll_clmd->clothObject)
result += collisions_collision_response_moving_tris(clmd, coll_clmd);
else
printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
*/
// apply impulses in parallel
ic=0;
for(i = 0; i < numverts; i++)
{
// calculate "velocities" (just xnew = xold + v; no dt in v)
if(verts[i].impulse_count)
{
VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count);
VECCOPY(verts[i].impulse, tnull);
verts[i].impulse_count = 0;
ic++;
ret++;
}
}
}
// verts come from clmd
for(i = 0; i < numverts; i++)
{
VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
}
// update cloth bvh
// bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING
// free collision list
if(collision_list)
{
LinkNode *search = collision_list;
while(search)
{
CollisionPair *coll_pair = search->link;
MEM_freeN(coll_pair);
search = search->next;
}
BLI_linklist_free(collision_list,NULL);
collision_list = NULL;
}
}
else
printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
}
}
printf("ic: %d\n", ic);
rounds++;
}
while(result && (CLOTH_MAX_THRESHOLD>rounds));
////////////////////////////////////////////////////////////
// update positions + velocities
////////////////////////////////////////////////////////////
// verts come from clmd
for(i = 0; i < numverts; i++)
{
VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
}
////////////////////////////////////////////////////////////
return MIN2(ret, 1);
}

View File

@@ -49,6 +49,7 @@
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_threads.h"
#include "BKE_collisions.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
@@ -1585,3 +1586,841 @@ void implicit_set_positions (ClothModifierData *clmd)
VECCOPY(id->V[i], verts[i].v);
}
}
int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd)
{
/*
unsigned int i = 0;
int result = 0;
LinkNode *search = NULL;
CollPair *collpair = NULL;
Cloth *cloth1, *cloth2;
float w1, w2, w3, u1, u2, u3;
float v1[3], v2[3], relativeVelocity[3];
float magrelVel;
cloth1 = clmd->clothObject;
cloth2 = coll_clmd->clothObject;
// search = clmd->coll_parms.collision_list;
while(search)
{
collpair = search->link;
// compute barycentric coordinates for both collision points
collisions_compute_barycentric(collpair->pa,
cloth1->verts[collpair->ap1].txold,
cloth1->verts[collpair->ap2].txold,
cloth1->verts[collpair->ap3].txold,
&w1, &w2, &w3);
collisions_compute_barycentric(collpair->pb,
cloth2->verts[collpair->bp1].txold,
cloth2->verts[collpair->bp2].txold,
cloth2->verts[collpair->bp3].txold,
&u1, &u2, &u3);
// Calculate relative "velocity".
interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3);
interpolateOnTriangle(v2, cloth2->verts[collpair->bp1].tv, cloth2->verts[collpair->bp2].tv, cloth2->verts[collpair->bp3].tv, u1, u2, u3);
VECSUB(relativeVelocity, v1, v2);
// Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal').
magrelVel = INPR(relativeVelocity, collpair->normal);
// printf("magrelVel: %f\n", magrelVel);
// Calculate masses of points.
// If v_n_mag < 0 the edges are approaching each other.
if(magrelVel < -ALMOST_ZERO)
{
// Calculate Impulse magnitude to stop all motion in normal direction.
// const double I_mag = v_n_mag / (1/m1 + 1/m2);
float magnitude_i = magrelVel / 2.0f; // TODO implement masses
float tangential[3], magtangent, magnormal, collvel[3];
float vrel_t_pre[3];
float vrel_t[3];
double impulse;
float epsilon = clmd->coll_parms.epsilon;
float overlap = (epsilon + ALMOST_ZERO-collpair->distance);
// calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel);
// magtangent = INPR(tangential, tangential);
// Apply friction impulse.
if (magtangent < -ALMOST_ZERO)
{
// printf("friction applied: %f\n", magtangent);
// TODO check original code
}
impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3);
// printf("impulse: %f\n", impulse);
// face A
VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse);
cloth1->verts[collpair->ap1].impulse_count++;
VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse);
cloth1->verts[collpair->ap2].impulse_count++;
VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse);
cloth1->verts[collpair->ap3].impulse_count++;
// face B
VECADDMUL(cloth2->verts[collpair->bp1].impulse, collpair->normal, u1 * impulse);
cloth2->verts[collpair->bp1].impulse_count++;
VECADDMUL(cloth2->verts[collpair->bp2].impulse, collpair->normal, u2 * impulse);
cloth2->verts[collpair->bp2].impulse_count++;
VECADDMUL(cloth2->verts[collpair->bp3].impulse, collpair->normal, u3 * impulse);
cloth2->verts[collpair->bp3].impulse_count++;
result = 1;
// printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case
// Apply the impulse and increase impulse counters.
}
search = search->next;
}
return result;
*/
return 0;
}
int collisions_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd)
{
}
int collisions_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd)
{
}
void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
{
/*
CollPair *collpair = NULL;
Cloth *cloth1=NULL, *cloth2=NULL;
MFace *face1=NULL, *face2=NULL;
ClothVertex *verts1=NULL, *verts2=NULL;
double distance = 0;
float epsilon = clmd->coll_parms.epsilon;
unsigned int i = 0;
for(i = 0; i < 4; i++)
{
collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair");
cloth1 = clmd->clothObject;
cloth2 = coll_clmd->clothObject;
verts1 = cloth1->verts;
verts2 = cloth2->verts;
face1 = &(cloth1->mfaces[tree1->tri_index]);
face2 = &(cloth2->mfaces[tree2->tri_index]);
// check all possible pairs of triangles
if(i == 0)
{
collpair->ap1 = face1->v1;
collpair->ap2 = face1->v2;
collpair->ap3 = face1->v3;
collpair->bp1 = face2->v1;
collpair->bp2 = face2->v2;
collpair->bp3 = face2->v3;
}
if(i == 1)
{
if(face1->v4)
{
collpair->ap1 = face1->v3;
collpair->ap2 = face1->v4;
collpair->ap3 = face1->v1;
collpair->bp1 = face2->v1;
collpair->bp2 = face2->v2;
collpair->bp3 = face2->v3;
}
else
i++;
}
if(i == 2)
{
if(face2->v4)
{
collpair->ap1 = face1->v1;
collpair->ap2 = face1->v2;
collpair->ap3 = face1->v3;
collpair->bp1 = face2->v3;
collpair->bp2 = face2->v4;
collpair->bp3 = face2->v1;
}
else
i+=2;
}
if(i == 3)
{
if((face1->v4)&&(face2->v4))
{
collpair->ap1 = face1->v3;
collpair->ap2 = face1->v4;
collpair->ap3 = face1->v1;
collpair->bp1 = face2->v3;
collpair->bp2 = face2->v4;
collpair->bp3 = face2->v1;
}
else
i++;
}
// calc SIPcode (?)
if(i < 4)
{
// calc distance + normal
distance = plNearestPoints(
verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, collpair->pa,collpair->pb,collpair->vector);
if (distance <= (epsilon + ALMOST_ZERO))
{
// printf("dist: %f\n", (float)distance);
// collpair->face1 = tree1->tri_index;
// collpair->face2 = tree2->tri_index;
// VECCOPY(collpair->normal, collpair->vector);
// Normalize(collpair->normal);
// collpair->distance = distance;
}
else
{
MEM_freeN(collpair);
}
}
else
{
MEM_freeN(collpair);
}
}
*/
}
int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair)
{
Cloth *cloth1, *cloth2;
ClothVertex *verts1, *verts2;
float temp[3];
cloth1 = clmd->clothObject;
cloth2 = coll_clmd->clothObject;
verts1 = cloth1->verts;
verts2 = cloth2->verts;
VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold);
if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
return 1;
VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold);
if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
return 1;
VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold);
if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
return 1;
VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold);
if(ABS(INPR(temp, temp)) < ALMOST_ZERO)
return 1;
return 0;
}
void collisions_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
{
/*
EdgeCollPair edgecollpair;
Cloth *cloth1=NULL, *cloth2=NULL;
MFace *face1=NULL, *face2=NULL;
ClothVertex *verts1=NULL, *verts2=NULL;
double distance = 0;
float epsilon = clmd->coll_parms.epsilon;
unsigned int i = 0, j = 0, k = 0;
int numsolutions = 0;
float a[3], b[3], c[3], d[3], e[3], f[3], solution[3];
cloth1 = clmd->clothObject;
cloth2 = coll_clmd->clothObject;
verts1 = cloth1->verts;
verts2 = cloth2->verts;
face1 = &(cloth1->mfaces[tree1->tri_index]);
face2 = &(cloth2->mfaces[tree2->tri_index]);
for( i = 0; i < 5; i++)
{
if(i == 0)
{
edgecollpair.p11 = face1->v1;
edgecollpair.p12 = face1->v2;
}
else if(i == 1)
{
edgecollpair.p11 = face1->v2;
edgecollpair.p12 = face1->v3;
}
else if(i == 2)
{
if(face1->v4)
{
edgecollpair.p11 = face1->v3;
edgecollpair.p12 = face1->v4;
}
else
{
edgecollpair.p11 = face1->v3;
edgecollpair.p12 = face1->v1;
i+=5; // get out of here after this edge pair is handled
}
}
else if(i == 3)
{
if(face1->v4)
{
edgecollpair.p11 = face1->v4;
edgecollpair.p12 = face1->v1;
}
else
continue;
}
else
{
edgecollpair.p11 = face1->v3;
edgecollpair.p12 = face1->v1;
}
for( j = 0; j < 5; j++)
{
if(j == 0)
{
edgecollpair.p21 = face2->v1;
edgecollpair.p22 = face2->v2;
}
else if(j == 1)
{
edgecollpair.p21 = face2->v2;
edgecollpair.p22 = face2->v3;
}
else if(j == 2)
{
if(face2->v4)
{
edgecollpair.p21 = face2->v3;
edgecollpair.p22 = face2->v4;
}
else
{
edgecollpair.p21 = face2->v3;
edgecollpair.p22 = face2->v1;
}
}
else if(j == 3)
{
if(face2->v4)
{
edgecollpair.p21 = face2->v4;
edgecollpair.p22 = face2->v1;
}
else
continue;
}
else
{
edgecollpair.p21 = face2->v3;
edgecollpair.p22 = face2->v1;
}
if(!collisions_are_edges_adjacent(clmd, coll_clmd, &edgecollpair))
{
VECSUB(a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold);
VECSUB(b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v);
VECSUB(c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold);
VECSUB(d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v);
VECSUB(e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold);
VECSUB(f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v);
numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution);
for (k = 0; k < numsolutions; k++)
{
if ((solution[k] >= 0.0) && (solution[k] <= 1.0))
{
float out_collisionTime = solution[k];
// TODO: check for collisions
// TODO: put into (edge) collision list
printf("Moving edge found!\n");
}
}
}
}
}
*/
}
void collisions_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
{
/*
CollPair collpair;
Cloth *cloth1=NULL, *cloth2=NULL;
MFace *face1=NULL, *face2=NULL;
ClothVertex *verts1=NULL, *verts2=NULL;
double distance = 0;
float epsilon = clmd->coll_parms.epsilon;
unsigned int i = 0, j = 0, k = 0;
int numsolutions = 0;
float a[3], b[3], c[3], d[3], e[3], f[3], solution[3];
for(i = 0; i < 2; i++)
{
cloth1 = clmd->clothObject;
cloth2 = coll_clmd->clothObject;
verts1 = cloth1->verts;
verts2 = cloth2->verts;
face1 = &(cloth1->mfaces[tree1->tri_index]);
face2 = &(cloth2->mfaces[tree2->tri_index]);
// check all possible pairs of triangles
if(i == 0)
{
collpair.ap1 = face1->v1;
collpair.ap2 = face1->v2;
collpair.ap3 = face1->v3;
collpair.pointsb[0] = face2->v1;
collpair.pointsb[1] = face2->v2;
collpair.pointsb[2] = face2->v3;
collpair.pointsb[3] = face2->v4;
}
if(i == 1)
{
if(face1->v4)
{
collpair.ap1 = face1->v3;
collpair.ap2 = face1->v4;
collpair.ap3 = face1->v1;
collpair.pointsb[0] = face2->v1;
collpair.pointsb[1] = face2->v2;
collpair.pointsb[2] = face2->v3;
collpair.pointsb[3] = face2->v4;
}
else
i++;
}
// calc SIPcode (?)
if(i < 2)
{
VECSUB(a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold);
VECSUB(b, verts1[collpair.ap2].v, verts1[collpair.ap1].v);
VECSUB(c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold);
VECSUB(d, verts1[collpair.ap3].v, verts1[collpair.ap1].v);
for(j = 0; j < 4; j++)
{
if((j==3) && !(face2->v4))
break;
VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold);
VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v);
numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution);
for (k = 0; k < numsolutions; k++)
{
if ((solution[k] >= 0.0) && (solution[k] <= 1.0))
{
float out_collisionTime = solution[k];
// TODO: check for collisions
// TODO: put into (point-face) collision list
printf("Moving found!\n");
}
}
// TODO: check borders for collisions
}
}
}
*/
}
// move collision objects forward in time and update static bounding boxes
void collisions_update_collision_objects(float step)
{
Base *base=NULL;
ClothModifierData *coll_clmd=NULL;
Object *coll_ob=NULL;
unsigned int i=0;
// search all objects for collision object
for (base = G.scene->base.first; base; base = base->next)
{
coll_ob = base->object;
coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
if (!coll_clmd)
continue;
// if collision object go on
if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)
{
if (coll_clmd->clothObject && coll_clmd->clothObject->tree)
{
Cloth *coll_cloth = coll_clmd->clothObject;
BVH *coll_bvh = coll_clmd->clothObject->tree;
unsigned int coll_numverts = coll_cloth->numverts;
// update position of collision object
for(i = 0; i < coll_numverts; i++)
{
VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx);
VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step);
// no dt here because of float rounding errors
VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold);
}
// update BVH of collision object
// bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING
}
else
printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
}
}
}
void collisions_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2)
{
/*
// TODO: check for adjacent
collisions_collision_moving_edges(clmd, coll_clmd, tree1, tree2);
collisions_collision_moving_tris(clmd, coll_clmd, tree1, tree2);
collisions_collision_moving_tris(coll_clmd, clmd, tree2, tree1);
*/
}
// cloth - object collisions
int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt)
{
/*
Base *base=NULL;
ClothModifierData *coll_clmd=NULL;
Cloth *cloth=NULL;
Object *coll_ob=NULL;
BVH *collisions_bvh=NULL;
unsigned int i=0, j = 0, numfaces = 0, numverts = 0;
unsigned int result = 0, ic = 0, rounds = 0; // result counts applied collisions; ic is for debug output;
ClothVertex *verts = NULL;
float tnull[3] = {0,0,0};
int ret = 0;
LinkNode *collision_list = NULL;
if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree))
{
return 0;
}
cloth = clmd->clothObject;
verts = cloth->verts;
collisions_bvh = (BVH *) cloth->tree;
numfaces = clmd->clothObject->numfaces;
numverts = clmd->clothObject->numverts;
////////////////////////////////////////////////////////////
// static collisions
////////////////////////////////////////////////////////////
// update cloth bvh
// bvh_update(clmd, collisions_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function)
// update collision objects
collisions_update_collision_objects(step);
do
{
result = 0;
ic = 0;
// check all collision objects
for (base = G.scene->base.first; base; base = base->next)
{
coll_ob = base->object;
coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
if (!coll_clmd)
continue;
// if collision object go on
if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)
{
if (coll_clmd->clothObject && coll_clmd->clothObject->tree)
{
BVH *coll_bvh = coll_clmd->clothObject->tree;
// fill collision list
bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list);
// process all collisions (calculate impulses, TODO: also repulses if distance too short)
result = 1;
for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence
{
result = 0;
// result += collisions_collision_response_static_tris(clmd, coll_clmd, collision_list, 0);
// result += collisions_collision_response_static_tris(coll_clmd, clmd, collision_list, 1);
// apply impulses in parallel
ic=0;
for(i = 0; i < numverts; i++)
{
// calculate "velocities" (just xnew = xold + v; no dt in v)
if(verts[i].impulse_count)
{
VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count);
VECCOPY(verts[i].impulse, tnull);
verts[i].impulse_count = 0;
ic++;
ret++;
}
}
}
// free collision list
if(collision_list)
{
LinkNode *search = collision_list;
while(search)
{
CollisionPair *coll_pair = search->link;
MEM_freeN(coll_pair);
search = search->next;
}
BLI_linklist_free(collision_list,NULL);
collision_list = NULL;
}
}
else
printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
}
}
printf("ic: %d\n", ic);
rounds++;
}
while(result && (10>rounds));// CLOTH_MAX_THRESHOLD
printf("\n");
////////////////////////////////////////////////////////////
// update positions
// this is needed for bvh_calc_DOP_hull_moving() [kdop.c]
////////////////////////////////////////////////////////////
// verts come from clmd
for(i = 0; i < numverts; i++)
{
VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// moving collisions
////////////////////////////////////////////////////////////
// update cloth bvh
// bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING
// update moving bvh for collision object once
for (base = G.scene->base.first; base; base = base->next)
{
coll_ob = base->object;
coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
if (!coll_clmd)
continue;
if(!coll_clmd->clothObject)
continue;
// if collision object go on
if (coll_clmd->clothObject && coll_clmd->clothObject->tree)
{
BVH *coll_bvh = coll_clmd->clothObject->tree;
// bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING
}
}
do
{
result = 0;
ic = 0;
// check all collision objects
for (base = G.scene->base.first; base; base = base->next)
{
coll_ob = base->object;
coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
if (!coll_clmd)
continue;
// if collision object go on
if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)
{
if (coll_clmd->clothObject && coll_clmd->clothObject->tree)
{
BVH *coll_bvh = coll_clmd->clothObject->tree;
bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list);
// process all collisions (calculate impulses, TODO: also repulses if distance too short)
result = 1;
for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence
{
result = 0;
// handle all collision objects
if (coll_clmd->clothObject)
result += collisions_collision_response_moving_tris(clmd, coll_clmd);
else
printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
// apply impulses in parallel
ic=0;
for(i = 0; i < numverts; i++)
{
// calculate "velocities" (just xnew = xold + v; no dt in v)
if(verts[i].impulse_count)
{
VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count);
VECCOPY(verts[i].impulse, tnull);
verts[i].impulse_count = 0;
ic++;
ret++;
}
}
}
// verts come from clmd
for(i = 0; i < numverts; i++)
{
VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
}
// update cloth bvh
// bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING
// free collision list
if(collision_list)
{
LinkNode *search = collision_list;
while(search)
{
CollisionPair *coll_pair = search->link;
MEM_freeN(coll_pair);
search = search->next;
}
BLI_linklist_free(collision_list,NULL);
collision_list = NULL;
}
}
else
printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
}
}
printf("ic: %d\n", ic);
rounds++;
}
while(result && (10>rounds)); // CLOTH_MAX_THRESHOLD
////////////////////////////////////////////////////////////
// update positions + velocities
////////////////////////////////////////////////////////////
// verts come from clmd
for(i = 0; i < numverts; i++)
{
VECADD(verts[i].tx, verts[i].txold, verts[i].tv);
}
////////////////////////////////////////////////////////////
return MIN2(ret, 1);
*/
}

View File

@@ -164,9 +164,9 @@ static int size_threshold = 16;
/*
* Common methods for all algorithms
*/
void bvh_exchange(Tree **a, int i, int j)
void bvh_exchange(CollisionTree **a, int i, int j)
{
Tree *t=a[i];
CollisionTree *t=a[i];
a[i]=a[j];
a[j]=t;
}
@@ -178,10 +178,10 @@ int floor_lg(int a)
/*
* Insertion sort algorithm
*/
static void bvh_insertionsort(Tree **a, int lo, int hi, int axis)
static void bvh_insertionsort(CollisionTree **a, int lo, int hi, int axis)
{
int i,j;
Tree *t;
CollisionTree *t;
for (i=lo; i < hi; i++)
{
j=i;
@@ -195,7 +195,7 @@ static void bvh_insertionsort(Tree **a, int lo, int hi, int axis)
}
}
static int bvh_partition(Tree **a, int lo, int hi, Tree * x, int axis)
static int bvh_partition(CollisionTree **a, int lo, int hi, CollisionTree *x, int axis)
{
int i=lo, j=hi;
while (1)
@@ -213,9 +213,9 @@ static int bvh_partition(Tree **a, int lo, int hi, Tree * x, int axis)
/*
* Heapsort algorithm
*/
static void bvh_downheap(Tree **a, int i, int n, int lo, int axis)
static void bvh_downheap(CollisionTree **a, int i, int n, int lo, int axis)
{
Tree * d = a[lo+i-1];
CollisionTree *d = a[lo+i-1];
int child;
while (i<=n/2)
{
@@ -231,7 +231,7 @@ static void bvh_downheap(Tree **a, int i, int n, int lo, int axis)
a[lo+i-1] = d;
}
static void bvh_heapsort(Tree **a, int lo, int hi, int axis)
static void bvh_heapsort(CollisionTree **a, int lo, int hi, int axis)
{
int n = hi-lo, i;
for (i=n/2; i>=1; i=i-1)
@@ -245,7 +245,7 @@ static void bvh_heapsort(Tree **a, int lo, int hi, int axis)
}
}
static Tree *bvh_medianof3(Tree **a, int lo, int mid, int hi, int axis) // returns Sortable
static CollisionTree *bvh_medianof3(CollisionTree **a, int lo, int mid, int hi, int axis) // returns Sortable
{
if ((a[mid])->bv[axis] < (a[lo])->bv[axis])
{
@@ -275,7 +275,7 @@ static Tree *bvh_medianof3(Tree **a, int lo, int mid, int hi, int axis) // retur
/*
* Quicksort algorithm modified for Introsort
*/
static void bvh_introsort_loop (Tree **a, int lo, int hi, int depth_limit, int axis)
static void bvh_introsort_loop (CollisionTree **a, int lo, int hi, int depth_limit, int axis)
{
int p;
@@ -293,16 +293,16 @@ static void bvh_introsort_loop (Tree **a, int lo, int hi, int depth_limit, int a
}
}
void bvh_sort(Tree **a0, int begin, int end, int axis)
void bvh_sort(CollisionTree **a0, int begin, int end, int axis)
{
if (begin < end)
{
Tree **a=a0;
CollisionTree **a=a0;
bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis);
bvh_insertionsort(a, begin, end, axis);
}
}
void bvh_sort_along_axis(Tree **face_list, int start, int end, int axis)
void bvh_sort_along_axis(CollisionTree **face_list, int start, int end, int axis)
{
bvh_sort(face_list, start, end, axis);
}
@@ -310,7 +310,7 @@ void bvh_sort_along_axis(Tree **face_list, int start, int end, int axis)
void bvh_free(BVH * bvh)
{
LinkNode *search = NULL;
Tree *tree = NULL;
CollisionTree *tree = NULL;
if (bvh)
{
@@ -361,7 +361,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, Tree **tri, int numfaces, float *bv)
void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
{
float newmin,newmax;
int i, j;
@@ -385,32 +385,22 @@ void bvh_calc_DOP_hull_from_faces(BVH * bvh, Tree **tri, int numfaces, float *bv
}
}
void bvh_calc_DOP_hull_static(BVH * bvh, Tree **tri, int numfaces, float *bv)
void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
{
MVert *tempMVert = bvh->x;
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.
// 1 up to 4 vertices per leaf.
for (k = 0; k < 4; k++)
{
int temp = 0;
// If this is a triangle.
if (k == 3 && !tempMFace->v4)
int temp = tri[j]->point_index[k];
if(temp < 0)
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++)
{
@@ -424,33 +414,23 @@ void bvh_calc_DOP_hull_static(BVH * bvh, Tree **tri, int numfaces, float *bv)
}
}
void bvh_calc_DOP_hull_moving(BVH * bvh, Tree **tri, int numfaces, float *bv)
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 = 0;
// If this is a triangle.
if (k == 3 && !tempMFace->v4)
int temp = tri[j]->point_index[k];
if(temp < 0)
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++)
{
@@ -470,10 +450,10 @@ void bvh_calc_DOP_hull_moving(BVH * bvh, Tree **tri, int numfaces, float *bv)
}
}
static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink)
static void bvh_div_env_node(BVH * bvh, TreeNode *tree, CollisionTree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink)
{
int i = 0;
Tree *newtree = NULL;
CollisionTree *newtree = NULL;
int laxis = 0, max_nodes=4;
unsigned int tstart, tend;
LinkNode *nlink1 = nlink;
@@ -512,7 +492,7 @@ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsign
// Build tree until 4 node left.
if ((tend-tstart + 1 ) > 1)
{
newtree = (Tree *)MEM_callocN(sizeof(Tree), "Tree");
newtree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
tnlink = BLI_linklist_append_fast(&nlink1->next, newtree);
newtree->nodes[0] = newtree->nodes[1] = newtree->nodes[2] = newtree->nodes[3] = NULL;
@@ -530,7 +510,7 @@ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsign
}
else // ok, we have 1 left for this node
{
Tree *tnode = face_list[tstart];
CollisionTree *tnode = face_list[tstart];
tree->nodes[i] = tnode;
tree->nodes[i]->parent = tree;
}
@@ -538,19 +518,16 @@ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsign
return;
}
BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xnew, unsigned int numverts, float epsilon)
// mfaces is allowed to be null
// just vertexes are used if mfaces=NULL
BVH *bvh_build (MFace *mfaces, unsigned int numfaces, MVert *x, MVert *xnew, unsigned int numverts, float epsilon)
{
unsigned int i = 0, j = 0, k = 0;
Tree **face_list=NULL;
unsigned int i = 0, j = 0;
CollisionTree **face_list=NULL;
BVH *bvh=NULL;
Tree *tree=NULL;
CollisionTree *tree=NULL;
LinkNode *nlink = NULL;
EdgeHash *edgehash = NULL;
unsigned int numsprings = 0;
MFace *mface = NULL;
if(!dm)
return NULL;
bvh = MEM_callocN(sizeof(BVH), "BVH");
if (bvh == NULL)
@@ -565,13 +542,19 @@ BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xnew, unsigned int numverts, f
bvh->tree = NULL;
bvh->epsilon = epsilon;
bvh->numfaces = dm->getNumFaces(dm);
mface = bvh->mfaces = dm->getFaceArray(dm);
bvh->numfaces = numfaces;
mface = bvh->mfaces = mfaces;
// we have no faces, we save seperate points
if(!bvh->mfaces)
{
bvh->numfaces = numverts;
}
bvh->numverts = numverts;
bvh->xnew = xnew;
bvh->x = x;
tree = (Tree *)MEM_callocN(sizeof(Tree), "Tree");
tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
// TODO: check succesfull alloc
BLI_linklist_append(&bvh->tree, tree);
@@ -590,7 +573,25 @@ BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xnew, unsigned int numverts, f
if(bvh->numfaces<=1)
{
bvh->root->tri_index = 0; // Why that? --> only one face there
// 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->isleaf = 1;
bvh->root->traversed = 0;
bvh->root->count_nodes = 0;
@@ -602,7 +603,7 @@ BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xnew, unsigned int numverts, f
else
{
// create face boxes
face_list = MEM_callocN (bvh->numfaces * sizeof (Tree *), "Tree");
face_list = MEM_callocN (bvh->numfaces * sizeof (CollisionTree *), "CollisionTree");
if (face_list == NULL)
{
printf("bvh_build: Out of memory for face_list.\n");
@@ -611,17 +612,35 @@ BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xnew, unsigned int numverts, f
}
// create face boxes
for(i = 0, k = 0; i < bvh->numfaces; i++)
for(i = 0; i < bvh->numfaces; i++)
{
LinkNode *tnlink = NULL;
tree = (Tree *)MEM_callocN(sizeof(Tree), "Tree");
tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
// TODO: check succesfull alloc
tnlink = BLI_linklist_append_fast(&nlink->next, tree);
face_list[i] = tree;
tree->tri_index = i;
if(bvh->mfaces)
{
bvh->root->point_index[0] = mfaces[i].v1;
bvh->root->point_index[1] = mfaces[i].v2;
bvh->root->point_index[2] = mfaces[i].v3;
if(mfaces[i].v4)
bvh->root->point_index[3] = mfaces[i].v4;
else
bvh->root->point_index[3] = -1;
}
else
{
bvh->root->point_index[0] = i;
bvh->root->point_index[1] = -1;
bvh->root->point_index[2] = -1;
bvh->root->point_index[3] = -1;
}
tree->isleaf = 1;
tree->nextLeaf = NULL;
tree->prevLeaf = bvh->leaf_tree;
@@ -694,7 +713,7 @@ int bvh_overlap(float *bv1, float *bv2)
* every other triangle that doesn't require any realloc, but uses
* much memory
*/
int bvh_traverse(Tree * tree1, Tree * tree2, LinkNode *collision_list)
int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision_list)
{
int i = 0, ret = 0;
@@ -709,8 +728,11 @@ int bvh_traverse(Tree * tree1, Tree * tree2, LinkNode *collision_list)
// save potential colliding triangles
CollisionPair *collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair");
collpair->indexA = tree1->tri_index;
collpair->indexB = tree2->tri_index;
VECCOPY(collpair->point_indexA, tree1->point_index);
collpair->point_indexA[3] = tree1->point_index[3];
VECCOPY(collpair->point_indexB, tree2->point_index);
collpair->point_indexB[3] = tree2->point_index[3];
BLI_linklist_append(&collision_list, collpair);
@@ -744,7 +766,7 @@ int bvh_traverse(Tree * tree1, Tree * tree2, LinkNode *collision_list)
// bottom up update of bvh tree:
// join the 4 children here
void bvh_join(Tree * tree)
void bvh_join(CollisionTree *tree)
{
int i = 0, j = 0;
if (!tree)
@@ -775,17 +797,12 @@ void bvh_join(Tree * tree)
// update static bvh
// needs new positions in bvh->x, bvh->xnew
void bvh_update(DerivedMesh *dm, BVH * bvh, int moving)
void bvh_update(BVH * bvh, int moving)
{
TreeNode *leaf, *parent;
int traversecheck = 1; // if this is zero we don't go further
unsigned int j = 0;
if(bvh->numfaces != dm->getNumFaces(dm))
return;
bvh->mfaces = dm->getFaceArray(dm);
for (leaf = bvh->leaf_root; leaf; leaf = leaf->nextLeaf)
{
traversecheck = 1;

View File

@@ -4866,7 +4866,7 @@ static void clothModifier_initData(ModifierData *md)
ClothModifierData *clmd = (ClothModifierData*) md;
cloth_init (clmd);
}
/*
static void clothModifier_deformVerts(
ModifierData *md, Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts)
@@ -4889,6 +4889,22 @@ static void clothModifier_deformVerts(
if(dm)
dm->release(dm);
}
*/
static DerivedMesh *clothModifier_applyModifier(
ModifierData *md, Object *ob, DerivedMesh *derivedData,
int useRenderParams, int isFinalCalc)
{
DerivedMesh *result = NULL;
ClothModifierData *clmd = (ClothModifierData*) md;
result = clothModifier_do(clmd, ob, derivedData);
CDDM_calc_normals(result);
return derivedData;
}
static void clothModifier_updateDepgraph(
ModifierData *md, DagForest *forest, Object *ob,
@@ -4957,6 +4973,8 @@ static void collisionModifier_initData(ModifierData *md)
collmd->x = NULL;
collmd->xnew = NULL;
collmd->current_x = NULL;
collmd->current_xnew = NULL;
collmd->time = -1;
collmd->numverts = 0;
collmd->tree = NULL;
@@ -4974,22 +4992,32 @@ static void collisionModifier_freeData(ModifierData *md)
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);
collmd->x = NULL;
collmd->xnew = NULL;
collmd->current_x = NULL;
collmd->current_xnew = 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;
MVert *mvert = NULL;
float current_time = 0;
unsigned int numverts = 0, i = 0;
MVert *tempVert = NULL;
@@ -4999,6 +5027,12 @@ static void collisionModifier_deformVerts(
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);
@@ -5013,17 +5047,26 @@ static void collisionModifier_deformVerts(
// check if mesh has changed
if(collmd->x && (numverts != collmd->numverts))
collisionModifier_freeData(collmd);
collisionModifier_freeData((ModifierData *)collmd);
if(collmd->time == -1) // first time
{
collmd->x = dm->dupVertArray(dm);
collmd->xnew = dm->dupVertArray(dm);
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->numverts = numverts;
// TODO: epsilon
// create bounding box hierarchy
collmd->tree = bvh_build(dm, collmd->x, collmd->xnew, numverts, 0.01);
collmd->tree = bvh_build(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->current_x, collmd->current_xnew, numverts, ob->pd->pdef_sbift);
}
else if(numverts == collmd->numverts)
{
@@ -5040,7 +5083,10 @@ static void collisionModifier_deformVerts(
Mat4MulVecfl ( ob->obmat, collmd->xnew[i].co );
}
bvh_update(dm, collmd->tree, 0); // recalc static bounding boxes
memcpy(collmd->current_xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
memcpy(collmd->current_x, dm->getVertArray(dm), numverts*sizeof(MVert));
bvh_update(collmd->tree, 0); // recalc static bounding boxes
}
collmd->time = current_time;
@@ -5051,11 +5097,6 @@ static void collisionModifier_deformVerts(
dm->release(dm);
}
static int collisionModifier_dependsOnTime(ModifierData *md)
{
return 1;
}
/* Boolean */
static void booleanModifier_copyData(ModifierData *md, ModifierData *target)
@@ -5342,10 +5383,10 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti->deformVerts = softbodyModifier_deformVerts;
mti = INIT_TYPE(Cloth);
mti->type = eModifierTypeType_OnlyDeform;
mti->type = eModifierTypeType_Nonconstructive;
mti->initData = clothModifier_initData;
mti->flags = eModifierTypeFlag_AcceptsCVs;
// | eModifierTypeFlag_RequiresOriginalData;
mti->flags = eModifierTypeFlag_AcceptsMesh
| eModifierTypeFlag_RequiresOriginalData;
// | eModifierTypeFlag_SupportsMapping
// | eModifierTypeFlag_SupportsEditmode
// | eModifierTypeFlag_EnableInEditmode;
@@ -5353,7 +5394,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti->freeData = clothModifier_freeData;
mti->requiredDataMask = clothModifier_requiredDataMask;
// mti->copyData = clothModifier_copyData;
mti->deformVerts = clothModifier_deformVerts;
// mti->deformVerts = clothModifier_deformVerts;
mti->applyModifier = clothModifier_applyModifier;
mti->updateDepgraph = clothModifier_updateDepgraph;
mti = INIT_TYPE(Collision);
@@ -5567,11 +5609,11 @@ int modifiers_isSoftbodyEnabled(Object *ob)
return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
}
ModifierData *modifiers_isClothEnabled(Object *ob)
ClothModifierData *modifiers_isClothEnabled(Object *ob)
{
ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
return md;
return clmd;
}
LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask)

View File

@@ -2893,6 +2893,8 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
collmd->x = NULL;
collmd->xnew = NULL;
collmd->current_x = NULL;
collmd->current_xnew = NULL;
collmd->time = -1;
collmd->numverts = 0;
collmd->tree = NULL;
@@ -3009,7 +3011,6 @@ static void direct_link_object(FileData *fd, Object *ob)
sb->bpoint= NULL; // init pointers so it gets rebuilt nicely
sb->bspring= NULL;
sb->scratch= NULL;
sb->keys= newdataadr(fd, sb->keys);
test_pointer_array(fd, (void **)&sb->keys);

View File

@@ -156,9 +156,13 @@ typedef struct Cloth
unsigned char old_solver_type;
unsigned char pad2;
short pad3;
void *tree; /* collision tree for this cloth object */
struct CollisionTree *tree; /* collision tree for this cloth object */
struct MFace *mfaces;
void *implicit; /* our implicit solver connects to this pointer */
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
struct MVert *x;
struct MVert *xnew;
struct MVert *current_x;
struct MVert *current_xnew;
}
Cloth;

View File

@@ -350,12 +350,14 @@ typedef struct ClothModifierData {
typedef struct CollisionModifierData {
ModifierData modifier;
struct MVert *x;
struct MVert *xnew;
struct MVert *x; /* position at the beginning of the frame */
struct MVert *xnew; /* position at the end of the frame */
struct MVert *current_xnew; /* new position at the actual inter-frame step */
struct MVert *current_x; /* position at the actual inter-frame step */
unsigned int numverts;
float time;
void *tree; /* collision tree for this cloth object */
struct BVH *tree; /* collision tree for this cloth object */
} CollisionModifierData;
typedef enum {

View File

@@ -113,7 +113,6 @@ typedef struct SoftBody {
;
struct SBScratch *scratch; /* scratch pad/cache on live time not saved in file */
} SoftBody;
/* pd->forcefield: Effector Fields types */

View File

@@ -99,6 +99,7 @@
#include "BKE_customdata.h"
#include "BKE_blender.h"
#include "BKE_booleanops.h"
#include "BKE_cloth.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_depsgraph.h"