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:
authorNils Thuerey <nils@thuerey.de>2006-02-27 14:45:42 +0300
committerNils Thuerey <nils@thuerey.de>2006-02-27 14:45:42 +0300
commit9a36e9b65175ecb56fdcf314adf2fd933e77d08b (patch)
tree32e134587975a6a406547a75198026800e7a53af /source/blender
parentb7ff45f9147016629dfd032b9815daf7a10aadae (diff)
Sorry for the big commit, but I've been fixing many of these
issues in parallel... So this commit contains: an update of the solver (e.g. moving objects), integration of blender IPOs, improved rendering (motion blur, smoothed normals) and a first particle test. In more detail: Solver update: - Moving objects using a relatively simple model, and not yet fully optimized - ok for box falling into water, water in a moving glass might cause trouble. Simulation times are influenced by overall no. of triangles of the mesh, scaling meshes up a lot might also cause slowdowns. - Additional obstacle settings: noslip (as before), free slip (move along wall freely) and part slip (mix of both). - Obstacle settings also added for domain boundaries now, the six walls of the domain are obstacles after all as well - Got rid of templates, should make compiling for e.g. macs more convenient, for linux there's not much difference. Finally got rid of parser (and some other code parts), the simulation now uses the internal API to transfer data. - Some unnecessary file were removed, the GUI now needs 3 settings buttons... This should still be changed (maybe by adding a new panel for domain objects). IPOs: - Animated params: viscosity, time and gravity for domains. In contrast to normal time IPO for Blender objects, the fluidsim one scales the time step size - so a constant 1 has no effect, values towards 0 slow it down, larger ones speed the simulation up (-> longer time steps, more compuations). The viscosity IPO is also only a factor for the selected viscosity (again, 1=no effect). - For objects that are enabled for fluidsim, a new IPO type shows up. Inflow objects can use the velocity channels to animate the inflow. Obstacles, in/outflow objects can be switched on (Active IPO>0) and off (<0) during the simulation. - Movement, rotation and scaling of those 3 types is exported from the normal Blender channels (Loc,dLoc,etc.). Particles: - This is still experimental, so it might be deactivated for a release... It should at some point be used to model smaller splashes, depending on the the realworld size and the particle generation settings particles are generated during simulation (stored in _particles_X.gz files). - These are loaded by enabling the particle field for an arbitrary object, which should be given a halo material. For each frame, similar to the mesh loading, the particle system them loads the simulated particle positions. - For rendering, I "abused" the part->rt field - I couldnt find any use for it in the code and it seems to work fine. The fluidsim particles store their size there. Rendering: - The fluidims particles use scaled sizes and alpha values to give a more varied appearance. In convertblender.c fluidsim particle systems use the p->rt field to scale up the size and down the alpha of "smaller particles". Setting the influence fields in the fluidims settings to 0 gives equally sized particles with same alpha everywhere. Higher values cause larger differences. - Smoothed normals: for unmodified fluid meshes (e.g. no subdivision) the normals computed by the solver are used. This is basically done by switching off the normal recalculation in convertblender.c (the function calc_fluidsimnormals handles other mesh inits instead of calc_vertexnormals). This could also be used to e.g. modify mesh normals in a modifier... - Another change is that fluidsim meshes load the velocities computed during the simulation for image based motion blur. This is inited in load_fluidsimspeedvectors for the vector pass (they're loaded during the normal load in DerivedMesh readBobjgz). Generation and loading can be switched off in the settings. Vector pass currently loads the fluidism meshes 3 times, so this should still be optimized. Examples: - smoothed normals versus normals from subdividing once: http://www10.informatik.uni-erlangen.de/~sinithue/temp/v060227_1smoothnorms.png http://www10.informatik.uni-erlangen.de/~sinithue/temp/v060227_2subdivnorms.png - fluidsim particles, size/alpha influence 0: http://www10.informatik.uni-erlangen.de/~sinithue/temp/v060227_3particlesnorm.png size influence 1: http://www10.informatik.uni-erlangen.de/~sinithue/temp/v060227_4particlessize.png size & alpha influence 1: http://www10.informatik.uni-erlangen.de/~sinithue/temp/v060227_5particlesalpha.png - the standard drop with motion blur and particles: http://www10.informatik.uni-erlangen.de/~sinithue/temp/elbeemupdate_t2new.mpg (here's how it looks without http://www10.informatik.uni-erlangen.de/~sinithue/temp/elbeemupdate_t1old.mpg) - another inflow animation (moving, switched on/off) with a moving obstacle (and strong mblur :) http://www10.informatik.uni-erlangen.de/~sinithue/temp/elbeemupdate_t3ipos.mpg Things still to fix: - rotating & scaling domains causes wrong speed vectors - get rid of SDL code for threading, use pthreads as well? - update wiki documentation - cool effects for rendering would be photon maps for caustics, and motion blur for particles :)
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c219
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c4
-rw-r--r--source/blender/blenkernel/intern/effect.c104
-rw-r--r--source/blender/blenkernel/intern/ipo.c7
-rw-r--r--source/blender/blenloader/intern/readfile.c4
-rw-r--r--source/blender/include/BSE_editipo.h1
-rw-r--r--source/blender/include/butspace.h3
-rw-r--r--source/blender/makesdna/DNA_ID.h1
-rw-r--r--source/blender/makesdna/DNA_ipo_types.h20
-rw-r--r--source/blender/makesdna/DNA_object_fluidsim.h39
-rw-r--r--source/blender/render/intern/source/convertblender.c243
-rw-r--r--source/blender/src/buttons_object.c115
-rw-r--r--source/blender/src/drawobject.c12
-rw-r--r--source/blender/src/editipo.c52
-rw-r--r--source/blender/src/editipo_lib.c7
-rw-r--r--source/blender/src/editipo_mods.c1
-rw-r--r--source/blender/src/fluidsim.c1036
-rw-r--r--source/blender/src/header_ipo.c14
18 files changed, 1525 insertions, 357 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index c51a50dd313..89ac6040eb6 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -555,26 +555,46 @@ static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3]
mdm->freeNors = 0;
mdm->freeVerts = 0;
- if (vertCos) {
+ if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
+ (ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&&
+ (ob->fluidsimSettings->meshSurface) &&
+ (me->totvert == ((Mesh *)(ob->fluidsimSettings->meshSurface))->totvert) ) {
+ // dont recompute for fluidsim mesh, use from readBobjgz
+ // TODO? check for modifiers!?
int i;
-
- /* copy the original verts to preserve flag settings; if this is too
- * costly, must at least use MEM_callocN to clear flags */
- mdm->verts = MEM_dupallocN( me->mvert );
- for (i=0; i<me->totvert; i++) {
- VECCOPY(mdm->verts[i].co, vertCos[i]);
- }
mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
mdm->freeNors = 1;
- mdm->freeVerts = 1;
+ for (i=0; i<me->totvert; i++) {
+ MVert *mv= &mdm->verts[i];
+ MVert *fsv;
+ fsv = &ob->fluidsimSettings->meshSurfNormals[i];
+ VECCOPY(mv->no, fsv->no);
+ //mv->no[0]= 30000; mv->no[1]= mv->no[2]= 0; // DEBUG fixed test normals
+ }
} else {
+ // recompute normally
+
+ if (vertCos) {
+ int i;
+
+ /* copy the original verts to preserve flag settings; if this is too
+ * costly, must at least use MEM_callocN to clear flags */
+ mdm->verts = MEM_dupallocN( me->mvert );
+ for (i=0; i<me->totvert; i++) {
+ VECCOPY(mdm->verts[i].co, vertCos[i]);
+ }
+ mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
+ mdm->freeNors = 1;
+ mdm->freeVerts = 1;
+ } else {
// XXX this is kinda hacky because we shouldn't really be editing
// the mesh here, however, we can't just call mesh_build_faceNormals(ob)
// because in the case when a key is applied to a mesh the vertex normals
// would never be correctly computed.
- mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
- mdm->freeNors = 1;
- }
+ mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
+ mdm->freeNors = 1;
+ }
+ } // fs TEST
return (DerivedMesh*) mdm;
}
@@ -2072,8 +2092,9 @@ void writeBobjgz(char *filename, struct Object *ob)
wri = dlm->totvert;
gzwrite(gzf, &wri, sizeof(wri));
for(i=0; i<wri;i++) {
- VECCOPY(vec, dlm->mvert[i].co); /* get transformed point */
- Mat4MulVecfl(ob->obmat, vec);
+ VECCOPY(vec, dlm->mvert[i].co);
+ //VECCOPY(vec, dlm->mvert[i].co); /* get transformed point */
+ //Mat4MulVecfl(ob->obmat, vec);
for(j=0; j<3; j++) {
wrf = vec[j];
gzwrite(gzf, &wrf, sizeof( wrf ));
@@ -2087,7 +2108,8 @@ void writeBobjgz(char *filename, struct Object *ob)
for(i=0; i<wri;i++) {
VECCOPY(vec, dlm->mvert[i].no);
// FIXME divide? mv->no[0]= (short)(no[0]*32767.0);
- Mat3MulVecfl(rotmat, vec);
+ //VECCOPY(vec, dlm->mvert[i].no);
+ //Mat3MulVecfl(rotmat, vec);
Normalise(vec);
for(j=0; j<3; j++) {
wrf = vec[j];
@@ -2130,8 +2152,63 @@ void writeBobjgz(char *filename, struct Object *ob)
dm->release(dm);
}
+void initElbeemMesh(struct Object *ob,
+ int *numVertices, float **vertices,
+ int *numTriangles, int **triangles)
+{
+ DispListMesh *dlm = NULL;
+ DerivedMesh *dm = NULL;
+ MFace *mface = NULL;
+ int countTris=0, i;
+ float *verts;
+ int *tris;
+
+ dm = mesh_create_derived_render(ob);
+ if(!dm) { *numVertices = *numTriangles = 0; *triangles=NULL; *vertices=NULL; }
+ dlm = dm->convertToDispListMesh(dm, 1);
+ if(!dlm) { dm->release(dm); *numVertices = *numTriangles = 0; *triangles=NULL; *vertices=NULL; }
+ mface = dlm->mface;
+
+ *numVertices = dlm->totvert;
+ verts = MEM_callocN( dlm->totvert*3*sizeof(float), "elbeemmesh_vertices");
+ for(i=0; i<dlm->totvert; i++) {
+ VECCOPY( &verts[i*3], dlm->mvert[i].co);
+ }
+ *vertices = verts;
+
+ for(i=0; i<dlm->totface; i++) {
+ countTris++;
+ if(mface[i].v4) { countTris++; }
+ }
+ *numTriangles = countTris;
+ tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles");
+ countTris = 0;
+ for(i=0; i<dlm->totface; i++) {
+ int face[4];
+ face[0] = mface[i].v1;
+ face[1] = mface[i].v2;
+ face[2] = mface[i].v3;
+ face[3] = mface[i].v4;
+
+ tris[countTris*3+0] = face[0];
+ tris[countTris*3+1] = face[1];
+ tris[countTris*3+2] = face[2];
+ countTris++;
+ if(face[3]) {
+ tris[countTris*3+0] = face[0];
+ tris[countTris*3+1] = face[2];
+ tris[countTris*3+2] = face[3];
+ countTris++;
+ }
+ }
+ *triangles = tris;
+
+ if(dlm) displistmesh_free(dlm);
+ dm->release(dm);
+}
+
/* read .bobj.gz file into a fluidsimDerivedMesh struct */
-Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm)
+Mesh* readBobjgz(char *filename, Mesh *orgmesh, float* bbstart, float *bbsize) //, fluidsimDerivedMesh *fsdm)
{
int wri,i,j;
char debugStrBuffer[256];
@@ -2211,9 +2288,13 @@ Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm)
for(i=0; i<newmesh->totvert;i++) {
for(j=0; j<3; j++) {
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
- newmesh->mvert[i].no[j] = wrf*32767.0;
+ newmesh->mvert[i].no[j] = (short)(wrf*32767.0f);
+ //newmesh->mvert[i].no[j] = 0.5; // DEBUG tst
}
+ //fprintf(stderr," DEBDPCN nm%d, %d = %d,%d,%d \n",
+ //(int)(newmesh->mvert), i, newmesh->mvert[i].no[0], newmesh->mvert[i].no[1], newmesh->mvert[i].no[2]);
}
+ //fprintf(stderr," DPCN 0 = %d,%d,%d \n", newmesh->mvert[0].no[0], newmesh->mvert[0].no[1], newmesh->mvert[0].no[2]);
/* compute no. of triangles */
@@ -2258,6 +2339,61 @@ Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm)
return newmesh;
}
+/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
+void readVelgz(char *filename, Object *srcob)
+{
+ char debugStrBuffer[256];
+ int wri, i, j;
+ float wrf;
+ gzFile gzf;
+ MVert *vverts = srcob->fluidsimSettings->meshSurfNormals;
+ int len = strlen(filename);
+ Mesh *mesh = srcob->data;
+ // mesh and vverts have to be valid from loading...
+
+ // clean up in any case
+ for(i=0; i<mesh->totvert;i++) {
+ for(j=0; j<3; j++) {
+ vverts[i].co[j] = 0.;
+ }
+ }
+ if(srcob->fluidsimSettings->typeFlags&OB_FSDOMAIN_NOVECGEN) return;
+
+ if(len<7) {
+ //printf("readVelgz Eror: invalid filename '%s'\n",filename); // DEBUG
+ return;
+ }
+
+ // .bobj.gz , correct filename
+ // 87654321
+ filename[len-6] = 'v';
+ filename[len-5] = 'e';
+ filename[len-4] = 'l';
+
+ snprintf(debugStrBuffer,256,"Reading '%s' GZ_VEL... ",filename); elbeemDebugOut(debugStrBuffer);
+ gzf = gzopen(filename, "rb");
+ if (!gzf) {
+ //printf("readVelgz Eror: unable to open file '%s'\n",filename); // DEBUG
+ return;
+ }
+
+ gzread(gzf, &wri, sizeof( wri ));
+ if(wri != mesh->totvert) {
+ //printf("readVelgz Eror: invalid no. of velocities %d vs. %d aborting.\n" ,wri ,mesh->totvert ); // DEBUG
+ return;
+ }
+
+ for(i=0; i<mesh->totvert;i++) {
+ for(j=0; j<3; j++) {
+ gzread(gzf, &wrf, sizeof( wrf ));
+ vverts[i].co[j] = wrf;
+ }
+ //if(i<20) fprintf(stderr, "GZ_VELload %d = %f,%f,%f \n",i,vverts[i].co[0],vverts[i].co[1],vverts[i].co[2]); // DEBUG
+ }
+
+ gzclose(gzf);
+}
+
/* ***************************** fluidsim derived mesh ***************************** */
@@ -2297,6 +2433,9 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams)
if(srcob->data == srcob->fluidsimSettings->meshSurface)
srcob->data = srcob->fluidsimSettings->orgMesh;
srcob->fluidsimSettings->meshSurface = NULL;
+
+ if(srcob->fluidsimSettings->meshSurfNormals) MEM_freeN(srcob->fluidsimSettings->meshSurfNormals);
+ srcob->fluidsimSettings->meshSurfNormals = NULL;
}
// init bounding box
@@ -2305,7 +2444,7 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams)
lastBB[0] = bbSize[0]; // TEST
lastBB[1] = bbSize[1];
lastBB[2] = bbSize[2];
- fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize);
+ fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize, &srcob->fluidsimSettings->meshBB);
// check free fsmesh... TODO
if(!useRenderParams) {
@@ -2314,7 +2453,8 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams)
displaymode = srcob->fluidsimSettings->renderDisplayMode;
}
- snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d)\n", srcob->id.name, useRenderParams, displaymode); // debug
+ snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d), curFra=%d, sFra=%d #=%d \n",
+ srcob->id.name, useRenderParams, displaymode, G.scene->r.cfra, G.scene->r.sfra, curFrame ); // debug
elbeemDebugOut(debugStrBuffer); // debug
strncpy(targetDir, srcob->fluidsimSettings->surfdataPath, FILE_MAXDIR);
@@ -2335,7 +2475,11 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams)
snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile); // debug
elbeemDebugOut(debugStrBuffer); // debug
- mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh );
+ if(displaymode!=2) { // dont add bounding box for final
+ mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh ,NULL,NULL);
+ } else {
+ mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh, bbSize,bbSize );
+ }
if(!mesh) {
// display org. object upon failure
srcob->data = srcob->fluidsimSettings->orgMesh;
@@ -2347,13 +2491,27 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams)
}
srcob->fluidsimSettings->meshSurface = mesh;
srcob->data = mesh;
+ srcob->fluidsimSettings->meshSurfNormals = MEM_dupallocN(mesh->mvert);
+
+ // load vertex velocities, if they exist...
+ // TODO? use generate flag as loading flag as well?
+ // warning, needs original .bobj.gz mesh loading filename
+ if(displaymode==3) {
+ readVelgz(targetFile, srcob);
+ } else {
+ // no data for preview, only clear...
+ int i,j;
+ for(i=0; i<mesh->totvert;i++) { for(j=0; j<3; j++) { srcob->fluidsimSettings->meshSurfNormals[i].co[j] = 0.; }}
+ }
+
+ //fprintf(stderr,"LOADFLM DEBXHCH fs=%d 3:%d,%d,%d \n", (int)mesh, ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[0], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[1], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[2]);
return;
}
/* helper function */
/* init axis aligned BB for mesh object */
void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
- /*RET*/ float start[3], /*RET*/ float size[3] )
+ /*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh )
{
float bbsx=0.0, bbsy=0.0, bbsz=0.0;
float bbex=1.0, bbey=1.0, bbez=1.0;
@@ -2388,6 +2546,25 @@ void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
size[1] = bbey-bbsy;
size[2] = bbez-bbsz;
}
+
+ // init bounding box mesh?
+ if(bbmesh) {
+ int i,j;
+ Mesh *newmesh = NULL;
+ if(!(*bbmesh)) { newmesh = MEM_callocN(sizeof(Mesh), "fluidsimGetAxisAlignedBB_meshbb"); }
+ else { newmesh = *bbmesh; }
+
+ newmesh->totvert = 8;
+ if(!newmesh->mvert) newmesh->mvert = MEM_callocN(sizeof(MVert)*newmesh->totvert, "fluidsimBBMesh_bobjvertices");
+ for(i=0; i<8; i++) {
+ for(j=0; j<3; j++) newmesh->mvert[i].co[j] = start[j];
+ }
+
+ newmesh->totface = 6;
+ if(!newmesh->mface) newmesh->mface = MEM_callocN(sizeof(MFace)*newmesh->totface, "fluidsimBBMesh_bobjfaces");
+
+ *bbmesh = newmesh;
+ }
}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 51701c19ca0..9d8857d4119 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -1610,8 +1610,8 @@ static void dag_object_time_update_flags(Object *ob)
}
if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings)) {
// fluidsimSettings might not be initialized during load...
- if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
- ob->recalc |= OB_RECALC_DATA; // NT
+ if(ob->fluidsimSettings->type & (OB_FLUIDSIM_DOMAIN|OB_FLUIDSIM_PARTICLE)) {
+ ob->recalc |= OB_RECALC_DATA; // NT FSPARTICLE
}
}
break;
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 663fe02aaf0..2a95bd82872 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -51,6 +51,11 @@
#include "DNA_object_force.h"
#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
+// FSPARTICLE
+#include "DNA_object_fluidsim.h"
+#include "LBM_fluidsim.h"
+#include <zlib.h>
+#include <string.h>
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
@@ -1594,6 +1599,7 @@ void build_particle_system(Object *ob)
float *volengths= NULL, *folengths= NULL;
int deform=0, a, totpart, paf_sta, paf_end;
int waitcursor_set= 0, totvert, totface, curface, curvert;
+ int readMask =0, activeParts;
/* return conditions */
if(ob->type!=OB_MESH) return;
@@ -1604,6 +1610,104 @@ void build_particle_system(Object *ob)
if(paf->keys) MEM_freeN(paf->keys); /* free as early as possible, for returns */
paf->keys= NULL;
+ // FSPARTICLE all own created...
+ if( (1) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
+ (ob->fluidsimSettings) &&
+ (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) {
+ char *suffix = "fluidsurface_particles_#";
+ char *suffix2 = ".gz";
+ char filename[256];
+ int curFrame = G.scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading
+ int j, numFileParts;
+ gzFile gzf;
+ float vel[3];
+
+ if(ob==G.obedit) { // off...
+ paf->totpart = 1;
+ return;
+ }
+
+ // ok, start loading
+ strcpy(filename, ob->fluidsimSettings->surfdataPath);
+ strcat(filename, suffix);
+ BLI_convertstringcode(filename, G.sce, curFrame); // fixed #frame-no
+ strcat(filename, suffix2);
+
+ gzf = gzopen(filename, "rb");
+ if (!gzf) {
+ //char debugStrBuffer[256];
+ //define win32... snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s'\n", filename);
+ //elbeemDebugOut(debugStrBuffer);
+ paf->totpart = 1;
+ return;
+ }
+
+ gzread(gzf, &totpart, sizeof(totpart));
+ numFileParts = totpart;
+ totpart = (G.rendering)?totpart:(paf->disp*totpart)/100;
+ paf->totpart= totpart;
+ paf->totkey= 1;
+ /* initialize particles */
+ new_particle(paf);// ?
+ ftime = 0.0;
+ dtime= 0.0f;
+
+ // set up reading mask
+ //for(j=1; j<=4; j++ ){ if(ob->fluidsimSettings->guiDisplayMode&j) readMask |= (1<<j); }
+ readMask = ob->fluidsimSettings->guiDisplayMode;
+ activeParts=0;
+ // FIXME only allocate needed ones?
+
+ //fprintf(stderr,"FSPARTICLE debug set %s , tot%d mask=%d \n", filename, totpart, readMask );
+ for(a=0; a<totpart; a++, ftime+=dtime) {
+ int ptype=0;
+ short shsize=0;
+ float convertSize=0.0;
+ gzread(gzf, &ptype, sizeof( ptype ));
+ //if(a<25) fprintf(stderr,"FSPARTICLE debug set %s , a%d t=%d , mask=%d , active%d\n", filename, a, ptype, readMask, activeParts );
+ if(ptype&readMask) {
+ activeParts++;
+ pa= new_particle(paf);
+ pa->time= ftime;
+ pa->lifetime= ftime + G.scene->r.efra +1.0;
+ pa->co[0] = 0.0;
+ pa->co[1] =
+ pa->co[2] = 1.0*(float)a / (float)totpart;
+ pa->no[0] = pa->no[1] = pa->no[2] = 0.0;
+ pa->mat_nr= paf->omat;
+ gzread(gzf, &convertSize, sizeof( float ));
+ // convert range of 1.0-10.0 to shorts 1000-10000)
+ shsize = (short)(convertSize*1000.0);
+ pa->rt = shsize;
+ //if(a<200) fprintf(stderr,"SREAD %f %d %d \n",convertSize,shsize,pa->rt);
+
+ for(j=0; j<3; j++) {
+ float wrf;
+ gzread(gzf, &wrf, sizeof( wrf ));
+ pa->co[j] = wrf;
+ //fprintf(stderr,"Rj%d ",j);
+ }
+ for(j=0; j<3; j++) {
+ float wrf;
+ gzread(gzf, &wrf, sizeof( wrf ));
+ vel[j] = wrf;
+ }
+ } else {
+ // skip...
+ for(j=0; j<2*3+1; j++) {
+ float wrf; gzread(gzf, &wrf, sizeof( wrf ));
+ }
+ }
+ //fprintf(stderr,"FSPARTICLE debug set %s , a%d = %f,%f,%f , life=%f \n", filename, a, pa->co[0],pa->co[1],pa->co[2], pa->lifetime );
+ }
+ gzclose( gzf );
+
+ totpart = paf->totpart = activeParts;
+ //fprintf(stderr,"PARTOBH debug %s %d \n", ob->id.name, totpart); // DEBUG
+ return;
+ }
+
+
if(paf->end < paf->sta) return;
if( (paf->flag & PAF_OFACE) && (paf->flag & PAF_FACE)==0) return;
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 13821ea3712..c7587bbeb59 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -171,6 +171,13 @@ int snd_ar[SND_TOTIPO]= {
SND_VOLUME, SND_PITCH, SND_PANNING, SND_ATTEN
};
+int fluidsim_ar[FLUIDSIM_TOTIPO]= {
+ FLUIDSIM_VISC, FLUIDSIM_TIME,
+ FLUIDSIM_GRAV_X , FLUIDSIM_GRAV_Y , FLUIDSIM_GRAV_Z ,
+ FLUIDSIM_VEL_X , FLUIDSIM_VEL_Y , FLUIDSIM_VEL_Z ,
+ FLUIDSIM_ACTIVE
+};
+
float frame_to_float(int cfra) /* see also bsystem_time in object.c */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index ff1948af18d..cbe3195da27 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2371,6 +2371,10 @@ static void lib_link_object(FileData *fd, Main *main)
act= act->next;
}
+ if(ob->fluidsimSettings) {
+ ob->fluidsimSettings->ipo = newlibadr_us(fd, ob->id.lib, ob->fluidsimSettings->ipo);
+ }
+
lib_link_scriptlink(fd, &ob->id, &ob->scriptlink);
lib_link_modifiers(fd, ob);
}
diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h
index 06611ec6dda..8ae27f26e7d 100644
--- a/source/blender/include/BSE_editipo.h
+++ b/source/blender/include/BSE_editipo.h
@@ -58,6 +58,7 @@ char *getname_cu_ei(int nr);
char *getname_la_ei(int nr);
char *getname_cam_ei(int nr);
char *getname_snd_ei(int nr);
+char *getname_fluidsim_ei(int nr);
struct EditIpo *get_active_editipo(void);
diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h
index 82c9756f2b3..b5b0e5ac39e 100644
--- a/source/blender/include/butspace.h
+++ b/source/blender/include/butspace.h
@@ -252,8 +252,9 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
/* Fluidsim button defines */
#define B_FLUIDSIM_BAKE 1450
-#define B_FLUIDSIM_SELDIR 1451
+#define B_FLUIDSIM_SELDIR 1451
#define B_FLUIDSIM_FORCEREDRAW 1452
+#define B_FLUIDSIM_MAKEPART 1453
#define B_GROUP_RELINK 1460
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 71f4a30bb24..7e71da6df76 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -127,6 +127,7 @@ typedef struct Library {
#define ID_AR MAKE_ID2('A', 'R')
#define ID_AC MAKE_ID2('A', 'C')
#define ID_SCRIPT MAKE_ID2('P', 'Y')
+#define ID_FLUIDSIM MAKE_ID2('F', 'S')
#define ID_NT MAKE_ID2('N', 'T')
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */
diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h
index c05c27ede6b..fc30c1ec5e6 100644
--- a/source/blender/makesdna/DNA_ipo_types.h
+++ b/source/blender/makesdna/DNA_ipo_types.h
@@ -326,6 +326,26 @@ typedef short IPO_Channel;
#define CO_ROLL 9
*/
+/* ******************** */
+/* fluidsim ipos NT */
+
+#define FLUIDSIM_TOTIPO 9
+#define FLUIDSIM_TOTNAM 9
+
+#define FLUIDSIM_VISC 1
+#define FLUIDSIM_TIME 2
+
+#define FLUIDSIM_GRAV_X 3
+#define FLUIDSIM_GRAV_Y 4
+#define FLUIDSIM_GRAV_Z 5
+
+#define FLUIDSIM_VEL_X 6
+#define FLUIDSIM_VEL_Y 7
+#define FLUIDSIM_VEL_Z 8
+
+#define FLUIDSIM_ACTIVE 9
+
+
/* these are IpoCurve specific */
/* **************** IPO ********************* */
diff --git a/source/blender/makesdna/DNA_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim.h
index 1b5b77591f7..e2e2ecd5570 100644
--- a/source/blender/makesdna/DNA_object_fluidsim.h
+++ b/source/blender/makesdna/DNA_object_fluidsim.h
@@ -33,12 +33,15 @@
#ifndef DNA_OBJECT_FLUIDSIM_H
#define DNA_OBJECT_FLUIDSIM_H
+#include "DNA_ID.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Mesh;
+struct Ipo;
+struct MVert;
typedef struct FluidsimSettings {
/* domain,fluid or obstacle */
@@ -87,6 +90,24 @@ typedef struct FluidsimSettings {
/* store start coords of axis aligned bounding box together with size */
/* values are inited during derived mesh display */
float bbStart[3], bbSize[3];
+
+ /* animated params */
+ struct Ipo *ipo;
+
+ /* additional flags depending on the type, lower short contains flags
+ * to check validity, higher short additional flags */
+ int typeFlags;
+
+ /* boundary "stickiness" for part slip values */
+ float partSlipValue;
+ /* particle generation - on if >0, then determines amount */
+ float generateParticles, dummy;
+ /* particle display - size scaling, and alpha influence */
+ float particleInfSize, particleInfAlpha;
+
+ /* save fluidsurface normals in mvert.no, and surface vertex velocities (if available) in mvert.co */
+ struct MVert *meshSurfNormals;
+
} FluidsimSettings;
/* ob->fluidsimSettings defines */
@@ -96,6 +117,24 @@ typedef struct FluidsimSettings {
#define OB_FLUIDSIM_OBSTACLE 8
#define OB_FLUIDSIM_INFLOW 16
#define OB_FLUIDSIM_OUTFLOW 32
+#define OB_FLUIDSIM_PARTICLE 64
+
+#define OB_TYPEFLAG_START 16
+#define OB_FSGEO_THIN (1<<(OB_TYPEFLAG_START+1))
+#define OB_FSBND_NOSLIP (1<<(OB_TYPEFLAG_START+2))
+#define OB_FSBND_PARTSLIP (1<<(OB_TYPEFLAG_START+3))
+#define OB_FSBND_FREESLIP (1<<(OB_TYPEFLAG_START+4))
+#define OB_FSINFLOW_LOCALCOORD (1<<(OB_TYPEFLAG_START+5))
+#define OB_FSDOMAIN_NOVECGEN (1<<(OB_TYPEFLAG_START+6))
+
+// guiDisplayMode particle flags
+#define OB_FSDOM_GEOM 1
+#define OB_FSDOM_PREVIEW 2
+#define OB_FSDOM_FINAL 3
+#define OB_FSPART_BUBBLE (1<<1)
+#define OB_FSPART_DROP (1<<2)
+#define OB_FSPART_NEWPART (1<<3)
+#define OB_FSPART_FLOAT (1<<4)
#ifdef __cplusplus
}
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 937a5834964..6498cf534ba 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -56,6 +56,7 @@
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
+#include "DNA_object_fluidsim.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "DNA_view3d_types.h"
@@ -447,6 +448,104 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_
}
}
+// NT same as calc_vertexnormals, but dont modify the existing vertex normals
+// only recalculate other render data. If this is at some point used for other things than fluidsim,
+// this could be made on option for the normal calc_vertexnormals
+static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int do_tangent)
+{
+ int a;
+
+ /* dont clear vertex normals here */
+ // OFF for(a=startvert; a<re->totvert; a++) { VertRen *ver= RE_findOrAddVert(re, a); ver->n[0]=ver->n[1]=ver->n[2]= 0.0; }
+ /* calculate cos of angles and point-masses, use as weight factor to add face normal to vertex */
+ for(a=startvlak; a<re->totvlak; a++) {
+ VlakRen *vlr= RE_findOrAddVlak(re, a);
+ if(vlr->flag & ME_SMOOTH) {
+ VertRen *adrve1= vlr->v1;
+ VertRen *adrve2= vlr->v2;
+ VertRen *adrve3= vlr->v3;
+ VertRen *adrve4= vlr->v4;
+ float n1[3], n2[3], n3[3], n4[3];
+ float fac1, fac2, fac3, fac4=0.0f;
+
+ VecSubf(n1, adrve2->co, adrve1->co);
+ Normalise(n1);
+ VecSubf(n2, adrve3->co, adrve2->co);
+ Normalise(n2);
+ if(adrve4==NULL) {
+ VecSubf(n3, adrve1->co, adrve3->co);
+ Normalise(n3);
+ fac1= saacos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]);
+ fac2= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
+ fac3= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
+ }
+ else {
+ VecSubf(n3, adrve4->co, adrve3->co);
+ Normalise(n3);
+ VecSubf(n4, adrve1->co, adrve4->co);
+ Normalise(n4);
+
+ fac1= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
+ fac2= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
+ fac3= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
+ fac4= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
+
+ if(!(vlr->flag & R_NOPUNOFLIP)) {
+ if( contrpuntnormr(vlr->n, adrve4->n) ) fac4= -fac4;
+ }
+ }
+
+ if(do_tangent)
+ calc_tangent_vector(re, vlr, fac1, fac2, fac3, fac4);
+ }
+ }
+
+ /* do solid faces */
+ for(a=startvlak; a<re->totvlak; a++) {
+ VlakRen *vlr= RE_findOrAddVlak(re, a);
+ if((vlr->flag & ME_SMOOTH)==0) {
+ float *f1= vlr->v1->n;
+ if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
+ f1= vlr->v2->n;
+ if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
+ f1= vlr->v3->n;
+ if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
+ if(vlr->v4) {
+ f1= vlr->v4->n;
+ if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
+ }
+ }
+ }
+
+ /* normalise vertex normals */
+ for(a=startvert; a<re->totvert; a++) {
+ VertRen *ver= RE_findOrAddVert(re, a);
+ Normalise(ver->n);
+ if(do_tangent) {
+ float *tav= RE_vertren_get_tangent(re, ver, 0);
+ if(tav) Normalise(tav);
+ }
+ }
+
+ /* vertex normal (puno) switch flags for during render */
+ for(a=startvlak; a<re->totvlak; a++) {
+ VlakRen *vlr= RE_findOrAddVlak(re, a);
+ if((vlr->flag & R_NOPUNOFLIP)==0) {
+ VertRen *adrve1= vlr->v1;
+ VertRen *adrve2= vlr->v2;
+ VertRen *adrve3= vlr->v3;
+ VertRen *adrve4= vlr->v4;
+ vlr->puno &= ~15;
+ if ((vlr->n[0]*adrve1->n[0]+vlr->n[1]*adrve1->n[1]+vlr->n[2]*adrve1->n[2])<0.0) vlr->puno= 1;
+ if ((vlr->n[0]*adrve2->n[0]+vlr->n[1]*adrve2->n[1]+vlr->n[2]*adrve2->n[2])<0.0) vlr->puno+= 2;
+ if ((vlr->n[0]*adrve3->n[0]+vlr->n[1]*adrve3->n[1]+vlr->n[2]*adrve3->n[2])<0.0) vlr->puno+= 4;
+ if(adrve4) {
+ if((vlr->n[0]*adrve4->n[0]+vlr->n[1]*adrve4->n[1]+vlr->n[2]*adrve4->n[2])<0.0) vlr->puno+= 8;
+ }
+ }
+ }
+}
+
/* ------------------------------------------------------------------------- */
/* Autosmoothing: */
/* ------------------------------------------------------------------------- */
@@ -742,6 +841,12 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf)
float xn, yn, zn, imat[3][3], tmat[4][4], mat[4][4], hasize, stime, ptime, ctime, vec[3], vec1[3], view[3], nor[3];
int a, mat_nr=1, seed;
+ int useFluidsimParticles = 0; // FSPARTICLE
+ float haloScale = 1.0; //NT scale halos
+ float iniAlpha = 0.0; // restore material alpha
+
+
+
pa= paf->keys;
if(pa==NULL || paf->disp!=100) {
build_particle_system(ob);
@@ -767,6 +872,10 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf)
else ptime= 0.0;
ctime= bsystem_time(ob, 0, (float)re->scene->r.cfra, ptime);
seed= ma->seed1;
+ if( (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) {
+ useFluidsimParticles = 1;
+ iniAlpha = ma->alpha;
+ }
for(a=0; a<paf->totpart; a++, pa+=paf->totkey, seed++) {
@@ -810,7 +919,16 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf)
execute_ipo((ID *)ma, ma->ipo);
}
- hasize= ma->hasize;
+ //NT scale halos FSPARTICLE
+ if(useFluidsimParticles) {
+ // rescale to 1.0-10.0, then div by 5 afterwards, gives values in range 0.2-2.0
+ double fspsize = ((double)pa->rt / 1000.0f) / 5.0 ;
+ haloScale = (float)pow(fspsize, (double)ob->fluidsimSettings->particleInfSize);
+ ma->alpha = iniAlpha / (float)pow( fspsize, (double)ob->fluidsimSettings->particleInfAlpha);
+ if(ma->alpha>1.) ma->alpha = 1.;
+ }
+
+ hasize= ma->hasize * haloScale;
if(ma->mode & MA_HALOPUNO) {
xn= pa->no[0];
@@ -852,6 +970,8 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf)
MEM_freeN(paf->keys);
paf->keys= NULL;
}
+
+ if(useFluidsimParticles) { ma->alpha = iniAlpha; }// FSPARTICLE restore...
}
@@ -1442,6 +1562,7 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts)
float *orco=0;
int a, a1, ok, need_orco=0, need_stress=0, need_tangent=0, totvlako, totverto, vertofs;
int end, do_autosmooth=0, totvert = 0, dm_needsfree;
+ int useFluidmeshNormals = 0; // NT fluidsim, use smoothed normals?
me= ob->data;
@@ -1493,6 +1614,12 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts)
dm_needsfree= 1;
if(dm==NULL) return; /* in case duplicated object fails? */
+
+ if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
+ (ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&&
+ (ob->fluidsimSettings->meshSurface) ) {
+ useFluidmeshNormals = 1;
+ }
dlm = dm->convertToDispListMesh(dm, 1);
@@ -1514,6 +1641,16 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts)
if(do_autosmooth==0) /* autosmooth on original unrotated data to prevent differences between frames */
MTC_Mat4MulVecfl(mat, ver->co);
+ if(useFluidmeshNormals) {
+ xn = mvert->no[0]/ 32767.0;
+ yn = mvert->no[1]/ 32767.0;
+ zn = mvert->no[2]/ 32767.0;
+ /* transfor to cam space */
+ ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+ } // useFluidmeshNormals
+
if(orco) {
ver->orco= orco;
orco+=3;
@@ -1705,7 +1842,12 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts)
autosmooth(re, mat, totverto, totvlako, me->smoothresh);
}
- calc_vertexnormals(re, totverto, totvlako, need_tangent);
+ if(useFluidmeshNormals) {
+ // do not recalculate, only init render data
+ calc_fluidsimnormals(re, totverto, totvlako, need_tangent);
+ } else {
+ calc_vertexnormals(re, totverto, totvlako, need_tangent);
+ }
if(need_stress)
calc_edge_stress(re, me, totverto, totvlako);
@@ -3126,9 +3268,84 @@ static void calculate_speedvectors(Render *re, float *vectors, int startvert, in
speed[0]= zco[0];
speed[1]= zco[1];
}
+
}
}
+static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert, int endvert, int step, Object *fsob)
+{
+ VertRen *ver= NULL;
+ float *speed, div, zco[2];
+ float zmulx= re->winx/2, zmuly= re->winy/2, len;
+ float winsq= re->winx*re->winy, winroot= sqrt(winsq);
+ int a, j;
+ float hoco[4], fsvec[4], camco[4];
+ float mat[4][4];
+ float imat[4][4];
+ MVert *vverts;
+
+ /* only one step needed */
+ if(step) return 1;
+
+ Mat4CpyMat4(mat, re->viewmat);
+ MTC_Mat4Invert(imat, mat);
+
+ /* set first vertex OK */
+ a= startvert-1;
+ ver= re->vertnodes[a>>8].vert + (a & 255);
+
+ if( (!fsob->fluidsimSettings) || (!fsob->fluidsimSettings->meshSurfNormals) ) return 0;
+ vverts = fsob->fluidsimSettings->meshSurfNormals;
+ //fprintf(stderr, "GZ_VEL obj '%s', calc load_fluidsimspeedvectors\n",fsob->id.name); // NT DEBUG
+
+ if( endvert-startvert != fsob->fluidsimSettings->meshSurface->totvert ) {
+ //fprintf(stderr, "load_fluidsimspeedvectors - modified fluidsim mesh, not using speed vectors (%d,%d)...\n", endvert-startvert , fsob->fluidsimSettings->meshSurface->totvert); // DEBUG
+ return 0;
+ }
+
+ for(a=startvert; a<endvert; a++, vectors+=2) {
+ if((a & 255)==0)
+ ver= re->vertnodes[a>>8].vert;
+ else
+ ver++;
+
+ // get fluid velocity
+ fsvec[3] = 0.;
+ //fsvec[0] = fsvec[1] = fsvec[2] = fsvec[3] = 0.; fsvec[2] = 2.; // NT fixed test
+ for(j=0;j<3;j++) fsvec[j] = vverts[a-startvert].co[j];
+
+ // transform (=rotate) to cam space
+ camco[0]= imat[0][0]*fsvec[0] + imat[0][1]*fsvec[1] + imat[0][2]*fsvec[2];
+ camco[1]= imat[1][0]*fsvec[0] + imat[1][1]*fsvec[1] + imat[1][2]*fsvec[2];
+ camco[2]= imat[2][0]*fsvec[0] + imat[2][1]*fsvec[1] + imat[2][2]*fsvec[2];
+
+ // get homogenous coordinates
+ projectverto(camco, re->winmat, hoco);
+
+ /* now map hocos to screenspace, uses very primitive clip still */
+ // use ho[3] of original vertex, xy component of vel. direction
+ if(ver->ho[3]<0.1f) div= 10.0f;
+ else div= 1.0f/ver->ho[3];
+ zco[0]= zmulx*hoco[0]*div;
+ zco[1]= zmuly*hoco[1]*div;
+
+ // maximize speed as usual
+ len= zco[0]*zco[0] + zco[1]*zco[1];
+ if(len > winsq) {
+ len= winroot/sqrt(len);
+ zco[0]*= len; zco[1]*= len;
+ }
+
+ speed= RE_vertren_get_winspeed(re, ver, 1);
+ // set both to the same value
+ speed[0]= speed[2]= zco[0];
+ speed[1]= speed[3]= zco[1];
+ //if(a<20) fprintf(stderr,"speed %d %f,%f | camco %f,%f,%f | hoco %f,%f,%f,%f \n", a, speed[0], speed[1], camco[0],camco[1], camco[2], hoco[0],hoco[1], hoco[2],hoco[3]); // NT DEBUG
+ }
+
+ return 1;
+}
+
/* makes copy per object of all vectors */
/* result should be that we can free entire database */
static void copy_dbase_object_vectors(Render *re, ListBase *lb)
@@ -3236,13 +3453,21 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
// printf("speed table: missing object %s\n", obren->ob->id.name+2);
continue;
}
- /* check if both have same amounts of vertices */
- if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert) {
- printf("Warning: object %s has different amount of vertices on other frame\n", obren->ob->id.name+2);
- continue;
- }
-
- calculate_speedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step);
+
+ // NT check for fluidsim special treatment
+ if((obren->ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (obren->ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)) {
+ // use preloaded per vertex simulation data , only does calculation for step=1
+ // NOTE/FIXME - velocities and meshes loaded unnecessarily often during the database_fromscene_vectors calls...
+ load_fluidsimspeedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step, obren->ob);
+ } else {
+ /* check if both have same amounts of vertices */
+ if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert) {
+ printf("Warning: object %s has different amount of vertices on other frame\n", obren->ob->id.name+2);
+ continue;
+ }
+
+ calculate_speedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step);
+ } // not fluidsim
}
}
}
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index 9f43e06926c..f584109db81 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -1377,6 +1377,27 @@ void do_object_panels(unsigned short event)
/* write config files (currently no simulation) */
fluidsimBake(ob);
break;
+ case B_FLUIDSIM_MAKEPART:
+ ob= OBACT;
+ {
+ PartEff *paf= NULL;
+ /* prepare fluidsim particle display */
+ // simplified delete effect, create new - recalc some particles...
+ if(ob==NULL || ob->type!=OB_MESH) break;
+ ob->fluidsimSettings->type = 0;
+ // reset type, and init particle system once normally
+ eff= ob->effect.first;
+ //if((eff) && (eff->flag & SELECT)) { BLI_remlink(&ob->effect, eff); free_effect(eff); }
+ if(!eff){ copy_act_effect(ob); DAG_scene_sort(G.scene); }
+ paf = give_parteff(ob);
+ paf->totpart = 1000; paf->sta = paf->end = 1.0; // generate some particles...
+ build_particle_system(ob);
+
+ ob->fluidsimSettings->type = OB_FLUIDSIM_PARTICLE;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSOBJECT, 0);
+ break;
case B_FLUIDSIM_SELDIR: {
ScrArea *sa = closest_bigger_area();
ob= OBACT;
@@ -2290,6 +2311,7 @@ static void object_panel_fluidsim(Object *ob)
uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Inflow", 90, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_INFLOW, 20.0, 4.0, "Object adds fluid to the simulation.");
uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Outflow", 160, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_OUTFLOW, 20.0, 5.0, "Object removes fluid from the simulation.");
+ uiDefButS(block, ROW, B_FLUIDSIM_MAKEPART ,"Particle", 230, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_PARTICLE,20.0, 3.0, "Object is a fixed obstacle.");
uiBlockEndAlign(block);
yline -= lineHeight;
yline -= 2*separateHeight;
@@ -2304,7 +2326,11 @@ static void object_panel_fluidsim(Object *ob)
elbeemEstimateMemreq(fss->resolutionxyz,
ob->fluidsimSettings->bbSize[0],ob->fluidsimSettings->bbSize[1],ob->fluidsimSettings->bbSize[2], fss->maxRefine, memString);
- uiDefButBitS(block, TOG, 1, REDRAWBUTSOBJECT, "Advanced>>", 0,yline, 75,objHeight, &fss->show_advancedoptions, 0, 0, 0, 0, "Show advanced domain options.");
+ //uiDefButBitS(block, TOG, 1, REDRAWBUTSOBJECT, "Advanced>>", 0,yline, 75,objHeight, &fss->show_advancedoptions, 0, 0, 0, 0, "Show advanced domain options.");
+ uiDefButS(block, ROW, REDRAWBUTSOBJECT, "Std", 0,yline, 25,objHeight, &fss->show_advancedoptions, 16.0, 0, 20.0, 0, "Show standard domain options.");
+ uiDefButS(block, ROW, REDRAWBUTSOBJECT, "Adv", 25,yline, 25,objHeight, &fss->show_advancedoptions, 16.0, 1, 20.0, 1, "Show advanced domain options.");
+ uiDefButS(block, ROW, REDRAWBUTSOBJECT, "Bnd", 50,yline, 25,objHeight, &fss->show_advancedoptions, 16.0, 2, 20.0, 2, "Show domain boundary options.");
+
uiDefBut(block, BUT, B_FLUIDSIM_BAKE, "BAKE",90, yline,210,objHeight, NULL, 0.0, 0.0, 10, 0, "Perform simulation and output and surface&preview meshes for each frame.");
yline -= lineHeight;
yline -= 2*separateHeight;
@@ -2324,6 +2350,7 @@ static void object_panel_fluidsim(Object *ob)
yline -= lineHeight;
yline -= 2*separateHeight;
+ if((fss->guiDisplayMode<1) || (fss->guiDisplayMode>3)){ fss->guiDisplayMode=2; } // can be changed by particle setting
uiDefBut(block, LABEL, 0, "Disp.-Qual.:", 0,yline, 90,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButS(block, MENU, B_FLUIDSIM_FORCEREDRAW, "GuiDisplayMode%t|Geometry %x1|Preview %x2|Final %x3",
90,yline,105,objHeight, &fss->guiDisplayMode, 0, 0, 0, 0, "How to display the fluid mesh in the blender gui.");
@@ -2335,7 +2362,7 @@ static void object_panel_fluidsim(Object *ob)
uiDefIconBut(block, BUT, B_FLUIDSIM_SELDIR, ICON_FILESEL, 0, yline, 20, objHeight, 0, 0, 0, 0, 0, "Select Directory (and/or filename prefix) to store baked fluid simulation files in");
uiDefBut(block, TEX, B_FLUIDSIM_FORCEREDRAW,"", 20, yline, 280, objHeight, fss->surfdataPath, 0.0,79.0, 0, 0, "Enter Directory (and/or filename prefix) to store baked fluid simulation files in");
// FIXME what is the 79.0 above?
- } else {
+ } else if(fss->show_advancedoptions == 1) {
// advanced options
uiBlockBeginAlign(block);
uiDefBut(block, LABEL, 0, "Gravity:", 0, yline, 90,objHeight, NULL, 0.0, 0, 0, 0, "");
@@ -2362,7 +2389,7 @@ static void object_panel_fluidsim(Object *ob)
yline -= 1*separateHeight;
uiDefBut(block, LABEL, 0, "Realworld-size:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
- uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->realsize, 0.001, 1.0, 10, 0, "Size of the simulation domain in meters.");
+ uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->realsize, 0.001, 10.0, 10, 0, "Size of the simulation domain in meters.");
yline -= lineHeight;
yline -= 2*separateHeight;
@@ -2374,6 +2401,31 @@ static void object_panel_fluidsim(Object *ob)
uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->gstar, 0.001, 0.10, 10,0, "Allowed compressibility due to gravitational force for standing fluid (directly affects simulation step size).");
yline -= lineHeight;
+ } else if(fss->show_advancedoptions == 2) {
+ // copied from obstacle...
+ //yline -= lineHeight + 5;
+ uiDefBut(block, LABEL, 0, "Domain boundary type settings:", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
+ yline -= lineHeight;
+ uiBlockBeginAlign(block);
+ uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Noslip", 00, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_NOSLIP, 20.0, 1.0, "Obstacle causes zero normal and tangential velocity (=sticky). Default for all. Only option for moving objects.");
+ uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Part", 100, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_PARTSLIP, 20.0, 2.0, "Mix between no-slip and free-slip. Non moving objects only!");
+ uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Free", 200, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_FREESLIP, 20.0, 3.0, "Obstacle only causes zero normal velocity (=not sticky). Non moving objects only!");
+ uiBlockEndAlign(block);
+ yline -= lineHeight;
+ if(fss->typeFlags&OB_FSBND_PARTSLIP) {
+ uiDefBut(block, LABEL, 0, "PartSlipValue:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
+ uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->partSlipValue, 0.0, 0.1, 10,0, ".");
+ yline -= lineHeight;
+ }
+
+ uiDefBut(block, LABEL, 0, "Generate Particles:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
+ uiDefButF(block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->generateParticles, 0.0, 10.0, 10,0, "Amount of particles to generate (0=off, 1=normal, >1=more).");
+ yline -= lineHeight;
+
+ uiDefBut(block, LABEL, 0, "Generate&Use SpeedVecs:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
+ uiDefButBitI(block, TOG, OB_FSDOMAIN_NOVECGEN, REDRAWBUTSOBJECT, "Disable", 200, yline,100,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Default is to generate and use fluidsim vertex speed vectors, this option switches calculation off during bake, and disables loading.");
+ yline -= lineHeight;
+ // copied from obstacle...
}
}
else if(
@@ -2390,15 +2442,64 @@ static void object_panel_fluidsim(Object *ob)
uiDefButF(block, NUM, B_DIFF, "Z:", 200, yline, 100,objHeight, &fss->iniVelz, -1000.1, 1000.1, 10, 0, "Fluid velocity in Z direction");
uiBlockEndAlign(block);
yline -= lineHeight;
+
+ if(fss->type == OB_FLUIDSIM_INFLOW) {
+ uiDefBut(block, LABEL, 0, "Local Inflow Coords", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
+ uiDefButBitI(block, TOG, OB_FSINFLOW_LOCALCOORD, REDRAWBUTSOBJECT, "Enable", 200, yline,100,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Use local coordinates for inflow (e.g. for rotating objects).");
+ yline -= lineHeight;
+ }
}
- else if(
- (fss->type == OB_FLUIDSIM_OBSTACLE)
- || (fss->type == OB_FLUIDSIM_OUTFLOW)
- ) {
+ else if( (fss->type == OB_FLUIDSIM_OUTFLOW) ) {
yline -= lineHeight + 5;
uiDefBut(block, LABEL, 0, "No additional settings as of now...", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
+ }
+ else if( (fss->type == OB_FLUIDSIM_OBSTACLE) ) {
+ yline -= lineHeight + 5;
+
+ uiBlockBeginAlign(block);
+ uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Noslip", 00, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_NOSLIP, 20.0, 1.0, "Obstacle causes zero normal and tangential velocity (=sticky). Default for all. Only option for moving objects.");
+ uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Part", 100, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_PARTSLIP, 20.0, 2.0, "Mix between no-slip and free-slip. Non moving objects only!");
+ uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Free", 200, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_FREESLIP, 20.0, 3.0, "Obstacle only causes zero normal velocity (=not sticky). Non moving objects only!");
+ uiBlockEndAlign(block);
+ yline -= lineHeight;
+
+ if(fss->typeFlags&OB_FSBND_PARTSLIP) {
+ uiDefBut(block, LABEL, 0, "PartSlipValue:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
+ uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->partSlipValue, 0.0, 0.1, 10,0, ".");
+ yline -= lineHeight;
+ }
+
yline -= lineHeight;
}
+ else if(fss->type == OB_FLUIDSIM_PARTICLE) {
+
+ if(fss->guiDisplayMode==0) fss->guiDisplayMode=2; // default drops
+ uiDefBut(block, LABEL, 0, "Part.-Type:", 0,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "");
+ // TODO make toggle buttons
+ //uiDefButS(block, MENU, B_FLUIDSIM_FORCEREDRAW, "Gui%t|Bubble %x2|Drop %x4|Newparts %x8|Float %x16",
+ //100,yline,200,objHeight, &fss->guiDisplayMode, 0, 0, 0, 0, "Which type of particles to display.");
+ //uiDefButS(block, MENU, B_DIFF, "Render%t|Geometry %x1|Preview %x2|Final %x3",
+ //195,yline,105,objHeight, &fss->renderDisplayMode, 0, 0, 0, 0, "How to display the fluid mesh for rendering.");
+ uiDefBut(block, LABEL, 0, "Drops", 100,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
+ fss->guiDisplayMode = 4; // fix to drops for now
+ yline -= lineHeight;
+
+ uiDefBut(block, LABEL, 0, "Size Influence:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
+ uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->particleInfSize, 0.0, 2.0, 10,0, "Amount of particle size scaling: 0=off (all same size), 1=full (range 0.2-2.0), >1=stronger.");
+ yline -= lineHeight;
+ uiDefBut(block, LABEL, 0, "Alpha Influence:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
+ uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->particleInfAlpha, 0.0, 2.0, 10,0, "Amount of particle alpha change, inverse of size influence: 0=off (all same alpha), 1=full (large particles get lower alphas, smaller ones higher values).");
+ yline -= lineHeight;
+
+ yline -= 1*separateHeight;
+
+ // FSPARTICLE also select input files
+ uiDefIconBut(block, BUT, B_FLUIDSIM_SELDIR, ICON_FILESEL, 0, yline, 20, objHeight, 0, 0, 0, 0, 0, "Select Directory (and/or filename prefix) to store baked fluid simulation files in");
+ uiDefBut(block, TEX, B_FLUIDSIM_FORCEREDRAW,"", 20, yline, 280, objHeight, fss->surfdataPath, 0.0,79.0, 0, 0, "Enter Directory (and/or filename prefix) to store baked fluid simulation files in");
+ yline -= lineHeight;
+
+
+ }
else {
yline -= lineHeight + 5;
/* not yet set */
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index 7a09fc9a80d..697dcce20cb 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -67,6 +67,8 @@
#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
+// FSPARTICLE
+#include "DNA_object_fluidsim.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
@@ -2502,7 +2504,10 @@ static void draw_particle_system(Object *ob, PartEff *paf)
int a, totpart;
pa= paf->keys;
- if(pa==NULL) {
+ // FSPARTICLE always rebuild fluid particle system upon change...
+ if( (pa==NULL)
+ || ( (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE))
+ ) {
build_particle_system(ob);
pa= paf->keys;
if(pa==NULL) return;
@@ -2558,7 +2563,10 @@ static void draw_static_particle_system(Object *ob, PartEff *paf, int dt)
int a, use_norm=0, totpart;
pa= paf->keys;
- if(pa==NULL) {
+ // FSPARTICLE always rebuild upon change...
+ if( (pa==NULL)
+ || ( (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE))
+ ) {
build_particle_system(ob);
pa= paf->keys;
if(pa==NULL) return;
diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c
index b8953a63fc6..aaf60c62ceb 100644
--- a/source/blender/src/editipo.c
+++ b/source/blender/src/editipo.c
@@ -60,6 +60,7 @@
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
+#include "DNA_object_fluidsim.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
@@ -122,6 +123,7 @@ extern int snd_ar[];
extern int ac_ar[];
extern int co_ar[];
extern int te_ar[];
+extern int fluidsim_ar[]; // NT
/* forwards */
#define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
@@ -428,6 +430,32 @@ static void make_ob_editipo(Object *ob, SpaceIpo *si)
ei++;
}
+ //fprintf(stderr,"FSIMAKE_OPBJ call %d \n", si->totipo);
+}
+
+// copied from make_seq_editipo
+static void make_fluidsim_editipo(SpaceIpo *si) // NT
+{
+ EditIpo *ei;
+ int a;
+ char *name;
+ ei= si->editipo= MEM_callocN(FLUIDSIM_TOTIPO*sizeof(EditIpo), "fluidsim_editipo");
+ si->totipo = FLUIDSIM_TOTIPO;
+ for(a=0; a<FLUIDSIM_TOTIPO; a++) {
+ //fprintf(stderr,"FSINAME %d %d \n",a,fluidsim_ar[a], (int)(getname_fluidsim_ei(fluidsim_ar[a])) );
+ name = getname_fluidsim_ei(fluidsim_ar[a]);
+ strcpy(ei->name, name);
+ ei->adrcode= fluidsim_ar[a];
+ ei->col= ipo_rainbow(a, FLUIDSIM_TOTIPO);
+ ei->icu= find_ipocurve(si->ipo, ei->adrcode);
+ if(ei->icu) {
+ ei->flag = ei->icu->flag;
+ }
+ //else { ei->flag |= IPO_VISIBLE; }
+ //fprintf(stderr,"FSIMAKE eif%d,icuf%d icu%d %d|%d\n", ei->flag,ei->icu->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT);
+ //fprintf(stderr,"FSIMAKE eif%d icu%d %d|%d\n", ei->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT);
+ ei++;
+ }
}
static void make_seq_editipo(SpaceIpo *si)
@@ -886,6 +914,12 @@ static void make_editipo(void)
ob->ipowin= ID_PO;
}
}
+ else if(G.sipo->blocktype==ID_FLUIDSIM) {
+ if (ob) { // NT
+ ob->ipowin= ID_FLUIDSIM;
+ make_fluidsim_editipo(G.sipo);
+ }
+ }
if(G.sipo->editipo==0) return;
@@ -1059,6 +1093,13 @@ static void get_ipo_context(short blocktype, ID **from, Ipo **ipo, char *actname
// if(sound) *ipo= sound->ipo;
// }
}
+ else if(blocktype==ID_FLUIDSIM) {
+ if(ob && ( ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
+ FluidsimSettings *fss= ob->fluidsimSettings;
+ *from= (ID *)ob;
+ if(fss) *ipo= fss->ipo;
+ }
+ }
}
/* called on each redraw, check if editipo data has to be remade */
@@ -1674,6 +1715,17 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname)
}
return NULL;
}
+ else if(blocktype== ID_FLUIDSIM) {
+ Object *ob= (Object *)from;
+ if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
+ FluidsimSettings *fss= ob->fluidsimSettings;
+ if(fss->ipo==NULL) {
+ fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM);
+ //fprintf(stderr,"FSIPO NEW!\n");
+ }
+ return fss->ipo;
+ }
+ }
}
break;
case ID_MA:
diff --git a/source/blender/src/editipo_lib.c b/source/blender/src/editipo_lib.c
index 22587c2da3c..ed9466a3bf9 100644
--- a/source/blender/src/editipo_lib.c
+++ b/source/blender/src/editipo_lib.c
@@ -93,6 +93,7 @@ char *snd_ic_names[SND_TOTNAM] = { "Vol", "Pitch", "Pan", "Atten" };
char *ac_ic_names[AC_TOTNAM] = {"LocX", "LocY", "LocZ", "SizeX", "SizeY",
"SizeZ", "QuatW", "QuatX", "QuatY", "QuatZ"};
char *ic_name_empty[1] ={ "" };
+char *fluidsim_ic_names[FLUIDSIM_TOTNAM] = { "Fac-Visc", "Fac-Time", "GravX","GravY","GravZ", "VelX","VelY","VelZ", "Active" };
char *getname_ac_ei(int nr)
{
@@ -198,6 +199,12 @@ char *getname_snd_ei(int nr)
return ic_name_empty[0];
}
+char *getname_fluidsim_ei(int nr)
+{
+ if(nr <= FLUIDSIM_TOTIPO) return fluidsim_ic_names[nr-1];
+ return ic_name_empty[0];
+}
+
void boundbox_ipocurve(IpoCurve *icu)
{
diff --git a/source/blender/src/editipo_mods.c b/source/blender/src/editipo_mods.c
index 83aec9ccbee..85119d9a2cc 100644
--- a/source/blender/src/editipo_mods.c
+++ b/source/blender/src/editipo_mods.c
@@ -178,6 +178,7 @@ void swap_visible_editipo(void)
}
}
else ei->flag &= ~IPO_VISIBLE;
+ printf("FSISWAP %d, icu%d %d|%d\n", ei->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT);
ei++;
}
diff --git a/source/blender/src/fluidsim.c b/source/blender/src/fluidsim.c
index bab93250d23..a608b079266 100644
--- a/source/blender/src/fluidsim.c
+++ b/source/blender/src/fluidsim.c
@@ -52,6 +52,7 @@
#include "DNA_scene_types.h"
#include "DNA_camera_types.h"
#include "DNA_screen_types.h"
+#include "DNA_ipo_types.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
@@ -69,6 +70,9 @@
#include "BKE_DerivedMesh.h"
#include "BKE_ipo.h"
#include "LBM_fluidsim.h"
+// FIXME move?
+// TODO FIXME DOUBLE elbeem.h! in intern/extern...
+#include "elbeem.h"
#include "BLI_editVert.h"
#include "BIF_editdeform.h"
@@ -80,7 +84,6 @@
#include "BSE_headerbuttons.h"
#include "mydevice.h"
-
#include "SDL.h"
#include "SDL_thread.h"
#include "SDL_mutex.h"
@@ -99,6 +102,9 @@
#undef main
#endif
+// from DerivedMesh.c
+void initElbeemMesh(struct Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles);
+
/* from header info.c */
extern int start_progress_bar(void);
extern void end_progress_bar(void);
@@ -179,6 +185,7 @@ FluidsimSettings *fluidsimSettingsNew(struct Object *srcob)
fss->orgMesh = (Mesh *)srcob->data;
fss->meshSurface = NULL;
fss->meshBB = NULL;
+ fss->meshSurfNormals = NULL;
// first init of bounding box
fss->bbStart[0] = 0.0;
@@ -187,7 +194,15 @@ FluidsimSettings *fluidsimSettingsNew(struct Object *srcob)
fss->bbSize[0] = 1.0;
fss->bbSize[1] = 1.0;
fss->bbSize[2] = 1.0;
- fluidsimGetAxisAlignedBB(srcob->data, srcob->obmat, fss->bbStart, fss->bbSize);
+ fluidsimGetAxisAlignedBB(srcob->data, srcob->obmat, fss->bbStart, fss->bbSize, &fss->meshBB);
+
+ fss->typeFlags = 0;
+ fss->partSlipValue = 0.0;
+
+ fss->generateParticles = 0.0;
+ fss->particleInfSize = 0.0;
+ fss->particleInfAlpha = 0.0;
+
return fss;
}
@@ -202,6 +217,16 @@ void fluidsimSettingsFree(FluidsimSettings *fss)
MEM_freeN(freeFsMesh);
}
+ freeFsMesh = fss->meshBB;
+ if(freeFsMesh) { // same as before...
+ if(freeFsMesh->mvert) MEM_freeN(freeFsMesh->mvert);
+ if(freeFsMesh->medge) MEM_freeN(freeFsMesh->medge);
+ if(freeFsMesh->mface) MEM_freeN(freeFsMesh->mface);
+ MEM_freeN(freeFsMesh);
+ }
+
+ if(fss->meshSurfNormals) MEM_freeN(fss->meshSurfNormals);
+
MEM_freeN(fss);
}
@@ -213,17 +238,121 @@ void fluidsimGetGeometryObjFilename(struct Object *ob, char *dst) { //, char *sr
}
+
+
+/* ******************************************************************************** */
+/* ********************** fluid sim channel helper functions ********************** */
+/* ******************************************************************************** */
+
+// no. of entries for the two channel sizes
+#define CHANNEL_FLOAT 1
+#define CHANNEL_VEC 3
+
+#define FS_FREE_ONECHANNEL(c,str) { \
+ if(c){ MEM_freeN(c); c=NULL; } \
+} // end ONE CHANN, debug: fprintf(stderr,"freeing " str " \n");
+
+#define FS_FREE_CHANNELS { \
+ FS_FREE_ONECHANNEL(timeAtIndex,"timeAtIndex");\
+ FS_FREE_ONECHANNEL(timeAtFrame,"timeAtFrame");\
+ FS_FREE_ONECHANNEL(channelDomainTime,"channelDomainTime"); \
+ FS_FREE_ONECHANNEL(channelDomainGravity,"channelDomainGravity");\
+ FS_FREE_ONECHANNEL(channelDomainViscosity,"channelDomainViscosity");\
+ for(i=0;i<256;i++) { \
+ FS_FREE_ONECHANNEL(channelObjMove[i][0],"channelObjMove0"); \
+ FS_FREE_ONECHANNEL(channelObjMove[i][1],"channelObjMove1"); \
+ FS_FREE_ONECHANNEL(channelObjMove[i][2],"channelObjMove2"); \
+ FS_FREE_ONECHANNEL(channelObjInivel[i],"channelObjInivel"); \
+ FS_FREE_ONECHANNEL(channelObjActive[i],"channelObjActive"); \
+ } \
+} // end FS FREE CHANNELS
+
+
+// simplify channels before printing
+// for API this is done anyway upon init
+static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char *str, int entries)
+{
+ int i,j;
+ int channelSize = paramsize;
+
+ if(entries==3) {
+ elbeemSimplifyChannelVec3( channel, &channelSize);
+ } else if(entries==1) {
+ elbeemSimplifyChannelFloat( channel, &channelSize);
+ } else {
+ // invalid, cant happen?
+ }
+
+ fprintf(file, " CHANNEL %s = \n", str);
+ for(i=0; i<channelSize;i++) {
+ fprintf(file," ");
+ for(j=0;j<=entries;j++) { // also print time value
+ fprintf(file," %f ", channel[i*(entries+1)+j] );
+ if(j==entries-1){ fprintf(file," "); }
+ }
+ fprintf(file," \n");
+ }
+
+ fprintf(file, " ; \n" );
+}
+
+
+static void fluidsimInitChannel(float **setchannel, int size, float *time,
+ int *icuIds, float *defaults, Ipo* ipo, int entries) {
+ int i,j;
+ IpoCurve* icus[3];
+ char *cstr = NULL;
+ float *channel = NULL;
+ float aniFrlen = G.scene->r.framelen;
+ if((entries<1) || (entries>3)) {
+ printf("fluidsimInitChannel::Error - invalid no. of entries: %d\n",entries);
+ entries = 1;
+ }
+
+ cstr = "fluidsiminit_channelfloat";
+ if(entries>1) cstr = "fluidsiminit_channelvec";
+ channel = MEM_callocN( size* (entries+1)* sizeof(float), cstr );
+
+ if(ipo) {
+ for(i=0; i<entries; i++) icus[i] = find_ipocurve(ipo, icuIds[i] );
+ } else {
+ for(i=0; i<entries; i++) icus[i] = NULL;
+ }
+
+ for(j=0; j<entries; j++) {
+ if(icus[j]) {
+ for(i=1; i<=size; i++) {
+ calc_icu(icus[j], aniFrlen*((float)i) );
+ channel[(i-1)*(entries+1) + j] = icus[j]->curval;
+ }
+ } else {
+ for(i=1; i<=size; i++) { channel[(i-1)*(entries+1) + j] = defaults[j]; }
+ }
+ }
+ // set time values
+ for(i=1; i<=size; i++) {
+ channel[(i-1)*(entries+1) + entries] = time[i];
+ }
+
+ *setchannel = channel;
+}
+
+
+
+/* ******************************************************************************** */
/* ********************** simulation thread ************************* */
+/* ******************************************************************************** */
+
SDL_mutex *globalBakeLock=NULL;
int globalBakeState = 0; // 0 everything ok, -1 abort simulation, 1 sim done
int globalBakeFrame = 0;
// run simulation in seperate thread
-int fluidsimSimulateThread(void *ptr) {
- char* fnameCfgPath = (char*)(ptr);
- int ret;
+int fluidsimSimulateThread(void) { // *ptr) {
+ //char* fnameCfgPath = (char*)(ptr);
+ int ret=0;
- ret = performElbeemSimulation(fnameCfgPath);
+ ret = elbeemSimulate();
SDL_mutexP(globalBakeLock);
if(globalBakeState==0) {
// if no error, set to normal exit
@@ -242,31 +371,27 @@ void simulateThreadIncreaseFrame(void) {
SDL_mutexV(globalBakeLock);
}
-/* remember files created during bake for deletion */
- //createdFiles[numCreatedFiles] = (char *)malloc(strlen(str)+1);
- //strcpy(createdFiles[numCreatedFiles] ,str);
-#define ADD_CREATEDFILE(str) \
- if(numCreatedFiles<255) {\
- createdFiles[numCreatedFiles] = strdup(str); \
- numCreatedFiles++; }
+/* ******************************************************************************** */
/* ********************** write fluidsim config to file ************************* */
+/* ******************************************************************************** */
+
void fluidsimBake(struct Object *ob)
{
FILE *fileCfg;
int i;
struct Object *fsDomain = NULL;
- FluidsimSettings *fssDomain;
+ FluidsimSettings *domainSettings;
struct Object *obit = NULL; /* object iterator */
int origFrame = G.scene->r.cfra;
char debugStrBuffer[256];
int dirExist = 0;
int gridlevels = 0;
- char *createdFiles[256];
- int numCreatedFiles = 0;
- int doDeleteCreatedFiles = 1;
int simAborted = 0; // was the simulation aborted by user?
- char *delEnvStr = "BLENDER_DELETEELBEEMFILES";
+ int doExportOnly = 0;
+ char *exportEnvStr = "BLENDER_ELBEEMEXPORTONLY";
+ const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
+ //char *channelNames[3] = { "translation","rotation","scale" };
char *suffixConfig = "fluidsim.cfg";
char *suffixSurface = "fluidsurface";
@@ -275,17 +400,46 @@ void fluidsimBake(struct Object *ob)
char targetFile[FILE_MAXDIR+FILE_MAXFILE]; // temp. store filename from targetDir for access
int outStringsChanged = 0; // modified? copy back before baking
int haveSomeFluid = 0; // check if any fluid objects are set
- int noFrames = G.scene->r.efra - 1 /*G.scene->r.sfra*/;
- const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
+ // config vars, inited before either export or run...
+ double calcViscosity = 0.0;
+ int noFrames;
+ double aniFrameTime;
+ float aniFrlen;
+ int channelObjCount;
+ float *bbStart = NULL;
+ float *bbSize = NULL;
+ float domainMat[4][4];
+ float invDomMat[4][4];
+ // channel data
+ int allchannelSize; // fixed by no. of frames
+ int startFrame = 1; // dont use G.scene->r.sfra here, always start with frame 1
+ // easy frame -> sim time calc
+ float *timeAtFrame=NULL, *timeAtIndex=NULL;
+ // domain
+ float *channelDomainTime = NULL;
+ float *channelDomainViscosity = NULL;
+ float *channelDomainGravity = NULL;
+ // objects (currently max. 256 objs)
+ float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale
+ float *channelObjInivel[256]; // initial velocities
+ float *channelObjActive[256]; // obj active channel
if(getenv(strEnvName)) {
int dlevel = atoi(getenv(strEnvName));
elbeemSetDebugLevel(dlevel);
- snprintf(debugStrBuffer,256,"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName);
+ snprintf(debugStrBuffer,256,"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName);
+ elbeemDebugOut(debugStrBuffer);
+ }
+ if(getenv(exportEnvStr)) {
+ doExportOnly = atoi(getenv(exportEnvStr));
+ snprintf(debugStrBuffer,256,"fluidsimBake::msg: Exporting mode set to '%d' due to envvar '%s'\n",doExportOnly, exportEnvStr);
elbeemDebugOut(debugStrBuffer);
}
+ // make sure it corresponds to startFrame setting
+ // old: noFrames = G.scene->r.efra - G.scene->r.sfra +1;
+ noFrames = G.scene->r.efra - 0;
if(noFrames<=0) {
pupmenu("Fluidsim Bake Error%t|No frames to export - check your animation range settings. Aborted%x0");
return;
@@ -296,36 +450,37 @@ void fluidsimBake(struct Object *ob)
if((obit->fluidsimFlag & OB_FLUIDSIM_ENABLE)&&(obit->type==OB_MESH)) {
if(obit->fluidsimSettings->type == OB_FLUIDSIM_DOMAIN) {
if(obit != ob) {
- snprintf(debugStrBuffer,256,"fluidsimBake::warning - More than one domain!\n");
- elbeemDebugOut(debugStrBuffer);
+ //snprintf(debugStrBuffer,256,"fluidsimBake::warning - More than one domain!\n"); elbeemDebugOut(debugStrBuffer);
+ pupmenu("Fluidsim Bake Error%t|There should be only one domain object! Aborted%x0");
+ return;
}
}
}
}
/* these both have to be valid, otherwise we wouldnt be here...*/
fsDomain = ob;
- fssDomain = ob->fluidsimSettings;
+ domainSettings = ob->fluidsimSettings;
/* rough check of settings... */
- if(fssDomain->previewresxyz > fssDomain->resolutionxyz) {
- snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", fssDomain->previewresxyz , fssDomain->resolutionxyz);
+ if(domainSettings->previewresxyz > domainSettings->resolutionxyz) {
+ snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz , domainSettings->resolutionxyz);
elbeemDebugOut(debugStrBuffer);
- fssDomain->previewresxyz = fssDomain->resolutionxyz;
+ domainSettings->previewresxyz = domainSettings->resolutionxyz;
}
// set adaptive coarsening according to resolutionxyz
// this should do as an approximation, with in/outflow
// doing this more accurate would be overkill
// perhaps add manual setting?
- if(fssDomain->maxRefine <0) {
- if(fssDomain->resolutionxyz>128) {
+ if(domainSettings->maxRefine <0) {
+ if(domainSettings->resolutionxyz>128) {
gridlevels = 2;
} else
- if(fssDomain->resolutionxyz>64) {
+ if(domainSettings->resolutionxyz>64) {
gridlevels = 1;
} else {
gridlevels = 0;
}
} else {
- gridlevels = fssDomain->maxRefine;
+ gridlevels = domainSettings->maxRefine;
}
snprintf(debugStrBuffer,256,"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels );
elbeemDebugOut(debugStrBuffer);
@@ -347,12 +502,13 @@ void fluidsimBake(struct Object *ob)
}
// prepare names...
- strncpy(targetDir, fssDomain->surfdataPath, FILE_MAXDIR);
- strncpy(newSurfdataPath, fssDomain->surfdataPath, FILE_MAXDIR);
+ strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
+ strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR);
BLI_convertstringcode(targetDir, G.sce, 0); // fixed #frame-no
strcpy(targetFile, targetDir);
strcat(targetFile, suffixConfig);
+ if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file
// make sure all directories exist
// as the bobjs use the same dir, this only needs to be checked
// for the cfg output
@@ -361,7 +517,11 @@ void fluidsimBake(struct Object *ob)
// check selected directory
// simply try to open cfg file for writing to test validity of settings
fileCfg = fopen(targetFile, "w");
- if(fileCfg) { dirExist = 1; fclose(fileCfg); }
+ if(fileCfg) {
+ dirExist = 1; fclose(fileCfg);
+ // remove cfg dummy from directory test
+ if(!doExportOnly) { BLI_delete(targetFile, 0,0); }
+ }
if((strlen(targetDir)<1) || (!dirExist)) {
char blendDir[FILE_MAXDIR+FILE_MAXFILE], blendFile[FILE_MAXDIR+FILE_MAXFILE];
@@ -395,316 +555,302 @@ void fluidsimBake(struct Object *ob)
selection = pupmenu(dispmsg);
if(selection<1) return; // 0 from menu, or -1 aborted
strcpy(targetDir, newSurfdataPath);
+ strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR);
BLI_convertstringcode(targetDir, G.sce, 0); // fixed #frame-no
}
+ // --------------------------------------------------------------------------------------------
+ // dump data for start frame
+ // CHECK more reasonable to number frames according to blender?
// dump data for frame 0
- G.scene->r.cfra = 1 /*G.scene->r.sfra*/;
+ G.scene->r.cfra = startFrame;
scene_update_for_newframe(G.scene, G.scene->lay);
-
- // start writing
- strcpy(targetFile, targetDir);
- strcat(targetFile, suffixConfig);
- // make sure these directories exist as well
- if(outStringsChanged) {
- BLI_make_existing_file(targetFile);
- }
- fileCfg = fopen(targetFile, "w");
- if(!fileCfg) {
- snprintf(debugStrBuffer,256,"fluidsimBake::error - Unable to open file for writing '%s'\n", targetFile);
- elbeemDebugOut(debugStrBuffer);
- pupmenu("Fluidsim Bake Error%t|Unable to output files... Aborted%x0");
- return;
+ // init common export vars for both file export and run
+ for(i=0; i<256; i++) {
+ channelObjMove[i][0] = channelObjMove[i][1] = channelObjMove[i][2] = NULL;
+ channelObjInivel[i] = NULL;
+ channelObjActive[i] = NULL;
+ }
+ allchannelSize = G.scene->r.efra; // always use till last frame
+ aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames;
+ // blender specific - scale according to map old/new settings in anim panel:
+ aniFrlen = G.scene->r.framelen;
+ if(domainSettings->viscosityMode==1) {
+ /* manual mode */
+ calcViscosity = (1.0/(domainSettings->viscosityExponent*10)) * domainSettings->viscosityValue;
+ } else {
+ calcViscosity = fluidsimViscosityPreset[ domainSettings->viscosityMode ];
}
- ADD_CREATEDFILE(targetFile);
-
- fprintf(fileCfg, "# Blender ElBeem File , Source %s , Frame %d, to %s \n\n\n", G.sce, -1, targetFile );
- // file open -> valid settings -> store
- strncpy(fssDomain->surfdataPath, newSurfdataPath, FILE_MAXDIR);
-
- /* output simulation settings */
- {
- double calcViscosity = 0.0;
- double aniFrameTime = (fssDomain->animEnd - fssDomain->animStart)/(double)noFrames;
- char *simString = "\n"
- "attribute \"simulation1\" { \n"
- " solver = \"fsgr\"; \n" "\n"
- " p_domainsize = " "%f" /* realsize */ "; \n"
- " p_anistart = " "%f" /* aniStart*/ "; \n"
- " p_gravity = " "%f %f %f" /* pGravity*/ "; \n" "\n"
- " p_normgstar = %f; \n" /* use gstar param? */
- " p_viscosity = " "%f" /* pViscosity*/ "; \n" "\n"
-
- " maxrefine = " "%d" /* maxRefine*/ "; \n"
- " size = " "%d" /* gridSize*/ "; \n"
- " surfacepreview = " "%d" /* previewSize*/ "; \n"
- " smoothsurface = 1.0; \n"
-
- " geoinitid = 1; \n" "\n"
- " isovalue = 0.4900; \n"
- " isoweightmethod = 1; \n" "\n"
- "\n" ;
-
- if(fssDomain->viscosityMode==1) {
- /* manual mode */
- calcViscosity = (1.0/(fssDomain->viscosityExponent*10)) * fssDomain->viscosityValue;
- } else {
- calcViscosity = fluidsimViscosityPreset[ fssDomain->viscosityMode ];
+ bbStart = fsDomain->fluidsimSettings->bbStart;
+ bbSize = fsDomain->fluidsimSettings->bbSize;
+ fluidsimGetAxisAlignedBB(fsDomain->data, fsDomain->obmat, bbStart, bbSize, &domainSettings->meshBB);
+
+ // always init
+ { int timeIcu[1] = { FLUIDSIM_TIME };
+ float timeDef[1] = { 1. };
+ int gravIcu[3] = { FLUIDSIM_GRAV_X, FLUIDSIM_GRAV_Y, FLUIDSIM_GRAV_Z };
+ float gravDef[3] = { domainSettings->gravx, domainSettings->gravy, domainSettings->gravz };
+ int viscIcu[1] = { FLUIDSIM_VISC };
+ float viscDef[1] = { 1. };
+
+ // time channel is a bit special, init by hand...
+ timeAtIndex = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatindex");
+ for(i=0; i<=G.scene->r.efra; i++) {
+ timeAtIndex[i] = (float)(i-startFrame);
}
- fprintf(fileCfg, simString,
- (double)fssDomain->realsize,
- (double)fssDomain->animStart,
- (double)fssDomain->gravx, (double)fssDomain->gravy, (double)fssDomain->gravz,
- (double)fssDomain->gstar,
- calcViscosity,
- gridlevels, (int)fssDomain->resolutionxyz, (int)fssDomain->previewresxyz
- );
-
- // export animatable params
- if(fsDomain->ipo) {
- int i;
- float tsum=0.0, shouldbe=0.0;
- fprintf(fileCfg, " CHANNEL p_aniframetime = ");
- for(i=1 /*G.scene->r.sfra*/; i<G.scene->r.efra; i++) {
- float anit = (calc_ipo_time(fsDomain->ipo, i+1) -
- calc_ipo_time(fsDomain->ipo, i)) * aniFrameTime;
- if(anit<0.0) anit = 0.0;
- tsum += anit;
+ fluidsimInitChannel( &channelDomainTime, allchannelSize, timeAtIndex, timeIcu,timeDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB
+ // time channel is a multiplicator for aniFrameTime
+ if(channelDomainTime) {
+ for(i=0; i<allchannelSize; i++) {
+ channelDomainTime[i*2+0] = aniFrameTime * channelDomainTime[i*2+0];
+ if(channelDomainTime[i*2+0]<0.) channelDomainTime[i*2+0] = 0.;
}
- // make sure inaccurate integration doesnt modify end time
- shouldbe = ((float)(G.scene->r.efra - 1 /*G.scene->r.sfra*/)) *aniFrameTime;
- for(i=1 /*G.scene->r.sfra*/; i<G.scene->r.efra; i++) {
- float anit = (calc_ipo_time(fsDomain->ipo, i+1) -
- calc_ipo_time(fsDomain->ipo, i)) * aniFrameTime;
- if(anit<0.0) anit = 0.0;
- anit *= (shouldbe/tsum);
- fprintf(fileCfg," %f %d \n",anit, (i-1)); // start with 0
+ }
+ timeAtFrame = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatframe");
+ timeAtFrame[0] = timeAtFrame[1] = domainSettings->animStart; // start at index 1
+ if(channelDomainTime) {
+ for(i=2; i<=allchannelSize; i++) {
+ timeAtFrame[i] = timeAtFrame[i-1]+channelDomainTime[(i-1)*2+0];
}
- fprintf(fileCfg, "; #cfgset, base=%f \n", aniFrameTime );
- //fprintf(stderr, "DEBUG base=%f tsum=%f, sb=%f, ts2=%f \n", aniFrameTime, tsum,shouldbe,tsum2 );
} else {
- fprintf(fileCfg, " p_aniframetime = " "%f" /* 2 aniFrameTime*/ "; #cfgset \n" ,
- aniFrameTime );
+ for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; }
}
-
- fprintf(fileCfg, "} \n" );
- }
- // output blender object transformation
- {
- float domainMat[4][4];
- float invDomMat[4][4];
- char* blendattrString = "\n"
- "attribute \"btrafoattr\" { \n"
- " transform = %f %f %f %f "
- " %f %f %f %f "
- " %f %f %f %f "
- " %f %f %f %f ;\n"
- "} \n";
-
- MTC_Mat4CpyMat4(domainMat, fsDomain->obmat);
- if(!Mat4Invert(invDomMat, domainMat)) {
- snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n");
- elbeemDebugOut(debugStrBuffer);
- // FIXME add fatal msg
- return;
+ fluidsimInitChannel( &channelDomainViscosity, allchannelSize, timeAtFrame, viscIcu,viscDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB
+ if(channelDomainViscosity) {
+ for(i=0; i<allchannelSize; i++) { channelDomainViscosity[i*2+0] = calcViscosity * channelDomainViscosity[i*2+0]; }
}
+ fluidsimInitChannel( &channelDomainGravity, allchannelSize, timeAtFrame, gravIcu,gravDef, domainSettings->ipo, CHANNEL_VEC );
+ } // domain channel init
+
+ // init obj movement channels
+ channelObjCount=0;
+ for(obit= G.main->object.first; obit; obit= obit->id.next) {
+ //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG
+ if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
+ (obit->type==OB_MESH) &&
+ (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH
+ (obit->fluidsimSettings->type != OB_FLUIDSIM_PARTICLE) ) {
+
+ // cant use fluidsimInitChannel for obj channels right now, due
+ // to the special DXXX channels, and the rotation specialities
+ IpoCurve *icuex[3][3];
+ int icuIds[3][3] = {
+ {OB_LOC_X, OB_LOC_Y, OB_LOC_Z},
+ {OB_ROT_X, OB_ROT_Y, OB_ROT_Z},
+ {OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z}
+ };
+ // relative ipos
+ IpoCurve *icudex[3][3];
+ int icudIds[3][3] = {
+ {OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z},
+ {OB_DROT_X, OB_DROT_Y, OB_DROT_Z},
+ {OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z}
+ };
+ int j,k;
+ float vals[3] = {0.0,0.0,0.0};
+ int o = channelObjCount;
+ int inivelIcu[3] = { FLUIDSIM_VEL_X, FLUIDSIM_VEL_Y, FLUIDSIM_VEL_Z };
+ float inivelDefs[3] = { obit->fluidsimSettings->iniVelx, obit->fluidsimSettings->iniVely, obit->fluidsimSettings->iniVelz };
+ int activeIcu[1] = { FLUIDSIM_ACTIVE };
+ float activeDefs[1] = { 1 }; // default to on
+
+ // check & init loc,rot,size
+ for(j=0; j<3; j++) {
+ for(k=0; k<3; k++) {
+ icuex[j][k] = find_ipocurve(obit->ipo, icuIds[j][k] );
+ icudex[j][k] = find_ipocurve(obit->ipo, icudIds[j][k] );
+ }
+ }
- fprintf(fileCfg, blendattrString,
- invDomMat[0][0],invDomMat[1][0],invDomMat[2][0],invDomMat[3][0],
- invDomMat[0][1],invDomMat[1][1],invDomMat[2][1],invDomMat[3][1],
- invDomMat[0][2],invDomMat[1][2],invDomMat[2][2],invDomMat[3][2],
- invDomMat[0][3],invDomMat[1][3],invDomMat[2][3],invDomMat[3][3] );
- }
-
+ for(j=0; j<3; j++) {
+ channelObjMove[o][j] = MEM_callocN( allchannelSize*4*sizeof(float), "fluidsiminit_objmovchannel");
+ for(i=1; i<=allchannelSize; i++) {
+
+ for(k=0; k<3; k++) {
+ if(icuex[j][k]) {
+ calc_icu(icuex[j][k], aniFrlen*((float)i) );
+ vals[k] = icuex[j][k]->curval;
+ } else {
+ float setval=0.0;
+ if(j==0) { setval = obit->loc[k];
+ } else if(j==1) { setval = ( 180.0*obit->rot[k] )/( 10.0*M_PI );
+ } else { setval = obit->size[k]; }
+ vals[k] = setval;
+ }
+ if(icudex[j][k]) {
+ calc_icu(icudex[j][k], aniFrlen*((float)i) );
+ vals[k] += icudex[j][k]->curval;
+ }
+ } // k
+
+ for(k=0; k<3; k++) {
+ float set = vals[k];
+ if(j==1) { // rot is downscaled by 10 for ipo !?
+ set = 360.0 - (10.0*set);
+ }
+ channelObjMove[o][j][(i-1)*4 + k] = set; // - obit->loc[k];
+ } // k
+ channelObjMove[o][j][(i-1)*4 + 3] = timeAtFrame[i];
+ }
+ }
+ fluidsimInitChannel( &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, obit->fluidsimSettings->ipo, CHANNEL_VEC );
+ fluidsimInitChannel( &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, obit->fluidsimSettings->ipo, CHANNEL_FLOAT );
- fprintf(fileCfg, "raytracing {\n");
-
- /* output picture settings for preview renders */
- {
- char *rayString = "\n"
- " anistart= 0; \n"
- " aniframes= " "%d" /*1 frameEnd-frameStart+0*/ "; #cfgset \n"
- " frameSkip= false; \n"
- " filename= \"" "%s" /* rayPicFilename*/ "\"; #cfgset \n"
- " aspect 1.0; \n"
- " resolution " "%d %d" /*2,3 blendResx,blendResy*/ "; #cfgset \n"
- " antialias 1; \n"
- " ambientlight (1, 1, 1); \n"
- " maxRayDepth 6; \n"
- " treeMaxDepth 25; \n"
- " treeMaxTriangles 8; \n"
- " background (0.08, 0.08, 0.20); \n"
- " eyepoint= (" "%f %f %f"/*4,5,6 eyep*/ "); #cfgset \n"
- " lookat= (" "%f %f %f"/*7,8,9 lookatp*/ "); #cfgset \n"
- " upvec= (0 0 1); \n"
- " fovy= " "%f" /*blendFov*/ "; #cfgset \n"
- " blenderattr= \"btrafoattr\"; \n"
- "\n\n";
-
- char *lightString = "\n"
- " light { \n"
- " type= omni; \n"
- " active= 1; \n"
- " color= (1.0, 1.0, 1.0); \n"
- " position= (" "%f %f %f"/*1,2,3 eyep*/ "); #cfgset \n"
- " castShadows= 1; \n"
- " } \n\n" ;
-
- struct Object *cam = G.scene->camera;
- float eyex=2.0, eyey=2.0, eyez=2.0;
- int resx = 200, resy=200;
- float lookatx=0.0, lookaty=0.0, lookatz=0.0;
- float fov = 45.0;
+ channelObjCount++;
- strcpy(targetFile, targetDir);
- strcat(targetFile, suffixSurface);
- resx = G.scene->r.xsch;
- resy = G.scene->r.ysch;
- if((cam) && (cam->type == OB_CAMERA)) {
- Camera *camdata= G.scene->camera->data;
- double lens = camdata->lens;
- double imgRatio = (double)resx/(double)resy;
- fov = 360.0 * atan(16.0*imgRatio/lens) / M_PI;
- //R.near= camdata->clipsta; R.far= camdata->clipend;
-
- eyex = cam->loc[0];
- eyey = cam->loc[1];
- eyez = cam->loc[2];
- // TODO - place lookat in middle of domain?
}
+ }
- fprintf(fileCfg, rayString,
- (noFrames+1), targetFile, resx,resy,
- eyex, eyey, eyez ,
- lookatx, lookaty, lookatz,
- fov
- );
- fprintf(fileCfg, lightString,
- eyex, eyey, eyez );
+ // init trafo matrix
+ MTC_Mat4CpyMat4(domainMat, fsDomain->obmat);
+ if(!Mat4Invert(invDomMat, domainMat)) {
+ snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n");
+ elbeemDebugOut(debugStrBuffer);
+ // FIXME add fatal msg
+ FS_FREE_CHANNELS;
+ return;
}
- /* output fluid domain */
- {
- char * domainString = "\n"
- " geometry { \n"
- " type= fluidlbm; \n"
- " name = \"" "%s" /*name*/ "\"; #cfgset \n"
- " visible= 1; \n"
- " attributes= \"simulation1\"; \n"
- //" define { material_surf = \"fluidblue\"; } \n"
- " start= " "%f %f %f" /*bbstart*/ "; #cfgset \n"
- " end = " "%f %f %f" /*bbend */ "; #cfgset \n"
- " } \n"
- "\n";
- float *bbStart = fsDomain->fluidsimSettings->bbStart;
- float *bbSize = fsDomain->fluidsimSettings->bbSize;
- fluidsimGetAxisAlignedBB(fsDomain->data, fsDomain->obmat, bbStart, bbSize);
-
- fprintf(fileCfg, domainString,
- fsDomain->id.name,
- bbStart[0], bbStart[1], bbStart[2],
- bbStart[0]+bbSize[0], bbStart[1]+bbSize[1], bbStart[2]+bbSize[2]
- );
+ // --------------------------------------------------------------------------------------------
+ // start writing / exporting
+ strcpy(targetFile, targetDir);
+ strcat(targetFile, suffixConfig);
+ if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file
+ // make sure these directories exist as well
+ if(outStringsChanged) {
+ BLI_make_existing_file(targetFile);
}
-
- /* setup geometry */
- {
- char *objectStringStart =
- " geometry { \n"
- " type= objmodel; \n"
- " name = \"" "%s" /* name */ "\"; #cfgset \n"
- // DEBUG , also obs invisible?
- " visible= 0; \n"
- " define { \n" ;
- char *obstacleString =
- " geoinittype= \"" "%s" /* type */ "\"; #cfgset \n"
- " filename= \"" "%s" /* data filename */ "\"; #cfgset \n" ;
- char *fluidString =
- " geoinittype= \"" "%s" /* type */ "\"; \n"
- " filename= \"" "%s" /* data filename */ "\"; #cfgset \n"
- " initial_velocity= " "%f %f %f" /* vel vector */ "; #cfgset \n" ;
- char *objectStringEnd =
- " geoinit_intersect = 1; \n" /* always use accurate init here */
- " geoinitid= 1; \n"
- " } \n"
- " } \n"
- "\n" ;
- char fnameObjdat[FILE_MAXFILE];
-
+ if(!doExportOnly) {
+ SDL_Thread *simthr = NULL;
+
+ // perform simulation with El'Beem api and SDL threads
+ elbeemSimulationSettings fsset;
+ fsset.version = 1;
+
+ // setup global settings
+ for(i=0 ; i<3; i++) fsset.geoStart[i] = bbStart[i];
+ for(i=0 ; i<3; i++) fsset.geoSize[i] = bbSize[i];
+ // simulate with 50^3
+ fsset.resolutionxyz = (int)domainSettings->resolutionxyz;
+ fsset.previewresxyz = (int)domainSettings->previewresxyz;
+ // 10cm water domain
+ fsset.realsize = domainSettings->realsize;
+ fsset.viscosity = calcViscosity;
+ // earth gravity
+ fsset.gravity[0] = domainSettings->gravx;
+ fsset.gravity[1] = domainSettings->gravy;
+ fsset.gravity[2] = domainSettings->gravz;
+ // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
+ fsset.animStart = domainSettings->animStart;
+ fsset.aniFrameTime = aniFrameTime;
+ fsset.noOfFrames = noFrames - 1; // is otherwise subtracted in parser
+ strcpy(targetFile, targetDir);
+ strcat(targetFile, suffixSurface);
+ // defaults for compressibility and adaptive grids
+ fsset.gstar = domainSettings->gstar;
+ fsset.maxRefine = domainSettings->maxRefine; // check <-> gridlevels
+ fsset.generateParticles = domainSettings->generateParticles;
+ strcpy( fsset.outputPath, targetFile);
+
+ // domain channels
+ fsset.channelSizeFrameTime =
+ fsset.channelSizeViscosity =
+ fsset.channelSizeGravity = allchannelSize;
+ fsset.channelFrameTime = channelDomainTime;
+ fsset.channelViscosity = channelDomainViscosity;
+ fsset.channelGravity = channelDomainGravity;
+
+ if( (domainSettings->typeFlags&OB_FSBND_NOSLIP)) fsset.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
+ else if((domainSettings->typeFlags&OB_FSBND_PARTSLIP)) fsset.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
+ else if((domainSettings->typeFlags&OB_FSBND_FREESLIP)) fsset.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
+ fsset.obstaclePartslip = domainSettings->partSlipValue;
+ fsset.generateVertexVectors = (int)(!(domainSettings->typeFlags&OB_FSDOMAIN_NOVECGEN));
+ // fprintf(stderr," VVV %d %d \n",fsset.generateVertexVectors , (domainSettings->typeFlags&OB_FSDOMAIN_NOVECGEN)); // DEBUG
+
+ // init blender trafo matrix
+ // fprintf(stderr,"elbeemInit - mpTrafo:\n");
+ { int j;
+ for(i=0; i<4; i++) {
+ for(j=0; j<4; j++) {
+ fsset.surfaceTrafo[i*4+j] = invDomMat[j][i];
+ // fprintf(stderr,"elbeemInit - mpTrafo %d %d = %f (%d) \n", i,j, fsset.surfaceTrafo[i*4+j] , (i*4+j) );
+ }
+ } }
+
+ // init solver with settings
+ elbeemInit(&fsset);
+
+ // init objects
+ channelObjCount = 0;
for(obit= G.main->object.first; obit; obit= obit->id.next) {
//{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG
- if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
+ if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && // if has to match 3 places! // CHECKMATCH
(obit->type==OB_MESH) &&
- (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN)
+ (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) &&
+ (obit->fluidsimSettings->type != OB_FLUIDSIM_PARTICLE)
) {
- fluidsimGetGeometryObjFilename(obit, fnameObjdat); //, outPrefix);
- strcpy(targetFile, targetDir);
- strcat(targetFile, fnameObjdat);
- fprintf(fileCfg, objectStringStart, obit->id.name ); // abs path
- if(obit->fluidsimSettings->type == OB_FLUIDSIM_FLUID) {
- fprintf(fileCfg, fluidString, "fluid", targetFile, // do use absolute paths?
- (double)obit->fluidsimSettings->iniVelx, (double)obit->fluidsimSettings->iniVely, (double)obit->fluidsimSettings->iniVelz );
- }
- if(obit->fluidsimSettings->type == OB_FLUIDSIM_INFLOW) {
- fprintf(fileCfg, fluidString, "inflow", targetFile, // do use absolute paths?
- (double)obit->fluidsimSettings->iniVelx, (double)obit->fluidsimSettings->iniVely, (double)obit->fluidsimSettings->iniVelz );
- }
- if(obit->fluidsimSettings->type == OB_FLUIDSIM_OUTFLOW) {
- fprintf(fileCfg, fluidString, "outflow", targetFile, // do use absolute paths?
- (double)obit->fluidsimSettings->iniVelx, (double)obit->fluidsimSettings->iniVely, (double)obit->fluidsimSettings->iniVelz );
- }
- if(obit->fluidsimSettings->type == OB_FLUIDSIM_OBSTACLE) {
- fprintf(fileCfg, obstacleString, "bnd_no" , targetFile); // abs path
- }
- fprintf(fileCfg, objectStringEnd ); // abs path
- ADD_CREATEDFILE(targetFile);
- writeBobjgz(targetFile, obit);
- }
- }
- }
-
- /* fluid material */
- fprintf(fileCfg,
- " material { \n"
- " type= phong; \n"
- " name= \"fluidblue\"; \n"
- " diffuse= 0.3 0.5 0.9; \n"
- " ambient= 0.1 0.1 0.1; \n"
- " specular= 0.2 10.0; \n"
- " } \n" );
-
-
+ float *verts=NULL;
+ int *tris=NULL;
+ int numVerts=0, numTris=0;
+ int o = channelObjCount;
+ elbeemMesh fsmesh;
+ elbeemResetMesh( &fsmesh );
+ fsmesh.type = obit->fluidsimSettings->type;;
+ // get name of object for debugging solver
+ fsmesh.name = obit->id.name;
+
+ initElbeemMesh(obit, &numVerts, &verts, &numTris, &tris);
+ fsmesh.numVertices = numVerts;
+ fsmesh.numTriangles = numTris;
+ fsmesh.vertices = verts;
+ fsmesh.triangles = tris;
+
+ fsmesh.channelSizeTranslation =
+ fsmesh.channelSizeRotation =
+ fsmesh.channelSizeScale =
+ fsmesh.channelSizeInitialVel =
+ fsmesh.channelSizeActive = allchannelSize;
+
+ fsmesh.channelTranslation = channelObjMove[o][0];
+ fsmesh.channelRotation = channelObjMove[o][1];
+ fsmesh.channelScale = channelObjMove[o][2];
+ fsmesh.channelActive = channelObjActive[o];
+ if( (fsmesh.type == OB_FLUIDSIM_FLUID) ||
+ (fsmesh.type == OB_FLUIDSIM_INFLOW) ) {
+ fsmesh.channelInitialVel = channelObjInivel[o];
+ fsmesh.localInivelCoords = ((obit->fluidsimSettings->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0);
+ }
- fprintf(fileCfg, "} // end raytracing\n");
- fclose(fileCfg);
+ if( (obit->fluidsimSettings->typeFlags&OB_FSBND_NOSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
+ else if((obit->fluidsimSettings->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
+ else if((obit->fluidsimSettings->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
+ fsmesh.obstaclePartslip = obit->fluidsimSettings->partSlipValue;
- strcpy(targetFile, targetDir);
- strcat(targetFile, suffixConfig);
- snprintf(debugStrBuffer,256,"fluidsimBake::msg: Wrote %s\n", targetFile);
- elbeemDebugOut(debugStrBuffer);
+ elbeemAddMesh(&fsmesh);
- // perform simulation
- {
- SDL_Thread *simthr = NULL;
+ if(verts) MEM_freeN(verts);
+ if(tris) MEM_freeN(tris);
+ channelObjCount++;
+ } // valid mesh
+ } // objects
+
globalBakeLock = SDL_CreateMutex();
// set to neutral, -1 means user abort, -2 means init error
globalBakeState = 0;
- globalBakeFrame = 1;
+ globalBakeFrame = 0;
simthr = SDL_CreateThread(fluidsimSimulateThread, targetFile);
-#ifndef WIN32
- // DEBUG for win32 debugging, dont use threads...
-#endif // WIN32
+
if(!simthr) {
snprintf(debugStrBuffer,256,"fluidsimBake::error: Unable to create thread... running without one.\n");
elbeemDebugOut(debugStrBuffer);
set_timecursor(0);
- performElbeemSimulation(targetFile);
+ elbeemSimulate();
} else {
int done = 0;
unsigned short event=0;
@@ -747,7 +893,8 @@ void fluidsimBake(struct Object *ob)
// redraw the 3D for showing progress once in a while...
if(lastRedraw!=globalBakeFrame) {
ScrArea *sa;
- G.scene->r.cfra = lastRedraw = globalBakeFrame;
+ G.scene->r.cfra = startFrame+globalBakeFrame;
+ lastRedraw = globalBakeFrame;
update_for_newframe_muted();
sa= G.curscreen->areabase.first;
while(sa) {
@@ -762,19 +909,278 @@ void fluidsimBake(struct Object *ob)
}
SDL_DestroyMutex(globalBakeLock);
globalBakeLock = NULL;
- } // thread creation
+ } // El'Beem API init, thread creation
+ // --------------------------------------------------------------------------------------------
+ else
+ { // write config file to be run with command line simulator
+ fileCfg = fopen(targetFile, "w");
+ if(!fileCfg) {
+ snprintf(debugStrBuffer,256,"fluidsimBake::error - Unable to open file for writing '%s'\n", targetFile);
+ elbeemDebugOut(debugStrBuffer);
+
+ pupmenu("Fluidsim Bake Error%t|Unable to output files... Aborted%x0");
+ FS_FREE_CHANNELS;
+ return;
+ }
+ //ADD_CREATEDFILE(targetFile);
+
+ fprintf(fileCfg, "# Blender ElBeem File , Source %s , Frame %d, to %s \n\n\n", G.sce, -1, targetFile );
+ // file open -> valid settings -> store
+ strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR);
+
+ /* output simulation settings */
+ {
+ char *dtype[3] = { "no", "part", "free" };
+ float pslip = domainSettings->partSlipValue; int bi=0;
+ char *simString = "\n"
+ "attribute \"simulation1\" { \n"
+ " solver = \"fsgr\"; \n" "\n"
+ " p_domainsize = " "%f" /* realsize */ "; \n"
+ " p_anistart = " "%f" /* aniStart*/ "; \n"
+ " p_normgstar = %f; \n" /* use gstar param? */
+ " maxrefine = " "%d" /* maxRefine*/ "; \n"
+ " size = " "%d" /* gridSize*/ "; \n"
+ " surfacepreview = " "%d" /* previewSize*/ "; \n"
+ " dump_velocities = " "%d" /* vector dump */ "; \n"
+ " smoothsurface = 1.0; \n"
+ " smoothnormals = 1.0; \n"
+ " geoinitid = 1; \n" "\n"
+ " isovalue = 0.4900; \n"
+ " isoweightmethod = 1; \n" "\n" ;
- // cleanup sim files
- if(getenv(delEnvStr)) {
- doDeleteCreatedFiles = atoi(getenv(delEnvStr));
- }
- for(i=0; i<numCreatedFiles; i++) {
- if(doDeleteCreatedFiles>0) {
- //fprintf(stderr," CREATED '%s' deleting... \n", createdFiles[i]); // debug
- BLI_delete(createdFiles[i], 0,0);
+ fprintf(fileCfg, simString,
+ (double)domainSettings->realsize, (double)domainSettings->animStart, (double)domainSettings->gstar,
+ gridlevels, (int)domainSettings->resolutionxyz, (int)domainSettings->previewresxyz ,
+ (int)(!(domainSettings->typeFlags&OB_FSDOMAIN_NOVECGEN))
+ );
+
+ if((domainSettings->typeFlags&OB_FSBND_NOSLIP)) bi=0;
+ else if((domainSettings->typeFlags&OB_FSBND_PARTSLIP)) bi=1;
+ else if((domainSettings->typeFlags&OB_FSBND_FREESLIP)) bi=2;
+ fprintf(fileCfg, " domainbound = %s; domainpartslip=%f; \n", dtype[bi], pslip);
+
+ fprintf(fileCfg," # org aniframetime: %f \n", aniFrameTime);
+ fluidsimPrintChannel(fileCfg, channelDomainTime,allchannelSize,"p_aniframetime",CHANNEL_FLOAT);
+ fluidsimPrintChannel(fileCfg, channelDomainViscosity,allchannelSize,"p_viscosity",CHANNEL_FLOAT);
+ fluidsimPrintChannel(fileCfg, channelDomainGravity, allchannelSize,"p_gravity",CHANNEL_VEC);
+
+ fprintf(fileCfg, "\n} \n" );
}
- free(createdFiles[i]);
- }
+
+ // output blender object transformation
+ {
+ char* blendattrString = "\n"
+ "attribute \"btrafoattr\" { \n"
+ " transform = %f %f %f %f "
+ " %f %f %f %f "
+ " %f %f %f %f "
+ " %f %f %f %f ;\n"
+ "} \n";
+
+ fprintf(fileCfg, blendattrString,
+ invDomMat[0][0],invDomMat[1][0],invDomMat[2][0],invDomMat[3][0],
+ invDomMat[0][1],invDomMat[1][1],invDomMat[2][1],invDomMat[3][1],
+ invDomMat[0][2],invDomMat[1][2],invDomMat[2][2],invDomMat[3][2],
+ invDomMat[0][3],invDomMat[1][3],invDomMat[2][3],invDomMat[3][3] );
+ }
+
+
+
+ fprintf(fileCfg, "raytracing {\n");
+
+ /* output picture settings for preview renders */
+ {
+ char *rayString = "\n"
+ " anistart= 0; \n"
+ " aniframes= " "%d" /*1 frameEnd-frameStart+0*/ "; #cfgset \n"
+ " frameSkip= false; \n"
+ " filename= \"" "%s" /* rayPicFilename*/ "\"; #cfgset \n"
+ " aspect 1.0; \n"
+ " resolution " "%d %d" /*2,3 blendResx,blendResy*/ "; #cfgset \n"
+ " antialias 1; \n"
+ " ambientlight (1, 1, 1); \n"
+ " maxRayDepth 6; \n"
+ " treeMaxDepth 25; \n"
+ " treeMaxTriangles 8; \n"
+ " background (0.08, 0.08, 0.20); \n"
+ " eyepoint= (" "%f %f %f"/*4,5,6 eyep*/ "); #cfgset \n"
+ " lookat= (" "%f %f %f"/*7,8,9 lookatp*/ "); #cfgset \n"
+ " upvec= (0 0 1); \n"
+ " fovy= " "%f" /*blendFov*/ "; #cfgset \n"
+ " blenderattr= \"btrafoattr\"; \n"
+ "\n\n";
+
+ char *lightString = "\n"
+ " light { \n"
+ " type= omni; \n"
+ " active= 1; \n"
+ " color= (1.0, 1.0, 1.0); \n"
+ " position= (" "%f %f %f"/*1,2,3 eyep*/ "); #cfgset \n"
+ " castShadows= 1; \n"
+ " } \n\n" ;
+
+ struct Object *cam = G.scene->camera;
+ float eyex=2.0, eyey=2.0, eyez=2.0;
+ int resx = 200, resy=200;
+ float lookatx=0.0, lookaty=0.0, lookatz=0.0;
+ float fov = 45.0;
+
+ strcpy(targetFile, targetDir);
+ strcat(targetFile, suffixSurface);
+ resx = G.scene->r.xsch;
+ resy = G.scene->r.ysch;
+ if((cam) && (cam->type == OB_CAMERA)) {
+ Camera *camdata= G.scene->camera->data;
+ double lens = camdata->lens;
+ double imgRatio = (double)resx/(double)resy;
+ fov = 360.0 * atan(16.0*imgRatio/lens) / M_PI;
+ //R.near= camdata->clipsta; R.far= camdata->clipend;
+
+ eyex = cam->loc[0];
+ eyey = cam->loc[1];
+ eyez = cam->loc[2];
+ // TODO - place lookat in middle of domain?
+ }
+
+ fprintf(fileCfg, rayString,
+ (noFrames+0), targetFile, resx,resy,
+ eyex, eyey, eyez ,
+ lookatx, lookaty, lookatz,
+ fov
+ );
+ fprintf(fileCfg, lightString,
+ eyex, eyey, eyez );
+ }
+
+
+ /* output fluid domain */
+ {
+ char * domainString = "\n"
+ " geometry { \n"
+ " type= fluidlbm; \n"
+ " name = \"" "%s" /*name*/ "\"; #cfgset \n"
+ " visible= 1; \n"
+ " attributes= \"simulation1\"; \n"
+ //" define { material_surf = \"fluidblue\"; } \n"
+ " start= " "%f %f %f" /*bbstart*/ "; #cfgset \n"
+ " end = " "%f %f %f" /*bbend */ "; #cfgset \n"
+ " } \n"
+ "\n";
+ fprintf(fileCfg, domainString,
+ fsDomain->id.name,
+ bbStart[0], bbStart[1], bbStart[2],
+ bbStart[0]+bbSize[0], bbStart[1]+bbSize[1], bbStart[2]+bbSize[2]
+ );
+ }
+
+
+ /* setup geometry */
+ {
+ char *objectStringStart =
+ " geometry { \n"
+ " type= objmodel; \n"
+ " name = \"" "%s" /* name */ "\"; #cfgset \n"
+ // DEBUG , also obs invisible?
+ " visible= 0; \n"
+ " define { \n" ;
+ char *outflowString =
+ " geoinittype= \"" "%s" /* type */ "\"; #cfgset \n"
+ " filename= \"" "%s" /* data filename */ "\"; #cfgset \n" ;
+ char *obstacleString =
+ " geoinittype= \"" "%s" /* type */ "\"; #cfgset \n"
+ " geoinit_partslip = \"" "%f" /* partslip */ "\"; #cfgset \n"
+ " filename= \"" "%s" /* data filename */ "\"; #cfgset \n" ;
+ char *fluidString =
+ " geoinittype= \"" "%s" /* type */ "\"; \n"
+ " filename= \"" "%s" /* data filename */ "\"; #cfgset \n" ;
+ //" initial_velocity= " "%f %f %f" /* vel vector */ "; #cfgset \n" ;
+ char *inflowString =
+ " geoinittype= \"" "%s" /* type */ "\"; \n"
+ " filename= \"" "%s" /* data filename */ "\"; #cfgset \n"
+ //" initial_velocity= " "%f %f %f" /* vel vector */ "; #cfgset \n"
+ " geoinit_localinivel = " "%d" /* local coords */ "; #cfgset \n" ;
+ char *objectStringEnd =
+ " geoinit_intersect = 1; \n" /* always use accurate init here */
+ " geoinitid= 1; \n"
+ " } \n"
+ " } \n"
+ "\n" ;
+ char fnameObjdat[FILE_MAXFILE];
+
+ channelObjCount = 0;
+ for(obit= G.main->object.first; obit; obit= obit->id.next) {
+ if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
+ (obit->type==OB_MESH) && // if has to match 3 places! // CHECKMATCH
+ (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) &&
+ (obit->fluidsimSettings->type != OB_FLUIDSIM_PARTICLE)
+ ) {
+
+ fluidsimGetGeometryObjFilename(obit, fnameObjdat);
+ strcpy(targetFile, targetDir);
+ strcat(targetFile, fnameObjdat);
+ fprintf(fileCfg, objectStringStart, obit->id.name ); // abs path
+ if(obit->fluidsimSettings->type == OB_FLUIDSIM_FLUID) {
+ fprintf(fileCfg, fluidString, "fluid", targetFile // do use absolute paths?
+ //,(double)obit->fluidsimSettings->iniVelx, (double)obit->fluidsimSettings->iniVely, (double)obit->fluidsimSettings->iniVelz
+ );
+ }
+ if(obit->fluidsimSettings->type == OB_FLUIDSIM_INFLOW) {
+ int locc = ((obit->fluidsimSettings->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0);
+ fprintf(fileCfg, inflowString, "inflow", targetFile // do use absolute paths?
+ //,(double)obit->fluidsimSettings->iniVelx, (double)obit->fluidsimSettings->iniVely, (double)obit->fluidsimSettings->iniVelz
+ ,locc );
+ }
+ if(obit->fluidsimSettings->type == OB_FLUIDSIM_OBSTACLE) {
+ char *btype[3] = { "bnd_no", "bnd_part", "bnd_free" };
+ float pslip = obit->fluidsimSettings->partSlipValue; int bi=0;
+ if((obit->fluidsimSettings->typeFlags&OB_FSBND_NOSLIP)) bi=0;
+ else if((obit->fluidsimSettings->typeFlags&OB_FSBND_PARTSLIP)) bi=1;
+ else if((obit->fluidsimSettings->typeFlags&OB_FSBND_FREESLIP)) bi=2;
+ fprintf(fileCfg, obstacleString, btype[bi], pslip, targetFile); // abs path
+ }
+ if(obit->fluidsimSettings->type == OB_FLUIDSIM_OUTFLOW) {
+ fprintf(fileCfg, outflowString, "outflow" , targetFile); // abs path
+ }
+
+ fluidsimPrintChannel(fileCfg, channelObjMove[channelObjCount][0],allchannelSize, "translation", CHANNEL_VEC);
+ fluidsimPrintChannel(fileCfg, channelObjMove[channelObjCount][1],allchannelSize, "rotation" , CHANNEL_VEC);
+ fluidsimPrintChannel(fileCfg, channelObjMove[channelObjCount][2],allchannelSize, "scale" , CHANNEL_VEC);
+ fluidsimPrintChannel(fileCfg, channelObjActive[channelObjCount] ,allchannelSize, "geoactive" , CHANNEL_FLOAT);
+ if( (obit->fluidsimSettings->type == OB_FLUIDSIM_FLUID) ||
+ (obit->fluidsimSettings->type == OB_FLUIDSIM_INFLOW) ) {
+ fluidsimPrintChannel(fileCfg, channelObjInivel[channelObjCount],allchannelSize,"initial_velocity" ,CHANNEL_VEC);
+ }
+ channelObjCount++;
+
+ fprintf(fileCfg, objectStringEnd ); // abs path
+ writeBobjgz(targetFile, obit);
+ }
+ }
+ }
+
+ /* fluid material */
+ fprintf(fileCfg,
+ " material { \n"
+ " type= phong; \n"
+ " name= \"fluidblue\"; \n"
+ " diffuse= 0.3 0.5 0.9; \n"
+ " ambient= 0.1 0.1 0.1; \n"
+ " specular= 0.2 10.0; \n"
+ " } \n" );
+
+ fprintf(fileCfg, "} // end raytracing\n");
+ fclose(fileCfg);
+
+ strcpy(targetFile, targetDir);
+ strcat(targetFile, suffixConfig);
+ snprintf(debugStrBuffer,256,"fluidsimBake::msg: Wrote %s\n", targetFile);
+ elbeemDebugOut(debugStrBuffer);
+
+ pupmenu("Fluidsim Bake Message%t|Config files exported successfully!%x0");
+ } // config file export done!
+
+ // --------------------------------------------------------------------------------------------
+ FS_FREE_CHANNELS;
// go back to "current" blender time
waitcursor(0);
diff --git a/source/blender/src/header_ipo.c b/source/blender/src/header_ipo.c
index 9271fe834d4..48b98e9a65d 100644
--- a/source/blender/src/header_ipo.c
+++ b/source/blender/src/header_ipo.c
@@ -53,6 +53,7 @@
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
+#include "DNA_object_fluidsim.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_texture_types.h"
@@ -141,6 +142,14 @@ void spaceipo_assign_ipo(SpaceIpo *si, Ipo *ipo)
conchan->ipo= ipo;
}
}
+ else if(si->blocktype==ID_FLUIDSIM) { // NT
+ if( (ob->fluidsimSettings) &&
+ (ob->fluidsimSettings->ipo) ) {
+ // decrement users counter
+ ob->fluidsimSettings->ipo->id.us--;
+ }
+ ob->fluidsimSettings->ipo = ipo;
+ }
else if(si->blocktype==ID_OB) {
if(ob->ipo)
ob->ipo->id.us--;
@@ -798,6 +807,9 @@ static char *ipo_modeselect_pup(void)
#ifdef __CON_IPO
str += sprintf(str,formatstring, "Constraint",ID_CO, ICON_CONSTRAINT);
#endif
+ if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
+ str += sprintf(str,formatstring,"Fluidsim",ID_FLUIDSIM, ICON_WORLD);
+ }
}
str += sprintf(str,formatstring, "Sequence",ID_SEQ, ICON_SEQUENCE);
@@ -1135,6 +1147,8 @@ void ipo_buttons(void)
icon = ICON_SEQUENCE;
else if(G.sipo->blocktype == ID_TE)
icon = ICON_TEXTURE;
+ else if(G.sipo->blocktype == ID_FLUIDSIM)
+ icon = ICON_WORLD;
uiDefIconTextButS(block, MENU, B_IPOMAIN, icon, ipo_modeselect_pup(), xco,0,100,20, &(G.sipo->blocktype), 0, 0, 0, 0, "Show IPO type");