Moving functions and calls to have a cleaner situation for futre work (implicit solver .. n stuff)

This commit is contained in:
2005-08-19 22:55:05 +00:00
parent 6d60b0acfe
commit d81a5abf32
5 changed files with 295 additions and 288 deletions

View File

@@ -59,9 +59,6 @@ void build_particle_system(struct Object *ob);
void pdDoEffector(float *opco, float *force, float *speed, float cur_time, unsigned int par_layer,unsigned int flags);
int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
float facenormal[3], float *damp, float force[3], int mode,
float cur_time, unsigned int par_layer,struct Object *vertexowner);
#endif

View File

@@ -300,36 +300,6 @@ static void particle_tex(MTex *mtex, PartEff *paf, float *co, float *no)
}
}
static int linetriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *labda)
{
float p[3], s[3], d[3], e1[3], e2[3], q[3];
float a, f, u, v;
VECSUB(e1, v1, v0);
VECSUB(e2, v2, v0);
VECSUB(d, p2, p1);
Crossf(p, d, e2);
a = INPR(e1, p);
if ((a > -0.000001) && (a < 0.000001)) return 0;
f = 1.0f/a;
VECSUB(s, p1, v0);
Crossf(q, s, e1);
*labda = f * INPR(e2, q);
if ((*labda < 0.0)||(*labda > 1.0)) return 0;
u = f * INPR(s, p);
if ((u < 0.0)||(u > 1.0)) return 0;
v = f * INPR(d, q);
if ((v < 0.0)||((u + v) > 1.0)) return 0;
return 1;
}
/* -------- pdDoEffector() --------
generic force/speed system, now used for particles and softbodies
opco = global coord, as input
@@ -603,7 +573,7 @@ static int pdDoDeflection(RNG *rng, float opco[3], float npco[3], float opno[3],
// t= 0.5; // this is labda of line, can use it optimize quad intersection
// sorry but no .. see below (BM)
if( linetriangle(opco, npco, nv1, nv2, nv3, &t) ) {
if( LineIntersectsTriangle(opco, npco, nv1, nv2, nv3, &t) ) {
if (t < min_t) {
deflected = 1;
deflected_now = 1;
@@ -614,7 +584,7 @@ static int pdDoDeflection(RNG *rng, float opco[3], float npco[3], float opno[3],
// it might give a smaller t on (close to) the edge .. this is numerics not esoteric maths :)
// note: the 2 triangles don't need to share a plane ! (BM)
if (mface->v4) {
if( linetriangle(opco, npco, nv1, nv3, nv4, &t2) ) {
if( LineIntersectsTriangle(opco, npco, nv1, nv3, nv4, &t2) ) {
if (t2 < min_t) {
deflected = 1;
deflected_now = 2;
@@ -1383,255 +1353,3 @@ void build_particle_system(Object *ob)
rng_free(rng);
}
int SoftBodyDetectCollision(float opco[3], float npco[3], float colco[3],
float facenormal[3], float *damp, float force[3], int mode,
float cur_time, unsigned int par_layer,struct Object *vertexowner)
{
// static short recursion = 0;
// static short didokee = 0;
Base *base;
Object *ob;
float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3];
float dv1[3], dv2[3], dv3[3];
float facedist,n_mag,t,t2, min_t,force_mag_norm;
int a, deflected=0, deflected_now=0;
int d_object=0, d_face=0, ds_object=0, ds_face=0;
// i'm going to rearrange it to declaration rules when WIP is finished (BM)
float innerfacethickness = -0.5f;
float outerfacethickness = 0.2f;
float ee = 5.0f;
float ff = 0.1f;
float fa;
/*
if (recursion){
if (!didokee)
printf("SB collision detected recursion. We will CRASH now!");
didokee =1;
return 0;
}
recursion =1;
*/
min_t = 200000;
base= G.scene->base.first;
while (base) {
/*Only proceed for mesh object in same layer */
if(base->object->type==OB_MESH && (base->lay & par_layer)) {
ob= base->object;
if((vertexowner) && (ob == vertexowner)){
/* if vertexowner is given
* we don't want to check collision with owner object */
base = base->next;
continue;
}
/* only with deflecting set */
if(ob->pd && ob->pd->deflect) {
DerivedMesh *dm=NULL;
int dmNeedsFree;
Mesh *me= NULL;
DispListMesh *disp_mesh = 0;
MFace *mface;
Object *copyob;
/* do object level stuff */
/* need to have user control for that since it depends on model scale */
innerfacethickness =-ob->pd->pdef_sbift;
outerfacethickness =ob->pd->pdef_sboft;
fa = (ff*outerfacethickness-outerfacethickness);
fa *= fa;
fa = 1.0f/fa;
copyob = ob;
// if (ob->pd->flag & PDEFLE_DEFORM){// get colliding mesh from modifier stack
// keep this option for debugging but IMHO this is not needed
if (1){// get colliding mesh from modifier stack
if(1) { // so maybe someone wants overkill to collide with subsurfed
dm = mesh_get_derived_deform(copyob, &dmNeedsFree);
} else {
dm = mesh_get_derived_final(copyob, &dmNeedsFree);
}
}
if (dm) {
disp_mesh = dm->convertToDispListMesh(dm, 1);
mface= disp_mesh->mface;
a = disp_mesh->totface;
}
else {
me = ob->data;
mface= me->mface;
a = me->totface;
}
/* use mesh*/
while (a--) {
/* Calculate the global co-ordinates of the vertices*/
if (dm){
dm->getVertCo(dm,mface->v1,nv1);
Mat4MulVecfl(ob->obmat, nv1);
dm->getVertCo(dm,mface->v2,nv2);
Mat4MulVecfl(ob->obmat, nv2);
dm->getVertCo(dm,mface->v3,nv3);
Mat4MulVecfl(ob->obmat, nv3);
if (mface->v4){
dm->getVertCo(dm,mface->v4,nv4);
Mat4MulVecfl(ob->obmat, nv4);
}
}
else{
VECCOPY(nv1,(me->mvert+(mface->v1))->co);
Mat4MulVecfl(ob->obmat, nv1);
VECCOPY(nv2,(me->mvert+(mface->v2))->co);
Mat4MulVecfl(ob->obmat, nv2);
VECCOPY(nv3,(me->mvert+(mface->v3))->co);
Mat4MulVecfl(ob->obmat, nv3);
if (mface->v4){
VECCOPY(nv4,(me->mvert+(mface->v4))->co);
Mat4MulVecfl(ob->obmat, nv4);
}
}
deflected_now = 0;
if (mode == 1){ // face intrusion test
// switch origin to be nv2
VECSUB(edge1, nv1, nv2);
VECSUB(edge2, nv3, nv2);
VECSUB(dv1,opco,nv2); // abuse dv1 to have vertex in question at *origin* of triangle
Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect);
facedist = Inpf(dv1,d_nvect);
if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
dv2[0] = opco[0] - 2.0f*facedist*d_nvect[0];
dv2[1] = opco[1] - 2.0f*facedist*d_nvect[1];
dv2[2] = opco[2] - 2.0f*facedist*d_nvect[2];
if ( linetriangle( opco, dv2, nv1, nv2, nv3, &t)){
force_mag_norm =(float)exp(-ee*facedist);
if (facedist > outerfacethickness*ff)
force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
force[0] += force_mag_norm*d_nvect[0] ;
force[1] += force_mag_norm*d_nvect[1] ;
force[2] += force_mag_norm*d_nvect[2] ;
*damp=ob->pd->pdef_sbdamp;
deflected = 2;
}
}
if (mface->v4){ // quad
// switch origin to be nv4
VECSUB(edge1, nv3, nv4);
VECSUB(edge2, nv1, nv4);
VECSUB(dv1,opco,nv4); // abuse dv1 to have vertex in question at *origin* of triangle
Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect);
facedist = Inpf(dv1,d_nvect);
if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
dv2[0] = opco[0] - 2.0f*facedist*d_nvect[0];
dv2[1] = opco[1] - 2.0f*facedist*d_nvect[1];
dv2[2] = opco[2] - 2.0f*facedist*d_nvect[2];
if ( linetriangle( opco, dv2, nv1, nv3, nv4, &t)){
force_mag_norm =(float)exp(-ee*facedist);
if (facedist > outerfacethickness*ff)
force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
force[0] += force_mag_norm*d_nvect[0] ;
force[1] += force_mag_norm*d_nvect[1] ;
force[2] += force_mag_norm*d_nvect[2] ;
*damp=ob->pd->pdef_sbdamp;
deflected = 2;
}
}
}
}
if (mode == 2){ // edge intrusion test
//t= 0.5; // this is labda of line, can use it optimize quad intersection
// sorry but no .. see below (BM)
if( linetriangle(opco, npco, nv1, nv2, nv3, &t) ) {
if (t < min_t) {
deflected = 1;
deflected_now = 1;
}
}
if (mface->v4) {
if( linetriangle(opco, npco, nv1, nv3, nv4, &t2) ) {
if (t2 < min_t) {
deflected = 1;
deflected_now = 2;
}
}
}
if ((deflected_now > 0) && ((t < min_t) ||(t2 < min_t))) {
min_t = t;
ds_object = d_object;
ds_face = d_face;
if (deflected_now==1) {
min_t = t;
VECCOPY(dv1, nv1);
VECCOPY(dv2, nv2);
VECCOPY(dv3, nv3);
}
else {
min_t = t2;
VECCOPY(dv1, nv1);
VECCOPY(dv2, nv3);
VECCOPY(dv3, nv4);
}
}
}
mface++;
}//while a
/* give it away */
if (disp_mesh) {
displistmesh_free(disp_mesh);
}
if (dm) {
if (dmNeedsFree) dm->release(dm);
}
} // if(ob->pd && ob->pd->deflect)
}//if (base->object->type==OB_MESH && (base->lay & par_layer)) {
base = base->next;
} // while (base)
if (mode == 1){ // face
// recursion = 0;
return deflected;
}
if (mode == 2){ // edge intrusion test
if (deflected) {
VECSUB(edge1, dv1, dv2);
VECSUB(edge2, dv3, dv2);
Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect);
// return point of intersection
colco[0] = opco[0] + (min_t * (npco[0] - opco[0]));
colco[1] = opco[1] + (min_t * (npco[1] - opco[1]));
colco[2] = opco[2] + (min_t * (npco[2] - opco[2]));
VECCOPY(facenormal,d_nvect);
}
}
// recursion = 0;
return deflected;
}

