From 77685023caaee092a4c1ed4a3da13ff67861a962 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 29 Jan 2008 21:01:12 +0000 Subject: Initial commit of cloth modifier from branch rev 13453 --- source/blender/blenkernel/intern/collision.c | 1261 ++++++++++++++++++++++++++ 1 file changed, 1261 insertions(+) create mode 100644 source/blender/blenkernel/intern/collision.c (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c new file mode 100644 index 00000000000..5946b842d85 --- /dev/null +++ b/source/blender/blenkernel/intern/collision.c @@ -0,0 +1,1261 @@ +/* collision.c +* +* +* ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. The Blender +* Foundation also sells licenses for use in proprietary software under +* the Blender License. See http://www.blender.org/BL/ for information +* about this. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* The Original Code is Copyright (C) Blender Foundation +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): none yet. +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#include +#include +#include +#include "MEM_guardedalloc.h" +/* types */ +#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" +#include "DNA_lattice_types.h" +#include "DNA_scene_types.h" +#include "DNA_modifier_types.h" +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_edgehash.h" +#include "BLI_linklist.h" +#include "BKE_curve.h" +#include "BKE_deform.h" +#include "BKE_DerivedMesh.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_displist.h" +#include "BKE_effect.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_cloth.h" +#include "BKE_modifier.h" +#include "BKE_utildefines.h" +#include "BKE_DerivedMesh.h" +#include "DNA_screen_types.h" +#include "BSE_headerbuttons.h" +#include "BIF_screen.h" +#include "BIF_space.h" +#include "mydevice.h" + +#include "Bullet-C-Api.h" + +/*********************************** +Collision modifier code start +***********************************/ + +/* 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); + } +} + +/* build bounding volume hierarchy from mverts (see kdop.c for whole BVH code) */ +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); +} + +/*********************************** +Collision modifier code end +***********************************/ + +/** + * gsl_poly_solve_cubic - + * + * copied from SOLVE_CUBIC.C --> GSL + */ +#define mySWAP(a,b) { float tmp = b ; b = a ; a = tmp ; } + +int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float *x2) +{ + float q = (a * a - 3 * b); + float r = (2 * a * a * a - 9 * a * b + 27 * c); + + float Q = q / 9; + float R = r / 54; + + float Q3 = Q * Q * Q; + float R2 = R * R; + + float CR2 = 729 * r * r; + float CQ3 = 2916 * q * q * q; + + if (R == 0 && Q == 0) + { + *x0 = - a / 3 ; + *x1 = - a / 3 ; + *x2 = - a / 3 ; + return 3 ; + } + else if (CR2 == CQ3) + { + /* this test is actually R2 == Q3, written in a form suitable + for exact computation with integers */ + + /* Due to finite precision some float roots may be missed, and + considered to be a pair of complex roots z = x +/- epsilon i + close to the real axis. */ + + float sqrtQ = sqrtf (Q); + + if (R > 0) + { + *x0 = -2 * sqrtQ - a / 3; + *x1 = sqrtQ - a / 3; + *x2 = sqrtQ - a / 3; + } + else + { + *x0 = - sqrtQ - a / 3; + *x1 = - sqrtQ - a / 3; + *x2 = 2 * sqrtQ - a / 3; + } + return 3 ; + } + else if (CR2 < CQ3) /* equivalent to R2 < Q3 */ + { + float sqrtQ = sqrtf (Q); + float sqrtQ3 = sqrtQ * sqrtQ * sqrtQ; + float theta = acosf (R / sqrtQ3); + float norm = -2 * sqrtQ; + *x0 = norm * cosf (theta / 3) - a / 3; + *x1 = norm * cosf ((theta + 2.0 * M_PI) / 3) - a / 3; + *x2 = norm * cosf ((theta - 2.0 * M_PI) / 3) - a / 3; + + /* Sort *x0, *x1, *x2 into increasing order */ + + if (*x0 > *x1) + mySWAP(*x0, *x1) ; + + if (*x1 > *x2) + { + mySWAP(*x1, *x2) ; + + if (*x0 > *x1) + mySWAP(*x0, *x1) ; + } + + return 3; + } + else + { + float sgnR = (R >= 0 ? 1 : -1); + float A = -sgnR * powf (fabs (R) + sqrtf (R2 - Q3), 1.0/3.0); + float B = Q / A ; + *x0 = A + B - a / 3; + return 1; + } +} + + +/** + * gsl_poly_solve_quadratic + * + * copied from GSL + */ +int gsl_poly_solve_quadratic (float a, float b, float c, float *x0, float *x1) +{ + float disc = b * b - 4 * a * c; + + if (disc > 0) + { + if (b == 0) + { + float r = fabs (0.5 * sqrtf (disc) / a); + *x0 = -r; + *x1 = r; + } + else + { + float sgnb = (b > 0 ? 1 : -1); + float temp = -0.5 * (b + sgnb * sqrtf (disc)); + float r1 = temp / a ; + float r2 = c / temp ; + + if (r1 < r2) + { + *x0 = r1 ; + *x1 = r2 ; + } + else + { + *x0 = r2 ; + *x1 = r1 ; + } + } + return 2; + } + else if (disc == 0) + { + *x0 = -0.5 * b / a ; + *x1 = -0.5 * b / a ; + return 2 ; + } + else + { + return 0; + } +} + + + +/* + * See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation" + * page 4, left column + */ + +int cloth_get_collision_time(float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3]) +{ + int num_sols = 0; + + float g = -a[2] * c[1] * e[0] + a[1] * c[2] * e[0] + + a[2] * c[0] * e[1] - a[0] * c[2] * e[1] - + a[1] * c[0] * e[2] + a[0] * c[1] * e[2]; + + float h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] + + a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] + + a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] + + b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] - + a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] - + a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2]; + + float i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] + + b[2] * d[0] * e[1] - b[0] * d[2] * e[1] - + b[1] * d[0] * e[2] + b[0] * d[1] * e[2] - + b[2] * c[1] * f[0] + b[1] * c[2] * f[0] - + a[2] * d[1] * f[0] + a[1] * d[2] * f[0] + + b[2] * c[0] * f[1] - b[0] * c[2] * f[1] + + a[2] * d[0] * f[1] - a[0] * d[2] * f[1] - + b[1] * c[0] * f[2] + b[0] * c[1] * f[2] - + a[1] * d[0] * f[2] + a[0] * d[1] * f[2]; + + float j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] + + b[2] * d[0] * f[1] - b[0] * d[2] * f[1] - + b[1] * d[0] * f[2] + b[0] * d[1] * f[2]; + + // Solve cubic equation to determine times t1, t2, t3, when the collision will occur. + if(ABS(j) > ALMOST_ZERO) + { + i /= j; + h /= j; + g /= j; + + num_sols = gsl_poly_solve_cubic(i, h, g, &solution[0], &solution[1], &solution[2]); + } + else if(ABS(i) > ALMOST_ZERO) + { + num_sols = gsl_poly_solve_quadratic(i, h, g, &solution[0], &solution[1]); + solution[2] = -1.0; + } + else if(ABS(h) > ALMOST_ZERO) + { + solution[0] = -g / h; + solution[1] = solution[2] = -1.0; + num_sols = 1; + } + else if(ABS(g) > ALMOST_ZERO) + { + solution[0] = 0; + solution[1] = solution[2] = -1.0; + num_sols = 1; + } + + // Discard negative solutions + if ((num_sols >= 1) && (solution[0] < 0)) + { + --num_sols; + solution[0] = solution[num_sols]; + } + if ((num_sols >= 2) && (solution[1] < 0)) + { + --num_sols; + solution[1] = solution[num_sols]; + } + if ((num_sols == 3) && (solution[2] < 0)) + { + --num_sols; + } + + // Sort + if (num_sols == 2) + { + if (solution[0] > solution[1]) + { + double tmp = solution[0]; + solution[0] = solution[1]; + solution[1] = tmp; + } + } + else if (num_sols == 3) + { + + // Bubblesort + if (solution[0] > solution[1]) { + double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp; + } + if (solution[1] > solution[2]) { + double tmp = solution[1]; solution[1] = solution[2]; solution[2] = tmp; + } + if (solution[0] > solution[1]) { + double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp; + } + } + + return num_sols; +} + +// w3 is not perfect +void cloth_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) +{ + double tempV1[3], tempV2[3], tempV4[3]; + double a,b,c,d,e,f; + + VECSUB (tempV1, p1, p3); + VECSUB (tempV2, p2, p3); + VECSUB (tempV4, pv, p3); + + a = INPR (tempV1, tempV1); + b = INPR (tempV1, tempV2); + c = INPR (tempV2, tempV2); + e = INPR (tempV1, tempV4); + f = INPR (tempV2, tempV4); + + d = (a * c - b * b); + + if (ABS(d) < ALMOST_ZERO) { + *w1 = *w2 = *w3 = 1.0 / 3.0; + return; + } + + w1[0] = (float)((e * c - b * f) / d); + + if(w1[0] < 0) + w1[0] = 0; + + w2[0] = (float)((f - b * (double)w1[0]) / c); + + if(w2[0] < 0) + w2[0] = 0; + + w3[0] = 1.0f - w1[0] - w2[0]; +} + +DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3) +{ + to[0] = to[1] = to[2] = 0; + VECADDMUL(to, v1, w1); + VECADDMUL(to, v2, w2); + 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 cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierData *collmd) +{ + unsigned int i = 0; + int result = 0; + LinkNode *search = NULL; + CollPair *collpair = NULL; + Cloth *cloth1; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + + cloth1 = clmd->clothObject; + + search = clmd->coll_parms->collision_list; + + while(search) + { + collpair = search->link; + + // compute barycentric coordinates for both collision points + cloth_compute_barycentric(collpair->pa, + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3); + + // was: txold + cloth_compute_barycentric(collpair->pb, + collmd->current_x[collpair->bp1].co, + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, + &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, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, 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 + /* + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential); + */ + } + + + impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + // printf("impulse: %f\n", impulse); + + 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++; + + result = 1; + + /* + if (overlap > ALMOST_ZERO) { + double I_mag = overlap * 0.1; + + impulse = -I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + 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++; + } + */ + + // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case + + // Apply the impulse and increase impulse counters. + + /* + // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms->friction*0.01, magtangent); + VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); + // VecMulf(vrel_t_pre, clmd->coll_parms->friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); + magtangent = Normalize(vrel_t_pre); + VecMulf(vrel_t_pre, MIN2(clmd->coll_parms->friction*0.01f*magnormal,magtangent)); + + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre); + */ + + + + } + + search = search->next; + } + + + return result; +} + +int cloth_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + return 1; +} + + +int cloth_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + return 1; +} + +void cloth_collision_static(ClothModifierData *clmd, CollisionModifierData *collmd, CollisionTree *tree1, CollisionTree *tree2) +{ + CollPair *collpair = NULL; + Cloth *cloth1=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=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; + + verts1 = cloth1->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(collmd->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, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, 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; + BLI_linklist_prepend(&clmd->coll_parms->collision_list, collpair); + + } + else + { + MEM_freeN(collpair); + } + } + else + { + MEM_freeN(collpair); + } + } +} + +int cloth_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) +{ + Cloth *cloth1 = NULL, *cloth2 = NULL; + ClothVertex *verts1 = NULL, *verts2 = NULL; + 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 cloth_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(!cloth_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 = cloth_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 cloth_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 = cloth_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 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); + + cloth_collision_moving_tris(clmd, coll_clmd, tree1, tree2); + cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); +} + +// cloth - object collisions +int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) +{ + Base *base=NULL; + CollisionModifierData *collmd=NULL; + Cloth *cloth=NULL; + Object *coll_ob=NULL; + BVH *cloth_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; + ClothModifierData *tclmd; + + if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) + { + return 0; + } + + cloth = clmd->clothObject; + verts = cloth->verts; + cloth_bvh = (BVH *) cloth->tree; + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + + //////////////////////////////////////////////////////////// + // static collisions + //////////////////////////////////////////////////////////// + + // update cloth bvh + bvh_update_from_cloth(clmd, 0); // 0 means STATIC, 1 means MOVING (see later in this function) + + do + { + result = 0; + ic = 0; + clmd->coll_parms->collision_list = NULL; + + // check all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + coll_ob = base->object; + collmd = (CollisionModifierData *) modifiers_findByType (coll_ob, eModifierType_Collision); + + if (!collmd) + continue; + + tclmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if(tclmd == clmd) + continue; + + if (collmd->tree) + { + BVH *coll_bvh = collmd->tree; + + collision_move_object(collmd, step + dt, step); + + bvh_traverse(clmd, collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static); + } + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + + + // 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; + + if (collmd->tree) + result += cloth_collision_response_static(clmd, collmd); + + + // 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(clmd->coll_parms->collision_list) + { + LinkNode *search = clmd->coll_parms->collision_list; + while(search) + { + CollPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(clmd->coll_parms->collision_list,NULL); + + clmd->coll_parms->collision_list = NULL; + } + } + rounds++; + } + while(result && (clmd->coll_parms->loop_count>rounds)); + + //////////////////////////////////////////////////////////// + // update positions + // this is needed for bvh_calc_DOP_hull_moving() [kdop.c] + //////////////////////////////////////////////////////////// + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + { + if(verts [i].goal >= SOFTGOALSNAP) + { + continue; + } + } + + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // moving collisions + // + // response code is just missing itm + //////////////////////////////////////////////////////////// + + /* + // update cloth bvh + 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) + { + + 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_from_cloth(coll_clmd, 1); // 0 means STATIC, 1 means MOVING +} +} + + + do + { + result = 0; + ic = 0; + clmd->coll_parms->collision_list = NULL; + + // 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(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving); +} + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); +} +} + + // 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 + 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) + result += cloth_collision_response_moving_tris(clmd, coll_clmd); + else + printf ("cloth_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_from_cloth(clmd, 1); // 0 means STATIC, 1 means MOVING + + + // free collision list + if(clmd->coll_parms->collision_list) + { + LinkNode *search = clmd->coll_parms->collision_list; + while(search) + { + CollPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; +} + BLI_linklist_free(clmd->coll_parms->collision_list,NULL); + + clmd->coll_parms->collision_list = NULL; +} + + // 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); +} -- cgit v1.2.3 From 7a7a52226f52952534c93832c3e7b0492ec0ad30 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 29 Jan 2008 23:13:31 +0000 Subject: makes bullet independant from gameengine for cmake, introduces esc-key during sim, disables collisions when no bullet there --- source/blender/blenkernel/intern/collision.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 5946b842d85..7d2284e3193 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -680,9 +680,13 @@ void cloth_collision_static(ClothModifierData *clmd, CollisionModifierData *coll if(i < 4) { // calc distance + normal +#if WITH_BULLET == 1 distance = plNearestPoints( verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector); - +#else + // just be sure that we don't add anything + distance = 2.0 * (epsilon + ALMOST_ZERO); +#endif if (distance <= (epsilon + ALMOST_ZERO)) { // printf("dist: %f\n", (float)distance); -- cgit v1.2.3 From 2a3e93444a1624fe2baeab3ee135332eb0c4e765 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 31 Jan 2008 12:29:57 +0000 Subject: Replaced all *f geometric functions like sinf etc. with sin etc. (were used in 2 functions from the gnu scientific library) --- source/blender/blenkernel/intern/collision.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 7d2284e3193..afca64670eb 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -151,6 +151,8 @@ Collision modifier code end * * copied from SOLVE_CUBIC.C --> GSL */ + +/* DG: debug hint! don't forget that all functions were "fabs", "sinf", etc before */ #define mySWAP(a,b) { float tmp = b ; b = a ; a = tmp ; } int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float *x2) @@ -183,7 +185,7 @@ int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float considered to be a pair of complex roots z = x +/- epsilon i close to the real axis. */ - float sqrtQ = sqrtf (Q); + float sqrtQ = sqrt (Q); if (R > 0) { @@ -201,13 +203,13 @@ int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float } else if (CR2 < CQ3) /* equivalent to R2 < Q3 */ { - float sqrtQ = sqrtf (Q); + float sqrtQ = sqrt (Q); float sqrtQ3 = sqrtQ * sqrtQ * sqrtQ; - float theta = acosf (R / sqrtQ3); + float theta = acos (R / sqrtQ3); float norm = -2 * sqrtQ; - *x0 = norm * cosf (theta / 3) - a / 3; - *x1 = norm * cosf ((theta + 2.0 * M_PI) / 3) - a / 3; - *x2 = norm * cosf ((theta - 2.0 * M_PI) / 3) - a / 3; + *x0 = norm * cos (theta / 3) - a / 3; + *x1 = norm * cos ((theta + 2.0 * M_PI) / 3) - a / 3; + *x2 = norm * cos ((theta - 2.0 * M_PI) / 3) - a / 3; /* Sort *x0, *x1, *x2 into increasing order */ @@ -227,7 +229,7 @@ int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float else { float sgnR = (R >= 0 ? 1 : -1); - float A = -sgnR * powf (fabs (R) + sqrtf (R2 - Q3), 1.0/3.0); + float A = -sgnR * pow (ABS (R) + sqrt (R2 - Q3), 1.0/3.0); float B = Q / A ; *x0 = A + B - a / 3; return 1; @@ -248,14 +250,14 @@ int gsl_poly_solve_quadratic (float a, float b, float c, float *x0, float *x1) { if (b == 0) { - float r = fabs (0.5 * sqrtf (disc) / a); + float r = ABS (0.5 * sqrt (disc) / a); *x0 = -r; *x1 = r; } else { float sgnb = (b > 0 ? 1 : -1); - float temp = -0.5 * (b + sgnb * sqrtf (disc)); + float temp = -0.5 * (b + sgnb * sqrt (disc)); float r1 = temp / a ; float r2 = c / temp ; -- cgit v1.2.3 From 0e7bdb959eb694d384a1938d1f580365043c0ed6 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 3 Feb 2008 22:37:43 +0000 Subject: Cloth: Fixed: [#8210] (includes bad spring calculation), only mesh can get cloth assigned, New: initial try of Bridson/Fedkiw friction formula implementation, better GUI feedback when e.g. cache is protected and settings too --- source/blender/blenkernel/intern/collision.c | 95 ++++++++-------------------- 1 file changed, 26 insertions(+), 69 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index afca64670eb..7304ae09ef8 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -437,17 +437,6 @@ 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 cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierData *collmd) { unsigned int i = 0; @@ -477,9 +466,9 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa // was: txold cloth_compute_barycentric(collpair->pb, collmd->current_x[collpair->bp1].co, - collmd->current_x[collpair->bp2].co, - collmd->current_x[collpair->bp3].co, - &u1, &u2, &u3); + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, + &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); @@ -494,43 +483,45 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa // printf("magrelVel: %f\n", magrelVel); // Calculate masses of points. + // TODO // 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 magnitude_i = magrelVel / 2.0; // TODO implement masses + float tangential[3], magtangent, magnormal; + double impulse = 0.0; float epsilon = clmd->coll_parms->epsilon; - float overlap = (epsilon + ALMOST_ZERO-collpair->distance); + float vrel_t_pre[3]; + float vrel_t[3], temp[3]; + + VECCOPY(temp, collpair->normal); + VecMulf(temp, magrelVel); + VECSUB(vrel_t_pre, relativeVelocity, temp); + + VECCOPY(vrel_t, vrel_t_pre); + + VecMulf(vrel_t, MAX2(1.0 - (clmd->coll_parms->friction * magrelVel / sqrt(INPR(vrel_t_pre,vrel_t_pre))), 0)); - // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms->friction*0.01, magrelVel); + VECSUB(tangential, vrel_t_pre, vrel_t); + VecMulf(tangential, 0.5); - // magtangent = INPR(tangential, tangential); + // i_tangential = tangential + magtangent = INPR(tangential, tangential); // Apply friction impulse. - if (magtangent < -ALMOST_ZERO) + if (magtangent > ALMOST_ZERO) { - - // printf("friction applied: %f\n", magtangent); - // TODO check original code - /* - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,tangential); - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv,tangential); - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv,tangential); - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential); - */ + impulse = magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + VECADDMUL(cloth1->verts[collpair->ap1].impulse, tangential, w1 * impulse/magtangent); + VECADDMUL(cloth1->verts[collpair->ap2].impulse, tangential, w2 * impulse/magtangent); + VECADDMUL(cloth1->verts[collpair->ap3].impulse, tangential, w3 * impulse/magtangent); } impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - // printf("impulse: %f\n", impulse); - VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); cloth1->verts[collpair->ap1].impulse_count++; @@ -541,40 +532,6 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa cloth1->verts[collpair->ap3].impulse_count++; result = 1; - - /* - if (overlap > ALMOST_ZERO) { - double I_mag = overlap * 0.1; - - impulse = -I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - - 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++; - } - */ - - // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case - - // Apply the impulse and increase impulse counters. - - /* - // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms->friction*0.01, magtangent); - VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); - // VecMulf(vrel_t_pre, clmd->coll_parms->friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); - magtangent = Normalize(vrel_t_pre); - VecMulf(vrel_t_pre, MIN2(clmd->coll_parms->friction*0.01f*magnormal,magtangent)); - - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre); - */ - - - } search = search->next; -- cgit v1.2.3 From 7a70e5c0c0eacda814ffc32035a649a88b5326d0 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 5 Feb 2008 14:11:48 +0000 Subject: Cloth: 1. Fix for deflection being enabled thourgh softbody interface, 2. Fix for wrong calculated friction, 3. Fix for some header which was accitently blown up by my editor --- source/blender/blenkernel/intern/collision.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 7304ae09ef8..788f5adc922 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -496,24 +496,25 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa float vrel_t_pre[3]; float vrel_t[3], temp[3]; + // calculate tangential velocity VECCOPY(temp, collpair->normal); VecMulf(temp, magrelVel); VECSUB(vrel_t_pre, relativeVelocity, temp); VECCOPY(vrel_t, vrel_t_pre); - VecMulf(vrel_t, MAX2(1.0 - (clmd->coll_parms->friction * magrelVel / sqrt(INPR(vrel_t_pre,vrel_t_pre))), 0)); + VecMulf(vrel_t, MAX2(1.0 - (clmd->coll_parms->friction * magrelVel / sqrt(INPR(vrel_t_pre,vrel_t_pre))), 0.0)); VECSUB(tangential, vrel_t_pre, vrel_t); VecMulf(tangential, 0.5); - // i_tangential = tangential magtangent = INPR(tangential, tangential); // Apply friction impulse. if (magtangent > ALMOST_ZERO) { impulse = magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + magtangent = sqrt(magtangent); VECADDMUL(cloth1->verts[collpair->ap1].impulse, tangential, w1 * impulse/magtangent); VECADDMUL(cloth1->verts[collpair->ap2].impulse, tangential, w2 * impulse/magtangent); VECADDMUL(cloth1->verts[collpair->ap3].impulse, tangential, w3 * impulse/magtangent); -- cgit v1.2.3 From a8c25e279d2209665cf7f561c4cb32837dc83aa3 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 5 Feb 2008 15:09:48 +0000 Subject: Cloth: Fix for crash with meshes with no faces, 2. Fix for crash on switching from to another mesh --- source/blender/blenkernel/intern/collision.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 788f5adc922..4ce0cc79502 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -101,6 +101,10 @@ BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsig return NULL; } + // in the moment, return zero if no faces there + if(!numfaces) + return NULL; + bvh->flags = 0; bvh->leaf_tree = NULL; bvh->leaf_root = NULL; -- cgit v1.2.3 From 69e6a6cbc9cfdae6804d538cb4810672c5318d48 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 11 Feb 2008 13:30:52 +0000 Subject: Pointcache: Fixed non-availability when blend file was loaded from command line and also another case where you startet from an unsaved blend and switched to a saved one; Cloth: Fixid mass init, little speedup for collisions; Collision Modifier: More generalized it --- source/blender/blenkernel/intern/collision.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 4ce0cc79502..da9312b01ab 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -557,8 +557,10 @@ int cloth_collision_response_moving_edges(ClothModifierData *clmd, ClothModifier return 1; } -void cloth_collision_static(ClothModifierData *clmd, CollisionModifierData *collmd, CollisionTree *tree1, CollisionTree *tree2) +void cloth_collision_static(ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2) { + ClothModifierData *clmd = (ClothModifierData *)md1; + CollisionModifierData *collmd = (CollisionModifierData *)md2; CollPair *collpair = NULL; Cloth *cloth1=NULL; MFace *face1=NULL, *face2=NULL; @@ -1004,7 +1006,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) collision_move_object(collmd, step + dt, step); - bvh_traverse(clmd, collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static); + bvh_traverse((ModifierData *)clmd, (ModifierData *)collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static); } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); @@ -1012,13 +1014,12 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) // 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 + for(j = 0; j < 5; j++) // 5 is just a value that ensures convergence { result = 0; if (collmd->tree) result += cloth_collision_response_static(clmd, collmd); - // apply impulses in parallel ic=0; -- cgit v1.2.3 From e82484b0bb628a533fc1cd43be804c365d54f3f1 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 12 Feb 2008 11:04:58 +0000 Subject: Cloth: New: *simple* (OpenMP enabled) Selfcollisions available --- source/blender/blenkernel/intern/collision.c | 130 +++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 5 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index da9312b01ab..9ec99548bb1 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -948,6 +948,29 @@ void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clm cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); } +void cloth_collision_self_static(ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2) +{ + ClothModifierData *clmd = (ClothModifierData *)md1; + CollisionModifierData *collmd = (CollisionModifierData *)md2; + CollPair *collpair = NULL; + Cloth *cloth1=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL; + double distance = 0; + float epsilon = clmd->coll_parms->epsilon; + unsigned int i = 0; + + +} + +/* aye this belongs to arith.c */ +static void Vec3PlusStVec(float *v, float s, float *v1) +{ + v[0] += s*v1[0]; + v[1] += s*v1[1]; + v[2] += s*v1[2]; +} + // cloth - object collisions int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { @@ -956,12 +979,13 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) Cloth *cloth=NULL; Object *coll_ob=NULL; BVH *cloth_bvh=NULL; - unsigned int i=0, j = 0, numfaces = 0, numverts = 0; + long 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; ClothModifierData *tclmd; + int collisions = 0, count = 0; if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) { @@ -1006,7 +1030,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) collision_move_object(collmd, step + dt, step); - bvh_traverse((ModifierData *)clmd, (ModifierData *)collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static); + bvh_traverse((ModifierData *)clmd, (ModifierData *)collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0); } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); @@ -1068,7 +1092,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { - if(verts [i].goal >= SOFTGOALSNAP) + if(verts [i].flags & CLOTH_VERT_FLAG_PINNED) { continue; } @@ -1077,7 +1101,103 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) VECADD(verts[i].tx, verts[i].txold, verts[i].tv); } //////////////////////////////////////////////////////////// - + + + //////////////////////////////////////////////////////////// + // Test on *simple* selfcollisions + //////////////////////////////////////////////////////////// + if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) + { + collisions = 1; + verts = cloth->verts; // needed for openMP + + for(count = 0; count < clmd->coll_parms->self_loop_count; count++) + { + if(collisions) + { + collisions = 0; + #pragma omp parallel for private(i,j, collisions) shared(verts, ret) + for(i = 0; i < cloth->numverts; i++) + { + for(j = i + 1; j < cloth->numverts; j++) + { + float temp[3]; + float length = 0; + float mindistance = clmd->coll_parms->selfepsilon*(cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len); + + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + { + if((cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED) + && (cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED)) + { + continue; + } + } + + VECSUB(temp, verts[i].tx, verts[j].tx); + + if ((ABS(temp[0]) > mindistance) || (ABS(temp[1]) > mindistance) || (ABS(temp[2]) > mindistance)) continue; + + // check for adjacent points + if(BLI_edgehash_haskey (cloth->edgehash, i, j )) + { + continue; + } + + length = Normalize(temp); + + if(length < mindistance) + { + float correction = mindistance - length; + + if(cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED) + { + VecMulf(temp, -correction); + VECADD(verts[j].tx, verts[j].tx, temp); + } + else if(cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED) + { + VecMulf(temp, correction); + VECADD(verts[i].tx, verts[i].tx, temp); + } + else + { + VecMulf(temp, -correction*0.5); + VECADD(verts[j].tx, verts[j].tx, temp); + + VECSUB(verts[i].tx, verts[i].tx, temp); + } + + collisions = 1; + + if(!ret) + { + #pragma omp critical + { + ret = 1; + } + } + } + } + } + } + } + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // SELFCOLLISIONS: update velocities + //////////////////////////////////////////////////////////// + if(ret) + { + for(i = 0; i < cloth->numverts; i++) + { + if(!(cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED)) + VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + } + } + //////////////////////////////////////////////////////////// + } + //////////////////////////////////////////////////////////// // moving collisions // @@ -1132,7 +1252,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { BVH *coll_bvh = coll_clmd->clothObject->tree; - bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving); + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving, 0); } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); -- cgit v1.2.3 From a21c765f4b8eeab488bf6d913037e52735a41ce1 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 12 Feb 2008 12:02:39 +0000 Subject: Cloth: Fix order in collision loop -> solving selfcollision could result in new cloth-object collisions, adjust 'collision quality' for the number of loops taken --- source/blender/blenkernel/intern/collision.c | 190 +++++++++++++-------------- 1 file changed, 95 insertions(+), 95 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 9ec99548bb1..8cadb7e5f1b 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -979,7 +979,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) Cloth *cloth=NULL; Object *coll_ob=NULL; BVH *cloth_bvh=NULL; - long i=0, j = 0, numfaces = 0, numverts = 0; + long i=0, j = 0, numfaces = 0, numverts = 0, k = 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}; @@ -1079,124 +1079,124 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) } } rounds++; - } - while(result && (clmd->coll_parms->loop_count>rounds)); - - //////////////////////////////////////////////////////////// - // update positions - // this is needed for bvh_calc_DOP_hull_moving() [kdop.c] - //////////////////////////////////////////////////////////// - // verts come from clmd - for(i = 0; i < numverts; i++) - { - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - { - if(verts [i].flags & CLOTH_VERT_FLAG_PINNED) - { - continue; + //////////////////////////////////////////////////////////// + // update positions + // this is needed for bvh_calc_DOP_hull_moving() [kdop.c] + //////////////////////////////////////////////////////////// + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + { + if(verts [i].flags & CLOTH_VERT_FLAG_PINNED) + { + continue; + } } + + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); } + //////////////////////////////////////////////////////////// - VECADD(verts[i].tx, verts[i].txold, verts[i].tv); - } - //////////////////////////////////////////////////////////// - - - //////////////////////////////////////////////////////////// - // Test on *simple* selfcollisions - //////////////////////////////////////////////////////////// - if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) - { - collisions = 1; - verts = cloth->verts; // needed for openMP - for(count = 0; count < clmd->coll_parms->self_loop_count; count++) - { - if(collisions) - { - collisions = 0; - #pragma omp parallel for private(i,j, collisions) shared(verts, ret) - for(i = 0; i < cloth->numverts; i++) + //////////////////////////////////////////////////////////// + // Test on *simple* selfcollisions + //////////////////////////////////////////////////////////// + if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) + { + collisions = 1; + verts = cloth->verts; // needed for openMP + + for(count = 0; count < clmd->coll_parms->self_loop_count; count++) + { + if(collisions) { - for(j = i + 1; j < cloth->numverts; j++) + collisions = 0; + #pragma omp parallel for private(i,j, collisions) shared(verts, ret) + for(i = 0; i < cloth->numverts; i++) { - float temp[3]; - float length = 0; - float mindistance = clmd->coll_parms->selfepsilon*(cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len); - - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - { - if((cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED) - && (cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED)) - { - continue; - } - } - - VECSUB(temp, verts[i].tx, verts[j].tx); - - if ((ABS(temp[0]) > mindistance) || (ABS(temp[1]) > mindistance) || (ABS(temp[2]) > mindistance)) continue; - - // check for adjacent points - if(BLI_edgehash_haskey (cloth->edgehash, i, j )) + for(j = i + 1; j < cloth->numverts; j++) { - continue; - } + float temp[3]; + float length = 0; + float mindistance = clmd->coll_parms->selfepsilon*(cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len); + + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + { + if((cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED) + && (cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED)) + { + continue; + } + } - length = Normalize(temp); + VECSUB(temp, verts[i].tx, verts[j].tx); - if(length < mindistance) - { - float correction = mindistance - length; + if ((ABS(temp[0]) > mindistance) || (ABS(temp[1]) > mindistance) || (ABS(temp[2]) > mindistance)) continue; - if(cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED) - { - VecMulf(temp, -correction); - VECADD(verts[j].tx, verts[j].tx, temp); - } - else if(cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED) + // check for adjacent points + if(BLI_edgehash_haskey (cloth->edgehash, i, j )) { - VecMulf(temp, correction); - VECADD(verts[i].tx, verts[i].tx, temp); + continue; } - else + + length = Normalize(temp); + + if(length < mindistance) { - VecMulf(temp, -correction*0.5); - VECADD(verts[j].tx, verts[j].tx, temp); + float correction = mindistance - length; + + if(cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED) + { + VecMulf(temp, -correction); + VECADD(verts[j].tx, verts[j].tx, temp); + } + else if(cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED) + { + VecMulf(temp, correction); + VECADD(verts[i].tx, verts[i].tx, temp); + } + else + { + VecMulf(temp, -correction*0.5); + VECADD(verts[j].tx, verts[j].tx, temp); + + VECSUB(verts[i].tx, verts[i].tx, temp); + } - VECSUB(verts[i].tx, verts[i].tx, temp); - } - - collisions = 1; - - if(!ret) - { - #pragma omp critical - { - ret = 1; - } + collisions = 1; + + if(!ret) + { + #pragma omp critical + { + ret = 1; + } + } } } } } } - } - //////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////// - // SELFCOLLISIONS: update velocities - //////////////////////////////////////////////////////////// - if(ret) - { - for(i = 0; i < cloth->numverts; i++) + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // SELFCOLLISIONS: update velocities + //////////////////////////////////////////////////////////// + if(ret) { - if(!(cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED)) - VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + for(i = 0; i < cloth->numverts; i++) + { + if(!(cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED)) + VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + } } + //////////////////////////////////////////////////////////// } - //////////////////////////////////////////////////////////// } + while(result && (clmd->coll_parms->loop_count>rounds)); //////////////////////////////////////////////////////////// // moving collisions -- cgit v1.2.3 From 31922633670f03ceb2e963984e418fecd1a59d40 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 13 Feb 2008 10:44:36 +0000 Subject: Cloth: changes in editmode will influence the velocity by 10% now, changed/add some update calls for the implicit function --- source/blender/blenkernel/intern/collision.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 8cadb7e5f1b..8f681ea9865 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -979,7 +979,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) Cloth *cloth=NULL; Object *coll_ob=NULL; BVH *cloth_bvh=NULL; - long i=0, j = 0, numfaces = 0, numverts = 0, k = 0; + long 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}; -- cgit v1.2.3 From 824a714b470b4648b168410a61277bef5a50c81a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 24 Feb 2008 11:16:37 +0000 Subject: Purge of compiler warnings... (hopefully everything still compiles, there are still more to remove) --- source/blender/blenkernel/intern/collision.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 8f681ea9865..793a4973475 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -443,7 +443,6 @@ DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], floa int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierData *collmd) { - unsigned int i = 0; int result = 0; LinkNode *search = NULL; CollPair *collpair = NULL; @@ -493,10 +492,8 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa if(magrelVel < -ALMOST_ZERO) { // Calculate Impulse magnitude to stop all motion in normal direction. - float magnitude_i = magrelVel / 2.0; // TODO implement masses - float tangential[3], magtangent, magnormal; + float tangential[3], magtangent; double impulse = 0.0; - float epsilon = clmd->coll_parms->epsilon; float vrel_t_pre[3]; float vrel_t[3], temp[3]; @@ -716,8 +713,6 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co 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]; @@ -831,7 +826,7 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co { if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) { - float out_collisionTime = solution[k]; + //float out_collisionTime = solution[k]; // TODO: check for collisions @@ -851,8 +846,6 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col 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]; @@ -921,7 +914,7 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col { if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) { - float out_collisionTime = solution[k]; + //float out_collisionTime = solution[k]; // TODO: check for collisions @@ -950,6 +943,7 @@ void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clm void cloth_collision_self_static(ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2) { +/* ClothModifierData *clmd = (ClothModifierData *)md1; CollisionModifierData *collmd = (CollisionModifierData *)md2; CollPair *collpair = NULL; @@ -959,10 +953,11 @@ void cloth_collision_self_static(ModifierData *md1, ModifierData *md2, Collision double distance = 0; float epsilon = clmd->coll_parms->epsilon; unsigned int i = 0; - +*/ } +#if 0 /* aye this belongs to arith.c */ static void Vec3PlusStVec(float *v, float s, float *v1) { @@ -970,6 +965,7 @@ static void Vec3PlusStVec(float *v, float s, float *v1) v[1] += s*v1[1]; v[2] += s*v1[2]; } +#endif // cloth - object collisions int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) -- cgit v1.2.3 From 7d310f4e5c9059a7e734d852424915e8aac7319e Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 27 Feb 2008 03:23:17 +0000 Subject: Cloth: fixed completely useless/wrong friction force; changed some initial settings --- source/blender/blenkernel/intern/collision.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 793a4973475..6ef6758cab6 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -492,33 +492,27 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa if(magrelVel < -ALMOST_ZERO) { // Calculate Impulse magnitude to stop all motion in normal direction. - float tangential[3], magtangent; + float magtangent; double impulse = 0.0; float vrel_t_pre[3]; - float vrel_t[3], temp[3]; + float temp[3]; // calculate tangential velocity VECCOPY(temp, collpair->normal); VecMulf(temp, magrelVel); VECSUB(vrel_t_pre, relativeVelocity, temp); - VECCOPY(vrel_t, vrel_t_pre); - - VecMulf(vrel_t, MAX2(1.0 - (clmd->coll_parms->friction * magrelVel / sqrt(INPR(vrel_t_pre,vrel_t_pre))), 0.0)); - - VECSUB(tangential, vrel_t_pre, vrel_t); - VecMulf(tangential, 0.5); - - magtangent = INPR(tangential, tangential); + magtangent = INPR(vrel_t_pre,vrel_t_pre) - MIN2(clmd->coll_parms->friction * 0.01 * magrelVel,INPR(vrel_t_pre,vrel_t_pre)); // Apply friction impulse. if (magtangent > ALMOST_ZERO) - { - impulse = magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - magtangent = sqrt(magtangent); - VECADDMUL(cloth1->verts[collpair->ap1].impulse, tangential, w1 * impulse/magtangent); - VECADDMUL(cloth1->verts[collpair->ap2].impulse, tangential, w2 * impulse/magtangent); - VECADDMUL(cloth1->verts[collpair->ap3].impulse, tangential, w3 * impulse/magtangent); + { + Normalize(vrel_t_pre); + + impulse = -2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + VECADDMUL(cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse); + VECADDMUL(cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse); + VECADDMUL(cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse); } -- cgit v1.2.3 From 905a2d374a9b418fe2d358f4c7fdbc12a6253f91 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 28 Feb 2008 00:01:19 +0000 Subject: Cloth: 1. Bugfix for possible memory leak reported by Kenneth Styrberg (via mailing list), 2. Bugfix for friction again, 3. Preset menu on GUI (thanks to help from nudelZ (#blendercoders), 4. Possibility to disable autoprotect cache, 5. Some cache bugs fixed, 6. Some speedup in generating cloth --- source/blender/blenkernel/intern/collision.c | 39 ++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 6ef6758cab6..de13d952f8e 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -478,7 +478,7 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa interpolateOnTriangle(v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3); - VECSUB(relativeVelocity, v1, v2); + VECSUB(relativeVelocity, v2, v1); // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). magrelVel = INPR(relativeVelocity, collpair->normal); @@ -489,10 +489,10 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa // TODO // If v_n_mag < 0 the edges are approaching each other. - if(magrelVel < -ALMOST_ZERO) + if(magrelVel > ALMOST_ZERO) { // Calculate Impulse magnitude to stop all motion in normal direction. - float magtangent; + float magtangent = 0, repulse = 0, d = 0; double impulse = 0.0; float vrel_t_pre[3]; float temp[3]; @@ -502,21 +502,25 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa VecMulf(temp, magrelVel); VECSUB(vrel_t_pre, relativeVelocity, temp); - magtangent = INPR(vrel_t_pre,vrel_t_pre) - MIN2(clmd->coll_parms->friction * 0.01 * magrelVel,INPR(vrel_t_pre,vrel_t_pre)); + // Decrease in magnitude of relative tangential velocity due to coulomb friction + // in original formula "magrelVel" should be the "change of relative velocity in normal direction" + magtangent = MIN2(clmd->coll_parms->friction * 0.01 * magrelVel,sqrt(INPR(vrel_t_pre,vrel_t_pre))); // Apply friction impulse. if (magtangent > ALMOST_ZERO) { Normalize(vrel_t_pre); - - impulse = -2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + impulse = 2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3); VECADDMUL(cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse); VECADDMUL(cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse); VECADDMUL(cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse); } - - impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + // Apply velocity stopping impulse + // I_c = m * v_N / 2.0 + // no 2.0 * magrelVel normally, but looks nicer DG + impulse = 2.0 * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); cloth1->verts[collpair->ap1].impulse_count++; @@ -527,6 +531,22 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); cloth1->verts[collpair->ap3].impulse_count++; + /* + // doesn't perform nice, dunno why DG + // Apply repulse impulse if distance too short + // I_r = -min(dt*kd, m(0,1d/dt - v_n)) + d = clmd->coll_parms->epsilon - collpair->distance; + if((magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame) && (d > ALMOST_ZERO)) + { + repulse = MIN2(d*5.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel); + + impulse = 0.25 * repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3); // original 2.0 / 0.25 + VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); + VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); + VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); + } + */ + result = 1; } @@ -1023,7 +1043,10 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) bvh_traverse((ModifierData *)clmd, (ModifierData *)collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0); } else + { + if(G.rt > 0) printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } // process all collisions (calculate impulses, TODO: also repulses if distance too short) -- cgit v1.2.3 From 6169b29b3a53eca3e342aeee9d33809e61f026c3 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 28 Feb 2008 23:12:50 +0000 Subject: Cloth: Bugfix for wrong calculated bending springs, Bugfix for selfcollisions (faster + bugfix for explode), Changed: Collision response also put vertices back to surface now --- source/blender/blenkernel/intern/collision.c | 34 +++++++++++----------------- 1 file changed, 13 insertions(+), 21 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index de13d952f8e..32c5c3b16d6 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -520,7 +520,7 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa // Apply velocity stopping impulse // I_c = m * v_N / 2.0 // no 2.0 * magrelVel normally, but looks nicer DG - impulse = 2.0 * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + impulse = magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); cloth1->verts[collpair->ap1].impulse_count++; @@ -531,21 +531,23 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); cloth1->verts[collpair->ap3].impulse_count++; - /* - // doesn't perform nice, dunno why DG // Apply repulse impulse if distance too short // I_r = -min(dt*kd, m(0,1d/dt - v_n)) - d = clmd->coll_parms->epsilon - collpair->distance; + d = clmd->coll_parms->epsilon*8.0/9.0 - collpair->distance; if((magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame) && (d > ALMOST_ZERO)) { - repulse = MIN2(d*5.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel); + repulse = MIN2(d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel); - impulse = 0.25 * repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3); // original 2.0 / 0.25 - VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); - VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); - VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); + // stay on the safe side and clamp repulse + if(impulse > ALMOST_ZERO) + repulse = MIN2(repulse, 5.0*impulse); + repulse = MAX2(impulse, repulse); + + impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3); // original 2.0 / 0.25 + VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse); + VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse); + VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse); } - */ result = 1; } @@ -971,16 +973,6 @@ void cloth_collision_self_static(ModifierData *md1, ModifierData *md2, Collision } -#if 0 -/* aye this belongs to arith.c */ -static void Vec3PlusStVec(float *v, float s, float *v1) -{ - v[0] += s*v1[0]; - v[1] += s*v1[1]; - v[2] += s*v1[2]; -} -#endif - // cloth - object collisions int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { @@ -1149,7 +1141,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) if ((ABS(temp[0]) > mindistance) || (ABS(temp[1]) > mindistance) || (ABS(temp[2]) > mindistance)) continue; - // check for adjacent points + // check for adjacent points (i must be smaller j) if(BLI_edgehash_haskey (cloth->edgehash, i, j )) { continue; -- cgit v1.2.3 From 156d24646242a442cda1f53a1df8d4b9d4eea966 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 3 Mar 2008 19:02:01 +0000 Subject: Cloth bugfix for linked deflector groups (reported by alchibal on #blendercoders incl. source) - please verify --- source/blender/blenkernel/intern/collision.c | 319 +++++++++------------------ 1 file changed, 102 insertions(+), 217 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 32c5c3b16d6..65583a6c9c4 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -36,6 +36,7 @@ #include "MEM_guardedalloc.h" /* types */ #include "DNA_curve_types.h" +#include "DNA_group_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_cloth_types.h" @@ -957,20 +958,85 @@ void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clm cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); } -void cloth_collision_self_static(ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2) +void cloth_free_collision_list(ClothModifierData *clmd) { -/* - ClothModifierData *clmd = (ClothModifierData *)md1; - CollisionModifierData *collmd = (CollisionModifierData *)md2; - CollPair *collpair = NULL; - Cloth *cloth1=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL; - double distance = 0; - float epsilon = clmd->coll_parms->epsilon; - unsigned int i = 0; -*/ + // free collision list + if(clmd->coll_parms->collision_list) + { + LinkNode *search = clmd->coll_parms->collision_list; + while(search) + { + CollPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(clmd->coll_parms->collision_list,NULL); + + clmd->coll_parms->collision_list = NULL; + } +} + +int cloth_bvh_objcollisions_do(ClothModifierData * clmd, CollisionModifierData *collmd, float step, float dt) +{ + Cloth *cloth = clmd->clothObject; + BVH *cloth_bvh=(BVH *) cloth->tree; + long i=0, j = 0, numfaces = 0, numverts = 0; + ClothVertex *verts = NULL; + int ret = 0; + unsigned int result = 0; + float tnull[3] = {0,0,0}; + + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + + verts = cloth->verts; + + if (collmd->tree) + { + BVH *coll_bvh = collmd->tree; + + collision_move_object(collmd, step + dt, step); + + bvh_traverse((ModifierData *)clmd, (ModifierData *)collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0); + } + else + { + if(G.rt > 0) + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 5; j++) // 5 is just a value that ensures convergence + { + result = 0; + + if (collmd->tree) + result += cloth_collision_response_static(clmd, collmd); + + // apply impulses in parallel + if(result) + 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; + + ret++; + } + } + + if(!result) + break; + } + + cloth_free_collision_list(clmd); + return ret; } // cloth - object collisions @@ -982,9 +1048,8 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) Object *coll_ob=NULL; BVH *cloth_bvh=NULL; long 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; + unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; - float tnull[3] = {0,0,0}; int ret = 0; ClothModifierData *tclmd; int collisions = 0, count = 0; @@ -1010,7 +1075,6 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) do { result = 0; - ic = 0; clmd->coll_parms->collision_list = NULL; // check all collision objects @@ -1020,67 +1084,36 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) collmd = (CollisionModifierData *) modifiers_findByType (coll_ob, eModifierType_Collision); if (!collmd) - continue; - - tclmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - if(tclmd == clmd) - continue; - - if (collmd->tree) - { - BVH *coll_bvh = collmd->tree; - - collision_move_object(collmd, step + dt, step); - - bvh_traverse((ModifierData *)clmd, (ModifierData *)collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0); - } - else - { - if(G.rt > 0) - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } - - - // process all collisions (calculate impulses, TODO: also repulses if distance too short) - result = 1; - for(j = 0; j < 5; j++) // 5 is just a value that ensures convergence { - result = 0; - - if (collmd->tree) - result += cloth_collision_response_static(clmd, collmd); - - // apply impulses in parallel - ic=0; - for(i = 0; i < numverts; i++) + if(coll_ob->dup_group) { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if(verts[i].impulse_count) + GroupObject *go; + Group *group = coll_ob->dup_group; + + for(go= group->gobject.first; go; go= go->next) { - 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++; + coll_ob = go->ob; + + collmd = (CollisionModifierData *) modifiers_findByType (coll_ob, eModifierType_Collision); + + if (!collmd) + continue; + + tclmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if(tclmd == clmd) + continue; + + ret += cloth_bvh_objcollisions_do(clmd, collmd, step, dt); } } } - - // free collision list - if(clmd->coll_parms->collision_list) + else { - LinkNode *search = clmd->coll_parms->collision_list; - while(search) - { - CollPair *coll_pair = search->link; - - MEM_freeN(coll_pair); - search = search->next; - } - BLI_linklist_free(clmd->coll_parms->collision_list,NULL); - - clmd->coll_parms->collision_list = NULL; + tclmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if(tclmd == clmd) + continue; + + ret += cloth_bvh_objcollisions_do(clmd, collmd, step, dt); } } rounds++; @@ -1203,153 +1236,5 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) } while(result && (clmd->coll_parms->loop_count>rounds)); - //////////////////////////////////////////////////////////// - // moving collisions - // - // response code is just missing itm - //////////////////////////////////////////////////////////// - - /* - // update cloth bvh - 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) - { - - 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_from_cloth(coll_clmd, 1); // 0 means STATIC, 1 means MOVING -} -} - - - do - { - result = 0; - ic = 0; - clmd->coll_parms->collision_list = NULL; - - // 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(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving, 0); -} - else - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); -} -} - - // 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 - 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) - result += cloth_collision_response_moving_tris(clmd, coll_clmd); - else - printf ("cloth_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_from_cloth(clmd, 1); // 0 means STATIC, 1 means MOVING - - - // free collision list - if(clmd->coll_parms->collision_list) - { - LinkNode *search = clmd->coll_parms->collision_list; - while(search) - { - CollPair *coll_pair = search->link; - - MEM_freeN(coll_pair); - search = search->next; -} - BLI_linklist_free(clmd->coll_parms->collision_list,NULL); - - clmd->coll_parms->collision_list = NULL; -} - - // 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); } -- cgit v1.2.3 From 3ebcb390906a2d0e4685d3fbf374c7a5eb740874 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 6 Mar 2008 01:21:40 +0000 Subject: Cloth bugfix for jumpy cloth (users were complaining), so the mass can be changed on GUI now (reference: in old blendfiles, mass=1.0 was used) --- source/blender/blenkernel/intern/collision.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 65583a6c9c4..f9391a0adb8 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -399,7 +399,7 @@ int cloth_get_collision_time(float a[3], float b[3], float c[3], float d[3], flo } // w3 is not perfect -void cloth_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) +void collision_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) { double tempV1[3], tempV2[3], tempV4[3]; double a,b,c,d,e,f; @@ -434,7 +434,7 @@ void cloth_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[ w3[0] = 1.0f - w1[0] - w2[0]; } -DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3) +DO_INLINE void collision_interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3) { to[0] = to[1] = to[2] = 0; VECADDMUL(to, v1, w1); @@ -461,23 +461,23 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa collpair = search->link; // compute barycentric coordinates for both collision points - cloth_compute_barycentric(collpair->pa, + collision_compute_barycentric(collpair->pa, cloth1->verts[collpair->ap1].txold, cloth1->verts[collpair->ap2].txold, cloth1->verts[collpair->ap3].txold, &w1, &w2, &w3); // was: txold - cloth_compute_barycentric(collpair->pb, + collision_compute_barycentric(collpair->pb, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, &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); + collision_interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3); - interpolateOnTriangle(v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3); + collision_interpolateOnTriangle(v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3); VECSUB(relativeVelocity, v2, v1); -- cgit v1.2.3 From df27557b81d8463c4274d11f4131be619da255f1 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 13 Mar 2008 22:45:36 +0000 Subject: Cloth header cleanup, bugfix (again) in wind calculation, bugfix for not working fields mindist GUI option --- source/blender/blenkernel/intern/collision.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index f9391a0adb8..a1c49ac4655 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -30,32 +30,17 @@ * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ -#include -#include -#include #include "MEM_guardedalloc.h" -/* types */ -#include "DNA_curve_types.h" + +#include "BKE_cloth.h" + #include "DNA_group_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" -#include "DNA_lattice_types.h" #include "DNA_scene_types.h" -#include "DNA_modifier_types.h" -#include "BLI_blenlib.h" -#include "BLI_arithb.h" -#include "BLI_edgehash.h" -#include "BLI_linklist.h" -#include "BKE_curve.h" -#include "BKE_deform.h" + #include "BKE_DerivedMesh.h" -#include "BKE_cdderivedmesh.h" -#include "BKE_displist.h" -#include "BKE_effect.h" #include "BKE_global.h" #include "BKE_mesh.h" #include "BKE_object.h" @@ -63,10 +48,6 @@ #include "BKE_modifier.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" -#include "DNA_screen_types.h" -#include "BSE_headerbuttons.h" -#include "BIF_screen.h" -#include "BIF_space.h" #include "mydevice.h" #include "Bullet-C-Api.h" -- cgit v1.2.3 From 7c1a21c385ac8450e295f73a71f104ab17a076c5 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 17 Mar 2008 21:45:40 +0000 Subject: Collision Modifier/KDOP: Rearrange things to be more generic. Also fix possible crash if not enough memory there. --- source/blender/blenkernel/intern/collision.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index a1c49ac4655..f2200a24ea2 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -86,11 +86,6 @@ BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsig // in the moment, return zero if no faces there if(!numfaces) return NULL; - - bvh->flags = 0; - bvh->leaf_tree = NULL; - bvh->leaf_root = NULL; - bvh->tree = NULL; bvh->epsilon = epsilon; bvh->numfaces = numfaces; @@ -103,8 +98,7 @@ BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsig } bvh->numverts = numverts; - bvh->current_x = MEM_dupallocN(x); - bvh->current_xold = MEM_dupallocN(x); + bvh->current_x = MEM_dupallocN(x); bvh_build(bvh); @@ -975,10 +969,13 @@ int cloth_bvh_objcollisions_do(ClothModifierData * clmd, CollisionModifierData * if (collmd->tree) { + /* get pointer to bounding volume hierarchy */ BVH *coll_bvh = collmd->tree; - + + /* move object to position (step) in time */ collision_move_object(collmd, step + dt, step); - + + /* search for overlapping collision pairs */ bvh_traverse((ModifierData *)clmd, (ModifierData *)collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0); } else -- cgit v1.2.3 From 9362772ffda053186780e5f976d43a99f7cfd699 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 20 Mar 2008 18:16:11 +0000 Subject: Collision modifier: Update from mvert was using only static update, now uses dynamic update and catches therefore also faster movements - reported by nudelZ (#blendercoders) --- source/blender/blenkernel/intern/collision.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index f2200a24ea2..ef69da0ed86 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -69,6 +69,7 @@ void collision_move_object(CollisionModifierData *collmd, float step, float prev 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_update_from_mvert(collmd->tree, collmd->current_x, collmd->numverts, collmd->current_xnew, 1); } /* build bounding volume hierarchy from mverts (see kdop.c for whole BVH code) */ -- cgit v1.2.3 From af8c68ddc4a67b9c329d15b540a1bc0f07d98838 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 20 Mar 2008 18:28:40 +0000 Subject: Cloth structure names update: Sorry about this commit, it will kill all your cloth settings in old files but I had to do it before release because naming convention was really bad in cloth (e.g. using SimulationSettings instead of ClothSimSettings in DNA). Same for some structure in CollisionModifier but with no sideeffects. --- source/blender/blenkernel/intern/collision.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index ef69da0ed86..403762e36bf 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -427,6 +427,7 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa float w1, w2, w3, u1, u2, u3; float v1[3], v2[3], relativeVelocity[3]; float magrelVel; + float epsilon2 = collmd->bvh->epsilon; cloth1 = clmd->clothObject; @@ -510,7 +511,7 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa // Apply repulse impulse if distance too short // I_r = -min(dt*kd, m(0,1d/dt - v_n)) - d = clmd->coll_parms->epsilon*8.0/9.0 - collpair->distance; + d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance; if((magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame) && (d > ALMOST_ZERO)) { repulse = MIN2(d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel); @@ -557,6 +558,7 @@ void cloth_collision_static(ModifierData *md1, ModifierData *md2, CollisionTree ClothVertex *verts1=NULL; double distance = 0; float epsilon = clmd->coll_parms->epsilon; + float epsilon2 = ((CollisionModifierData *)md2)->bvh->epsilon; unsigned int i = 0; for(i = 0; i < 4; i++) @@ -641,9 +643,9 @@ void cloth_collision_static(ModifierData *md1, ModifierData *md2, CollisionTree verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector); #else // just be sure that we don't add anything - distance = 2.0 * (epsilon + ALMOST_ZERO); + distance = 2.0 * (epsilon + epsilon2 + ALMOST_ZERO); #endif - if (distance <= (epsilon + ALMOST_ZERO)) + if (distance <= (epsilon + epsilon2 + ALMOST_ZERO)) { // printf("dist: %f\n", (float)distance); @@ -968,10 +970,10 @@ int cloth_bvh_objcollisions_do(ClothModifierData * clmd, CollisionModifierData * verts = cloth->verts; - if (collmd->tree) + if (collmd->bvh) { /* get pointer to bounding volume hierarchy */ - BVH *coll_bvh = collmd->tree; + BVH *coll_bvh = collmd->bvh; /* move object to position (step) in time */ collision_move_object(collmd, step + dt, step); @@ -991,7 +993,7 @@ int cloth_bvh_objcollisions_do(ClothModifierData * clmd, CollisionModifierData * { result = 0; - if (collmd->tree) + if (collmd->bvh) result += cloth_collision_response_static(clmd, collmd); // apply impulses in parallel -- cgit v1.2.3 From 6111ad655126c54cff652bbc371538f8e46ba59d Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 20 Mar 2008 20:28:51 +0000 Subject: Collision commit was messed up - reported by Mr. Barton :) --- source/blender/blenkernel/intern/collision.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 403762e36bf..61f2288f8e8 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -69,7 +69,7 @@ void collision_move_object(CollisionModifierData *collmd, float step, float prev 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_update_from_mvert(collmd->tree, collmd->current_x, collmd->numverts, collmd->current_xnew, 1); + bvh_update_from_mvert(collmd->bvh, collmd->current_x, collmd->numverts, collmd->current_xnew, 1); } /* build bounding volume hierarchy from mverts (see kdop.c for whole BVH code) */ -- cgit v1.2.3 From fef157ac075f84bdd7bfc39a1234aa6b31024bdf Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 8 Apr 2008 12:55:35 +0000 Subject: Cloth bugfix: used old dm instead of new created result derivedmesh; Code cleanup + deactivation of unsued selfcollision code in kdop.c + little speedup there --- source/blender/blenkernel/intern/collision.c | 988 ++++++++++++++------------- 1 file changed, 496 insertions(+), 492 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 61f2288f8e8..bb0622a61cb 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1,5 +1,5 @@ -/* collision.c -* +/* collision.c +* * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * @@ -36,7 +36,7 @@ #include "DNA_group_types.h" #include "DNA_object_types.h" -#include "DNA_cloth_types.h" +#include "DNA_cloth_types.h" #include "DNA_mesh_types.h" #include "DNA_scene_types.h" @@ -57,70 +57,70 @@ Collision modifier code start ***********************************/ /* step is limited from 0 (frame start position) to 1 (frame end position) */ -void collision_move_object(CollisionModifierData *collmd, float step, float prevstep) +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); + 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_update_from_mvert(collmd->bvh, collmd->current_x, collmd->numverts, collmd->current_xnew, 1); + bvh_update_from_mvert ( collmd->bvh, collmd->current_x, collmd->numverts, collmd->current_xnew, 1 ); } /* build bounding volume hierarchy from mverts (see kdop.c for whole BVH code) */ -BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon) +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) + + bvh = MEM_callocN ( sizeof ( BVH ), "BVH" ); + if ( bvh == NULL ) { - printf("bvh: Out of memory.\n"); + printf ( "bvh: Out of memory.\n" ); return NULL; } - + // in the moment, return zero if no faces there - if(!numfaces) + if ( !numfaces ) return NULL; bvh->epsilon = epsilon; bvh->numfaces = numfaces; bvh->mfaces = mfaces; - + // we have no faces, we save seperate points - if(!mfaces) + if ( !mfaces ) { bvh->numfaces = numverts; } bvh->numverts = numverts; - bvh->current_x = MEM_dupallocN(x); - - bvh_build(bvh); - + bvh->current_x = MEM_dupallocN ( x ); + + bvh_build ( bvh ); + return bvh; } -void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving) +void bvh_update_from_mvert ( BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving ) { - if(!bvh) + if ( !bvh ) return; - - if(numverts!=bvh->numverts) + + 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); + + if ( x ) + memcpy ( bvh->current_xold, x, sizeof ( MVert ) * numverts ); + + if ( xnew ) + memcpy ( bvh->current_x, xnew, sizeof ( MVert ) * numverts ); + + bvh_update ( bvh, moving ); } /*********************************** @@ -136,10 +136,10 @@ Collision modifier code end /* DG: debug hint! don't forget that all functions were "fabs", "sinf", etc before */ #define mySWAP(a,b) { float tmp = b ; b = a ; a = tmp ; } -int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float *x2) +int gsl_poly_solve_cubic ( float a, float b, float c, float *x0, float *x1, float *x2 ) { - float q = (a * a - 3 * b); - float r = (2 * a * a * a - 9 * a * b + 27 * c); + float q = ( a * a - 3 * b ); + float r = ( 2 * a * a * a - 9 * a * b + 27 * c ); float Q = q / 9; float R = r / 54; @@ -150,25 +150,25 @@ int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float float CR2 = 729 * r * r; float CQ3 = 2916 * q * q * q; - if (R == 0 && Q == 0) + if ( R == 0 && Q == 0 ) { *x0 = - a / 3 ; *x1 = - a / 3 ; *x2 = - a / 3 ; return 3 ; } - else if (CR2 == CQ3) + else if ( CR2 == CQ3 ) { - /* this test is actually R2 == Q3, written in a form suitable - for exact computation with integers */ + /* this test is actually R2 == Q3, written in a form suitable + for exact computation with integers */ - /* Due to finite precision some float roots may be missed, and - considered to be a pair of complex roots z = x +/- epsilon i - close to the real axis. */ + /* Due to finite precision some float roots may be missed, and + considered to be a pair of complex roots z = x +/- epsilon i + close to the real axis. */ - float sqrtQ = sqrt (Q); + float sqrtQ = sqrt ( Q ); - if (R > 0) + if ( R > 0 ) { *x0 = -2 * sqrtQ - a / 3; *x1 = sqrtQ - a / 3; @@ -182,35 +182,35 @@ int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float } return 3 ; } - else if (CR2 < CQ3) /* equivalent to R2 < Q3 */ + else if ( CR2 < CQ3 ) /* equivalent to R2 < Q3 */ { - float sqrtQ = sqrt (Q); + float sqrtQ = sqrt ( Q ); float sqrtQ3 = sqrtQ * sqrtQ * sqrtQ; - float theta = acos (R / sqrtQ3); + float theta = acos ( R / sqrtQ3 ); float norm = -2 * sqrtQ; - *x0 = norm * cos (theta / 3) - a / 3; - *x1 = norm * cos ((theta + 2.0 * M_PI) / 3) - a / 3; - *x2 = norm * cos ((theta - 2.0 * M_PI) / 3) - a / 3; - + *x0 = norm * cos ( theta / 3 ) - a / 3; + *x1 = norm * cos ( ( theta + 2.0 * M_PI ) / 3 ) - a / 3; + *x2 = norm * cos ( ( theta - 2.0 * M_PI ) / 3 ) - a / 3; + /* Sort *x0, *x1, *x2 into increasing order */ - if (*x0 > *x1) - mySWAP(*x0, *x1) ; - - if (*x1 > *x2) + if ( *x0 > *x1 ) + mySWAP ( *x0, *x1 ) ; + + if ( *x1 > *x2 ) { - mySWAP(*x1, *x2) ; - - if (*x0 > *x1) - mySWAP(*x0, *x1) ; + mySWAP ( *x1, *x2 ) ; + + if ( *x0 > *x1 ) + mySWAP ( *x0, *x1 ) ; } - + return 3; } else { - float sgnR = (R >= 0 ? 1 : -1); - float A = -sgnR * pow (ABS (R) + sqrt (R2 - Q3), 1.0/3.0); + float sgnR = ( R >= 0 ? 1 : -1 ); + float A = -sgnR * pow ( ABS ( R ) + sqrt ( R2 - Q3 ), 1.0/3.0 ); float B = Q / A ; *x0 = A + B - a / 3; return 1; @@ -223,31 +223,31 @@ int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float * * copied from GSL */ -int gsl_poly_solve_quadratic (float a, float b, float c, float *x0, float *x1) +int gsl_poly_solve_quadratic ( float a, float b, float c, float *x0, float *x1 ) { float disc = b * b - 4 * a * c; - if (disc > 0) + if ( disc > 0 ) { - if (b == 0) + if ( b == 0 ) { - float r = ABS (0.5 * sqrt (disc) / a); + float r = ABS ( 0.5 * sqrt ( disc ) / a ); *x0 = -r; *x1 = r; } else { - float sgnb = (b > 0 ? 1 : -1); - float temp = -0.5 * (b + sgnb * sqrt (disc)); + float sgnb = ( b > 0 ? 1 : -1 ); + float temp = -0.5 * ( b + sgnb * sqrt ( disc ) ); float r1 = temp / a ; float r2 = c / temp ; - if (r1 < r2) + if ( r1 < r2 ) { *x0 = r1 ; *x1 = r2 ; - } - else + } + else { *x0 = r2 ; *x1 = r1 ; @@ -255,7 +255,7 @@ int gsl_poly_solve_quadratic (float a, float b, float c, float *x0, float *x1) } return 2; } - else if (disc == 0) + else if ( disc == 0 ) { *x0 = -0.5 * b / a ; *x1 = -0.5 * b / a ; @@ -274,56 +274,56 @@ int gsl_poly_solve_quadratic (float a, float b, float c, float *x0, float *x1) * page 4, left column */ -int cloth_get_collision_time(float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3]) +int cloth_get_collision_time ( float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3] ) { int num_sols = 0; - + float g = -a[2] * c[1] * e[0] + a[1] * c[2] * e[0] + - a[2] * c[0] * e[1] - a[0] * c[2] * e[1] - - a[1] * c[0] * e[2] + a[0] * c[1] * e[2]; + a[2] * c[0] * e[1] - a[0] * c[2] * e[1] - + a[1] * c[0] * e[2] + a[0] * c[1] * e[2]; float h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] + - a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] + - a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] + - b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] - - a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] - - a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2]; + a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] + + a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] + + b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] - + a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] - + a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2]; float i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] + - b[2] * d[0] * e[1] - b[0] * d[2] * e[1] - - b[1] * d[0] * e[2] + b[0] * d[1] * e[2] - - b[2] * c[1] * f[0] + b[1] * c[2] * f[0] - - a[2] * d[1] * f[0] + a[1] * d[2] * f[0] + - b[2] * c[0] * f[1] - b[0] * c[2] * f[1] + - a[2] * d[0] * f[1] - a[0] * d[2] * f[1] - - b[1] * c[0] * f[2] + b[0] * c[1] * f[2] - - a[1] * d[0] * f[2] + a[0] * d[1] * f[2]; + b[2] * d[0] * e[1] - b[0] * d[2] * e[1] - + b[1] * d[0] * e[2] + b[0] * d[1] * e[2] - + b[2] * c[1] * f[0] + b[1] * c[2] * f[0] - + a[2] * d[1] * f[0] + a[1] * d[2] * f[0] + + b[2] * c[0] * f[1] - b[0] * c[2] * f[1] + + a[2] * d[0] * f[1] - a[0] * d[2] * f[1] - + b[1] * c[0] * f[2] + b[0] * c[1] * f[2] - + a[1] * d[0] * f[2] + a[0] * d[1] * f[2]; float j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] + - b[2] * d[0] * f[1] - b[0] * d[2] * f[1] - - b[1] * d[0] * f[2] + b[0] * d[1] * f[2]; + b[2] * d[0] * f[1] - b[0] * d[2] * f[1] - + b[1] * d[0] * f[2] + b[0] * d[1] * f[2]; // Solve cubic equation to determine times t1, t2, t3, when the collision will occur. - if(ABS(j) > ALMOST_ZERO) + if ( ABS ( j ) > ALMOST_ZERO ) { i /= j; h /= j; g /= j; - - num_sols = gsl_poly_solve_cubic(i, h, g, &solution[0], &solution[1], &solution[2]); + + num_sols = gsl_poly_solve_cubic ( i, h, g, &solution[0], &solution[1], &solution[2] ); } - else if(ABS(i) > ALMOST_ZERO) - { - num_sols = gsl_poly_solve_quadratic(i, h, g, &solution[0], &solution[1]); + else if ( ABS ( i ) > ALMOST_ZERO ) + { + num_sols = gsl_poly_solve_quadratic ( i, h, g, &solution[0], &solution[1] ); solution[2] = -1.0; } - else if(ABS(h) > ALMOST_ZERO) + else if ( ABS ( h ) > ALMOST_ZERO ) { solution[0] = -g / h; solution[1] = solution[2] = -1.0; num_sols = 1; } - else if(ABS(g) > ALMOST_ZERO) + else if ( ABS ( g ) > ALMOST_ZERO ) { solution[0] = 0; solution[1] = solution[2] = -1.0; @@ -331,42 +331,45 @@ int cloth_get_collision_time(float a[3], float b[3], float c[3], float d[3], flo } // Discard negative solutions - if ((num_sols >= 1) && (solution[0] < 0)) + if ( ( num_sols >= 1 ) && ( solution[0] < 0 ) ) { --num_sols; solution[0] = solution[num_sols]; } - if ((num_sols >= 2) && (solution[1] < 0)) + if ( ( num_sols >= 2 ) && ( solution[1] < 0 ) ) { --num_sols; solution[1] = solution[num_sols]; } - if ((num_sols == 3) && (solution[2] < 0)) + if ( ( num_sols == 3 ) && ( solution[2] < 0 ) ) { --num_sols; } // Sort - if (num_sols == 2) + if ( num_sols == 2 ) { - if (solution[0] > solution[1]) + if ( solution[0] > solution[1] ) { double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp; } } - else if (num_sols == 3) + else if ( num_sols == 3 ) { // Bubblesort - if (solution[0] > solution[1]) { + if ( solution[0] > solution[1] ) + { double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp; } - if (solution[1] > solution[2]) { + if ( solution[1] > solution[2] ) + { double tmp = solution[1]; solution[1] = solution[2]; solution[2] = tmp; } - if (solution[0] > solution[1]) { + if ( solution[0] > solution[1] ) + { double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp; } } @@ -375,50 +378,51 @@ int cloth_get_collision_time(float a[3], float b[3], float c[3], float d[3], flo } // w3 is not perfect -void collision_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) +void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 ) { double tempV1[3], tempV2[3], tempV4[3]; double a,b,c,d,e,f; - VECSUB (tempV1, p1, p3); - VECSUB (tempV2, p2, p3); - VECSUB (tempV4, pv, p3); - - a = INPR (tempV1, tempV1); - b = INPR (tempV1, tempV2); - c = INPR (tempV2, tempV2); - e = INPR (tempV1, tempV4); - f = INPR (tempV2, tempV4); - - d = (a * c - b * b); - - if (ABS(d) < ALMOST_ZERO) { + VECSUB ( tempV1, p1, p3 ); + VECSUB ( tempV2, p2, p3 ); + VECSUB ( tempV4, pv, p3 ); + + a = INPR ( tempV1, tempV1 ); + b = INPR ( tempV1, tempV2 ); + c = INPR ( tempV2, tempV2 ); + e = INPR ( tempV1, tempV4 ); + f = INPR ( tempV2, tempV4 ); + + d = ( a * c - b * b ); + + if ( ABS ( d ) < ALMOST_ZERO ) + { *w1 = *w2 = *w3 = 1.0 / 3.0; return; } - - w1[0] = (float)((e * c - b * f) / d); - - if(w1[0] < 0) + + w1[0] = ( float ) ( ( e * c - b * f ) / d ); + + if ( w1[0] < 0 ) w1[0] = 0; - - w2[0] = (float)((f - b * (double)w1[0]) / c); - - if(w2[0] < 0) + + w2[0] = ( float ) ( ( f - b * ( double ) w1[0] ) / c ); + + if ( w2[0] < 0 ) w2[0] = 0; - + w3[0] = 1.0f - w1[0] - w2[0]; } -DO_INLINE void collision_interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3) +DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3 ) { to[0] = to[1] = to[2] = 0; - VECADDMUL(to, v1, w1); - VECADDMUL(to, v2, w2); - VECADDMUL(to, v3, w3); + VECADDMUL ( to, v1, w1 ); + VECADDMUL ( to, v2, w2 ); + VECADDMUL ( to, v3, w3 ); } -int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierData *collmd) +int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd ) { int result = 0; LinkNode *search = NULL; @@ -428,171 +432,171 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa float v1[3], v2[3], relativeVelocity[3]; float magrelVel; float epsilon2 = collmd->bvh->epsilon; - + cloth1 = clmd->clothObject; search = clmd->coll_parms->collision_list; - - while(search) + + while ( search ) { collpair = search->link; - + // compute barycentric coordinates for both collision points - collision_compute_barycentric(collpair->pa, - cloth1->verts[collpair->ap1].txold, - cloth1->verts[collpair->ap2].txold, - cloth1->verts[collpair->ap3].txold, - &w1, &w2, &w3); - + collision_compute_barycentric ( collpair->pa, + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3 ); + // was: txold - collision_compute_barycentric(collpair->pb, - collmd->current_x[collpair->bp1].co, - collmd->current_x[collpair->bp2].co, - collmd->current_x[collpair->bp3].co, - &u1, &u2, &u3); - + collision_compute_barycentric ( collpair->pb, + collmd->current_x[collpair->bp1].co, + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, + &u1, &u2, &u3 ); + // Calculate relative "velocity". - collision_interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3); - - collision_interpolateOnTriangle(v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3); - - VECSUB(relativeVelocity, v2, v1); - + collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 ); + + collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 ); + + VECSUB ( relativeVelocity, v2, v1 ); + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). - magrelVel = INPR(relativeVelocity, collpair->normal); - + magrelVel = INPR ( relativeVelocity, collpair->normal ); + // printf("magrelVel: %f\n", magrelVel); - + // Calculate masses of points. // TODO - + // If v_n_mag < 0 the edges are approaching each other. - if(magrelVel > ALMOST_ZERO) + if ( magrelVel > ALMOST_ZERO ) { // Calculate Impulse magnitude to stop all motion in normal direction. float magtangent = 0, repulse = 0, d = 0; double impulse = 0.0; float vrel_t_pre[3]; float temp[3]; - + // calculate tangential velocity - VECCOPY(temp, collpair->normal); - VecMulf(temp, magrelVel); - VECSUB(vrel_t_pre, relativeVelocity, temp); - + VECCOPY ( temp, collpair->normal ); + VecMulf ( temp, magrelVel ); + VECSUB ( vrel_t_pre, relativeVelocity, temp ); + // Decrease in magnitude of relative tangential velocity due to coulomb friction - // in original formula "magrelVel" should be the "change of relative velocity in normal direction" - magtangent = MIN2(clmd->coll_parms->friction * 0.01 * magrelVel,sqrt(INPR(vrel_t_pre,vrel_t_pre))); - + // in original formula "magrelVel" should be the "change of relative velocity in normal direction" + magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel,sqrt ( INPR ( vrel_t_pre,vrel_t_pre ) ) ); + // Apply friction impulse. - if (magtangent > ALMOST_ZERO) - { - Normalize(vrel_t_pre); - - impulse = 2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - VECADDMUL(cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse); - VECADDMUL(cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse); - VECADDMUL(cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse); + if ( magtangent > ALMOST_ZERO ) + { + Normalize ( vrel_t_pre ); + + impulse = 2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); + VECADDMUL ( cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse ); + VECADDMUL ( cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse ); + VECADDMUL ( cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse ); } - + // Apply velocity stopping impulse // I_c = m * v_N / 2.0 // no 2.0 * magrelVel normally, but looks nicer DG - impulse = magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - - VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); + impulse = magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); + + 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); + + 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); + + VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse ); cloth1->verts[collpair->ap3].impulse_count++; - + // Apply repulse impulse if distance too short // I_r = -min(dt*kd, m(0,1d/dt - v_n)) d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance; - if((magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame) && (d > ALMOST_ZERO)) + if ( ( magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame ) && ( d > ALMOST_ZERO ) ) { - repulse = MIN2(d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel); - + repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel ); + // stay on the safe side and clamp repulse - if(impulse > ALMOST_ZERO) - repulse = MIN2(repulse, 5.0*impulse); - repulse = MAX2(impulse, repulse); - - impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3); // original 2.0 / 0.25 - VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse); - VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse); - VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse); + if ( impulse > ALMOST_ZERO ) + repulse = MIN2 ( repulse, 5.0*impulse ); + repulse = MAX2 ( impulse, repulse ); + + impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25 + VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse ); + VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse ); + VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse ); } - + result = 1; } - + search = search->next; } - - + + return result; } -int cloth_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) +int cloth_collision_response_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd ) { return 1; } -int cloth_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) +int cloth_collision_response_moving_edges ( ClothModifierData *clmd, ClothModifierData *coll_clmd ) { return 1; } -void cloth_collision_static(ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2) +void cloth_collision_static ( ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2 ) { - ClothModifierData *clmd = (ClothModifierData *)md1; - CollisionModifierData *collmd = (CollisionModifierData *)md2; + ClothModifierData *clmd = ( ClothModifierData * ) md1; + CollisionModifierData *collmd = ( CollisionModifierData * ) md2; CollPair *collpair = NULL; Cloth *cloth1=NULL; MFace *face1=NULL, *face2=NULL; ClothVertex *verts1=NULL; double distance = 0; float epsilon = clmd->coll_parms->epsilon; - float epsilon2 = ((CollisionModifierData *)md2)->bvh->epsilon; + float epsilon2 = ( ( CollisionModifierData * ) md2 )->bvh->epsilon; unsigned int i = 0; - for(i = 0; i < 4; i++) + for ( i = 0; i < 4; i++ ) { - collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); - + collpair = ( CollPair * ) MEM_callocN ( sizeof ( CollPair ), "cloth coll pair" ); + cloth1 = clmd->clothObject; - + verts1 = cloth1->verts; - - face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(collmd->mfaces[tree2->tri_index]); - + + face1 = & ( cloth1->mfaces[tree1->tri_index] ); + face2 = & ( collmd->mfaces[tree2->tri_index] ); + // check all possible pairs of triangles - if(i == 0) + 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 ( i == 1 ) { - if(face1->v4) + 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; @@ -600,15 +604,15 @@ void cloth_collision_static(ModifierData *md1, ModifierData *md2, CollisionTree else i++; } - - if(i == 2) + + if ( i == 2 ) { - if(face2->v4) + 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; @@ -616,15 +620,15 @@ void cloth_collision_static(ModifierData *md1, ModifierData *md2, CollisionTree else i+=2; } - - if(i == 3) + + if ( i == 3 ) { - if((face1->v4)&&(face2->v4)) + 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; @@ -632,77 +636,77 @@ void cloth_collision_static(ModifierData *md1, ModifierData *md2, CollisionTree else i++; } - + // calc SIPcode (?) - - if(i < 4) + + if ( i < 4 ) { - // calc distance + normal + // calc distance + normal #if WITH_BULLET == 1 - distance = plNearestPoints( - verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector); + distance = plNearestPoints ( + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector ); #else // just be sure that we don't add anything - distance = 2.0 * (epsilon + epsilon2 + ALMOST_ZERO); -#endif - if (distance <= (epsilon + epsilon2 + ALMOST_ZERO)) + distance = 2.0 * ( epsilon + epsilon2 + ALMOST_ZERO ); +#endif + if ( distance <= ( epsilon + epsilon2 + 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); - + + VECCOPY ( collpair->normal, collpair->vector ); + Normalize ( collpair->normal ); + collpair->distance = distance; - BLI_linklist_prepend(&clmd->coll_parms->collision_list, collpair); - + BLI_linklist_prepend ( &clmd->coll_parms->collision_list, collpair ); + } else { - MEM_freeN(collpair); + MEM_freeN ( collpair ); } } else { - MEM_freeN(collpair); + MEM_freeN ( collpair ); } } } -int cloth_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) +int cloth_are_edges_adjacent ( ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair ) { Cloth *cloth1 = NULL, *cloth2 = NULL; ClothVertex *verts1 = NULL, *verts2 = NULL; 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) + + 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) + + 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) + + 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) + + VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold ); + if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - + return 0; } -void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) +void cloth_collision_moving_edges ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 ) { EdgeCollPair edgecollpair; Cloth *cloth1=NULL, *cloth2=NULL; @@ -711,49 +715,49 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co 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++) + face1 = & ( cloth1->mfaces[tree1->tri_index] ); + face2 = & ( cloth2->mfaces[tree2->tri_index] ); + + for ( i = 0; i < 5; i++ ) { - if(i == 0) + if ( i == 0 ) { edgecollpair.p11 = face1->v1; edgecollpair.p12 = face1->v2; } - else if(i == 1) + else if ( i == 1 ) { edgecollpair.p11 = face1->v2; edgecollpair.p12 = face1->v3; } - else if(i == 2) + else if ( i == 2 ) { - if(face1->v4) + if ( face1->v4 ) { edgecollpair.p11 = face1->v3; edgecollpair.p12 = face1->v4; } - else + 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) + else if ( i == 3 ) { - if(face1->v4) + if ( face1->v4 ) { edgecollpair.p11 = face1->v4; edgecollpair.p12 = face1->v1; - } + } else continue; } @@ -763,35 +767,35 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co edgecollpair.p12 = face1->v1; } - - for( j = 0; j < 5; j++) + + for ( j = 0; j < 5; j++ ) { - if(j == 0) + if ( j == 0 ) { edgecollpair.p21 = face2->v1; edgecollpair.p22 = face2->v2; } - else if(j == 1) + else if ( j == 1 ) { edgecollpair.p21 = face2->v2; edgecollpair.p22 = face2->v3; } - else if(j == 2) + else if ( j == 2 ) { - if(face2->v4) + if ( face2->v4 ) { edgecollpair.p21 = face2->v3; edgecollpair.p22 = face2->v4; } - else + else { edgecollpair.p21 = face2->v3; edgecollpair.p22 = face2->v1; } } - else if(j == 3) + else if ( j == 3 ) { - if(face2->v4) + if ( face2->v4 ) { edgecollpair.p21 = face2->v4; edgecollpair.p22 = face2->v1; @@ -804,38 +808,38 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co edgecollpair.p21 = face2->v3; edgecollpair.p22 = face2->v1; } - - - if(!cloth_are_edges_adjacent(clmd, coll_clmd, &edgecollpair)) + + + if ( !cloth_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 = cloth_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)) + 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 = cloth_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: check for collisions + // TODO: put into (edge) collision list - + // printf("Moving edge found!\n"); } } } } - } + } } -void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) +void cloth_collision_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 ) { CollPair collpair; Cloth *cloth1=NULL, *cloth2=NULL; @@ -845,38 +849,38 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col int numsolutions = 0; float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; - for(i = 0; i < 2; i++) - { + 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]); - + + face1 = & ( cloth1->mfaces[tree1->tri_index] ); + face2 = & ( cloth2->mfaces[tree2->tri_index] ); + // check all possible pairs of triangles - if(i == 0) + 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 ( i == 1 ) { - if(face1->v4) + 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; @@ -885,143 +889,143 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col else i++; } - + // calc SIPcode (?) - - if(i < 2) + + 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)) + 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 = cloth_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)) + + VECSUB ( e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold ); + VECSUB ( f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v ); + + numsolutions = cloth_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: check for collisions + // TODO: put into (point-face) collision list - + // printf("Moving found!\n"); - + } } - + // TODO: check borders for collisions } - + } } } -void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *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); - - cloth_collision_moving_tris(clmd, coll_clmd, tree1, tree2); - cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); + cloth_collision_moving_edges ( clmd, coll_clmd, tree1, tree2 ); + + cloth_collision_moving_tris ( clmd, coll_clmd, tree1, tree2 ); + cloth_collision_moving_tris ( coll_clmd, clmd, tree2, tree1 ); } -void cloth_free_collision_list(ClothModifierData *clmd) +void cloth_free_collision_list ( ClothModifierData *clmd ) { // free collision list - if(clmd->coll_parms->collision_list) + if ( clmd->coll_parms->collision_list ) { LinkNode *search = clmd->coll_parms->collision_list; - while(search) + while ( search ) { CollPair *coll_pair = search->link; - - MEM_freeN(coll_pair); + + MEM_freeN ( coll_pair ); search = search->next; } - BLI_linklist_free(clmd->coll_parms->collision_list,NULL); - + BLI_linklist_free ( clmd->coll_parms->collision_list,NULL ); + clmd->coll_parms->collision_list = NULL; } } -int cloth_bvh_objcollisions_do(ClothModifierData * clmd, CollisionModifierData *collmd, float step, float dt) +int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData *collmd, float step, float dt ) { Cloth *cloth = clmd->clothObject; - BVH *cloth_bvh=(BVH *) cloth->tree; + BVH *cloth_bvh= ( BVH * ) cloth->tree; long i=0, j = 0, numfaces = 0, numverts = 0; ClothVertex *verts = NULL; int ret = 0; unsigned int result = 0; float tnull[3] = {0,0,0}; - + numfaces = clmd->clothObject->numfaces; numverts = clmd->clothObject->numverts; - + verts = cloth->verts; - - if (collmd->bvh) + + if ( collmd->bvh ) { /* get pointer to bounding volume hierarchy */ BVH *coll_bvh = collmd->bvh; - + /* move object to position (step) in time */ - collision_move_object(collmd, step + dt, step); - + collision_move_object ( collmd, step + dt, step ); + /* search for overlapping collision pairs */ - bvh_traverse((ModifierData *)clmd, (ModifierData *)collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0); + bvh_traverse ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0 ); } else { - if(G.rt > 0) - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + if ( G.rt > 0 ) + printf ( "cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n" ); } - + // process all collisions (calculate impulses, TODO: also repulses if distance too short) result = 1; - for(j = 0; j < 5; j++) // 5 is just a value that ensures convergence + for ( j = 0; j < 5; j++ ) // 5 is just a value that ensures convergence { result = 0; - - if (collmd->bvh) - result += cloth_collision_response_static(clmd, collmd); - - // apply impulses in parallel - if(result) - for(i = 0; i < numverts; i++) - { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if(verts[i].impulse_count) + + if ( collmd->bvh ) + result += cloth_collision_response_static ( clmd, collmd ); + + // apply impulses in parallel + if ( result ) + for ( i = 0; i < numverts; i++ ) { - VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); - VECCOPY(verts[i].impulse, tnull); - verts[i].impulse_count = 0; - - ret++; + // 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; + + ret++; + } } - } - - if(!result) + + if ( !result ) break; } - - cloth_free_collision_list(clmd); - + + cloth_free_collision_list ( clmd ); + return ret; } // cloth - object collisions -int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) +int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) { Base *base=NULL; CollisionModifierData *collmd=NULL; @@ -1029,170 +1033,170 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) Object *coll_ob=NULL; BVH *cloth_bvh=NULL; long i=0, j = 0, numfaces = 0, numverts = 0; - unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; + unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0; ClothModifierData *tclmd; int collisions = 0, count = 0; - if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) + if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->tree ) ) { return 0; } - + cloth = clmd->clothObject; verts = cloth->verts; - cloth_bvh = (BVH *) cloth->tree; + cloth_bvh = ( BVH * ) cloth->tree; numfaces = clmd->clothObject->numfaces; numverts = clmd->clothObject->numverts; - + //////////////////////////////////////////////////////////// // static collisions //////////////////////////////////////////////////////////// // update cloth bvh - bvh_update_from_cloth(clmd, 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) + do { result = 0; - clmd->coll_parms->collision_list = NULL; - + clmd->coll_parms->collision_list = NULL; + // check all collision objects - for (base = G.scene->base.first; base; base = base->next) + for ( base = G.scene->base.first; base; base = base->next ) { coll_ob = base->object; - collmd = (CollisionModifierData *) modifiers_findByType (coll_ob, eModifierType_Collision); - - if (!collmd) + collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); + + if ( !collmd ) { - if(coll_ob->dup_group) + if ( coll_ob->dup_group ) { GroupObject *go; Group *group = coll_ob->dup_group; - - for(go= group->gobject.first; go; go= go->next) + + for ( go= group->gobject.first; go; go= go->next ) { coll_ob = go->ob; - - collmd = (CollisionModifierData *) modifiers_findByType (coll_ob, eModifierType_Collision); - - if (!collmd) + + collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); + + if ( !collmd ) continue; - - tclmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - if(tclmd == clmd) + + tclmd = ( ClothModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Cloth ); + if ( tclmd == clmd ) continue; - - ret += cloth_bvh_objcollisions_do(clmd, collmd, step, dt); + + ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt ); } } } else { - tclmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - if(tclmd == clmd) + tclmd = ( ClothModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Cloth ); + if ( tclmd == clmd ) continue; - - ret += cloth_bvh_objcollisions_do(clmd, collmd, step, dt); + + ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt ); } } rounds++; - + //////////////////////////////////////////////////////////// // update positions // this is needed for bvh_calc_DOP_hull_moving() [kdop.c] //////////////////////////////////////////////////////////// - + // verts come from clmd - for(i = 0; i < numverts; i++) + for ( i = 0; i < numverts; i++ ) { - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - { - if(verts [i].flags & CLOTH_VERT_FLAG_PINNED) + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + { + if ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) { continue; } } - - VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + + VECADD ( verts[i].tx, verts[i].txold, verts[i].tv ); } //////////////////////////////////////////////////////////// - - + + //////////////////////////////////////////////////////////// // Test on *simple* selfcollisions //////////////////////////////////////////////////////////// - if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) + if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { collisions = 1; verts = cloth->verts; // needed for openMP - - for(count = 0; count < clmd->coll_parms->self_loop_count; count++) - { - if(collisions) + + for ( count = 0; count < clmd->coll_parms->self_loop_count; count++ ) + { + if ( collisions ) { collisions = 0; - #pragma omp parallel for private(i,j, collisions) shared(verts, ret) - for(i = 0; i < cloth->numverts; i++) +#pragma omp parallel for private(i,j, collisions) shared(verts, ret) + for ( i = 0; i < cloth->numverts; i++ ) { - for(j = i + 1; j < cloth->numverts; j++) + for ( j = i + 1; j < cloth->numverts; j++ ) { float temp[3]; float length = 0; - float mindistance = clmd->coll_parms->selfepsilon*(cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len); - - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - { - if((cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED) - && (cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED)) + float mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); + + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + { + if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) { continue; } } - - VECSUB(temp, verts[i].tx, verts[j].tx); - - if ((ABS(temp[0]) > mindistance) || (ABS(temp[1]) > mindistance) || (ABS(temp[2]) > mindistance)) continue; - + + VECSUB ( temp, verts[i].tx, verts[j].tx ); + + if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; + // check for adjacent points (i must be smaller j) - if(BLI_edgehash_haskey (cloth->edgehash, i, j )) + if ( BLI_edgehash_haskey ( cloth->edgehash, i, j ) ) { continue; } - - length = Normalize(temp); - - if(length < mindistance) + + length = Normalize ( temp ); + + if ( length < mindistance ) { float correction = mindistance - length; - - if(cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED) + + if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) { - VecMulf(temp, -correction); - VECADD(verts[j].tx, verts[j].tx, temp); + VecMulf ( temp, -correction ); + VECADD ( verts[j].tx, verts[j].tx, temp ); } - else if(cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED) + else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) { - VecMulf(temp, correction); - VECADD(verts[i].tx, verts[i].tx, temp); + VecMulf ( temp, correction ); + VECADD ( verts[i].tx, verts[i].tx, temp ); } else { - VecMulf(temp, -correction*0.5); - VECADD(verts[j].tx, verts[j].tx, temp); - - VECSUB(verts[i].tx, verts[i].tx, temp); + VecMulf ( temp, -correction*0.5 ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + + VECSUB ( verts[i].tx, verts[i].tx, temp ); } - + collisions = 1; - - if(!ret) - { - #pragma omp critical - { - ret = 1; - } + + if ( !ret ) + { +#pragma omp critical + { + ret = 1; + } } } } @@ -1200,22 +1204,22 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) } } //////////////////////////////////////////////////////////// - + //////////////////////////////////////////////////////////// // SELFCOLLISIONS: update velocities //////////////////////////////////////////////////////////// - if(ret) + if ( ret ) { - for(i = 0; i < cloth->numverts; i++) + for ( i = 0; i < cloth->numverts; i++ ) { - if(!(cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED)) - VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + if ( ! ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) + VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold ); } } //////////////////////////////////////////////////////////// } } - while(result && (clmd->coll_parms->loop_count>rounds)); - - return MIN2(ret, 1); + while ( result && ( clmd->coll_parms->loop_count>rounds ) ); + + return MIN2 ( ret, 1 ); } -- cgit v1.2.3 From 5d0a207ecb843c4c73be897cfccbf3a0d2db574b Mon Sep 17 00:00:00 2001 From: Chris Want Date: Wed, 16 Apr 2008 22:40:48 +0000 Subject: Patch from GSR that a) fixes a whole bunch of GPL/BL license blocks that were previously missed; and b) greatly increase my ohloh stats! --- source/blender/blenkernel/intern/collision.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index bb0622a61cb..22f68eecd3f 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1,15 +1,12 @@ /* collision.c * * -* ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +* ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. The Blender -* Foundation also sells licenses for use in proprietary software under -* the Blender License. See http://www.blender.org/BL/ for information -* about this. +* of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,7 +24,7 @@ * * Contributor(s): none yet. * -* ***** END GPL/BL DUAL LICENSE BLOCK ***** +* ***** END GPL LICENSE BLOCK ***** */ #include "MEM_guardedalloc.h" -- cgit v1.2.3 From ff26d59577bad5051ea872100b7d725d1af817a0 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Tue, 22 Apr 2008 19:14:33 +0000 Subject: WITH_BULLET wasn't working for Makefiles. I changed it so its tests are more inline with other defines. Jesterking said this shouldn't affect scons so yell at him if it does. ;) Kent --- source/blender/blenkernel/intern/collision.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 22f68eecd3f..e244ccca306 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -639,7 +639,7 @@ void cloth_collision_static ( ModifierData *md1, ModifierData *md2, CollisionTre if ( i < 4 ) { // calc distance + normal -#if WITH_BULLET == 1 +#ifdef WITH_BULLET distance = plNearestPoints ( verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector ); #else -- cgit v1.2.3 From a68c03e409e01285bee622b12313117012e486a8 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 7 May 2008 20:42:16 +0000 Subject: Reason of all this work: Commiting my work-in-progress on reviewed collision system (better + general access to kdop, uses less memory, put it into BLI_* namespace and usage defined like existing BLI_kdtree_*). Deleted old kdop.c --- source/blender/blenkernel/intern/collision.c | 680 ++++++++++++++------------- 1 file changed, 365 insertions(+), 315 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index e244ccca306..f3637b4dda2 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -41,7 +41,6 @@ #include "BKE_global.h" #include "BKE_mesh.h" #include "BKE_object.h" -#include "BKE_cloth.h" #include "BKE_modifier.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" @@ -49,6 +48,38 @@ #include "Bullet-C-Api.h" +#include "BLI_kdopbvh.h" +#include "BKE_collision.h" + +#ifdef _WIN32 +static void start ( void ) +{} +static void end ( void ) +{ +} +static double val() +{ + return 0; +} +#else +#include +static void mystart ( struct timeval *start, struct timezone *z ) +{ + gettimeofday ( start, z ); +} +static void myend ( struct timeval *end, struct timezone *z ) +{ + gettimeofday ( end,z ); +} +static double myval ( struct timeval *start, struct timeval *end ) +{ + double t1, t2; + t1 = ( double ) start->tv_sec + ( double ) start->tv_usec/ ( 1000*1000 ); + t2 = ( double ) end->tv_sec + ( double ) end->tv_usec/ ( 1000*1000 ); + return t2-t1; +} +#endif + /*********************************** Collision modifier code start ***********************************/ @@ -66,58 +97,80 @@ void collision_move_object ( CollisionModifierData *collmd, float step, float pr 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_update_from_mvert ( collmd->bvh, collmd->current_x, collmd->numverts, collmd->current_xnew, 1 ); + bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 ); } -/* build bounding volume hierarchy from mverts (see kdop.c for whole BVH code) */ -BVH *bvh_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon ) +BVHTree *bvhtree_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; - } - - // in the moment, return zero if no faces there - if ( !numfaces ) - return NULL; + BVHTree *tree; + float co[12]; + int i; + MFace *tface = mfaces; - bvh->epsilon = epsilon; - bvh->numfaces = numfaces; - bvh->mfaces = mfaces; + tree = BLI_bvhtree_new ( numfaces*2, epsilon, 4, 26 ); - // we have no faces, we save seperate points - if ( !mfaces ) + // fill tree + for ( i = 0; i < numfaces; i++, tface++ ) { - bvh->numfaces = numverts; - } + VECCOPY ( &co[0*3], x[tface->v1].co ); + VECCOPY ( &co[1*3], x[tface->v2].co ); + VECCOPY ( &co[2*3], x[tface->v3].co ); + if ( tface->v4 ) + VECCOPY ( &co[3*3], x[tface->v4].co ); - bvh->numverts = numverts; - bvh->current_x = MEM_dupallocN ( x ); + BLI_bvhtree_insert ( tree, i, co, ( mfaces->v4 ? 4 : 3 ) ); + } - bvh_build ( bvh ); + // balance tree + BLI_bvhtree_balance ( tree ); - return bvh; + return tree; } -void bvh_update_from_mvert ( BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving ) +void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, int moving ) { - if ( !bvh ) - return; + int i; + MFace *mfaces = faces; + float co[12], co_moving[12]; + int ret = 0; - if ( numverts!=bvh->numverts ) + if ( !bvhtree ) return; if ( x ) - memcpy ( bvh->current_xold, x, sizeof ( MVert ) * numverts ); + { + for ( i = 0; i < numfaces; i++, mfaces++ ) + { + VECCOPY ( &co[0*3], x[mfaces->v1].co ); + VECCOPY ( &co[1*3], x[mfaces->v2].co ); + VECCOPY ( &co[2*3], x[mfaces->v3].co ); + if ( mfaces->v4 ) + VECCOPY ( &co[3*3], x[mfaces->v4].co ); + + // copy new locations into array + if ( moving && xnew ) + { + // update moving positions + VECCOPY ( &co_moving[0*3], xnew[mfaces->v1].co ); + VECCOPY ( &co_moving[1*3], xnew[mfaces->v2].co ); + VECCOPY ( &co_moving[2*3], xnew[mfaces->v3].co ); + if ( mfaces->v4 ) + VECCOPY ( &co_moving[3*3], xnew[mfaces->v4].co ); + + ret = BLI_bvhtree_update_node ( bvhtree, i, co, co_moving, ( mfaces->v4 ? 4 : 3 ) ); + } + else + { + ret = BLI_bvhtree_update_node ( bvhtree, i, co, NULL, ( mfaces->v4 ? 4 : 3 ) ); + } - if ( xnew ) - memcpy ( bvh->current_x, xnew, sizeof ( MVert ) * numverts ); + // check if tree is already full + if ( !ret ) + break; + } - bvh_update ( bvh, moving ); + BLI_bvhtree_update_tree ( bvhtree ); + } } /*********************************** @@ -157,11 +210,11 @@ int gsl_poly_solve_cubic ( float a, float b, float c, float *x0, float *x1, floa else if ( CR2 == CQ3 ) { /* this test is actually R2 == Q3, written in a form suitable - for exact computation with integers */ + for exact computation with integers */ /* Due to finite precision some float roots may be missed, and - considered to be a pair of complex roots z = x +/- epsilon i - close to the real axis. */ + considered to be a pair of complex roots z = x +/- epsilon i + close to the real axis. */ float sqrtQ = sqrt ( Q ); @@ -419,24 +472,22 @@ DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float VECADDMUL ( to, v3, w3 ); } -int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd ) +int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { int result = 0; - LinkNode *search = NULL; - CollPair *collpair = NULL; Cloth *cloth1; float w1, w2, w3, u1, u2, u3; float v1[3], v2[3], relativeVelocity[3]; float magrelVel; - float epsilon2 = collmd->bvh->epsilon; + float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); cloth1 = clmd->clothObject; - search = clmd->coll_parms->collision_list; - - while ( search ) + for ( ; collpair != collision_end; collpair++ ) { - collpair = search->link; + // only handle static collisions here + if ( collpair->flag & COLLISION_IN_FUTURE ) + continue; // compute barycentric coordinates for both collision points collision_compute_barycentric ( collpair->pa, @@ -530,8 +581,6 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier result = 1; } - - search = search->next; } @@ -549,51 +598,46 @@ int cloth_collision_response_moving_edges ( ClothModifierData *clmd, ClothModifi return 1; } -void cloth_collision_static ( ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2 ) +//Determines collisions on overlap, collisions are writen to collpair[i] and collision+number_collision_found is returned +CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair ) { ClothModifierData *clmd = ( ClothModifierData * ) md1; CollisionModifierData *collmd = ( CollisionModifierData * ) md2; - CollPair *collpair = NULL; - Cloth *cloth1=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL; + MFace *face1=NULL, *face2 = NULL; + ClothVertex *verts1 = clmd->clothObject->verts; double distance = 0; - float epsilon = clmd->coll_parms->epsilon; - float epsilon2 = ( ( CollisionModifierData * ) md2 )->bvh->epsilon; - unsigned int i = 0; + float epsilon1 = clmd->coll_parms->epsilon; + float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); + int i; + face1 = & ( clmd->clothObject->mfaces[overlap->indexA] ); + face2 = & ( collmd->mfaces[overlap->indexB] ); + + // check all 4 possible collisions for ( i = 0; i < 4; i++ ) { - collpair = ( CollPair * ) MEM_callocN ( sizeof ( CollPair ), "cloth coll pair" ); - - cloth1 = clmd->clothObject; - - verts1 = cloth1->verts; - - face1 = & ( cloth1->mfaces[tree1->tri_index] ); - face2 = & ( collmd->mfaces[tree2->tri_index] ); - - // check all possible pairs of triangles if ( i == 0 ) { + // fill faceA collpair->ap1 = face1->v1; collpair->ap2 = face1->v2; collpair->ap3 = face1->v3; + // fill faceB collpair->bp1 = face2->v1; collpair->bp2 = face2->v2; collpair->bp3 = face2->v3; - } - - if ( i == 1 ) + else if ( i == 1 ) { if ( face1->v4 ) { - collpair->ap1 = face1->v3; + // fill faceA + collpair->ap1 = face1->v1; collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; + collpair->ap3 = face1->v3; + // fill faceB collpair->bp1 = face2->v1; collpair->bp2 = face2->v2; collpair->bp3 = face2->v3; @@ -601,235 +645,215 @@ void cloth_collision_static ( ModifierData *md1, ModifierData *md2, CollisionTre else i++; } - if ( i == 2 ) { if ( face2->v4 ) { + // fill faceA collpair->ap1 = face1->v1; collpair->ap2 = face1->v2; collpair->ap3 = face1->v3; - collpair->bp1 = face2->v3; + // fill faceB + collpair->bp1 = face2->v1; collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; + collpair->bp3 = face2->v3; } else - i+=2; + break; } - - if ( i == 3 ) + else if ( i == 3 ) { - if ( ( face1->v4 ) && ( face2->v4 ) ) + if ( face1->v4 && face2->v4 ) { - collpair->ap1 = face1->v3; + // fill faceA + collpair->ap1 = face1->v1; collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; + collpair->ap3 = face1->v3; - collpair->bp1 = face2->v3; + // fill faceB + collpair->bp1 = face2->v1; collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; + collpair->bp3 = face2->v3; } else - i++; + break; } - // calc SIPcode (?) - - if ( i < 4 ) - { - // calc distance + normal #ifdef WITH_BULLET - distance = plNearestPoints ( - verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector ); + // calc distance + normal + distance = plNearestPoints ( + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector ); #else - // just be sure that we don't add anything - distance = 2.0 * ( epsilon + epsilon2 + ALMOST_ZERO ); + // just be sure that we don't add anything + distance = 2.0 * ( epsilon1 + epsilon2 + ALMOST_ZERO ); #endif - if ( distance <= ( epsilon + epsilon2 + 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; - BLI_linklist_prepend ( &clmd->coll_parms->collision_list, collpair ); + if ( distance <= ( epsilon1 + epsilon2 + ALMOST_ZERO ) ) + { + VECCOPY ( collpair->normal, collpair->vector ); + Normalize ( collpair->normal ); - } - else - { - MEM_freeN ( collpair ); - } + collpair->distance = distance; + collpair->flag = 0; } else { - MEM_freeN ( collpair ); + // check for collision in the future + collpair->flag |= COLLISION_IN_FUTURE; } + collpair++; } + return collpair; } -int cloth_are_edges_adjacent ( ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair ) +int cloth_are_edges_adjacent ( ClothModifierData *clmd, CollisionModifierData *collmd, EdgeCollPair *edgecollpair ) { - Cloth *cloth1 = NULL, *cloth2 = NULL; - ClothVertex *verts1 = NULL, *verts2 = NULL; + Cloth *cloth1 = NULL; + ClothVertex *verts1 = NULL; float temp[3]; + MVert *verts2 = collmd->current_x; // old x cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - verts1 = cloth1->verts; - verts2 = cloth2->verts; - VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold ); + VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold ); + VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold ); + VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold ); + VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; return 0; } -void cloth_collision_moving_edges ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 ) +void cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) { EdgeCollPair edgecollpair; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; + Cloth *cloth1=NULL; + ClothVertex *verts1=NULL; 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]; + MVert *verts2 = collmd->current_x; // old x + MVert *velocity2 = collmd->current_v; // velocity + float mintime = 0; 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++ ) + for(i = 0; i < 9; i++) { - if ( i == 0 ) + // 9 edge - edge possibilities + + if(i == 0) // cloth edge: 1-2; coll edge: 1-2 { - edgecollpair.p11 = face1->v1; - edgecollpair.p12 = face1->v2; + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap2; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp2; } - else if ( i == 1 ) + else if(i == 1) // cloth edge: 1-2; coll edge: 2-3 { - edgecollpair.p11 = face1->v2; - edgecollpair.p12 = face1->v3; + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap2; + + edgecollpair.p21 = collpair->bp2; + edgecollpair.p22 = collpair->bp3; } - else if ( i == 2 ) + else if(i == 2) // cloth edge: 1-2; coll edge: 1-3 { - 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 - } + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap2; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp3; } - else if ( i == 3 ) + else if(i == 3) // cloth edge: 2-3; coll edge: 1-2 { - if ( face1->v4 ) - { - edgecollpair.p11 = face1->v4; - edgecollpair.p12 = face1->v1; - } - else - continue; + edgecollpair.p11 = collpair->ap2; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp2; } - else + else if(i == 4) // cloth edge: 2-3; coll edge: 2-3 { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v1; + edgecollpair.p11 = collpair->ap2; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp2; + edgecollpair.p22 = collpair->bp3; } - - - for ( j = 0; j < 5; j++ ) + else if(i == 5) // cloth edge: 2-3; coll edge: 1-3 { - 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 ( !cloth_are_edges_adjacent ( clmd, coll_clmd, &edgecollpair ) ) + edgecollpair.p11 = collpair->ap2; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp3; + } + else if(i ==6) // cloth edge: 1-3; coll edge: 1-2 + { + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp2; + } + else if(i ==7) // cloth edge: 1-3; coll edge: 2-3 + { + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp2; + edgecollpair.p22 = collpair->bp3; + } + else if(i == 8) // cloth edge: 1-3; coll edge: 1-3 + { + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp3; + } + + if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) ) + { + // always put coll points in p21/p22 + VECSUB ( a, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold ); + VECSUB ( b, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv ); + VECSUB ( c, verts2[edgecollpair.p21].co, verts1[edgecollpair.p11].txold ); + VECSUB ( d, velocity2[edgecollpair.p21].co, verts1[edgecollpair.p11].tv ); + VECSUB ( e, verts2[edgecollpair.p22].co, verts1[edgecollpair.p11].txold ); + VECSUB ( f, velocity2[edgecollpair.p22].co, verts1[edgecollpair.p11].v ); + + numsolutions = cloth_get_collision_time ( a, b, c, d, e, f, solution ); + + for ( k = 0; k < numsolutions; k++ ) { - 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 = cloth_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 ) ) { - 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"); - } + //float out_collisionTime = solution[k]; + + // TODO: check for collisions + + // TODO: put into (edge) collision list + + mintime = MIN2(mintime, solution[k]); + + printf("Moving edge found!, mintime: %f\n", mintime); + break; } } } @@ -928,6 +952,7 @@ void cloth_collision_moving_tris ( ClothModifierData *clmd, ClothModifierData *c } } +/* void cloth_collision_moving ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 ) { // TODO: check for adjacent @@ -936,51 +961,68 @@ void cloth_collision_moving ( ClothModifierData *clmd, ClothModifierData *coll_c cloth_collision_moving_tris ( clmd, coll_clmd, tree1, tree2 ); cloth_collision_moving_tris ( coll_clmd, clmd, tree2, tree1 ); } +*/ -void cloth_free_collision_list ( ClothModifierData *clmd ) +int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { - // free collision list - if ( clmd->coll_parms->collision_list ) - { - LinkNode *search = clmd->coll_parms->collision_list; - while ( search ) - { - CollPair *coll_pair = search->link; + int result = 0; + Cloth *cloth1; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); - MEM_freeN ( coll_pair ); - search = search->next; - } - BLI_linklist_free ( clmd->coll_parms->collision_list,NULL ); + cloth1 = clmd->clothObject; - clmd->coll_parms->collision_list = NULL; + for ( ; collpair != collision_end; collpair++ ) + { + // only handle moving collisions here + if (!( collpair->flag & COLLISION_IN_FUTURE )) + continue; + + cloth_collision_moving_edges ( clmd, collmd, collpair); } } int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData *collmd, float step, float dt ) { Cloth *cloth = clmd->clothObject; - BVH *cloth_bvh= ( BVH * ) cloth->tree; + BVHTree *cloth_bvh= ( BVHTree * ) cloth->bvhtree; long i=0, j = 0, numfaces = 0, numverts = 0; ClothVertex *verts = NULL; + CollPair *collisions = NULL, *collisions_index = NULL; int ret = 0; - unsigned int result = 0; + int result = 0; float tnull[3] = {0,0,0}; + BVHTreeOverlap *overlap = NULL; + numfaces = clmd->clothObject->numfaces; numverts = clmd->clothObject->numverts; verts = cloth->verts; - if ( collmd->bvh ) + if ( collmd->bvhtree ) { /* get pointer to bounding volume hierarchy */ - BVH *coll_bvh = collmd->bvh; + BVHTree *coll_bvh = collmd->bvhtree; /* move object to position (step) in time */ collision_move_object ( collmd, step + dt, step ); /* search for overlapping collision pairs */ - bvh_traverse ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0 ); + overlap = BLI_bvhtree_overlap ( cloth_bvh, coll_bvh, &result ); + + collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * result*4, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision + collisions_index = collisions; + + for ( i = 0; i < result; i++ ) + { + collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, overlap+i, collisions_index ); + } + + if ( overlap ) + MEM_freeN ( overlap ); } else { @@ -994,11 +1036,15 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData { result = 0; - if ( collmd->bvh ) - result += cloth_collision_response_static ( clmd, collmd ); + if ( collmd->bvhtree ) + { + result += cloth_collision_response_static ( clmd, collmd, collisions, collisions_index ); + result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); + } // apply impulses in parallel if ( result ) + { for ( i = 0; i < numverts; i++ ) { // calculate "velocities" (just xnew = xold + v; no dt in v) @@ -1011,12 +1057,10 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData ret++; } } - - if ( !result ) - break; + } } - cloth_free_collision_list ( clmd ); + if ( collisions ) MEM_freeN ( collisions ); return ret; } @@ -1028,7 +1072,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) CollisionModifierData *collmd=NULL; Cloth *cloth=NULL; Object *coll_ob=NULL; - BVH *cloth_bvh=NULL; + BVHTree *cloth_bvh=NULL; long i=0, j = 0, numfaces = 0, numverts = 0; unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; @@ -1036,14 +1080,14 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) ClothModifierData *tclmd; int collisions = 0, count = 0; - if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->tree ) ) + if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->bvhtree ) ) { return 0; } cloth = clmd->clothObject; verts = cloth->verts; - cloth_bvh = ( BVH * ) cloth->tree; + cloth_bvh = ( BVHTree * ) cloth->bvhtree; numfaces = clmd->clothObject->numfaces; numverts = clmd->clothObject->numverts; @@ -1052,12 +1096,11 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// // update cloth bvh - bvh_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) + bvhtree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) do { result = 0; - clmd->coll_parms->collision_list = NULL; // check all collision objects for ( base = G.scene->base.first; base; base = base->next ) @@ -1126,80 +1169,87 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { + + MFace *mface = clmd->clothObject->mfaces; + collisions = 1; verts = cloth->verts; // needed for openMP + + + /* for ( count = 0; count < clmd->coll_parms->self_loop_count; count++ ) { - if ( collisions ) - { - collisions = 0; -#pragma omp parallel for private(i,j, collisions) shared(verts, ret) - for ( i = 0; i < cloth->numverts; i++ ) - { - for ( j = i + 1; j < cloth->numverts; j++ ) - { - float temp[3]; - float length = 0; - float mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); + if ( collisions ) + { + collisions = 0; + #pragma omp parallel for private(i,j, collisions) shared(verts, ret) + for ( i = 0; i < cloth->numverts; i++ ) + { + for ( j = i + 1; j < cloth->numverts; j++ ) + { + float temp[3]; + float length = 0; + float mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - { - if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) - { - continue; - } - } + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + { + if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) + { + continue; + } + } - VECSUB ( temp, verts[i].tx, verts[j].tx ); + VECSUB ( temp, verts[i].tx, verts[j].tx ); - if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; + if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; // check for adjacent points (i must be smaller j) - if ( BLI_edgehash_haskey ( cloth->edgehash, i, j ) ) - { - continue; - } - - length = Normalize ( temp ); - - if ( length < mindistance ) - { - float correction = mindistance - length; - - if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, -correction ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - } - else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, correction ); - VECADD ( verts[i].tx, verts[i].tx, temp ); - } - else - { - VecMulf ( temp, -correction*0.5 ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - - VECSUB ( verts[i].tx, verts[i].tx, temp ); - } - - collisions = 1; - - if ( !ret ) - { -#pragma omp critical - { - ret = 1; - } - } - } - } - } - } + if ( BLI_edgehash_haskey ( cloth->edgehash, i, j ) ) + { + continue; + } + + length = Normalize ( temp ); + + if ( length < mindistance ) + { + float correction = mindistance - length; + + if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, -correction ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + } + else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, correction ); + VECADD ( verts[i].tx, verts[i].tx, temp ); + } + else + { + VecMulf ( temp, -correction*0.5 ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + + VECSUB ( verts[i].tx, verts[i].tx, temp ); + } + + collisions = 1; + + if ( !ret ) + { + #pragma omp critical + { + ret = 1; + } + } + } + } + } + } } + */ //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// -- cgit v1.2.3 From 4d8b5587b867e53c22b4f3f3c56ba8714e9b7bfb Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 14 May 2008 16:09:56 +0000 Subject: Pre merge commit (includes commented moving stuff) --- source/blender/blenkernel/intern/collision.c | 276 +++++++++++++++++---------- 1 file changed, 176 insertions(+), 100 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 9ba47874d3c..1e8b8706658 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -608,22 +608,9 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier result = 1; } } - - return result; } -int cloth_collision_response_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd ) -{ - return 1; -} - - -int cloth_collision_response_moving_edges ( ClothModifierData *clmd, ClothModifierData *coll_clmd ) -{ - return 1; -} - //Determines collisions on overlap, collisions are writen to collpair[i] and collision+number_collision_found is returned CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair ) { @@ -743,25 +730,148 @@ int cloth_are_edges_adjacent ( ClothModifierData *clmd, CollisionModifierData *c cloth1 = clmd->clothObject; verts1 = cloth1->verts; - VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].co ); + VECSUB ( temp, verts1[edgecollpair->p11].txold, verts2[edgecollpair->p21].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].co ); + VECSUB ( temp, verts1[edgecollpair->p11].txold, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].co ); + VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p21].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].co ); + VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; + + VECSUB ( temp, verts1[edgecollpair->p11].txold, verts1[edgecollpair->p12].txold ); + if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) + return 1; + + VECSUB ( temp, verts2[edgecollpair->p21].co, verts2[edgecollpair->p22].co ); + if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) + return 1; + return 0; } +int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) +{ + int result = 0; + Cloth *cloth1; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); + + cloth1 = clmd->clothObject; + + for ( ; collpair != collision_end; collpair++ ) + { + // only handle static collisions here + if ( collpair->flag & COLLISION_IN_FUTURE ) + continue; + + // compute barycentric coordinates for both collision points + collision_compute_barycentric ( collpair->pa, + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3 ); + + // was: txold + collision_compute_barycentric ( collpair->pb, + collmd->current_x[collpair->bp1].co, + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, + &u1, &u2, &u3 ); + + // Calculate relative "velocity". + collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 ); + + collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 ); + + VECSUB ( relativeVelocity, v2, v1 ); + + // 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. + // TODO + + // 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. + float magtangent = 0, repulse = 0, d = 0; + double impulse = 0.0; + float vrel_t_pre[3]; + float temp[3]; + + // calculate tangential velocity + VECCOPY ( temp, collpair->normal ); + VecMulf ( temp, magrelVel ); + VECSUB ( vrel_t_pre, relativeVelocity, temp ); + + // Decrease in magnitude of relative tangential velocity due to coulomb friction + // in original formula "magrelVel" should be the "change of relative velocity in normal direction" + magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel,sqrt ( INPR ( vrel_t_pre,vrel_t_pre ) ) ); + + // Apply friction impulse. + if ( magtangent > ALMOST_ZERO ) + { + Normalize ( vrel_t_pre ); + + impulse = 2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); + VECADDMUL ( cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse ); + VECADDMUL ( cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse ); + VECADDMUL ( cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse ); + } + + // Apply velocity stopping impulse + // I_c = m * v_N / 2.0 + // no 2.0 * magrelVel normally, but looks nicer DG + impulse = magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); + + 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++; + + // Apply repulse impulse if distance too short + // I_r = -min(dt*kd, m(0,1d/dt - v_n)) + /* + d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance; + if ( ( magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame ) && ( d > ALMOST_ZERO ) ) + { + repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel ); + + // stay on the safe side and clamp repulse + if ( impulse > ALMOST_ZERO ) + repulse = MIN2 ( repulse, 5.0*impulse ); + repulse = MAX2 ( impulse, repulse ); + + impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25 + VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse ); + VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse ); + VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse ); + } +*/ + result = 1; + } + } + return result; +} + int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) { EdgeCollPair edgecollpair; @@ -781,53 +891,6 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat cloth1 = clmd->clothObject; verts1 = cloth1->verts; - /* - double p[4][3] = {{0,0,0},{0,2,0},{1,1,-1},{1,1,1}}; - double v[4][3] = {{0,0,0},{1,0,0},{-2,0,0},{-2,0,0}}; - - double pp[2][3] = {{-1,-1,-1}, {2,2,2}}; - - - VECSUB ( x1, p[1], p[0] ); - VECSUB ( v1, v[1], v[0] ); - - VECSUB ( x2, p[2], p[0] ); - VECSUB ( v2, v[2], v[0] ); - - VECSUB ( x3, p[3], p[0] ); - VECSUB ( v3, v[3], v[0] ); - - printf("x1 x: %f, y: %f, z: %f\n", x1[0], x1[1], x1[2]); - printf("x2 x: %f, y: %f, z: %f\n", x2[0], x2[1], x2[2]); - printf("x3 x: %f, y: %f, z: %f\n", x3[0], x3[1], x3[2]); - - printf("v1 x: %f, y: %f, z: %f\n", v1[0], v1[1], v1[2]); - printf("v2 x: %f, y: %f, z: %f\n", v2[0], v2[1], v2[2]); - printf("v3 x: %f, y: %f, z: %f\n", v3[0], v3[1], v3[2]); - - numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution ); - - for ( k = 0; k < numsolutions; k++ ) - printf("mintime: %f\n", solution[k]); - - mintime = solution[0]; - - // move triangles to collision point in time - VECADDS(triA[0], pp[0], v[0], solution[0]); - VECADDS(triA[1], p[0], v[0], solution[0]); - VECADDS(triA[2], p[1], v[1], solution[0]); - - VECADDS(triB[0], pp[1], v[0], solution[0]); - VECADDS(triB[1], p[2], v[2], solution[0]); - VECADDS(triB[2], p[3], v[3], solution[0]); - - // check distance there - distance = plNearestPoints (triA[0], triA[1], triA[2], triB[0], triB[1], triB[2], collpair->pa,collpair->pb,collpair->vector ); - - printf("mintime: %f, dist: %f\n", mintime, distance); - - exit(0); - */ for(i = 0; i < 9; i++) { // 9 edge - edge possibilities @@ -916,19 +979,12 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat VECSUB ( x3, verts2[edgecollpair.p22].co, verts1[edgecollpair.p11].txold ); VECSUB ( v3, velocity2[edgecollpair.p22].co, verts1[edgecollpair.p11].tv ); - /* - printf("A x: %f, y: %f, z: %f\n", a[0], a[1], a[2]); - printf("B x: %f, y: %f, z: %f\n", b[0], b[1], b[2]); - printf("C x: %f, y: %f, z: %f\n", c[0], c[1], c[2]); - printf("D x: %f, y: %f, z: %f\n", d[0], d[1], d[2]); - printf("E x: %f, y: %f, z: %f\n", e[0], e[1], e[2]); - printf("F x: %f, y: %f, z: %f\n", f[0], f[1], f[2]); - exit(0); - */ + numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution ); for ( k = 0; k < numsolutions; k++ ) { + // printf("sol %d: %lf\n", k, solution[k]); if ( ( solution[k] >= DBL_EPSILON ) && ( solution[k] <= 1.0 ) ) { //float out_collisionTime = solution[k]; @@ -939,8 +995,6 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat mintime = MIN2(mintime, (float)solution[k]); -// printf("mt: %f, %lf, %f\n", mintime, solution[k], (float)solution[k]); - result = 1; break; } @@ -962,12 +1016,25 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat // check distance there distance = plNearestPoints (triA[0], triA[1], triA[2], triB[0], triB[1], triB[2], collpair->pa,collpair->pb,collpair->vector ); - printf("mintime: %f, dist: %f\n", mintime, distance); + if(distance <= (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO)) + { + CollPair *next = collpair; + next++; + + collpair->distance = clmd->coll_parms->epsilon; + collpair->time = mintime; + + VECCOPY ( collpair->normal, collpair->vector ); + Normalize ( collpair->normal ); + + cloth_collision_response_moving ( clmd, collmd, collpair, next ); + } } return result; } +/* void cloth_collision_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 ) { CollPair collpair; @@ -1060,16 +1127,6 @@ void cloth_collision_moving_tris ( ClothModifierData *clmd, ClothModifierData *c } } } - -/* -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 ); - - cloth_collision_moving_tris ( clmd, coll_clmd, tree1, tree2 ); - cloth_collision_moving_tris ( coll_clmd, clmd, tree2, tree1 ); -} */ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) @@ -1150,24 +1207,43 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData if ( collmd->bvhtree ) { result += cloth_collision_response_static ( clmd, collmd, collisions, collisions_index ); - result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); - } - // apply impulses in parallel - if ( result ) - { - for ( i = 0; i < numverts; i++ ) + // apply impulses in parallel + if ( result ) { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if ( verts[i].impulse_count ) + for ( i = 0; i < numverts; i++ ) { - VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count ); - VECCOPY ( verts[i].impulse, tnull ); - verts[i].impulse_count = 0; - - ret++; + // 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; + + ret++; + } + } + } + /* + result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); + + // apply impulses in parallel + if ( result ) + { + 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; + + ret++; + } } } + */ } } @@ -1207,7 +1283,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// // update cloth bvh - bvhtree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) + bvhtree_update_from_cloth ( clmd, 1 ); // 0 means STATIC, 1 means MOVING (see later in this function) do { -- cgit v1.2.3 From 4bf01e8162dd3c30791a8a1d5d20fc80fbdef1ac Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 23 May 2008 20:20:14 +0000 Subject: Commit of selfcollisions using new kdop design. Should result in nice speedup. --- source/blender/blenkernel/intern/collision.c | 75 +++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 1e8b8706658..4d49ccc9eb3 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1260,7 +1260,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) Cloth *cloth=NULL; Object *coll_ob=NULL; BVHTree *cloth_bvh=NULL; - long i=0, j = 0, numfaces = 0, numverts = 0; + long i=0, j = 0, k = 0, numfaces = 0, numverts = 0; unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0; @@ -1284,6 +1284,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) // update cloth bvh bvhtree_update_from_cloth ( clmd, 1 ); // 0 means STATIC, 1 means MOVING (see later in this function) + bvhselftree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) do { @@ -1357,12 +1358,82 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { - MFace *mface = clmd->clothObject->mfaces; + MFace *mface = cloth->mfaces; + BVHTreeOverlap *overlap = NULL; collisions = 1; verts = cloth->verts; // needed for openMP + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + + verts = cloth->verts; + + if ( cloth->bvhselftree ) + { + /* search for overlapping collision pairs */ + overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); + + for ( k = 0; k < result; k++ ) + { + float temp[3]; + float length = 0; + float mindistance; + + i = overlap[k].indexA; + j = overlap[k].indexB; + + mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); + + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + { + if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) + { + continue; + } + } + + VECSUB ( temp, verts[i].tx, verts[j].tx ); + + if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; + + // check for adjacent points (i must be smaller j) + if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) + { + continue; + } + length = Normalize ( temp ); + + if ( length < mindistance ) + { + float correction = mindistance - length; + + if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, -correction ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + } + else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, correction ); + VECADD ( verts[i].tx, verts[i].tx, temp ); + } + else + { + VecMulf ( temp, -correction*0.5 ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + + VECSUB ( verts[i].tx, verts[i].tx, temp ); + } + } + } + + if ( overlap ) + MEM_freeN ( overlap ); + + } /* for ( count = 0; count < clmd->coll_parms->self_loop_count; count++ ) -- cgit v1.2.3 From cb378cbceb22ca95b4e60e46208bd1922641f00b Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 26 May 2008 09:39:32 +0000 Subject: -= Cloth =- 1. Fix selfcollisions (reported by nudelZ) --- source/blender/blenkernel/intern/collision.c | 697 ++++++++++++++++----------- 1 file changed, 419 insertions(+), 278 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 4d49ccc9eb3..edf8fec9ae1 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -178,16 +178,16 @@ Collision modifier code end ***********************************/ /** - * gsl_poly_solve_cubic - - * - * copied from SOLVE_CUBIC.C --> GSL - */ +* gsl_poly_solve_cubic - +* +* copied from SOLVE_CUBIC.C --> GSL +*/ #define mySWAP(a,b) do { double tmp = b ; b = a ; a = tmp ; } while(0) int - gsl_poly_solve_cubic (double a, double b, double c, - double *x0, double *x1, double *x2) +gsl_poly_solve_cubic (double a, double b, double c, + double *x0, double *x1, double *x2) { double q = (a * a - 3 * b); double r = (2 * a * a * a - 9 * a * b + 27 * c); @@ -210,10 +210,10 @@ int } else if (CR2 == CQ3) { - /* this test is actually R2 == Q3, written in a form suitable + /* this test is actually R2 == Q3, written in a form suitable for exact computation with integers */ - /* Due to finite precision some double roots may be missed, and + /* Due to finite precision some double roots may be missed, and considered to be a pair of complex roots z = x +/- epsilon i close to the real axis. */ @@ -242,20 +242,20 @@ int *x0 = norm * cos (theta / 3) - a / 3; *x1 = norm * cos ((theta + 2.0 * M_PI) / 3) - a / 3; *x2 = norm * cos ((theta - 2.0 * M_PI) / 3) - a / 3; - + /* Sort *x0, *x1, *x2 into increasing order */ if (*x0 > *x1) mySWAP(*x0, *x1) ; - + if (*x1 > *x2) { mySWAP(*x1, *x2) ; - + if (*x0 > *x1) mySWAP(*x0, *x1) ; } - + return 3; } else @@ -271,13 +271,13 @@ int /** - * gsl_poly_solve_quadratic - * - * copied from GSL - */ +* gsl_poly_solve_quadratic +* +* copied from GSL +*/ int - gsl_poly_solve_quadratic (double a, double b, double c, - double *x0, double *x1) +gsl_poly_solve_quadratic (double a, double b, double c, + double *x0, double *x1) { double disc = b * b - 4 * a * c; @@ -338,55 +338,55 @@ int /* - * See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation" - * page 4, left column - */ +* See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation" +* page 4, left column +*/ int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] ) { int num_sols = 0; // x^0 - checked double g = a[0] * c[1] * e[2] - a[0] * c[2] * e[1] + - a[1] * c[2] * e[0] - a[1] * c[0] * e[2] + - a[2] * c[0] * e[1] - a[2] * c[1] * e[0]; - + a[1] * c[2] * e[0] - a[1] * c[0] * e[2] + + a[2] * c[0] * e[1] - a[2] * c[1] * e[0]; + // x^1 double h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] + - a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] + - a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] + - b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] - - a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] - - a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2]; + a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] + + a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] + + b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] - + a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] - + a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2]; // x^2 double i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] + - b[2] * d[0] * e[1] - b[0] * d[2] * e[1] - - b[1] * d[0] * e[2] + b[0] * d[1] * e[2] - - b[2] * c[1] * f[0] + b[1] * c[2] * f[0] - - a[2] * d[1] * f[0] + a[1] * d[2] * f[0] + - b[2] * c[0] * f[1] - b[0] * c[2] * f[1] + - a[2] * d[0] * f[1] - a[0] * d[2] * f[1] - - b[1] * c[0] * f[2] + b[0] * c[1] * f[2] - - a[1] * d[0] * f[2] + a[0] * d[1] * f[2]; - + b[2] * d[0] * e[1] - b[0] * d[2] * e[1] - + b[1] * d[0] * e[2] + b[0] * d[1] * e[2] - + b[2] * c[1] * f[0] + b[1] * c[2] * f[0] - + a[2] * d[1] * f[0] + a[1] * d[2] * f[0] + + b[2] * c[0] * f[1] - b[0] * c[2] * f[1] + + a[2] * d[0] * f[1] - a[0] * d[2] * f[1] - + b[1] * c[0] * f[2] + b[0] * c[1] * f[2] - + a[1] * d[0] * f[2] + a[0] * d[1] * f[2]; + // x^3 - checked double j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] + - b[2] * d[0] * f[1] - b[0] * d[2] * f[1] - - b[1] * d[0] * f[2] + b[0] * d[1] * f[2]; - + b[2] * d[0] * f[1] - b[0] * d[2] * f[1] - + b[1] * d[0] * f[2] + b[0] * d[1] * f[2]; + /* printf("r1: %lf\n", a[0] * c[1] * e[2] - a[0] * c[2] * e[1]); printf("r2: %lf\n", a[1] * c[2] * e[0] - a[1] * c[0] * e[2]); printf("r3: %lf\n", a[2] * c[0] * e[1] - a[2] * c[1] * e[0]); - + printf("x1 x: %f, y: %f, z: %f\n", a[0], a[1], a[2]); printf("x2 x: %f, y: %f, z: %f\n", c[0], c[1], c[2]); printf("x3 x: %f, y: %f, z: %f\n", e[0], e[1], e[2]); - + printf("v1 x: %f, y: %f, z: %f\n", b[0], b[1], b[2]); printf("v2 x: %f, y: %f, z: %f\n", d[0], d[1], d[2]); printf("v3 x: %f, y: %f, z: %f\n", f[0], f[1], f[2]); - + printf("t^3: %lf, t^2: %lf, t^1: %lf, t^0: %lf\n", j, i, h, g); */ @@ -517,17 +517,17 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier // compute barycentric coordinates for both collision points collision_compute_barycentric ( collpair->pa, - cloth1->verts[collpair->ap1].txold, - cloth1->verts[collpair->ap2].txold, - cloth1->verts[collpair->ap3].txold, - &w1, &w2, &w3 ); + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3 ); // was: txold collision_compute_barycentric ( collpair->pb, - collmd->current_x[collpair->bp1].co, - collmd->current_x[collpair->bp2].co, - collmd->current_x[collpair->bp3].co, - &u1, &u2, &u3 ); + collmd->current_x[collpair->bp1].co, + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, + &u1, &u2, &u3 ); // Calculate relative "velocity". collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 ); @@ -696,7 +696,7 @@ CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap #ifdef WITH_BULLET // calc distance + normal distance = plNearestPoints ( - verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector ); + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector ); #else // just be sure that we don't add anything distance = 2.0 * ( epsilon1 + epsilon2 + ALMOST_ZERO ); @@ -745,15 +745,15 @@ int cloth_are_edges_adjacent ( ClothModifierData *clmd, CollisionModifierData *c VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - + VECSUB ( temp, verts1[edgecollpair->p11].txold, verts1[edgecollpair->p12].txold ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - + VECSUB ( temp, verts2[edgecollpair->p21].co, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - + return 0; } @@ -771,23 +771,19 @@ int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierD for ( ; collpair != collision_end; collpair++ ) { - // only handle static collisions here - if ( collpair->flag & COLLISION_IN_FUTURE ) - continue; - // compute barycentric coordinates for both collision points collision_compute_barycentric ( collpair->pa, - cloth1->verts[collpair->ap1].txold, - cloth1->verts[collpair->ap2].txold, - cloth1->verts[collpair->ap3].txold, - &w1, &w2, &w3 ); + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3 ); // was: txold collision_compute_barycentric ( collpair->pb, - collmd->current_x[collpair->bp1].co, - collmd->current_x[collpair->bp2].co, - collmd->current_x[collpair->bp3].co, - &u1, &u2, &u3 ); + collmd->current_x[collpair->bp1].co, + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, + &u1, &u2, &u3 ); // Calculate relative "velocity". collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 ); @@ -853,25 +849,250 @@ int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierD d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance; if ( ( magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame ) && ( d > ALMOST_ZERO ) ) { - repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel ); + repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel ); - // stay on the safe side and clamp repulse - if ( impulse > ALMOST_ZERO ) - repulse = MIN2 ( repulse, 5.0*impulse ); - repulse = MAX2 ( impulse, repulse ); + // stay on the safe side and clamp repulse + if ( impulse > ALMOST_ZERO ) + repulse = MIN2 ( repulse, 5.0*impulse ); + repulse = MAX2 ( impulse, repulse ); - impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25 - VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse ); - VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse ); - VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse ); + impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25 + VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse ); + VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse ); + VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse ); } -*/ + */ result = 1; } } return result; } +static float projectPointOntoLine(float *p, float *a, float *b) +{ + float ba[3], pa[3]; + VECSUB(ba, b, a); + VECSUB(pa, p, a); + return INPR(pa, ba) / INPR(ba, ba); +} + +static void calculateEENormal(float *np1, float *np2, float *np3, float *np4,float *out_normal) +{ + float line1[33], line2[3]; + float length; + + VECSUB(line1, np2, np1); + VECSUB(line2, np3, np1); + + Crossf(out_normal, line1, line2); + length = Normalize(out_normal); + if (length <= FLT_EPSILON) + { // lines are collinear + VECSUB(out_normal, np2, np1); + Normalize(out_normal); + } +} + +static void findClosestPointsEE(float *x1, float *x2, float *x3, float *x4, float *w1, float *w2) +{ + float temp[3], temp2[3]; + + double a, b, c, e, f; + + VECSUB(temp, x2, x1); + a = INPR(temp, temp); + + VECSUB(temp2, x4, x3); + b = -INPR(temp, temp2); + + c = INPR(temp2, temp2); + + VECSUB(temp2, x3, x1); + e = INPR(temp, temp2); + + VECSUB(temp, x4, x3); + f = -INPR(temp, temp2); + + *w1 = (e * c - b * f) / (a * c - b * b); + *w2 = (f - b * *w1) / c; + +} + +// calculates the distance of 2 edges +float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal) +{ + float line1[3], line2[3], cross[3]; + float length; + float temp[3], temp2[3]; + float dist_a1, dist_a2; + + VECSUB(line1, np12, np11); + VECSUB(line2, np22, np21); + + Crossf(cross, line1, line2); + length = INPR(cross, cross); + + if (length < FLT_EPSILON) + { + *out_a2 = projectPointOntoLine(np11, np21, np22); + if ((*out_a2 >= -FLT_EPSILON) && (*out_a2 <= 1.0 + FLT_EPSILON)) + { + *out_a1 = 0; + calculateEENormal(np11, np12, np21, np22, out_normal); + VECSUB(temp, np22, np21); + VecMulf(temp, *out_a2); + VECADD(temp2, temp, np21); + VECADD(temp2, temp2, np11); + return INPR(temp2, temp2); + } + + CLAMP(*out_a2, 0.0, 1.0); + if (*out_a2 > .5) + { // == 1.0 + *out_a1 = projectPointOntoLine(np22, np11, np12); + if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON)) + { + calculateEENormal(np11, np12, np21, np22, out_normal); + + // return (np22 - (np11 + (np12 - np11) * out_a1)).lengthSquared(); + VECSUB(temp, np12, np11); + VecMulf(temp, *out_a1); + VECADD(temp2, temp, np11); + VECSUB(temp2, np22, temp2); + return INPR(temp2, temp2); + } + } + else + { // == 0.0 + *out_a1 = projectPointOntoLine(np21, np11, np12); + if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON)) + { + calculateEENormal(np11, np11, np21, np22, out_normal); + + // return (np21 - (np11 + (np12 - np11) * out_a1)).lengthSquared(); + VECSUB(temp, np12, np11); + VecMulf(temp, *out_a1); + VECADD(temp2, temp, np11); + VECSUB(temp2, np21, temp2); + return INPR(temp2, temp2); + } + } + + CLAMP(*out_a1, 0.0, 1.0); + calculateEENormal(np11, np12, np21, np22, out_normal); + if(*out_a1 > .5) + { + if(*out_a2 > .5) + { + VECSUB(temp, np12, np22); + } + else + { + VECSUB(temp, np12, np21); + } + } + else + { + if(*out_a2 > .5) + { + VECSUB(temp, np11, np22); + } + else + { + VECSUB(temp, np11, np21); + } + } + + return INPR(temp, temp); + } + else + { + + // If the lines aren't parallel (but coplanar) they have to intersect + + findClosestPointsEE(np11, np12, np21, np22, out_a1, out_a2); + + // If both points are on the finite edges, we're done. + if (*out_a1 >= 0.0 && *out_a1 <= 1.0 && *out_a2 >= 0.0 && *out_a2 <= 1.0) + { + float p1[3], p2[3]; + + // p1= np11 + (np12 - np11) * out_a1; + VECSUB(temp, np12, np11); + VecMulf(temp, *out_a1); + VECADD(p1, np11, temp); + + // p2 = np21 + (np22 - np21) * out_a2; + VECSUB(temp, np22, np21); + VecMulf(temp, *out_a2); + VECADD(p2, np21, temp); + + calculateEENormal(np11, np12, np21, np22, out_normal); + VECSUB(temp, p1, p2); + return INPR(temp, temp); + } + + + /* + * Clamp both points to the finite edges. + * The one that moves most during clamping is one part of the solution. + */ + dist_a1 = *out_a1; + CLAMP(dist_a1, 0.0, 1.0); + dist_a2 = *out_a2; + CLAMP(dist_a2, 0.0, 1.0); + + // Now project the "most clamped" point on the other line. + if (dist_a1 > dist_a2) + { + /* keep out_a1 */ + float p1[3]; + + // p1 = np11 + (np12 - np11) * out_a1; + VECSUB(temp, np12, np11); + VecMulf(temp, *out_a1); + VECADD(p1, np11, temp); + + *out_a2 = projectPointOntoLine(p1, np21, np22); + CLAMP(*out_a2, 0.0, 1.0); + + calculateEENormal(np11, np12, np21, np22, out_normal); + + // return (p1 - (np21 + (np22 - np21) * out_a2)).lengthSquared(); + VECSUB(temp, np22, np21); + VecMulf(temp, *out_a2); + VECADD(temp, temp, np21); + VECSUB(temp, p1, temp); + return INPR(temp, temp); + } + else + { + /* keep out_a2 */ + float p2[3]; + + // p2 = np21 + (np22 - np21) * out_a2; + VECSUB(temp, np22, np21); + VecMulf(temp, *out_a2); + VECADD(p2, np21, temp); + + *out_a1 = projectPointOntoLine(p2, np11, np12); + CLAMP(*out_a1, 0.0, 1.0); + + calculateEENormal(np11, np12, np21, np22, out_normal); + + // return ((np11 + (np12 - np11) * out_a1) - p2).lengthSquared(); + VECSUB(temp, np12, np11); + VecMulf(temp, *out_a1); + VECADD(temp, temp, np11); + VECSUB(temp, temp, p2); + return INPR(temp, temp); + } + } + + printf("Error in edgedge_distance: end of function\n"); + return 0; +} + int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) { EdgeCollPair edgecollpair; @@ -890,16 +1111,16 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat cloth1 = clmd->clothObject; verts1 = cloth1->verts; - + for(i = 0; i < 9; i++) { // 9 edge - edge possibilities - + if(i == 0) // cloth edge: 1-2; coll edge: 1-2 { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap2; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp2; } @@ -907,7 +1128,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap2; - + edgecollpair.p21 = collpair->bp2; edgecollpair.p22 = collpair->bp3; } @@ -915,7 +1136,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap2; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp3; } @@ -923,7 +1144,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap2; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp2; } @@ -931,7 +1152,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap2; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp2; edgecollpair.p22 = collpair->bp3; } @@ -939,7 +1160,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap2; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp3; } @@ -947,7 +1168,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp2; } @@ -955,7 +1176,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp2; edgecollpair.p22 = collpair->bp3; } @@ -963,171 +1184,144 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp3; } - + if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) ) { // always put coll points in p21/p22 VECSUB ( x1, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold ); VECSUB ( v1, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv ); - + VECSUB ( x2, verts2[edgecollpair.p21].co, verts1[edgecollpair.p11].txold ); VECSUB ( v2, velocity2[edgecollpair.p21].co, verts1[edgecollpair.p11].tv ); - + VECSUB ( x3, verts2[edgecollpair.p22].co, verts1[edgecollpair.p11].txold ); VECSUB ( v3, velocity2[edgecollpair.p22].co, verts1[edgecollpair.p11].tv ); - + numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution ); - + for ( k = 0; k < numsolutions; k++ ) { // printf("sol %d: %lf\n", k, solution[k]); if ( ( solution[k] >= DBL_EPSILON ) && ( solution[k] <= 1.0 ) ) { - //float out_collisionTime = solution[k]; - + float a,b; + float out_normal[3]; + float distance; + + // move verts + VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, mintime); + VECADDS(triA[1], verts1[edgecollpair.p12].txold, verts1[edgecollpair.p12].tv, mintime); + + VECADDS(triB[0], collmd->current_x[edgecollpair.p21].co, collmd->current_v[edgecollpair.p21].co, mintime); + VECADDS(triB[1], collmd->current_x[edgecollpair.p22].co, collmd->current_v[edgecollpair.p22].co, mintime); + // TODO: check for collisions - - // TODO: put into (edge) collision list + distance = edgedge_distance(triA[0], triA[1], triB[0], triB[1], &a, &b, out_normal); + if ((distance <= clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO) && (INPR(out_normal, out_normal) > 0)) + { + // printf("found edge, dist: %f\n", distance); + + /* Inelastic repulsion impulse. */ +/* + // Calculate which normal velocity we need. + float desiredVn = (normalVelocity * (float)solution[k] - (.1 * (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree )) - sqrt(squaredDistance)) - ALMOST_ZERO); + + // Now calculate what impulse we need to reach that velocity. + float m1 = interpolateOnEdge(cloth1.getVertexWeight(v11idx), cloth1.getVertexWeight(v12idx), a1); + float m2 = interpolateOnEdge(cloth2.getVertexWeight(v21idx), cloth2.getVertexWeight(v22idx), a2); + float I_mag = (normalVelocity - desiredVn) / (1/m1 + 1/m2); + + // Finally apply that impulse. + applyInterpolatedImpulsesEdge(out_impulses1[v11idx], out_impulses1[v12idx], out_impulses2[v21idx], out_impulses2[v22idx], + a1, a2, -I_mag, normal); + ++out_impulseCounter1[v11idx]; ++out_impulseCounter1[v12idx]; + ++out_impulseCounter2[v21idx]; ++out_impulseCounter2[v22idx]; + + */ // return true; + result = 1; + } + mintime = MIN2(mintime, (float)solution[k]); - - result = 1; + break; } } } } - +/* if(result) { // move triangles to collision point in time VECADDS(triA[0], verts1[collpair->ap1].txold, verts1[collpair->ap1].tv, mintime); VECADDS(triA[1], verts1[collpair->ap2].txold, verts1[collpair->ap2].tv, mintime); VECADDS(triA[2], verts1[collpair->ap3].txold, verts1[collpair->ap3].tv, mintime); - + VECADDS(triB[0], collmd->current_x[collpair->bp1].co, collmd->current_v[collpair->bp1].co, mintime); VECADDS(triB[1], collmd->current_x[collpair->bp2].co, collmd->current_v[collpair->bp2].co, mintime); VECADDS(triB[2], collmd->current_x[collpair->bp3].co, collmd->current_v[collpair->bp3].co, mintime); - + // check distance there distance = plNearestPoints (triA[0], triA[1], triA[2], triB[0], triB[1], triB[2], collpair->pa,collpair->pb,collpair->vector ); - + if(distance <= (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO)) { CollPair *next = collpair; next++; - + collpair->distance = clmd->coll_parms->epsilon; collpair->time = mintime; - + VECCOPY ( collpair->normal, collpair->vector ); Normalize ( collpair->normal ); - - cloth_collision_response_moving ( clmd, collmd, collpair, next ); + + // cloth_collision_response_moving ( clmd, collmd, collpair, next ); + } } - +*/ return result; } -/* -void cloth_collision_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 ) +int cloth_collision_moving_tris ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) { - CollPair collpair; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; + EdgeCollPair edgecollpair; + Cloth *cloth1=NULL; + ClothVertex *verts1=NULL; unsigned int i = 0, j = 0, k = 0; int numsolutions = 0; - float a[3], b[3], c[3], d[3], e[3], f[3]; + double x1[3], v1[3], x2[3], v2[3], x3[3], v3[3]; double solution[3]; + MVert *verts2 = collmd->current_x; // old x + MVert *velocity2 = collmd->current_v; // velocity + float mintime = FLT_MAX; + float distance; + float triA[3][3], triB[3][3]; + int result = 0; - 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++; - } + cloth1 = clmd->clothObject; + verts1 = cloth1->verts; - // calc SIPcode (?) + for(i = 0; i < 9; i++) + { + // 9 edge - edge possibilities - if ( i < 2 ) + if(i == 0) { - 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 = cloth_get_collision_time ( a, b, c, d, e, f, solution ); - - for ( k = 0; k < numsolutions; k++ ) - { - if ( ( solution[k] >= ALMOST_ZERO ) && ( 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 - } + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap2; + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp2; } } + + return result; } -*/ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { @@ -1145,10 +1339,11 @@ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *col // only handle moving collisions here if (!( collpair->flag & COLLISION_IN_FUTURE )) continue; - + cloth_collision_moving_edges ( clmd, collmd, collpair); + // cloth_collision_moving_tris ( clmd, collmd, collpair); } - + return 1; } @@ -1219,14 +1414,14 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count ); VECCOPY ( verts[i].impulse, tnull ); verts[i].impulse_count = 0; - + ret++; } } } - /* +/* result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); - + // apply impulses in parallel if ( result ) { @@ -1238,12 +1433,12 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count ); VECCOPY ( verts[i].impulse, tnull ); verts[i].impulse_count = 0; - + ret++; } } } - */ +*/ } } @@ -1371,24 +1566,25 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) if ( cloth->bvhselftree ) { - /* search for overlapping collision pairs */ + // search for overlapping collision pairs overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); +// #pragma omp parallel for private(k, i, j) schedule(static) for ( k = 0; k < result; k++ ) { float temp[3]; float length = 0; float mindistance; - + i = overlap[k].indexA; j = overlap[k].indexB; - + mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) { if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) + && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) { continue; } @@ -1427,87 +1623,18 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) VECSUB ( verts[i].tx, verts[i].tx, temp ); } + ret = 1; + } + else + { + // check for approximated time collisions } } - + if ( overlap ) MEM_freeN ( overlap ); - - } - /* - for ( count = 0; count < clmd->coll_parms->self_loop_count; count++ ) - { - if ( collisions ) - { - collisions = 0; - #pragma omp parallel for private(i,j, collisions) shared(verts, ret) - for ( i = 0; i < cloth->numverts; i++ ) - { - for ( j = i + 1; j < cloth->numverts; j++ ) - { - float temp[3]; - float length = 0; - float mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); - - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - { - if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) - { - continue; } - } - - VECSUB ( temp, verts[i].tx, verts[j].tx ); - - if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; - - // check for adjacent points (i must be smaller j) - if ( BLI_edgehash_haskey ( cloth->edgehash, i, j ) ) - { - continue; - } - - length = Normalize ( temp ); - - if ( length < mindistance ) - { - float correction = mindistance - length; - - if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, -correction ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - } - else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, correction ); - VECADD ( verts[i].tx, verts[i].tx, temp ); - } - else - { - VecMulf ( temp, -correction*0.5 ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - - VECSUB ( verts[i].tx, verts[i].tx, temp ); - } - - collisions = 1; - - if ( !ret ) - { - #pragma omp critical - { - ret = 1; - } - } - } - } - } - } - } - */ //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// @@ -1517,8 +1644,10 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) { for ( i = 0; i < cloth->numverts; i++ ) { - if ( ! ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) + if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) + { VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold ); + } } } //////////////////////////////////////////////////////////// @@ -1528,3 +1657,15 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) return MIN2 ( ret, 1 ); } + + +/* +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; + + ret++; +} +*/ \ No newline at end of file -- cgit v1.2.3 From 391c7615d19561555ab29c090fcfd56447942548 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 26 May 2008 10:36:14 +0000 Subject: -= Collisions =- 1. fix for collisions (were working better with selfcolls enabled, now generally better) --- source/blender/blenkernel/intern/collision.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index edf8fec9ae1..0b291aaa695 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1458,7 +1458,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) long i=0, j = 0, k = 0, numfaces = 0, numverts = 0; unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; - int ret = 0; + int ret = 0, ret2 = 0; ClothModifierData *tclmd; int collisions = 0, count = 0; @@ -1484,6 +1484,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) do { result = 0; + ret2 = 0; // check all collision objects for ( base = G.scene->base.first; base; base = base->next ) @@ -1512,6 +1513,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) continue; ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt ); + ret2 += ret; } } } @@ -1522,6 +1524,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) continue; ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt ); + ret2 += ret; } } rounds++; @@ -1624,6 +1627,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) VECSUB ( verts[i].tx, verts[i].tx, temp ); } ret = 1; + ret2 += ret; } else { @@ -1640,7 +1644,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// // SELFCOLLISIONS: update velocities //////////////////////////////////////////////////////////// - if ( ret ) + if ( ret2 ) { for ( i = 0; i < cloth->numverts; i++ ) { @@ -1653,7 +1657,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// } } - while ( result && ( clmd->coll_parms->loop_count>rounds ) ); + while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) ); return MIN2 ( ret, 1 ); } -- cgit v1.2.3 From ed42c9a6768712c1eeba3b36af09620f668d663b Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 27 May 2008 22:46:57 +0000 Subject: -= Collisions -= 1. Test for fast moving edges --- source/blender/blenkernel/intern/collision.c | 102 +++++++++++++++------------ 1 file changed, 56 insertions(+), 46 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 0b291aaa695..37784b43cf9 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -498,6 +498,7 @@ DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float VECADDMUL ( to, v3, w3 ); } + int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { int result = 0; @@ -1189,8 +1190,16 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat edgecollpair.p22 = collpair->bp3; } + if((edgecollpair.p11 == 3) && (edgecollpair.p12 == 6)) + printf("Ahier!\n"); + if((edgecollpair.p11 == 6) && (edgecollpair.p12 == 3)) + printf("Ahier!\n"); + if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) ) { + // printf("Collision between:\n"); + // printf("p11: %d, p12: %d, p21: %d, p22: %d\n", edgecollpair.p11, edgecollpair.p12, edgecollpair.p21, edgecollpair.p22); + // always put coll points in p21/p22 VECSUB ( x1, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold ); VECSUB ( v1, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv ); @@ -1206,11 +1215,14 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat for ( k = 0; k < numsolutions; k++ ) { // printf("sol %d: %lf\n", k, solution[k]); - if ( ( solution[k] >= DBL_EPSILON ) && ( solution[k] <= 1.0 ) ) + if ( ( solution[k] >= ALMOST_ZERO ) && ( solution[k] <= 1.0 ) && ( solution[k] > ALMOST_ZERO)) { float a,b; float out_normal[3]; float distance; + float impulse = 0; + float I_mag; + float m1, m2; // move verts VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, mintime); @@ -1224,28 +1236,57 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat if ((distance <= clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO) && (INPR(out_normal, out_normal) > 0)) { - // printf("found edge, dist: %f\n", distance); + float vrel_1_to_2[3], temp[3], temp2[3], out_normalVelocity; + float desiredVn; + + VECCOPY(vrel_1_to_2, verts1[edgecollpair.p11].tv); + VecMulf(vrel_1_to_2, 1.0 - a); + VECCOPY(temp, verts1[edgecollpair.p12].tv); + VecMulf(temp, a); + + VECADD(vrel_1_to_2, vrel_1_to_2, temp); + + VECCOPY(temp, verts1[edgecollpair.p21].tv); + VecMulf(temp, 1.0 - b); + VECCOPY(temp2, verts1[edgecollpair.p22].tv); + VecMulf(temp2, b); + VECADD(temp, temp, temp2); + + VECSUB(vrel_1_to_2, vrel_1_to_2, temp); + + out_normalVelocity = INPR(vrel_1_to_2, out_normal); + + if(out_normalVelocity < 0.0) + { + out_normalVelocity*= -1.0; + VecMulf(out_normal, -1.0); + } /* Inelastic repulsion impulse. */ -/* + // Calculate which normal velocity we need. - float desiredVn = (normalVelocity * (float)solution[k] - (.1 * (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree )) - sqrt(squaredDistance)) - ALMOST_ZERO); + desiredVn = (out_normalVelocity * (float)solution[k] - (.1 * (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree )) - sqrt(distance)) - ALMOST_ZERO); // Now calculate what impulse we need to reach that velocity. - float m1 = interpolateOnEdge(cloth1.getVertexWeight(v11idx), cloth1.getVertexWeight(v12idx), a1); - float m2 = interpolateOnEdge(cloth2.getVertexWeight(v21idx), cloth2.getVertexWeight(v22idx), a2); - float I_mag = (normalVelocity - desiredVn) / (1/m1 + 1/m2); + I_mag = (out_normalVelocity - desiredVn) / 2.0; // / (1/m1 + 1/m2); // Finally apply that impulse. - applyInterpolatedImpulsesEdge(out_impulses1[v11idx], out_impulses1[v12idx], out_impulses2[v21idx], out_impulses2[v22idx], - a1, a2, -I_mag, normal); - ++out_impulseCounter1[v11idx]; ++out_impulseCounter1[v12idx]; - ++out_impulseCounter2[v21idx]; ++out_impulseCounter2[v22idx]; + impulse = (2.0 * -I_mag) / (a*a + (1.0-a)*(1.0-a) + b*b + (1.0-b)*(1.0-b)); + + VECADDMUL ( verts1[edgecollpair.p11].impulse, out_normal, (1.0-a) * impulse ); + verts1[edgecollpair.p11].impulse_count++; + + VECADDMUL ( verts1[edgecollpair.p12].impulse, out_normal, a * impulse ); + verts1[edgecollpair.p12].impulse_count++; - */ // return true; + // return true; result = 1; + break; + } + else + { + // missing from collision.hpp } - mintime = MIN2(mintime, (float)solution[k]); break; @@ -1253,37 +1294,6 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat } } } -/* - if(result) - { - // move triangles to collision point in time - VECADDS(triA[0], verts1[collpair->ap1].txold, verts1[collpair->ap1].tv, mintime); - VECADDS(triA[1], verts1[collpair->ap2].txold, verts1[collpair->ap2].tv, mintime); - VECADDS(triA[2], verts1[collpair->ap3].txold, verts1[collpair->ap3].tv, mintime); - - VECADDS(triB[0], collmd->current_x[collpair->bp1].co, collmd->current_v[collpair->bp1].co, mintime); - VECADDS(triB[1], collmd->current_x[collpair->bp2].co, collmd->current_v[collpair->bp2].co, mintime); - VECADDS(triB[2], collmd->current_x[collpair->bp3].co, collmd->current_v[collpair->bp3].co, mintime); - - // check distance there - distance = plNearestPoints (triA[0], triA[1], triA[2], triB[0], triB[1], triB[2], collpair->pa,collpair->pb,collpair->vector ); - - if(distance <= (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO)) - { - CollPair *next = collpair; - next++; - - collpair->distance = clmd->coll_parms->epsilon; - collpair->time = mintime; - - VECCOPY ( collpair->normal, collpair->vector ); - Normalize ( collpair->normal ); - - // cloth_collision_response_moving ( clmd, collmd, collpair, next ); - - } - } -*/ return result; } @@ -1419,7 +1429,7 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData } } } -/* + result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); // apply impulses in parallel @@ -1438,7 +1448,7 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData } } } -*/ + } } -- cgit v1.2.3 From f1d54f892b7480b746b6423d4388455fe7ede2b9 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 29 May 2008 14:23:08 +0000 Subject: -= Collisions =- Getting some weird results on moving fast edges. This is a backup commit, will try another thing --- source/blender/blenkernel/intern/collision.c | 123 ++++++++++++++------------- 1 file changed, 64 insertions(+), 59 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 37784b43cf9..36cc37eab44 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -388,8 +388,8 @@ int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3 printf("v3 x: %f, y: %f, z: %f\n", f[0], f[1], f[2]); printf("t^3: %lf, t^2: %lf, t^1: %lf, t^0: %lf\n", j, i, h, g); - */ - + +*/ // Solve cubic equation to determine times t1, t2, t3, when the collision will occur. if ( ABS ( j ) > DBL_EPSILON ) { @@ -453,6 +453,7 @@ int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3 return num_sols; } + // w3 is not perfect void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 ) { @@ -713,50 +714,41 @@ CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap } else { - // check for collision in the future - collpair->flag |= COLLISION_IN_FUTURE; - } - collpair++; - } - return collpair; -} - -int cloth_are_edges_adjacent ( ClothModifierData *clmd, CollisionModifierData *collmd, EdgeCollPair *edgecollpair ) -{ - Cloth *cloth1 = NULL; - ClothVertex *verts1 = NULL; - float temp[3]; - MVert *verts2 = collmd->current_x; // old x - - cloth1 = clmd->clothObject; - verts1 = cloth1->verts; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; - VECSUB ( temp, verts1[edgecollpair->p11].txold, verts2[edgecollpair->p21].co ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; - - VECSUB ( temp, verts1[edgecollpair->p11].txold, verts2[edgecollpair->p22].co ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; - - VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p21].co ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; + // calc relative velocity + + // compute barycentric coordinates for both collision points + collision_compute_barycentric ( collpair->pa, + verts1[collpair->ap1].txold, + verts1[collpair->ap2].txold, + verts1[collpair->ap3].txold, + &w1, &w2, &w3 ); - VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p22].co ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; + // was: txold + collision_compute_barycentric ( collpair->pb, + collmd->current_x[collpair->bp1].co, + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, + &u1, &u2, &u3 ); - VECSUB ( temp, verts1[edgecollpair->p11].txold, verts1[edgecollpair->p12].txold ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; + // Calculate relative "velocity". + collision_interpolateOnTriangle ( v1, verts1[collpair->ap1].tv, verts1[collpair->ap2].tv, verts1[collpair->ap3].tv, w1, w2, w3 ); - VECSUB ( temp, verts2[edgecollpair->p21].co, verts2[edgecollpair->p22].co ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; + collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 ); + VECSUB ( relativeVelocity, v2, v1 ); - return 0; + if(sqrt(INPR(relativeVelocity, relativeVelocity)) >= distance) + { + // check for collision in the future + collpair->flag |= COLLISION_IN_FUTURE; + } + } + collpair++; + } + return collpair; } int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) @@ -879,13 +871,18 @@ static float projectPointOntoLine(float *p, float *a, float *b) static void calculateEENormal(float *np1, float *np2, float *np3, float *np4,float *out_normal) { - float line1[33], line2[3]; + float line1[3], line2[3]; float length; VECSUB(line1, np2, np1); VECSUB(line2, np3, np1); + // printf("l1: %f, l1: %f, l2: %f, l2: %f\n", line1[0], line1[1], line2[0], line2[1]); + Crossf(out_normal, line1, line2); + + + length = Normalize(out_normal); if (length <= FLT_EPSILON) { // lines are collinear @@ -1102,10 +1099,9 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat unsigned int i = 0, j = 0, k = 0; int numsolutions = 0; double x1[3], v1[3], x2[3], v2[3], x3[3], v3[3]; - double solution[3]; + double solution[3], solution2[3]; MVert *verts2 = collmd->current_x; // old x MVert *velocity2 = collmd->current_v; // velocity - float mintime = FLT_MAX; float distance; float triA[3][3], triB[3][3]; int result = 0; @@ -1189,17 +1185,15 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp3; } - - if((edgecollpair.p11 == 3) && (edgecollpair.p12 == 6)) + /* + if((edgecollpair.p11 == 3) && (edgecollpair.p12 == 16)) printf("Ahier!\n"); - if((edgecollpair.p11 == 6) && (edgecollpair.p12 == 3)) + if((edgecollpair.p11 == 16) && (edgecollpair.p12 == 3)) printf("Ahier!\n"); + */ - if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) ) + // if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) ) { - // printf("Collision between:\n"); - // printf("p11: %d, p12: %d, p21: %d, p22: %d\n", edgecollpair.p11, edgecollpair.p12, edgecollpair.p21, edgecollpair.p22); - // always put coll points in p21/p22 VECSUB ( x1, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold ); VECSUB ( v1, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv ); @@ -1212,6 +1206,16 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution ); + if((edgecollpair.p11 == 3 && edgecollpair.p12==16)|| (edgecollpair.p11==16 && edgecollpair.p12==3)) + { + if(edgecollpair.p21==6 || edgecollpair.p22 == 6) + { + printf("dist: %f, sol[k]: %lf, sol2[k]: %lf\n", distance, solution[k], solution2[k]); + printf("a1: %f, a2: %f, b1: %f, b2: %f\n", x1[0], x2[0], x3[0], v1[0]); + printf("b21: %d, b22: %d\n", edgecollpair.p21, edgecollpair.p22); + } + } + for ( k = 0; k < numsolutions; k++ ) { // printf("sol %d: %lf\n", k, solution[k]); @@ -1225,11 +1229,11 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat float m1, m2; // move verts - VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, mintime); - VECADDS(triA[1], verts1[edgecollpair.p12].txold, verts1[edgecollpair.p12].tv, mintime); + VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, solution[k]); + VECADDS(triA[1], verts1[edgecollpair.p12].txold, verts1[edgecollpair.p12].tv, solution[k]); - VECADDS(triB[0], collmd->current_x[edgecollpair.p21].co, collmd->current_v[edgecollpair.p21].co, mintime); - VECADDS(triB[1], collmd->current_x[edgecollpair.p22].co, collmd->current_v[edgecollpair.p22].co, mintime); + VECADDS(triB[0], collmd->current_x[edgecollpair.p21].co, collmd->current_v[edgecollpair.p21].co, solution[k]); + VECADDS(triB[1], collmd->current_x[edgecollpair.p22].co, collmd->current_v[edgecollpair.p22].co, solution[k]); // TODO: check for collisions distance = edgedge_distance(triA[0], triA[1], triB[0], triB[1], &a, &b, out_normal); @@ -1255,13 +1259,14 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat VECSUB(vrel_1_to_2, vrel_1_to_2, temp); out_normalVelocity = INPR(vrel_1_to_2, out_normal); - +/* + // this correction results in wrong normals sometimes? if(out_normalVelocity < 0.0) { out_normalVelocity*= -1.0; VecMulf(out_normal, -1.0); } - +*/ /* Inelastic repulsion impulse. */ // Calculate which normal velocity we need. @@ -1287,7 +1292,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { // missing from collision.hpp } - mintime = MIN2(mintime, (float)solution[k]); + // mintime = MIN2(mintime, (float)solution[k]); break; } @@ -1429,7 +1434,7 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData } } } - +/* result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); // apply impulses in parallel @@ -1448,7 +1453,7 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData } } } - +*/ } } -- cgit v1.2.3 From 0c0c43f62001eb652b8a8c374cca390824ef2c5e Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 3 Jun 2008 19:06:54 +0000 Subject: Collision commit code cleanup for nicer compile --- source/blender/blenkernel/intern/collision.c | 97 ++-------------------------- 1 file changed, 6 insertions(+), 91 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 36cc37eab44..fc9a8132aaf 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -51,34 +51,6 @@ #include "BLI_kdopbvh.h" #include "BKE_collision.h" -#ifdef _WIN32 -static void start ( void ) -{} -static void end ( void ) -{ -} -static double val() -{ - return 0; -} -#else -#include -static void mystart ( struct timeval *start, struct timezone *z ) -{ - gettimeofday ( start, z ); -} -static void myend ( struct timeval *end, struct timezone *z ) -{ - gettimeofday ( end,z ); -} -static double myval ( struct timeval *start, struct timeval *end ) -{ - double t1, t2; - t1 = ( double ) start->tv_sec + ( double ) start->tv_usec/ ( 1000*1000 ); - t2 = ( double ) end->tv_sec + ( double ) end->tv_usec/ ( 1000*1000 ); - return t2-t1; -} -#endif /*********************************** Collision modifier code start @@ -758,7 +730,6 @@ int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierD float w1, w2, w3, u1, u2, u3; float v1[3], v2[3], relativeVelocity[3]; float magrelVel; - float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); cloth1 = clmd->clothObject; @@ -797,7 +768,7 @@ int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierD if ( magrelVel > ALMOST_ZERO ) { // Calculate Impulse magnitude to stop all motion in normal direction. - float magtangent = 0, repulse = 0, d = 0; + float magtangent = 0; double impulse = 0.0; float vrel_t_pre[3]; float temp[3]; @@ -1096,13 +1067,13 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat EdgeCollPair edgecollpair; Cloth *cloth1=NULL; ClothVertex *verts1=NULL; - unsigned int i = 0, j = 0, k = 0; + unsigned int i = 0, k = 0; int numsolutions = 0; double x1[3], v1[3], x2[3], v2[3], x3[3], v3[3]; double solution[3], solution2[3]; MVert *verts2 = collmd->current_x; // old x MVert *velocity2 = collmd->current_v; // velocity - float distance; + float distance = 0; float triA[3][3], triB[3][3]; int result = 0; @@ -1226,7 +1197,6 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat float distance; float impulse = 0; float I_mag; - float m1, m2; // move verts VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, solution[k]); @@ -1302,51 +1272,9 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat return result; } -int cloth_collision_moving_tris ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) -{ - EdgeCollPair edgecollpair; - Cloth *cloth1=NULL; - ClothVertex *verts1=NULL; - unsigned int i = 0, j = 0, k = 0; - int numsolutions = 0; - double x1[3], v1[3], x2[3], v2[3], x3[3], v3[3]; - double solution[3]; - MVert *verts2 = collmd->current_x; // old x - MVert *velocity2 = collmd->current_v; // velocity - float mintime = FLT_MAX; - float distance; - float triA[3][3], triB[3][3]; - int result = 0; - - cloth1 = clmd->clothObject; - verts1 = cloth1->verts; - - for(i = 0; i < 9; i++) - { - // 9 edge - edge possibilities - - if(i == 0) - { - edgecollpair.p11 = collpair->ap1; - edgecollpair.p12 = collpair->ap2; - - edgecollpair.p21 = collpair->bp1; - edgecollpair.p22 = collpair->bp2; - } - } - - return result; -} - int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { - int result = 0; Cloth *cloth1; - float w1, w2, w3, u1, u2, u3; - float v1[3], v2[3], relativeVelocity[3]; - float magrelVel; - float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); - cloth1 = clmd->clothObject; for ( ; collpair != collision_end; collpair++ ) @@ -1471,11 +1399,11 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) Object *coll_ob=NULL; BVHTree *cloth_bvh=NULL; long i=0, j = 0, k = 0, numfaces = 0, numverts = 0; - unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; + int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0, ret2 = 0; ClothModifierData *tclmd; - int collisions = 0, count = 0; + int collisions = 0; if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->bvhtree ) ) { @@ -1570,8 +1498,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { - - MFace *mface = cloth->mfaces; + // TODO: add coll quality rounds again BVHTreeOverlap *overlap = NULL; collisions = 1; @@ -1676,15 +1603,3 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) return MIN2 ( ret, 1 ); } - - -/* -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; - - ret++; -} -*/ \ No newline at end of file -- cgit v1.2.3 From 3d51c59034be1c3410ab5d2224cb0ef3b35f0ea1 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 5 Jun 2008 10:52:52 +0000 Subject: Bugfix for exploding cloth collisions --- source/blender/blenkernel/intern/collision.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index fc9a8132aaf..1809617fb3c 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -683,7 +683,8 @@ CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap collpair->distance = distance; collpair->flag = 0; - } + collpair++; + }/* else { float w1, w2, w3, u1, u2, u3; @@ -716,9 +717,9 @@ CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap { // check for collision in the future collpair->flag |= COLLISION_IN_FUTURE; + collpair++; } - } - collpair++; + }*/ } return collpair; } -- cgit v1.2.3 From fcdbd766257f09c04470f8d24ff5f9576a76f531 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 5 Jun 2008 11:08:51 +0000 Subject: Collisions: enabling self collision quality setting again (request by Nudel) --- source/blender/blenkernel/intern/collision.c | 141 ++++++++++++++------------- 1 file changed, 72 insertions(+), 69 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 1809617fb3c..7f41ca033d3 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1399,7 +1399,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) Cloth *cloth=NULL; Object *coll_ob=NULL; BVHTree *cloth_bvh=NULL; - long i=0, j = 0, k = 0, numfaces = 0, numverts = 0; + long i=0, j = 0, k = 0, l = 0, numfaces = 0, numverts = 0; int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0, ret2 = 0; @@ -1499,88 +1499,91 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { - // TODO: add coll quality rounds again - BVHTreeOverlap *overlap = NULL; - - collisions = 1; - verts = cloth->verts; // needed for openMP - - numfaces = clmd->clothObject->numfaces; - numverts = clmd->clothObject->numverts; - - verts = cloth->verts; - - if ( cloth->bvhselftree ) + for(l = 0; l < clmd->coll_parms->self_loop_count; l++) { - // search for overlapping collision pairs - overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); - -// #pragma omp parallel for private(k, i, j) schedule(static) - for ( k = 0; k < result; k++ ) + // TODO: add coll quality rounds again + BVHTreeOverlap *overlap = NULL; + + collisions = 1; + verts = cloth->verts; // needed for openMP + + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + + verts = cloth->verts; + + if ( cloth->bvhselftree ) { - float temp[3]; - float length = 0; - float mindistance; - - i = overlap[k].indexA; - j = overlap[k].indexB; - - mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); - - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + // search for overlapping collision pairs + overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); + + // #pragma omp parallel for private(k, i, j) schedule(static) + for ( k = 0; k < result; k++ ) { - if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) + float temp[3]; + float length = 0; + float mindistance; + + i = overlap[k].indexA; + j = overlap[k].indexB; + + mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); + + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) { - continue; + if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) + { + continue; + } } - } - - VECSUB ( temp, verts[i].tx, verts[j].tx ); - - if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; - - // check for adjacent points (i must be smaller j) - if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) - { - continue; - } - - length = Normalize ( temp ); - - if ( length < mindistance ) - { - float correction = mindistance - length; - - if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + + VECSUB ( temp, verts[i].tx, verts[j].tx ); + + if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; + + // check for adjacent points (i must be smaller j) + if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) { - VecMulf ( temp, -correction ); - VECADD ( verts[j].tx, verts[j].tx, temp ); + continue; } - else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) + + length = Normalize ( temp ); + + if ( length < mindistance ) { - VecMulf ( temp, correction ); - VECADD ( verts[i].tx, verts[i].tx, temp ); + float correction = mindistance - length; + + if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, -correction ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + } + else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, correction ); + VECADD ( verts[i].tx, verts[i].tx, temp ); + } + else + { + VecMulf ( temp, -correction*0.5 ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + + VECSUB ( verts[i].tx, verts[i].tx, temp ); + } + ret = 1; + ret2 += ret; } else { - VecMulf ( temp, -correction*0.5 ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - - VECSUB ( verts[i].tx, verts[i].tx, temp ); + // check for approximated time collisions } - ret = 1; - ret2 += ret; - } - else - { - // check for approximated time collisions } + + if ( overlap ) + MEM_freeN ( overlap ); + } - - if ( overlap ) - MEM_freeN ( overlap ); - } //////////////////////////////////////////////////////////// -- cgit v1.2.3 From 8ca128414ddbe73bf31755df6cf19e5c70aba99c Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 2 Jul 2008 20:28:49 +0000 Subject: Cloth collisions: Reorganized collision system to be more flexible for other parts of blender, so it can be more easily reused. Also slowed down friction impulse. --- source/blender/blenkernel/intern/collision.c | 467 +++++++++++++++------------ 1 file changed, 261 insertions(+), 206 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 7f41ca033d3..26c5d186d87 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -541,7 +541,7 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier { Normalize ( vrel_t_pre ); - impulse = 2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); + impulse = magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // 2.0 * VECADDMUL ( cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse ); VECADDMUL ( cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse ); VECADDMUL ( cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse ); @@ -1291,52 +1291,223 @@ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *col return 1; } -int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData *collmd, float step, float dt ) -{ +int cloth_do_selfcollisions(ClothModifierData * clmd) +{ + int ret2 = 0, l; Cloth *cloth = clmd->clothObject; - BVHTree *cloth_bvh= ( BVHTree * ) cloth->bvhtree; - long i=0, j = 0, numfaces = 0, numverts = 0; - ClothVertex *verts = NULL; - CollPair *collisions = NULL, *collisions_index = NULL; - int ret = 0; - int result = 0; - float tnull[3] = {0,0,0}; - BVHTreeOverlap *overlap = NULL; - - - numfaces = clmd->clothObject->numfaces; - numverts = clmd->clothObject->numverts; - - verts = cloth->verts; + + if ( clmd->clothObject->bvhselftree ) + { + for(l = 0; l < clmd->coll_parms->self_loop_count; l++) + { + BVHTreeOverlap *overlap = NULL; + ClothVertex *verts = clmd->clothObject->verts; // needed for openMP + int k; + int ret = 0, result = 0; + + // search for overlapping collision pairs + overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); + +// #pragma omp parallel for private(k, i, j) schedule(static) + for ( k = 0; k < result; k++ ) + { + float temp[3]; + float length = 0; + float mindistance; + int i, j; + + i = overlap[k].indexA; + j = overlap[k].indexB; + + mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); + + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + { + if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) + { + continue; + } + } + + VECSUB ( temp, verts[i].tx, verts[j].tx ); + + if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; + + // check for adjacent points (i must be smaller j) + if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) + { + continue; + } + + length = Normalize ( temp ); + + if ( length < mindistance ) + { + float correction = mindistance - length; + + if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, -correction ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + } + else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, correction ); + VECADD ( verts[i].tx, verts[i].tx, temp ); + } + else + { + VecMulf ( temp, -correction*0.5 ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + + VECSUB ( verts[i].tx, verts[i].tx, temp ); + } + ret = 1; + ret2 += ret; + } + else + { + // check for approximated time collisions + } + } + + if ( overlap ) + MEM_freeN ( overlap ); + + if(!ret) + break; + + } + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // SELFCOLLISIONS: update velocities + //////////////////////////////////////////////////////////// + if ( ret2 ) + { + int i; + ClothVertex *verts = clmd->clothObject->verts; // needed for openMP + + for ( i = 0; i < cloth->numverts; i++ ) + { + if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) + { + VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold ); + } + } + } + //////////////////////////////////////////////////////////// + } + return ret2; +} - if ( collmd->bvhtree ) +// return all collision objects in scene +// collision object will exclude self +CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) +{ + Base *base=NULL; + CollisionModifierData **objs = NULL; + Object *coll_ob = NULL; + CollisionModifierData *collmd = NULL; + int numobj = 0, maxobj = 100; + + objs = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); + // check all collision objects + for ( base = G.scene->base.first; base; base = base->next ) { - /* get pointer to bounding volume hierarchy */ - BVHTree *coll_bvh = collmd->bvhtree; + coll_ob = base->object; + collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); + + if ( !collmd ) + { + if ( coll_ob->dup_group ) + { + GroupObject *go; + Group *group = coll_ob->dup_group; - /* move object to position (step) in time */ - collision_move_object ( collmd, step + dt, step ); + for ( go= group->gobject.first; go; go= go->next ) + { + coll_ob = go->ob; - /* search for overlapping collision pairs */ - overlap = BLI_bvhtree_overlap ( cloth_bvh, coll_bvh, &result ); + collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); - collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * result*4, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision - collisions_index = collisions; + if ( !collmd ) + continue; - for ( i = 0; i < result; i++ ) - { - collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, overlap+i, collisions_index ); - } + if(coll_ob == self) + continue; - if ( overlap ) - MEM_freeN ( overlap ); + if(numobj >= maxobj) + { + // realloc + int oldmax = maxobj; + CollisionModifierData **tmp; + maxobj *= 2; + tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); + memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax); + MEM_freeN(objs); + objs = tmp; + } + + objs[numobj] = collmd; + numobj++; + } + } + } + else + { + if(coll_ob == self) + continue; + + if(numobj >= maxobj) + { + // realloc + int oldmax = maxobj; + CollisionModifierData **tmp; + maxobj *= 2; + tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); + memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax); + MEM_freeN(objs); + objs = tmp; + + } + + objs[numobj] = collmd; + numobj++; + } } - else + *numcollobj = numobj; + return objs; +} + +void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap) +{ + int i; + + *collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * numresult * 4, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision + *collisions_index = *collisions; + + for ( i = 0; i < numresult; i++ ) { - if ( G.rt > 0 ) - printf ( "cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n" ); + *collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, overlap+i, *collisions_index ); } +} +int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index) +{ + Cloth *cloth = clmd->clothObject; + int i=0, j = 0, numfaces = 0, numverts = 0; + ClothVertex *verts = NULL; + int ret = 0; + int result = 0; + float tnull[3] = {0,0,0}; + + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + + verts = cloth->verts; + // process all collisions (calculate impulses, TODO: also repulses if distance too short) result = 1; for ( j = 0; j < 5; j++ ) // 5 is just a value that ensures convergence @@ -1363,48 +1534,22 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData } } } -/* - result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); - - // apply impulses in parallel - if ( result ) - { - 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; - - ret++; - } - } - } -*/ } } - - if ( collisions ) MEM_freeN ( collisions ); - return ret; } // cloth - object collisions -int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) +int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, float dt ) { - Base *base=NULL; - CollisionModifierData *collmd=NULL; Cloth *cloth=NULL; - Object *coll_ob=NULL; BVHTree *cloth_bvh=NULL; - long i=0, j = 0, k = 0, l = 0, numfaces = 0, numverts = 0; - int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; + long i=0, numfaces = 0, numverts = 0; + int rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0, ret2 = 0; - ClothModifierData *tclmd; - int collisions = 0; + CollisionModifierData **collobjs = NULL; + int numcollobj = 0; if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->bvhtree ) ) { @@ -1424,54 +1569,61 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) // update cloth bvh bvhtree_update_from_cloth ( clmd, 1 ); // 0 means STATIC, 1 means MOVING (see later in this function) bvhselftree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) + + collobjs = get_collisionobjects(ob, &numcollobj); + + if(!collobjs) + return 0; do { - result = 0; + CollPair **collisions, **collisions_index; + ret2 = 0; + collisions = MEM_callocN(sizeof(CollPair *) *numcollobj , "CollPair"); + collisions_index = MEM_callocN(sizeof(CollPair *) *numcollobj , "CollPair"); + // check all collision objects - for ( base = G.scene->base.first; base; base = base->next ) + for(i = 0; i < numcollobj; i++) { - coll_ob = base->object; - collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); - - if ( !collmd ) - { - if ( coll_ob->dup_group ) - { - GroupObject *go; - Group *group = coll_ob->dup_group; - - for ( go= group->gobject.first; go; go= go->next ) - { - coll_ob = go->ob; - - collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); - - if ( !collmd ) - continue; - - tclmd = ( ClothModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Cloth ); - if ( tclmd == clmd ) - continue; - - ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt ); - ret2 += ret; - } - } - } - else + CollisionModifierData *collmd = collobjs[i]; + BVHTreeOverlap *overlap = NULL; + int result = 0; + + /* move object to position (step) in time */ + collision_move_object ( collmd, step + dt, step ); + + /* search for overlapping collision pairs */ + overlap = BLI_bvhtree_overlap ( cloth_bvh, collmd->bvhtree, &result ); + + // go to next object if no overlap is there + if(!result || !overlap) { - tclmd = ( ClothModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Cloth ); - if ( tclmd == clmd ) - continue; - - ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt ); - ret2 += ret; + if ( overlap ) + MEM_freeN ( overlap ); + continue; } + + /* check if collisions really happen (costly near check) */ + cloth_bvh_objcollisions_nearcheck ( clmd, collmd, &collisions[i], &collisions_index[i], result, overlap); + + // resolve nearby collisions + ret += cloth_bvh_objcollisions_resolve ( clmd, collmd, collisions[i], collisions_index[i]); + ret2 += ret; + + if ( overlap ) + MEM_freeN ( overlap ); } rounds++; + + for(i = 0; i < numcollobj; i++) + { + if ( collisions[i] ) MEM_freeN ( collisions[i] ); + } + + MEM_freeN(collisions); + MEM_freeN(collisions_index); //////////////////////////////////////////////////////////// // update positions @@ -1493,117 +1645,20 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) } //////////////////////////////////////////////////////////// - + //////////////////////////////////////////////////////////// // Test on *simple* selfcollisions //////////////////////////////////////////////////////////// if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { - for(l = 0; l < clmd->coll_parms->self_loop_count; l++) - { - // TODO: add coll quality rounds again - BVHTreeOverlap *overlap = NULL; - - collisions = 1; - verts = cloth->verts; // needed for openMP - - numfaces = clmd->clothObject->numfaces; - numverts = clmd->clothObject->numverts; - - verts = cloth->verts; - - if ( cloth->bvhselftree ) - { - // search for overlapping collision pairs - overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); - - // #pragma omp parallel for private(k, i, j) schedule(static) - for ( k = 0; k < result; k++ ) - { - float temp[3]; - float length = 0; - float mindistance; - - i = overlap[k].indexA; - j = overlap[k].indexB; - - mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); - - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - { - if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) - { - continue; - } - } - - VECSUB ( temp, verts[i].tx, verts[j].tx ); - - if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; - - // check for adjacent points (i must be smaller j) - if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) - { - continue; - } - - length = Normalize ( temp ); - - if ( length < mindistance ) - { - float correction = mindistance - length; - - if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, -correction ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - } - else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, correction ); - VECADD ( verts[i].tx, verts[i].tx, temp ); - } - else - { - VecMulf ( temp, -correction*0.5 ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - - VECSUB ( verts[i].tx, verts[i].tx, temp ); - } - ret = 1; - ret2 += ret; - } - else - { - // check for approximated time collisions - } - } - - if ( overlap ) - MEM_freeN ( overlap ); - - } - } - //////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////// - // SELFCOLLISIONS: update velocities - //////////////////////////////////////////////////////////// - if ( ret2 ) - { - for ( i = 0; i < cloth->numverts; i++ ) - { - if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) - { - VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold ); - } - } - } - //////////////////////////////////////////////////////////// + ret2 += cloth_do_selfcollisions(clmd); } + //////////////////////////////////////////////////////////// } while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) ); + + if(collobjs) + + MEM_freeN(collobjs); return MIN2 ( ret, 1 ); } -- cgit v1.2.3 From e0fc591697b5948aed097e7527b8adce4e280abb Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 20 Jul 2008 21:05:48 +0000 Subject: Fix for crash in collisions (introduced *after* 2.46 with my collision recode) --- source/blender/blenkernel/intern/collision.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 26c5d186d87..6dfb77504fb 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1437,6 +1437,9 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) if(coll_ob == self) continue; + + if( !collmd->bvhtree) + continue; if(numobj >= maxobj) { -- cgit v1.2.3 From 039814f7d22b05225b66da7135639712e865ef9a Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 29 Jul 2008 18:07:06 +0000 Subject: No long needed here (win64 cleanup) --- source/blender/blenkernel/intern/collision.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 6dfb77504fb..5b3cec25772 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1547,7 +1547,7 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f { Cloth *cloth=NULL; BVHTree *cloth_bvh=NULL; - long i=0, numfaces = 0, numverts = 0; + int i=0, numfaces = 0, numverts = 0; int rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0, ret2 = 0; -- cgit v1.2.3 From ad2be5f64f6f37f3e6591aadc2a4e4a4c4026bd9 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 3 Aug 2008 01:00:51 +0000 Subject: Bugfix for weird + in the code, no idea why it compiled (yet some selfcollision bug to fix) [no 2.47 fix] --- source/blender/blenkernel/intern/collision.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 5b3cec25772..e6dcc82e129 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1661,7 +1661,7 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) ); if(collobjs) - + MEM_freeN(collobjs); + MEM_freeN(collobjs); return MIN2 ( ret, 1 ); } -- cgit v1.2.3 From 1d49ed89cbbb8359a61eb2ced25f942825e129b0 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 3 Aug 2008 01:41:57 +0000 Subject: Bugfix for non working selfcollisions [no 2.47 bugfix] --- source/blender/blenkernel/intern/collision.c | 219 +++++++++++++-------------- 1 file changed, 105 insertions(+), 114 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index e6dcc82e129..cfcab54058d 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1291,116 +1291,6 @@ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *col return 1; } -int cloth_do_selfcollisions(ClothModifierData * clmd) -{ - int ret2 = 0, l; - Cloth *cloth = clmd->clothObject; - - if ( clmd->clothObject->bvhselftree ) - { - for(l = 0; l < clmd->coll_parms->self_loop_count; l++) - { - BVHTreeOverlap *overlap = NULL; - ClothVertex *verts = clmd->clothObject->verts; // needed for openMP - int k; - int ret = 0, result = 0; - - // search for overlapping collision pairs - overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); - -// #pragma omp parallel for private(k, i, j) schedule(static) - for ( k = 0; k < result; k++ ) - { - float temp[3]; - float length = 0; - float mindistance; - int i, j; - - i = overlap[k].indexA; - j = overlap[k].indexB; - - mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); - - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - { - if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) - { - continue; - } - } - - VECSUB ( temp, verts[i].tx, verts[j].tx ); - - if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; - - // check for adjacent points (i must be smaller j) - if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) - { - continue; - } - - length = Normalize ( temp ); - - if ( length < mindistance ) - { - float correction = mindistance - length; - - if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, -correction ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - } - else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, correction ); - VECADD ( verts[i].tx, verts[i].tx, temp ); - } - else - { - VecMulf ( temp, -correction*0.5 ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - - VECSUB ( verts[i].tx, verts[i].tx, temp ); - } - ret = 1; - ret2 += ret; - } - else - { - // check for approximated time collisions - } - } - - if ( overlap ) - MEM_freeN ( overlap ); - - if(!ret) - break; - - } - //////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////// - // SELFCOLLISIONS: update velocities - //////////////////////////////////////////////////////////// - if ( ret2 ) - { - int i; - ClothVertex *verts = clmd->clothObject->verts; // needed for openMP - - for ( i = 0; i < cloth->numverts; i++ ) - { - if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) - { - VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold ); - } - } - } - //////////////////////////////////////////////////////////// - } - return ret2; -} // return all collision objects in scene // collision object will exclude self @@ -1547,7 +1437,7 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f { Cloth *cloth=NULL; BVHTree *cloth_bvh=NULL; - int i=0, numfaces = 0, numverts = 0; + int i=0, numfaces = 0, numverts = 0, k, l, j; int rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0, ret2 = 0; @@ -1647,16 +1537,117 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f VECADD ( verts[i].tx, verts[i].txold, verts[i].tv ); } //////////////////////////////////////////////////////////// - + //////////////////////////////////////////////////////////// // Test on *simple* selfcollisions //////////////////////////////////////////////////////////// if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { - ret2 += cloth_do_selfcollisions(clmd); + for(l = 0; l < clmd->coll_parms->self_loop_count; l++) + { + // TODO: add coll quality rounds again + BVHTreeOverlap *overlap = NULL; + int result = 0; + + // collisions = 1; + verts = cloth->verts; // needed for openMP + + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + + verts = cloth->verts; + + if ( cloth->bvhselftree ) + { + // search for overlapping collision pairs + overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); + + // #pragma omp parallel for private(k, i, j) schedule(static) + for ( k = 0; k < result; k++ ) + { + float temp[3]; + float length = 0; + float mindistance; + + i = overlap[k].indexA; + j = overlap[k].indexB; + + mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); + + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + { + if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) + { + continue; + } + } + + VECSUB ( temp, verts[i].tx, verts[j].tx ); + + if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; + + // check for adjacent points (i must be smaller j) + if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) + { + continue; + } + + length = Normalize ( temp ); + + if ( length < mindistance ) + { + float correction = mindistance - length; + + if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, -correction ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + } + else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, correction ); + VECADD ( verts[i].tx, verts[i].tx, temp ); + } + else + { + VecMulf ( temp, -correction*0.5 ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + + VECSUB ( verts[i].tx, verts[i].tx, temp ); + } + ret = 1; + ret2 += ret; + } + else + { + // check for approximated time collisions + } + } + + if ( overlap ) + MEM_freeN ( overlap ); + + } + } + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // SELFCOLLISIONS: update velocities + //////////////////////////////////////////////////////////// + if ( ret2 ) + { + for ( i = 0; i < cloth->numverts; i++ ) + { + if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) + { + VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold ); + } + } + } + //////////////////////////////////////////////////////////// } - //////////////////////////////////////////////////////////// } while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) ); -- cgit v1.2.3 From 8562efe8a3f25c68251b080cae8c8c7e936bf476 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 18 Aug 2008 14:41:24 +0000 Subject: a) Forces can be hidden by deflector object now (need to talk with jahka about particle integration - should be copy-paste) see http://dldw.de/tmp/index.php?file=w2.blend (press play button in timeline and change the absorption value ob the cube) b) fixed deflector/collision bug with continues physics c) cloth wind/forces uses masses now d) even faster collision object gathering e) have fun ;) --- source/blender/blenkernel/intern/collision.c | 68 ++++++++++++++++------------ 1 file changed, 40 insertions(+), 28 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index cfcab54058d..b5e09d551f0 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -31,10 +31,11 @@ #include "BKE_cloth.h" -#include "DNA_group_types.h" -#include "DNA_object_types.h" #include "DNA_cloth_types.h" +#include "DNA_group_types.h" #include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" #include "DNA_scene_types.h" #include "BKE_DerivedMesh.h" @@ -1307,9 +1308,34 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) for ( base = G.scene->base.first; base; base = base->next ) { coll_ob = base->object; - collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); - - if ( !collmd ) + + if(coll_ob->pd && coll_ob->pd->deflect) + { + collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); + } + + if ( collmd ) + { + if(coll_ob == self) + continue; + + if(numobj >= maxobj) + { + // realloc + int oldmax = maxobj; + CollisionModifierData **tmp; + maxobj *= 2; + tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); + memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax); + MEM_freeN(objs); + objs = tmp; + + } + + objs[numobj] = collmd; + numobj++; + } + else { if ( coll_ob->dup_group ) { @@ -1319,8 +1345,12 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) for ( go= group->gobject.first; go; go= go->next ) { coll_ob = go->ob; - - collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); + collmd = NULL; + + if(coll_ob->pd && coll_ob->pd->deflect) + { + collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); + } if ( !collmd ) continue; @@ -1347,27 +1377,6 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) numobj++; } } - } - else - { - if(coll_ob == self) - continue; - - if(numobj >= maxobj) - { - // realloc - int oldmax = maxobj; - CollisionModifierData **tmp; - maxobj *= 2; - tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); - memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax); - MEM_freeN(objs); - objs = tmp; - - } - - objs[numobj] = collmd; - numobj++; } } *numcollobj = numobj; @@ -1484,6 +1493,9 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f BVHTreeOverlap *overlap = NULL; int result = 0; + if(!collmd->bvhtree) + continue; + /* move object to position (step) in time */ collision_move_object ( collmd, step + dt, step ); -- cgit v1.2.3 From 3996b82b50261b998f01881d77bccaddc1f31a86 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 29 Sep 2008 14:20:27 +0000 Subject: [#17707] Slow Cloth Baking --- source/blender/blenkernel/intern/collision.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index b5e09d551f0..b8f5b467c11 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1307,6 +1307,10 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) // check all collision objects for ( base = G.scene->base.first; base; base = base->next ) { + /*Only proceed for mesh object in same layer */ + if(!(base->object->type==OB_MESH && (base->lay & self->lay))) + continue; + coll_ob = base->object; if(coll_ob->pd && coll_ob->pd->deflect) -- cgit v1.2.3 From af7b777d2200eb7418d5004a8d6a33ab44f2383a Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 14 Oct 2008 11:50:30 +0000 Subject: Bugfix for regression from 2.46 on cloth collisions reported by Daniel Salazar via IRC --- source/blender/blenkernel/intern/collision.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index b8f5b467c11..e8cec7e1852 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1313,16 +1313,16 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) coll_ob = base->object; + if(coll_ob == self) + continue; + if(coll_ob->pd && coll_ob->pd->deflect) { collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); } if ( collmd ) - { - if(coll_ob == self) - continue; - + { if(numobj >= maxobj) { // realloc @@ -1351,6 +1351,9 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) coll_ob = go->ob; collmd = NULL; + if(coll_ob == self) + continue; + if(coll_ob->pd && coll_ob->pd->deflect) { collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); @@ -1358,9 +1361,6 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) if ( !collmd ) continue; - - if(coll_ob == self) - continue; if( !collmd->bvhtree) continue; -- cgit v1.2.3 From e1aff849e49b350e323310839a94f6cf3e48321c Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 14 Oct 2008 11:54:07 +0000 Subject: Collisions: CollisionModifier needs to be resetted for every loop --- source/blender/blenkernel/intern/collision.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/blender/blenkernel/intern/collision.c') diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index e8cec7e1852..775f1dee241 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1320,6 +1320,8 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) { collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); } + else + collmd = NULL; if ( collmd ) { @@ -1358,6 +1360,8 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) { collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); } + else + collmd = NULL; if ( !collmd ) continue; -- cgit v1.2.3