Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2007-11-27 01:09:57 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2007-11-27 01:09:57 +0300
commit7da56f4a9ba0bdd0cdcd40b8ca6e69d776d26abe (patch)
tree663c13aae5606937571ac1e7a4c77ca2866e75dd /source/blender/blenkernel/intern/softbody.c
parent121dab1bcd9467bd8e11d0a82e83a1621758fd8e (diff)
parent770291b9ea1ec03d98b6bae4fd2a2d3f0091be41 (diff)
Particles
========= Merge of the famous particle patch by Janne Karhu, a full rewrite of the Blender particle system. This includes: - Emitter, Hair and Reactor particle types. - Newtonian, Keyed and Boids physics. - Various particle visualisation and rendering types. - Vertex group and texture control for various properties. - Interpolated child particles from parents. - Hair editing with combing, growing, cutting, .. . - Explode modifier. - Harmonic, Magnetic fields, and multiple falloff types. .. and lots of other things, some more info is here: http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc The new particle system cannot be backwards compatible. Old particle systems are being converted to the new system, but will require tweaking to get them looking the same as before. Point Cache =========== The new system to replace manual baking, based on automatic caching on disk. This is currently used by softbodies and the particle system. See the Cache API section on: http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint Documentation ============= These new features still need good docs for the release logs, help for this is appreciated.
Diffstat (limited to 'source/blender/blenkernel/intern/softbody.c')
-rw-r--r--source/blender/blenkernel/intern/softbody.c453
1 files changed, 293 insertions, 160 deletions
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 36d114cf023..bd9d1cb75ca 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -61,9 +61,11 @@ variables on the UI for now
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h" /* here is the softbody struct */
+#include "DNA_particle_types.h"
#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_lattice_types.h"
#include "DNA_scene_types.h"
@@ -75,9 +77,12 @@ variables on the UI for now
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_object.h"
+#include "BKE_particle.h"
#include "BKE_softbody.h"
#include "BKE_utildefines.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_pointcache.h"
+#include "BKE_modifier.h"
#include "BIF_editdeform.h"
#include "BIF_graphics.h"
@@ -90,18 +95,6 @@ static int (*SB_localInterruptCallBack)(void) = NULL;
/* ********** soft body engine ******* */
-
-typedef struct BodyPoint {
- float origS[3], origE[3], origT[3], pos[3], vec[3], force[3];
- float goal;
- float prevpos[3], prevvec[3], prevdx[3], prevdv[3]; /* used for Heun integration */
- int nofsprings; int *springs;
- float choke;
- float colball;
- short flag;
- char octantflag;
-} BodyPoint;
-
typedef struct BodySpring {
int v1, v2;
float len, strength, cf;
@@ -480,21 +473,31 @@ void ccd_build_deflector_hache(Object *vertexowner,GHash *hash)
while (base) {
/*Only proceed for mesh object in same layer */
if(base->object->type==OB_MESH && (base->lay & vertexowner->lay)) {
+ int particles=0;
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;
+ if((vertexowner) && (ob == vertexowner)) {
+ if(vertexowner->soft->particles){
+ particles=1;
+ }
+ else {
+ /* 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 && BLI_ghash_lookup(hash, ob) == 0) {
DerivedMesh *dm= NULL;
-
- if(ob->softflag & OB_SB_COLLFINAL) { /* so maybe someone wants overkill to collide with subsurfed */
- dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
- } else {
- dm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH);
+
+ if(particles) {
+ dm = psys_get_modifier(ob,psys_get_current(ob))->dm;
+ }
+ else {
+ if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */
+ dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
+ else
+ dm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH);
}
if(dm){
@@ -852,10 +855,11 @@ static void renew_softbody(Object *ob, int totpoint, int totspring)
{
SoftBody *sb;
int i;
-
+ short softflag;
if(ob->soft==NULL) ob->soft= sbNew();
else free_softbody_intern(ob->soft);
sb= ob->soft;
+ softflag=ob->softflag;
if(totpoint) {
sb->totpoint= totpoint;
@@ -869,8 +873,8 @@ static void renew_softbody(Object *ob, int totpoint, int totspring)
for (i=0; i<totpoint; i++) {
BodyPoint *bp = &sb->bpoint[i];
- if(ob->softflag & OB_SB_GOAL) {
- bp->goal= ob->soft->defgoal;
+ if(softflag & OB_SB_GOAL) {
+ bp->goal= sb->defgoal;
}
else {
bp->goal= 0.0f;
@@ -900,7 +904,6 @@ static void free_softbody_baked(SoftBody *sb)
sb->keys= NULL;
sb->totkey= 0;
-
}
static void free_scratch(SoftBody *sb)
{
@@ -1203,9 +1206,9 @@ int sb_detect_face_collisionCached(float face_v1[3],float face_v2[3],float face_
Crossf(d_nvect, edge2, edge1);
Normalize(d_nvect);
if (
- LineIntersectsTriangle(nv1, nv2, face_v1, face_v2, face_v3, &t) ||
- LineIntersectsTriangle(nv2, nv3, face_v1, face_v2, face_v3, &t) ||
- LineIntersectsTriangle(nv3, nv1, face_v1, face_v2, face_v3, &t) ){
+ LineIntersectsTriangle(nv1, nv2, face_v1, face_v2, face_v3, &t, NULL) ||
+ LineIntersectsTriangle(nv2, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
+ LineIntersectsTriangle(nv3, nv1, face_v1, face_v2, face_v3, &t, NULL) ){
Vec3PlusStVec(force,-1.0f,d_nvect);
*damp=ob->pd->pdef_sbdamp;
deflected = 2;
@@ -1217,9 +1220,9 @@ int sb_detect_face_collisionCached(float face_v1[3],float face_v2[3],float face_
Crossf(d_nvect, edge2, edge1);
Normalize(d_nvect);
if (
- LineIntersectsTriangle(nv1, nv3, face_v1, face_v2, face_v3, &t) ||
- LineIntersectsTriangle(nv3, nv4, face_v1, face_v2, face_v3, &t) ||
- LineIntersectsTriangle(nv4, nv1, face_v1, face_v2, face_v3, &t) ){
+ LineIntersectsTriangle(nv1, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
+ LineIntersectsTriangle(nv3, nv4, face_v1, face_v2, face_v3, &t, NULL) ||
+ LineIntersectsTriangle(nv4, nv1, face_v1, face_v2, face_v3, &t, NULL) ){
Vec3PlusStVec(force,-1.0f,d_nvect);
*damp=ob->pd->pdef_sbdamp;
deflected = 2;
@@ -1402,7 +1405,7 @@ int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp
Crossf(d_nvect, edge2, edge1);
Normalize(d_nvect);
- if ( LineIntersectsTriangle(edge_v1, edge_v2, nv1, nv2, nv3, &t)){
+ if ( LineIntersectsTriangle(edge_v1, edge_v2, nv1, nv2, nv3, &t, NULL)){
float v1[3],v2[3];
float intrusiondepth,i1,i2;
VECSUB(v1, edge_v1, nv2);
@@ -1421,7 +1424,7 @@ int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp
Crossf(d_nvect, edge2, edge1);
Normalize(d_nvect);
- if (LineIntersectsTriangle( edge_v1, edge_v2,nv1, nv3, nv4, &t)){
+ if (LineIntersectsTriangle( edge_v1, edge_v2,nv1, nv3, nv4, &t, NULL)){
float v1[3],v2[3];
float intrusiondepth,i1,i2;
VECSUB(v1, edge_v1, nv4);
@@ -1550,7 +1553,7 @@ int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *
Object *ob= NULL;
GHash *hash;
GHashIterator *ihash;
- float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3], dv1[3],ve[3],avel[3],
+ float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3], dv1[3],ve[3],avel[3]={0.0,0.0,0.0},
vv1[3], vv2[3], vv3[3], vv4[3], coledge[3], mindistedge = 1000.0f,
outerforceaccu[3],innerforceaccu[3],
facedist,n_mag,force_mag_norm,minx,miny,minz,maxx,maxy,maxz,
@@ -2953,6 +2956,103 @@ static void curve_surf_to_softbody(Object *ob)
}
+static void springs_from_particles(Object *ob)
+{
+ ParticleSystem *psys;
+ ParticleSystemModifierData *psmd=0;
+ ParticleData *pa=0;
+ HairKey *key=0;
+ SoftBody *sb;
+ BodyPoint *bp;
+ BodySpring *bs;
+ int a,k;
+ float hairmat[4][4];
+
+ psys= ob->soft->particles;
+ sb= ob->soft;
+ if(ob && sb && psys) {
+ psmd = psys_get_modifier(ob, psys);
+
+ bp= sb->bpoint;
+ for(a=0, pa=psys->particles; a<psys->totpart; a++, pa++) {
+ for(k=0, key=pa->hair; k<pa->totkey; k++, bp++, key++) {
+ VECCOPY(bp->origS, key->co);
+
+ psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+
+ Mat4MulVecfl(hairmat, bp->origS);
+ }
+ }
+
+ for(a=0, bs=sb->bspring; a<sb->totspring; a++, bs++)
+ bs->len= VecLenf(sb->bpoint[bs->v1].origS, sb->bpoint[bs->v2].origS);
+ }
+}
+
+static void particles_to_softbody(Object *ob)
+{
+ SoftBody *sb;
+ BodyPoint *bp;
+ BodySpring *bs;
+ ParticleData *pa;
+ HairKey *key;
+ ParticleSystem *psys= ob->soft->particles;
+ float goalfac;
+ int a, k, curpoint;
+ int totpoint= psys_count_keys(psys);
+ int totedge= totpoint-psys->totpart;
+
+ /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
+ renew_softbody(ob, totpoint, totedge);
+
+ psys->particles->bpi = 0;
+ for(a=1, pa=psys->particles+1; a<psys->totpart; a++, pa++)
+ pa->bpi = (pa-1)->bpi + pa->totkey;
+
+ /* we always make body points */
+ sb= ob->soft;
+ bp= sb->bpoint;
+ bs= sb->bspring;
+ goalfac= ABS(sb->maxgoal - sb->mingoal);
+
+ if((ob->softflag & OB_SB_GOAL)) {
+ for(a=0, pa=psys->particles; a<psys->totpart; a++, pa++) {
+ for(k=0, key=pa->hair; k<pa->totkey; k++,bp++,key++) {
+ if(k) {
+ bp->goal= key->weight;
+ bp->goal= sb->mingoal + bp->goal*goalfac;
+ bp->goal= (float)pow(bp->goal, 4.0f);
+ }
+ else{
+ /* hair roots are allways fixed fully to goal */
+ bp->goal= 1.0f;
+ }
+ }
+ }
+ }
+
+ bp= sb->bpoint;
+ curpoint=0;
+ for(a=0, pa=psys->particles; a<psys->totpart; a++, curpoint++, pa++) {
+ for(k=0; k<pa->totkey-1; k++,bs++,curpoint++) {
+ bs->v1=curpoint;
+ bs->v2=curpoint+1;
+ bs->strength= 1.0;
+ bs->order=1;
+ }
+ }
+
+ build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */
+ /* insert *other second order* springs if desired */
+ if(sb->secondspring > 0.0000001f) {
+ add_2nd_order_springs(ob,sb->secondspring*10.0); /* exploits the the first run of build_bps_springlist(ob);*/
+ build_bps_springlist(ob); /* yes we need to do it again*/
+ }
+ springs_from_particles(ob); /* write the 'rest'-lenght of the springs */
+ if(ob->softflag & OB_SB_SELF)
+ calculate_collision_balls(ob);
+}
+
/* copies softbody result back in object */
static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, int local)
{
@@ -2969,117 +3069,94 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts,
}
}
-/* return 1 if succesfully baked and applied step */
-static int softbody_baked_step(Object *ob, float framenr, float (*vertexCos)[3], int numVerts)
+void softbody_clear_cache(Object *ob, float framenr)
{
- SoftBody *sb= ob->soft;
- SBVertex *key0, *key1, *key2, *key3;
- BodyPoint *bp;
- float data[4], sfra, efra, cfra, dfra, fac; /* start, end, current, delta */
- int ofs1, a;
-
- /* precondition check */
- if(sb==NULL || sb->keys==NULL || sb->totkey==0) return 0;
- /* so we got keys, but no bodypoints... even without simul we need it for the bake */
- if(sb->bpoint==NULL) sb->bpoint= MEM_callocN( sb->totpoint*sizeof(BodyPoint), "bodypoint");
-
- /* convert cfra time to system time */
- sfra= (float)sb->sfra;
- cfra= bsystem_time(ob, framenr, 0.0);
- efra= (float)sb->efra;
- dfra= (float)sb->interval;
+ SoftBody *sb = ob->soft;
+ ModifierData *md = ob->modifiers.first;
+ int stack_index = -1;
+ int a;
- /* offset in keys array */
- ofs1= (int)floor( (cfra-sfra)/dfra );
+ if(sb==NULL) return;
- if(ofs1 < 0) {
- key0=key1=key2=key3= *sb->keys;
- }
- else if(ofs1 >= sb->totkey-1) {
- key0=key1=key2=key3= *(sb->keys+sb->totkey-1);
- }
+ if(sb->particles)
+ stack_index = modifiers_indexInObject(ob,(ModifierData*)psys_get_modifier(ob,sb->particles));
else {
- key1= *(sb->keys+ofs1);
- key2= *(sb->keys+ofs1+1);
-
- if(ofs1>0) key0= *(sb->keys+ofs1-1);
- else key0= key1;
-
- if(ofs1<sb->totkey-2) key3= *(sb->keys+ofs1+2);
- else key3= key2;
- }
-
- sb->ctime= cfra; /* needed? */
-
- /* timing */
- fac= ((cfra-sfra)/dfra) - (float)ofs1;
- CLAMP(fac, 0.0, 1.0);
- set_four_ipo(fac, data, KEY_BSPLINE);
- if (key0&&key1&&key2&&key3) // may be null because we SHIFT_ESCAPED
- for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++, key0++, key1++, key2++, key3++) {
- bp->pos[0]= data[0]*key0->vec[0] + data[1]*key1->vec[0] + data[2]*key2->vec[0] + data[3]*key3->vec[0];
- bp->pos[1]= data[0]*key0->vec[1] + data[1]*key1->vec[1] + data[2]*key2->vec[1] + data[3]*key3->vec[1];
- bp->pos[2]= data[0]*key0->vec[2] + data[1]*key1->vec[2] + data[2]*key2->vec[2] + data[3]*key3->vec[2];
+ for(a=0; md; md=md->next, a++) {
+ if(md->type == eModifierType_Softbody) {
+ stack_index = a;
+ break;
+ }
+ }
}
-
- softbody_to_object(ob, vertexCos, numVerts, sb->local);
-
- return 1;
-}
-/* only gets called after succesfully doing softbody_step */
-/* already checked for OB_SB_BAKE flag */
-static void softbody_baked_add(Object *ob, float framenr)
+ BKE_ptcache_id_clear((ID *)ob, PTCACHE_CLEAR_ALL, framenr, stack_index);
+}
+static void softbody_write_cache(Object *ob, float framenr)
{
- SoftBody *sb= ob->soft;
- SBVertex *key;
+ FILE *fp = NULL;
+ SoftBody *sb = ob->soft;
BodyPoint *bp;
- float sfra, efra, cfra, dfra, fac1; /* start, end, current, delta */
- int ofs1, a;
-
- /* convert cfra time to system time */
- sfra= (float)sb->sfra;
- fac1= ob->sf; ob->sf= 0.0f; /* disable startframe */
- cfra= bsystem_time(ob, framenr, 0.0);
- ob->sf= fac1;
- efra= (float)sb->efra;
- dfra= (float)sb->interval;
-
- if(sb->totkey==0) {
- if(sb->sfra >= sb->efra) return; /* safety, UI or py setting allows */
- if(sb->interval<1) sb->interval= 1; /* just be sure */
-
- sb->totkey= 1 + (int)(ceil( (efra-sfra)/dfra ) );
- sb->keys= MEM_callocN( sizeof(void *)*sb->totkey, "sb keys");
+ ModifierData *md = ob->modifiers.first;
+ int stack_index = -1;
+ int a;
+
+ if(sb->totpoint == 0) return;
+
+ if(sb->particles)
+ stack_index = modifiers_indexInObject(ob,(ModifierData*)psys_get_modifier(ob,sb->particles));
+ else {
+ for(a=0; md; md=md->next, a++) {
+ if(md->type == eModifierType_Softbody) {
+ stack_index = a;
+ break;
+ }
+ }
}
+
+ fp = BKE_ptcache_id_fopen((ID *)ob, 'w', framenr, stack_index);
+ if(!fp) return;
+
+ for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++)
+ fwrite(&bp->pos, sizeof(float), 3, fp);
- /* inverse matrix might not be uptodate... */
- Mat4Invert(ob->imat, ob->obmat);
-
- /* now find out if we have to store a key */
-
- /* offset in keys array */
- if(cfra>=(efra)) {
- ofs1= sb->totkey-1;
- fac1= 0.0;
- }
+ fclose(fp);
+}
+static int softbody_read_cache(Object *ob, float framenr)
+{
+ FILE *fp = NULL;
+ SoftBody *sb = ob->soft;
+ BodyPoint *bp;
+ ModifierData *md = ob->modifiers.first;
+ int stack_index = -1;
+ int a, ret = 1;
+
+ if(sb->totpoint == 0) return 0;
+
+ if(sb->particles)
+ stack_index = modifiers_indexInObject(ob,(ModifierData*)psys_get_modifier(ob,sb->particles));
else {
- ofs1= (int)floor( (cfra-sfra)/dfra );
- fac1= ((cfra-sfra)/dfra) - (float)ofs1;
- }
- if( fac1 < 1.0/dfra ) {
-
- key= *(sb->keys+ofs1);
- if(key == NULL) {
- *(sb->keys+ofs1)= key= MEM_mallocN(sb->totpoint*sizeof(SBVertex), "softbody key");
-
- for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++, key++) {
- VECCOPY(key->vec, bp->pos);
- if(sb->local)
- Mat4MulVecfl(ob->imat, key->vec);
+ for(a=0; md; md=md->next, a++) {
+ if(md->type == eModifierType_Softbody) {
+ stack_index = a;
+ break;
}
}
}
+
+ fp = BKE_ptcache_id_fopen((ID *)ob, 'r', framenr, stack_index);
+ if(!fp)
+ ret = 0;
+ else {
+ for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++)
+ if(fread(&bp->pos, sizeof(float), 3, fp) != 3) {
+ ret = 0;
+ break;
+ }
+
+ fclose(fp);
+ }
+
+ return ret;
}
/* +++ ************ maintaining scratch *************** */
void sb_new_scratch(SoftBody *sb)
@@ -3175,15 +3252,14 @@ void sbSetInterruptCallBack(int (*f)(void))
/* simulates one step. framenr is in frames */
void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts)
{
+ ParticleSystemModifierData *psmd=0;
+ ParticleData *pa=0;
SoftBody *sb;
+ HairKey *key= NULL;
BodyPoint *bp;
int a;
float dtime,ctime,forcetime,err;
-
- /* baking works with global time */
- if(!(ob->softflag & OB_SB_BAKEDO) )
- if(softbody_baked_step(ob, framenr, vertexCos, numVerts) ) return;
-
+ float hairmat[4][4];
/* This part only sets goals and springs, based on original mesh/curve/lattice data.
Copying coordinates happens in next chunk by setting softbody flag OB_SB_RESET */
@@ -3194,7 +3270,13 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
(numVerts!=ob->soft->totpoint) || /* should never happen, just to be safe */
((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) /* happens when in UI edges was set */
{
- switch(ob->type) {
+ if(ob->soft && ob->soft->bpoint) /* don't clear on file load */
+ softbody_clear_cache(ob, framenr);
+
+ if(ob->soft->particles){
+ particles_to_softbody(ob);
+ }
+ else switch(ob->type) {
case OB_MESH:
mesh_to_softbody(ob);
break;
@@ -3220,6 +3302,10 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
/* still no points? go away */
if(sb->totpoint==0) return;
+ if(sb->particles){
+ psmd=psys_get_modifier(ob,sb->particles);
+ pa=sb->particles->particles;
+ }
/* checking time: */
@@ -3231,17 +3317,45 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
dtime= ctime - sb->ctime;
}
+ if(softbody_read_cache(ob, framenr)) {
+ if(sb->particles==0)
+ softbody_to_object(ob, vertexCos, numVerts, sb->local);
+ sb->ctime = ctime;
+ return;
+ }
+
/* the simulator */
/* update the vertex locations */
if (dtime!=0.0) {
+ if(sb->particles) {
+ pa=sb->particles->particles;
+ key = pa->hair;
+
+ psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
+ }
+
for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) {
/* store where goals are now */
VECCOPY(bp->origS, bp->origE);
/* copy the position of the goals at desired end time */
- VECCOPY(bp->origE, vertexCos[a]);
- /* vertexCos came from local world, go global */
- Mat4MulVecfl(ob->obmat, bp->origE);
+ if(sb->particles) {
+ if(key == pa->hair + pa->totkey) {
+ pa++;
+ key = pa->hair;
+
+ psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
+ }
+ VECCOPY(bp->origE, key->co);
+ Mat4MulVecfl(hairmat,bp->origE);
+
+ key++;
+ }
+ else{
+ VECCOPY(bp->origE, vertexCos[a]);
+ /* vertexCos came from local world, go global */
+ Mat4MulVecfl(ob->obmat, bp->origE);
+ }
/* just to be save give bp->origT a defined value
will be calulated in interpolate_exciter()*/
VECCOPY(bp->origT, bp->origE);
@@ -3253,9 +3367,29 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
(dtime>=9.9*G.scene->r.framelen) /* too far forward in time --> goals won't be accurate enough */
)
{
+ if(sb->particles) {
+ pa=sb->particles->particles;
+ key = pa->hair;
+
+ psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
+ }
+
for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) {
- VECCOPY(bp->pos, vertexCos[a]);
- Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/
+ if(sb->particles) {
+ if(key == pa->hair + pa->totkey) {
+ pa++;
+ key = pa->hair;
+
+ psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
+ }
+ VECCOPY(bp->pos, key->co);
+ Mat4MulVecfl(hairmat, bp->pos);
+ key++;
+ }
+ else {
+ VECCOPY(bp->pos, vertexCos[a]);
+ Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/
+ }
VECCOPY(bp->origS, bp->pos);
VECCOPY(bp->origE, bp->pos);
VECCOPY(bp->origT, bp->pos);
@@ -3283,23 +3417,22 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
sb_new_scratch(sb); /* make a new */
sb->scratch->needstobuildcollider=1;
-
- /* copy some info to scratch */
- switch(ob->type) {
- case OB_MESH:
- if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob);
- break;
- case OB_LATTICE:
- break;
- case OB_CURVE:
- case OB_SURF:
- break;
- default:
- break;
+ if((sb->particles)==0) {
+ /* copy some info to scratch */
+ switch(ob->type) {
+ case OB_MESH:
+ if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob);
+ break;
+ case OB_LATTICE:
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ break;
+ default:
+ break;
+ }
}
-
-
ob->softflag &= ~OB_SB_RESET;
}
else if(dtime>0.0) {
@@ -3411,10 +3544,10 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
}
}
- softbody_to_object(ob, vertexCos, numVerts, 0);
+ if(sb->particles==0)
+ softbody_to_object(ob, vertexCos, numVerts, 0);
sb->ctime= ctime;
-
- if(ob->softflag & OB_SB_BAKEDO) softbody_baked_add(ob, framenr);
+ softbody_write_cache(ob, framenr);
}