View File

@@ -77,9 +77,11 @@ variables on the UI for now
#include "BKE_object.h"
#include "BKE_softbody.h"
#include "BKE_utildefines.h"
#include "BKE_DerivedMesh.h"
#include "BIF_editdeform.h"
/* ********** soft body engine ******* */
typedef struct BodyPoint {
@@ -336,6 +338,257 @@ static void free_softbody_intern(SoftBody *sb)
/* ************ dynamics ********** */
int sb_detect_collision(float opco[3], float npco[3], float colco[3],
float facenormal[3], float *damp, float force[3], int mode,
float cur_time, unsigned int par_layer,struct Object *vertexowner)
{
// static short recursion = 0;
// static short didokee = 0;
Base *base;
Object *ob;
float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3];
float dv1[3], dv2[3], dv3[3];
float facedist,n_mag,t,t2, min_t,force_mag_norm;
int a, deflected=0, deflected_now=0;
int d_object=0, d_face=0, ds_object=0, ds_face=0;
// i'm going to rearrange it to declaration rules when WIP is finished (BM)
float innerfacethickness = -0.5f;
float outerfacethickness = 0.2f;
float ee = 5.0f;
float ff = 0.1f;
float fa;
/*
if (recursion){
if (!didokee)
printf("SB collision detected recursion. We will CRASH now!");
didokee =1;
return 0;
}
recursion =1;
*/
min_t = 200000;
base= G.scene->base.first;
while (base) {
/*Only proceed for mesh object in same layer */
if(base->object->type==OB_MESH && (base->lay & par_layer)) {
ob= base->object;
if((vertexowner) && (ob == vertexowner)){
/* if vertexowner is given
* we don't want to check collision with owner object */
base = base->next;
continue;
}
/* only with deflecting set */
if(ob->pd && ob->pd->deflect) {
DerivedMesh *dm=NULL;
int dmNeedsFree;
Mesh *me= NULL;
DispListMesh *disp_mesh = 0;
MFace *mface;
Object *copyob;
/* do object level stuff */
/* need to have user control for that since it depends on model scale */
innerfacethickness =-ob->pd->pdef_sbift;
outerfacethickness =ob->pd->pdef_sboft;
fa = (ff*outerfacethickness-outerfacethickness);
fa *= fa;
fa = 1.0f/fa;
copyob = ob;
// if (ob->pd->flag & PDEFLE_DEFORM){// get colliding mesh from modifier stack
// keep this option for debugging but IMHO this is not needed
if (1){// get colliding mesh from modifier stack
if(1) { // so maybe someone wants overkill to collide with subsurfed
dm = mesh_get_derived_deform(copyob, &dmNeedsFree);
} else {
dm = mesh_get_derived_final(copyob, &dmNeedsFree);
}
}
if (dm) {
disp_mesh = dm->convertToDispListMesh(dm, 1);
mface= disp_mesh->mface;
a = disp_mesh->totface;
}
else {
me = ob->data;
mface= me->mface;
a = me->totface;
}
/* use mesh*/
while (a--) {
/* Calculate the global co-ordinates of the vertices*/
if (dm){
dm->getVertCo(dm,mface->v1,nv1);
Mat4MulVecfl(ob->obmat, nv1);
dm->getVertCo(dm,mface->v2,nv2);
Mat4MulVecfl(ob->obmat, nv2);
dm->getVertCo(dm,mface->v3,nv3);
Mat4MulVecfl(ob->obmat, nv3);
if (mface->v4){
dm->getVertCo(dm,mface->v4,nv4);
Mat4MulVecfl(ob->obmat, nv4);
}
}
else{
VECCOPY(nv1,(me->mvert+(mface->v1))->co);
Mat4MulVecfl(ob->obmat, nv1);
VECCOPY(nv2,(me->mvert+(mface->v2))->co);
Mat4MulVecfl(ob->obmat, nv2);
VECCOPY(nv3,(me->mvert+(mface->v3))->co);
Mat4MulVecfl(ob->obmat, nv3);
if (mface->v4){
VECCOPY(nv4,(me->mvert+(mface->v4))->co);
Mat4MulVecfl(ob->obmat, nv4);
}
}
deflected_now = 0;
if (mode == 1){ // face intrusion test
// switch origin to be nv2
VECSUB(edge1, nv1, nv2);
VECSUB(edge2, nv3, nv2);
VECSUB(dv1,opco,nv2); // abuse dv1 to have vertex in question at *origin* of triangle
Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect);
facedist = Inpf(dv1,d_nvect);
if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
dv2[0] = opco[0] - 2.0f*facedist*d_nvect[0];
dv2[1] = opco[1] - 2.0f*facedist*d_nvect[1];
dv2[2] = opco[2] - 2.0f*facedist*d_nvect[2];
if ( LineIntersectsTriangle( opco, dv2, nv1, nv2, nv3, &t)){
force_mag_norm =(float)exp(-ee*facedist);
if (facedist > outerfacethickness*ff)
force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
force[0] += force_mag_norm*d_nvect[0] ;
force[1] += force_mag_norm*d_nvect[1] ;
force[2] += force_mag_norm*d_nvect[2] ;
*damp=ob->pd->pdef_sbdamp;
deflected = 2;
}
}
if (mface->v4){ // quad
// switch origin to be nv4
VECSUB(edge1, nv3, nv4);
VECSUB(edge2, nv1, nv4);
VECSUB(dv1,opco,nv4); // abuse dv1 to have vertex in question at *origin* of triangle
Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect);
facedist = Inpf(dv1,d_nvect);
if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
dv2[0] = opco[0] - 2.0f*facedist*d_nvect[0];
dv2[1] = opco[1] - 2.0f*facedist*d_nvect[1];
dv2[2] = opco[2] - 2.0f*facedist*d_nvect[2];
if (LineIntersectsTriangle( opco, dv2, nv1, nv3, nv4, &t)){
force_mag_norm =(float)exp(-ee*facedist);
if (facedist > outerfacethickness*ff)
force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
force[0] += force_mag_norm*d_nvect[0] ;
force[1] += force_mag_norm*d_nvect[1] ;
force[2] += force_mag_norm*d_nvect[2] ;
*damp=ob->pd->pdef_sbdamp;
deflected = 2;
}
}
}
}
if (mode == 2){ // edge intrusion test
//t= 0.5; // this is labda of line, can use it optimize quad intersection
// sorry but no .. see below (BM)
if(LineIntersectsTriangle(opco, npco, nv1, nv2, nv3, &t) ) {
if (t < min_t) {
deflected = 1;
deflected_now = 1;
}
}
if (mface->v4) {
if( LineIntersectsTriangle(opco, npco, nv1, nv3, nv4, &t2) ) {
if (t2 < min_t) {
deflected = 1;
deflected_now = 2;
}
}
}
if ((deflected_now > 0) && ((t < min_t) ||(t2 < min_t))) {
min_t = t;
ds_object = d_object;
ds_face = d_face;
if (deflected_now==1) {
min_t = t;
VECCOPY(dv1, nv1);
VECCOPY(dv2, nv2);
VECCOPY(dv3, nv3);
}
else {
min_t = t2;
VECCOPY(dv1, nv1);
VECCOPY(dv2, nv3);
VECCOPY(dv3, nv4);
}
}
}
mface++;
}//while a
/* give it away */
if (disp_mesh) {
displistmesh_free(disp_mesh);
}
if (dm) {
if (dmNeedsFree) dm->release(dm);
}
} // if(ob->pd && ob->pd->deflect)
}//if (base->object->type==OB_MESH && (base->lay & par_layer)) {
base = base->next;
} // while (base)
if (mode == 1){ // face
// recursion = 0;
return deflected;
}
if (mode == 2){ // edge intrusion test
if (deflected) {
VECSUB(edge1, dv1, dv2);
VECSUB(edge2, dv3, dv2);
Crossf(d_nvect, edge2, edge1);
n_mag = Normalise(d_nvect);
// return point of intersection
colco[0] = opco[0] + (min_t * (npco[0] - opco[0]));
colco[1] = opco[1] + (min_t * (npco[1] - opco[1]));
colco[2] = opco[2] + (min_t * (npco[2] - opco[2]));
VECCOPY(facenormal,d_nvect);
}
}
// recursion = 0;
return deflected;
}
/* aye this belongs to arith.c */
static void Vec3PlusStVec(float *v, float s, float *v1)
@@ -355,7 +608,7 @@ static int sb_deflect_face(Object *ob,float *actpos, float *futurepos,float *col
if (bounce) *bounce *= 1.5f;
deflected= SoftBodyDetectCollision(s_actpos, s_futurepos, collisionpos,
deflected= sb_detect_collision(s_actpos, s_futurepos, collisionpos,
facenormal, cf, force , 1,
G.scene->r.cfra, ob->lay, ob);
return(deflected);

View File

@@ -870,6 +870,7 @@ Normalise2(
void tubemap(float x, float y, float z, float *u, float *v);
void spheremap(float x, float y, float z, float *u, float *v);
int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda);
#ifdef __cplusplus
}

View File

@@ -2808,3 +2808,41 @@ void mul_v3_v3m4(float *v1, float *v2, float mat[][4])
v1[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*v2[2] + mat[3][2];
}
/* moved from effect.c
test if the line starting at p1 ending at p2 intersects the triangle v0..v2
return non zero if it does
wild guess .. says did not check the math since i don't need it
and if (it intersects) lambda returns intersection = p1 + lambda(p1-p2)
*/
int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda)
{
float p[3], s[3], d[3], e1[3], e2[3], q[3];
float a, f, u, v;
VecSubf(e1, v1, v0);
VecSubf(e2, v2, v0);
VecSubf(d, p2, p1);
Crossf(p, d, e2);
a = Inpf(e1, p);
if ((a > -0.000001) && (a < 0.000001)) return 0;
f = 1.0f/a;
VecSubf(s, p1, v0);
Crossf(q, s, e1);
*lambda = f * Inpf(e2, q);
if ((*lambda < 0.0)||(*lambda > 1.0)) return 0;
u = f * Inpf(s, p);
if ((u < 0.0)||(u > 1.0)) return 0;
v = f * Inpf(d, q);
if ((v < 0.0)||((u + v) > 1.0)) return 0;
return 1;
}