Fluid control: WIP commit before weekend, not working is crashing on the first 3 frames

This commit is contained in:
Daniel Genrich 2008-07-25 18:57:16 +00:00
parent 9bf0bfcae7
commit d7fecc9e96
29 changed files with 1600 additions and 1493 deletions

@ -166,8 +166,8 @@ CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing']
CPPFLAGS = ['-DXP_UNIX']
CXXFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing']
REL_CFLAGS = ['-O2']
REL_CCFLAGS = ['-O2']
REL_CFLAGS = ['-O3']
REL_CCFLAGS = ['-O3']
##BF_DEPEND = 'true'
##
##AR = ar

@ -32,7 +32,7 @@ typedef struct elbeemSimulationSettings {
short version;
/* id number of simulation domain, needed if more than a
* single domain should be simulated */
short domainId;
short domainId; // unused within blender
/* geometrical extent */
float geoStart[3], geoSize[3];
@ -187,6 +187,9 @@ void elbeemResetSettings(struct elbeemSimulationSettings*);
// start fluidsim init (returns !=0 upon failure)
int elbeemInit(void);
// frees fluidsim
int elbeemFree(void);
// start fluidsim init (returns !=0 upon failure)
int elbeemAddDomain(struct elbeemSimulationSettings*);

@ -57,6 +57,7 @@ void ControlParticles::initBlenderTest() {
initTime(0. , 1.);
}
// blender control object gets converted to mvm flui control object
int ControlParticles::initFromObject(ntlGeometryObjModel *model) {
vector<ntlTriangle> triangles;
vector<ntlVec3Gfx> vertices;
@ -73,6 +74,7 @@ int ControlParticles::initFromObject(ntlGeometryObjModel *model) {
printf("a animated? %d\n", model->getIsAnimated());
printf("b animated? %d\n", model->getMeshAnimated());
*/
model->setGeoInitType(FGI_FLUID);
model->getTriangles(mCPSTimeStart, &triangles, &vertices, &normals, 1 );
@ -137,7 +139,7 @@ int ControlParticles::initFromObject(ntlGeometryObjModel *model) {
// init first set, check dist
ControlParticleSet firstcps; //T
mPartSets.push_back(firstcps);
mPartSets[mPartSets.size()-1].time = (gfxReal)0.;
mPartSets[mPartSets.size()-1].time = mCPSTimeStart;
vector<bool> useCP;
for(int i=0; i<(int)inspos.size(); i++) {
@ -1378,8 +1380,10 @@ void ControlParticles::calculateCpInfluenceOpt(ControlParticle *cp, LbmVec fluid
#if (CP_PROJECT2D==1) && (defined(MAIN_2D) || LBMDIM==2)
// fillFactor *= 2.0 *0.75 * pdistance; // 2d>3d sampling
#endif // (CP_PROJECT2D==1) && (defined(MAIN_2D) || LBMDIM==2)
LbmFloat signum = getInfluenceAttraction() > 0.0 ? 1.0 : -1.0;
cp->density += falloffAtt * fillFactor;
force->forceAtt += posDelta *cp->densityWeight *cp->influence;
force->forceAtt += posDelta *cp->densityWeight *cp->influence *signum;
force->weightAtt += falloffAtt*cp->densityWeight *cp->influence;
LbmFloat falloffVel = 0.; //CPKernel::kernel(cpfo * 1.0, pdistance);

@ -96,6 +96,13 @@ int elbeemInit() {
return 0;
}
// fluidsim end
extern "C"
int elbeemFree() {
return 0;
}
// start fluidsim init
extern "C"
int elbeemAddDomain(elbeemSimulationSettings *settings) {
@ -253,6 +260,7 @@ int elbeemSimulate(void) {
if(getElbeemState() != SIMWORLD_STOP) {
// ok, we're done...
delete gpWorld;
gpWorld = NULL;
debMsgStd("elbeemSimulate",DM_NOTIFY, "El'Beem simulation done, time: "<<getTimeString(timeend-timestart)<<".\n", 2 );
} else {

@ -688,7 +688,8 @@ ntlScene::~ntlScene()
if(mpTree != NULL) delete mpTree;
// cleanup lists, only if this is the rendering cleanup scene
if(mSceneDel) {
if(mSceneDel)
{
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin();
iter != mGeos.end(); iter++) {
//errMsg("ntlScene::~ntlScene","Deleting obj "<<(*iter)->getName() );

@ -236,10 +236,15 @@ ntlWorld::~ntlWorld()
{
delete mpGlob->getRenderScene();
delete mpGlob->getSimScene();
delete mpGlob;
delete mpLightList;
delete mpPropList;
delete mpSims;
delete mpGlob;
// these get assigned to mpGlob but not freed there
delete mpLightList;
delete mpPropList; // materials
delete mpSims;
#ifndef NOGUI
if(mpOpenGLRenderer) delete mpOpenGLRenderer;
#endif // NOGUI
@ -895,6 +900,8 @@ ntlRenderGlobals::ntlRenderGlobals() :
ntlRenderGlobals::~ntlRenderGlobals() {
if(mpOpenGlAttr) delete mpOpenGlAttr;
if(mpBlenderAttr) delete mpBlenderAttr;
}

@ -236,7 +236,6 @@ LbmFsgrSolver::initCpdata()
// dont load any file
cset->mContrPartFile = string("");
// TODO dg: switch to channels later
cset->mcForceAtt = obj->getCpsAttrFStr();
cset->mcRadiusAtt = obj->getCpsAttrFRad();
cset->mcForceVel = obj->getCpsVelFStr();
@ -491,8 +490,8 @@ LbmFsgrSolver::handleCpdata()
// init for current time
for(int cpssi=0; cpssi<(int)mpControl->mCons.size(); cpssi++) {
ControlParticles *cparts = mpControl->mCons[cpssi]->mCparts;
LbmControlSet *cset = mpControl->mCons[cpssi];
cparts->setRadiusAtt(cset->mcRadiusAtt.get(mSimulationTime));
cparts->setRadiusVel(cset->mcRadiusVel.get(mSimulationTime));
cparts->setInfluenceAttraction(cset->mcForceAtt.get(mSimulationTime) );
@ -506,18 +505,22 @@ LbmFsgrSolver::handleCpdata()
cparts->setInfluenceVelocity( cset->mcForceVel.get(mSimulationTime), mLevel[fineLev].timestep );
cparts->setLastOffset( vec2L(cset->mcCpOffset.get(mSimulationTime-mLevel[fineLev].timestep)) );
cparts->setLastScale( vec2L(cset->mcCpScale.get(mSimulationTime-mLevel[fineLev].timestep)) );
}
// check actual values
LbmFloat iatt = mpControl->mCons[0]->mCparts->getInfluenceAttraction();
LbmFloat iatt = ABS(mpControl->mCons[0]->mCparts->getInfluenceAttraction());
LbmFloat ivel = mpControl->mCons[0]->mCparts->getInfluenceVelocity();
LbmFloat imaxd = mpControl->mCons[0]->mCparts->getInfluenceMaxdist();
//errMsg("FINCIT","iatt="<<iatt<<" ivel="<<ivel<<" imaxd="<<imaxd);
for(int cpssi=1; cpssi<(int)mpControl->mCons.size(); cpssi++) {
LbmFloat iatt2 = mpControl->mCons[cpssi]->mCparts->getInfluenceAttraction();
LbmFloat iatt2 = ABS(mpControl->mCons[cpssi]->mCparts->getInfluenceAttraction());
LbmFloat ivel2 = mpControl->mCons[cpssi]->mCparts->getInfluenceVelocity();
LbmFloat imaxd2 = mpControl->mCons[cpssi]->mCparts->getInfluenceMaxdist();
if(iatt2 >iatt) iatt = iatt2;
// we allow negative attraction force here!
if(iatt2 > iatt) iatt = iatt2;
if(ivel2 >ivel) ivel = ivel2;
if(imaxd2>imaxd) imaxd= imaxd2;
//errMsg("FINCIT"," "<<cpssi<<" iatt2="<<iatt2<<" ivel2="<<ivel2<<" imaxd2="<<imaxd<<" NEW "<<" iatt="<<iatt<<" ivel="<<ivel<<" imaxd="<<imaxd);
@ -582,6 +585,12 @@ LbmFsgrSolver::handleCpdata()
ControlParticles *cparts = mpControl->mCons[cpssi]->mCparts;
// ControlParticles *cpmotion = mpControl->mCons[cpssi]->mCpmotion;
// if control set is not active skip it
if((cparts->getControlTimStart() > mSimulationTime) || (cparts->getControlTimEnd() < mLastSimTime))
{
continue;
}
const LbmFloat velLatticeScale = mLevel[lev].timestep/mLevel[lev].nodeSize;
LbmFloat gsx = ((mvGeoEnd[0]-mvGeoStart[0])/(LbmFloat)mLevel[lev].lSizex);
LbmFloat gsy = ((mvGeoEnd[1]-mvGeoStart[1])/(LbmFloat)mLevel[lev].lSizey);

@ -41,7 +41,7 @@ struct ListBase;
struct MemFile;
#define BLENDER_VERSION 246
#define BLENDER_SUBVERSION 0
#define BLENDER_SUBVERSION 1
#define BLENDER_MINVERSION 245
#define BLENDER_MINSUBVERSION 15

@ -0,0 +1,57 @@
/**
* BKE_fluidsim.h
*
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) Blender Foundation
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "DNA_modifier_types.h"
#include "DNA_object_fluidsim.h" // N_T
#include "DNA_object_types.h"
#include "BKE_DerivedMesh.h"
/* old interface */
FluidsimSettings *fluidsimSettingsNew(struct Object *srcob);
void initElbeemMesh(Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords);
void loadFluidsimMesh(Object *srcob, int useRenderParams);
/* new fluid-modifier interface */
void fluidsim_init(FluidsimModifierData *fluidmd);
void fluidsim_free(FluidsimModifierData *fluidmd);
DerivedMesh *fluidsim_read_cache(Object *ob, FluidsimModifierData *fluidmd, int framenr, int useRenderParams);
DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc);
void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4],
/*RET*/ float start[3], /*RET*/ float size[3] );

@ -54,7 +54,8 @@
/* PTCacheID types */
#define PTCACHE_TYPE_SOFTBODY 0
#define PTCACHE_TYPE_PARTICLES 1
#define PTCACHE_TYPE_CLOTH 2
#define PTCACHE_TYPE_CLOTH 2
#define PTCACHE_TYPE_FLUIDSIM 3
/* Structs */
struct Object;
@ -83,6 +84,7 @@ typedef struct PTCacheID {
void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb);
void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys);
void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd);
void BKE_ptcache_id_from_fluidsim(PTCacheID *pid, struct Object *ob, struct FluidsimModifierData *fluidmd);
void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob);

@ -33,8 +33,6 @@
#include <config.h>
#endif
#include <zlib.h>
#include "PIL_time.h"
#include "MEM_guardedalloc.h"
@ -66,6 +64,7 @@
#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_fluidsim.h"
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_material.h"
@ -85,11 +84,6 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
// headers for fluidsim bobj meshes
#include <stdlib.h>
#include "LBM_fluidsim.h"
#include "elbeem.h"
///////////////////////////////////
///////////////////////////////////
@ -411,35 +405,15 @@ void DM_swap_face_data(DerivedMesh *dm, int index, int *corner_indices)
static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3])
{
DerivedMesh *dm = CDDM_from_mesh(me, ob);
int i, dofluidsim;
dofluidsim = ((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&&
(ob->fluidsimSettings->meshSurface) &&
(me->totvert == ((Mesh *)(ob->fluidsimSettings->meshSurface))->totvert));
if(!dm)
return NULL;
if (vertCos && !dofluidsim)
if (vertCos)
CDDM_apply_vert_coords(dm, vertCos);
CDDM_calc_normals(dm);
/* apply fluidsim normals */
if (dofluidsim) {
// use normals from readBobjgz
// TODO? check for modifiers!?
MVert *fsvert = ob->fluidsimSettings->meshSurfNormals;
short (*normals)[3] = MEM_mallocN(sizeof(short)*3*me->totvert, "fluidsim nor");
for (i=0; i<me->totvert; i++) {
VECCOPY(normals[i], fsvert[i].no);
//mv->no[0]= 30000; mv->no[1]= mv->no[2]= 0; // DEBUG fixed test normals
}
CDDM_apply_vert_normals(dm, normals);
MEM_freeN(normals);
}
return dm;
}
@ -1891,7 +1865,6 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
float (*deformedVerts)[3] = NULL;
DerivedMesh *dm, *orcodm, *finaldm;
int numVerts = me->totvert;
int fluidsimMeshUsed = 0;
int required_mode;
md = firstmd = modifiers_getVirtualModifierList(ob);
@ -1907,21 +1880,6 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
if(deform_r) *deform_r = NULL;
*final_r = NULL;
/* replace original mesh by fluidsim surface mesh for fluidsim
* domain objects
*/
if((G.obedit!=ob) && !needMapping) {
if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
loadFluidsimMesh(ob,useRenderParams);
fluidsimMeshUsed = 1;
/* might have changed... */
me = ob->data;
numVerts = me->totvert;
}
}
}
if(useRenderParams) required_mode = eModifierMode_Render;
else required_mode = eModifierMode_Realtime;
@ -1969,18 +1927,11 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
#endif
}
} else {
if(!fluidsimMeshUsed) {
/* default behaviour for meshes */
if(inputVertexCos)
deformedVerts = inputVertexCos;
else
deformedVerts = mesh_getRefKeyCos(me, &numVerts);
} else {
/* the fluid sim mesh might have more vertices than the original
* one, so inputVertexCos shouldnt be used
*/
deformedVerts = mesh_getVertexCos(me, &numVerts);
}
/* default behaviour for meshes */
if(inputVertexCos)
deformedVerts = inputVertexCos;
else
deformedVerts = mesh_getRefKeyCos(me, &numVerts);
}
@ -2158,9 +2109,6 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
MEM_freeN(deformedVerts);
BLI_linklist_free(datamasks, NULL);
/* restore mesh in any case */
if(fluidsimMeshUsed) ob->data = ob->fluidsimSettings->orgMesh;
}
static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3]
@ -2844,582 +2792,4 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo
return numleft;
}
/* ************************* fluidsim bobj file handling **************************** */
#ifndef DISABLE_ELBEEM
#ifdef WIN32
#ifndef snprintf
#define snprintf _snprintf
#endif
#endif
/* write .bobj.gz file for a mesh object */
void writeBobjgz(char *filename, struct Object *ob, int useGlobalCoords, int append, float time)
{
char debugStrBuffer[256];
int wri,i,j,totvert,totface;
float wrf;
gzFile gzf;
DerivedMesh *dm;
float vec[3];
float rotmat[3][3];
MVert *mvert;
MFace *mface;
//if(append)return; // DEBUG
if(!ob->data || (ob->type!=OB_MESH)) {
snprintf(debugStrBuffer,256,"Writing GZ_BOBJ Invalid object %s ...\n", ob->id.name);
elbeemDebugOut(debugStrBuffer);
return;
}
if((ob->size[0]<0.0) || (ob->size[0]<0.0) || (ob->size[0]<0.0) ) {
snprintf(debugStrBuffer,256,"\nfluidSim::writeBobjgz:: Warning object %s has negative scaling - check triangle ordering...?\n\n", ob->id.name);
elbeemDebugOut(debugStrBuffer);
}
snprintf(debugStrBuffer,256,"Writing GZ_BOBJ '%s' ... ",filename); elbeemDebugOut(debugStrBuffer);
if(append) gzf = gzopen(filename, "a+b9");
else gzf = gzopen(filename, "wb9");
if (!gzf) {
snprintf(debugStrBuffer,256,"writeBobjgz::error - Unable to open file for writing '%s'\n", filename);
elbeemDebugOut(debugStrBuffer);
return;
}
dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
//dm = mesh_create_derived_no_deform(ob,NULL);
mvert = dm->getVertArray(dm);
mface = dm->getFaceArray(dm);
totvert = dm->getNumVerts(dm);
totface = dm->getNumFaces(dm);
// write time value for appended anim mesh
if(append) {
gzwrite(gzf, &time, sizeof(time));
}
// continue with verts/norms
if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Writing GZ_BOBJ, Invalid int size %d...\n", wri); elbeemDebugOut(debugStrBuffer); return; } // paranoia check
wri = dm->getNumVerts(dm);
mvert = dm->getVertArray(dm);
gzwrite(gzf, &wri, sizeof(wri));
for(i=0; i<wri;i++) {
VECCOPY(vec, mvert[i].co);
if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, vec); }
for(j=0; j<3; j++) {
wrf = vec[j];
gzwrite(gzf, &wrf, sizeof( wrf ));
}
}
// should be the same as Vertices.size
wri = totvert;
gzwrite(gzf, &wri, sizeof(wri));
EulToMat3(ob->rot, rotmat);
for(i=0; i<wri;i++) {
VECCOPY(vec, mvert[i].no);
Normalize(vec);
if(useGlobalCoords) { Mat3MulVecfl(rotmat, vec); }
for(j=0; j<3; j++) {
wrf = vec[j];
gzwrite(gzf, &wrf, sizeof( wrf ));
}
}
// append only writes verts&norms
if(!append) {
//float side1[3],side2[3],norm1[3],norm2[3];
//float inpf;
// compute no. of triangles
wri = 0;
for(i=0; i<totface; i++) {
wri++;
if(mface[i].v4) { wri++; }
}
gzwrite(gzf, &wri, sizeof(wri));
for(i=0; i<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;
//snprintf(debugStrBuffer,256,"F %s %d = %d,%d,%d,%d \n",ob->id.name, i, face[0],face[1],face[2],face[3] ); elbeemDebugOut(debugStrBuffer);
//VecSubf(side1, mvert[face[1]].co,mvert[face[0]].co);
//VecSubf(side2, mvert[face[2]].co,mvert[face[0]].co);
//Crossf(norm1,side1,side2);
gzwrite(gzf, &(face[0]), sizeof( face[0] ));
gzwrite(gzf, &(face[1]), sizeof( face[1] ));
gzwrite(gzf, &(face[2]), sizeof( face[2] ));
if(face[3]) {
//VecSubf(side1, mvert[face[2]].co,mvert[face[0]].co);
//VecSubf(side2, mvert[face[3]].co,mvert[face[0]].co);
//Crossf(norm2,side1,side2);
//inpf = Inpf(norm1,norm2);
//if(inpf>0.) {
gzwrite(gzf, &(face[0]), sizeof( face[0] ));
gzwrite(gzf, &(face[2]), sizeof( face[2] ));
gzwrite(gzf, &(face[3]), sizeof( face[3] ));
//} else {
//gzwrite(gzf, &(face[0]), sizeof( face[0] ));
//gzwrite(gzf, &(face[3]), sizeof( face[3] ));
//gzwrite(gzf, &(face[2]), sizeof( face[2] ));
//}
} // quad
}
}
snprintf(debugStrBuffer,256,"Done. #Vertices: %d, #Triangles: %d\n", totvert, totface );
elbeemDebugOut(debugStrBuffer);
gzclose( gzf );
dm->release(dm);
}
void initElbeemMesh(struct Object *ob,
int *numVertices, float **vertices,
int *numTriangles, int **triangles,
int useGlobalCoords)
{
DerivedMesh *dm = NULL;
MVert *mvert;
MFace *mface;
int countTris=0, i, totvert, totface;
float *verts;
int *tris;
dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
//dm = mesh_create_derived_no_deform(ob,NULL);
mvert = dm->getVertArray(dm);
mface = dm->getFaceArray(dm);
totvert = dm->getNumVerts(dm);
totface = dm->getNumFaces(dm);
*numVertices = totvert;
verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices");
for(i=0; i<totvert; i++) {
VECCOPY( &verts[i*3], mvert[i].co);
if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, &verts[i*3]); }
}
*vertices = verts;
for(i=0; i<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<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;
dm->release(dm);
}
/* read .bobj.gz file into a fluidsimDerivedMesh struct */
Mesh* readBobjgz(char *filename, Mesh *orgmesh, float* bbstart, float *bbsize) //, fluidsimDerivedMesh *fsdm)
{
int wri,i,j;
char debugStrBuffer[256];
float wrf;
Mesh *newmesh;
const int debugBobjRead = 1;
// init data from old mesh (materials,flags)
MFace *origMFace = &((MFace*) orgmesh->mface)[0];
int mat_nr = -1;
int flag = -1;
MFace *fsface = NULL;
int gotBytes;
gzFile gzf;
if(!orgmesh) return NULL;
if(!origMFace) return NULL;
mat_nr = origMFace->mat_nr;
flag = origMFace->flag;
// similar to copy_mesh
newmesh = MEM_dupallocN(orgmesh);
newmesh->mat= orgmesh->mat;
newmesh->mvert= NULL;
newmesh->medge= NULL;
newmesh->mface= NULL;
newmesh->mtface= NULL;
newmesh->dvert = NULL;
newmesh->mcol= NULL;
newmesh->msticky= NULL;
newmesh->texcomesh= NULL;
memset(&newmesh->vdata, 0, sizeof(newmesh->vdata));
memset(&newmesh->edata, 0, sizeof(newmesh->edata));
memset(&newmesh->fdata, 0, sizeof(newmesh->fdata));
newmesh->key= NULL;
newmesh->totface = 0;
newmesh->totvert = 0;
newmesh->totedge = 0;
newmesh->medge = NULL;
snprintf(debugStrBuffer,256,"Reading '%s' GZ_BOBJ... ",filename); elbeemDebugOut(debugStrBuffer);
gzf = gzopen(filename, "rb");
// gzf = fopen(filename, "rb");
// debug: fread(b,c,1,a) = gzread(a,b,c)
if (!gzf) {
//snprintf(debugStrBuffer,256,"readBobjgz::error - Unable to open file for reading '%s'\n", filename); // DEBUG
MEM_freeN(newmesh);
return NULL;
}
//if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, Invalid int size %d...\n", wri); return NULL; } // paranoia check
gotBytes = gzread(gzf, &wri, sizeof(wri));
newmesh->totvert = wri;
newmesh->mvert = CustomData_add_layer(&newmesh->vdata, CD_MVERT, CD_CALLOC, NULL, newmesh->totvert);
if(debugBobjRead){ snprintf(debugStrBuffer,256,"#vertices %d ", newmesh->totvert); elbeemDebugOut(debugStrBuffer); } //DEBUG
for(i=0; i<newmesh->totvert;i++) {
//if(debugBobjRead) snprintf(debugStrBuffer,256,"V %d = ",i);
for(j=0; j<3; j++) {
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
newmesh->mvert[i].co[j] = wrf;
//if(debugBobjRead) snprintf(debugStrBuffer,256,"%25.20f ", wrf);
}
//if(debugBobjRead) snprintf(debugStrBuffer,256,"\n");
}
// should be the same as Vertices.size
gotBytes = gzread(gzf, &wri, sizeof(wri));
if(wri != newmesh->totvert) {
// complain #vertices has to be equal to #normals, reset&abort
CustomData_free_layer_active(&newmesh->vdata, CD_MVERT, newmesh->totvert);
MEM_freeN(newmesh);
snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, #normals=%d, #vertices=%d, aborting...\n", wri,newmesh->totvert );
return NULL;
}
for(i=0; i<newmesh->totvert;i++) {
for(j=0; j<3; j++) {
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
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 */
gotBytes = gzread(gzf, &wri, sizeof(wri));
newmesh->totface = wri;
newmesh->mface = CustomData_add_layer(&newmesh->fdata, CD_MFACE, CD_CALLOC, NULL, newmesh->totface);
if(debugBobjRead){ snprintf(debugStrBuffer,256,"#faces %d ", newmesh->totface); elbeemDebugOut(debugStrBuffer); } //DEBUG
fsface = newmesh->mface;
for(i=0; i<newmesh->totface; i++) {
int face[4];
gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] ));
gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] ));
gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] ));
face[3] = 0;
fsface[i].v1 = face[0];
fsface[i].v2 = face[1];
fsface[i].v3 = face[2];
fsface[i].v4 = face[3];
}
// correct triangles with v3==0 for blender, cycle verts
for(i=0; i<newmesh->totface; i++) {
if(!fsface[i].v3) {
int temp = fsface[i].v1;
fsface[i].v1 = fsface[i].v2;
fsface[i].v2 = fsface[i].v3;
fsface[i].v3 = temp;
}
}
gzclose( gzf );
for(i=0;i<newmesh->totface;i++) {
fsface[i].mat_nr = mat_nr;
fsface[i].flag = flag;
fsface[i].edcode = ME_V1V2 | ME_V2V3 | ME_V3V1;
//snprintf(debugStrBuffer,256,"%d : %d,%d,%d\n", i,fsface[i].mat_nr, fsface[i].flag, fsface[i].edcode );
}
snprintf(debugStrBuffer,256," (%d,%d) done\n", newmesh->totvert,newmesh->totface); elbeemDebugOut(debugStrBuffer); //DEBUG
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->domainNovecgen>0) 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 ***************************** */
/* check which file to load, and replace old mesh of the object with it */
/* this replacement is undone at the end of mesh_calc_modifiers */
void loadFluidsimMesh(Object *srcob, int useRenderParams)
{
Mesh *mesh = NULL;
float *bbStart = NULL, *bbSize = NULL;
float lastBB[3];
int displaymode = 0;
int curFrame = G.scene->r.cfra - 1 /*G.scene->r.sfra*/; /* start with 0 at start frame */
char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
char debugStrBuffer[256];
//snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
if((!srcob)||(!srcob->fluidsimSettings)) {
snprintf(debugStrBuffer,256,"DEBUG - Invalid loadFluidsimMesh call, rp %d, dm %d)\n", useRenderParams, displaymode); // debug
elbeemDebugOut(debugStrBuffer); // debug
return;
}
// make sure the original mesh data pointer is stored
if(!srcob->fluidsimSettings->orgMesh) {
srcob->fluidsimSettings->orgMesh = srcob->data;
}
// free old mesh, if there is one (todo, check if it's still valid?)
if(srcob->fluidsimSettings->meshSurface) {
Mesh *freeFsMesh = srcob->fluidsimSettings->meshSurface;
// similar to free_mesh(...) , but no things like unlink...
CustomData_free(&freeFsMesh->vdata, freeFsMesh->totvert);
CustomData_free(&freeFsMesh->edata, freeFsMesh->totedge);
CustomData_free(&freeFsMesh->fdata, freeFsMesh->totface);
MEM_freeN(freeFsMesh);
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
bbStart = srcob->fluidsimSettings->bbStart;
bbSize = srcob->fluidsimSettings->bbSize;
lastBB[0] = bbSize[0]; // TEST
lastBB[1] = bbSize[1];
lastBB[2] = bbSize[2];
fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize, &srcob->fluidsimSettings->meshBB);
// check free fsmesh... TODO
if(!useRenderParams) {
displaymode = srcob->fluidsimSettings->guiDisplayMode;
} else {
displaymode = srcob->fluidsimSettings->renderDisplayMode;
}
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);
// use preview or final mesh?
if(displaymode==1) {
// just display original object
srcob->data = srcob->fluidsimSettings->orgMesh;
return;
} else if(displaymode==2) {
strcat(targetDir,"fluidsurface_preview_####");
} else { // 3
strcat(targetDir,"fluidsurface_final_####");
}
BLI_convertstringcode(targetDir, G.sce);
BLI_convertstringframe(targetDir, curFrame); // fixed #frame-no
strcpy(targetFile,targetDir);
strcat(targetFile, ".bobj.gz");
snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile); // debug
elbeemDebugOut(debugStrBuffer); // debug
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) {
// switch, abort background rendering when fluidsim mesh is missing
const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
if(G.background==1) {
if(getenv(strEnvName2)) {
int elevel = atoi(getenv(strEnvName2));
if(elevel>0) {
printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
exit(1);
}
}
}
// display org. object upon failure
srcob->data = srcob->fluidsimSettings->orgMesh;
return;
}
if((mesh)&&(mesh->totvert>0)) {
make_edges(mesh, 0); // 0 = make all edges draw
}
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*/ struct Mesh **bbmesh )
{
float bbsx=0.0, bbsy=0.0, bbsz=0.0;
float bbex=1.0, bbey=1.0, bbez=1.0;
int i;
float vec[3];
VECCOPY(vec, mesh->mvert[0].co);
Mat4MulVecfl(obmat, vec);
bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
for(i=1; i<mesh->totvert;i++) {
VECCOPY(vec, mesh->mvert[i].co);
Mat4MulVecfl(obmat, vec);
if(vec[0] < bbsx){ bbsx= vec[0]; }
if(vec[1] < bbsy){ bbsy= vec[1]; }
if(vec[2] < bbsz){ bbsz= vec[2]; }
if(vec[0] > bbex){ bbex= vec[0]; }
if(vec[1] > bbey){ bbey= vec[1]; }
if(vec[2] > bbez){ bbez= vec[2]; }
}
// return values...
if(start) {
start[0] = bbsx;
start[1] = bbsy;
start[2] = bbsz;
}
if(size) {
size[0] = bbex-bbsx;
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 = CustomData_add_layer(&newmesh->vdata, CD_MVERT, CD_CALLOC, NULL, newmesh->totvert);
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 = CustomData_add_layer(&newmesh->fdata, CD_MFACE, CD_CALLOC, NULL, newmesh->totface);
*bbmesh = newmesh;
}
}
#else // DISABLE_ELBEEM
/* dummy for mesh_calc_modifiers */
void loadFluidsimMesh(Object *srcob, int useRenderParams) {
}
#endif // DISABLE_ELBEEM

@ -764,10 +764,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
dm->deformedOnly = 1;
if(ob && ob->fluidsimSettings && ob->fluidsimSettings->meshSurface)
alloctype= CD_DUPLICATE;
else
alloctype= CD_REFERENCE;
alloctype= CD_REFERENCE;
CustomData_merge(&mesh->vdata, &dm->vertData, CD_MASK_MESH, alloctype,
mesh->totvert);

@ -1963,12 +1963,6 @@ static void dag_object_time_update_flags(Object *ob)
ob->shapeflag &= ~OB_SHAPE_TEMPLOCK;
}
}
if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings)) {
// fluidsimSettings might not be initialized during load...
if(ob->fluidsimSettings->type & (OB_FLUIDSIM_DOMAIN|OB_FLUIDSIM_PARTICLE)) {
ob->recalc |= OB_RECALC_DATA; // NT FSPARTICLE
}
}
if(ob->particlesystem.first)
ob->recalc |= OB_RECALC_DATA;
break;

@ -0,0 +1,702 @@
/**
* fluidsim.c
*
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) Blender Foundation
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "MEM_guardedalloc.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_force.h" // for pointcache
#include "DNA_particle_types.h"
#include "DNA_scene_types.h" // N_T
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
#include "BKE_fluidsim.h"
#include "BKE_global.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
#include "BKE_pointcache.h"
#include "BKE_utildefines.h"
// headers for fluidsim bobj meshes
#include <stdlib.h>
#include "LBM_fluidsim.h"
#include "elbeem.h"
#include <zlib.h>
#include <string.h>
#include <stdio.h>
/* ************************* fluidsim bobj file handling **************************** */
#ifndef DISABLE_ELBEEM
// -----------------------------------------
// forward decleration
// -----------------------------------------
// -----------------------------------------
void fluidsim_init(FluidsimModifierData *fluidmd)
{
if(fluidmd)
{
FluidsimSettings *fss = MEM_callocN(sizeof(FluidsimSettings), "fluidsimsettings");
fluidmd->fss = fss;
if(!fss)
return;
fss->type = 0;
fss->show_advancedoptions = 0;
fss->resolutionxyz = 50;
fss->previewresxyz = 25;
fss->realsize = 0.03;
fss->guiDisplayMode = 2; // preview
fss->renderDisplayMode = 3; // render
fss->viscosityMode = 2; // default to water
fss->viscosityValue = 1.0;
fss->viscosityExponent = 6;
// dg TODO: change this to []
fss->gravx = 0.0;
fss->gravy = 0.0;
fss->gravz = -9.81;
fss->animStart = 0.0;
fss->animEnd = 0.30;
fss->gstar = 0.005; // used as normgstar
fss->maxRefine = -1;
// maxRefine is set according to resolutionxyz during bake
// fluid/inflow settings
// fss->iniVel --> automatically set to 0
/* elubie: changed this to default to the same dir as the render output
to prevent saving to C:\ on Windows */
BLI_strncpy(fss->surfdataPath, btempdir, FILE_MAX);
// first init of bounding box
// no bounding box needed
// todo - reuse default init from elbeem!
fss->typeFlags = 0;
fss->domainNovecgen = 0;
fss->volumeInitType = 1; // volume
fss->partSlipValue = 0.0;
fss->generateTracers = 0;
fss->generateParticles = 0.0;
fss->surfaceSmoothing = 1.0;
fss->surfaceSubdivs = 1.0;
fss->particleInfSize = 0.0;
fss->particleInfAlpha = 0.0;
// init fluid control settings
fss->attractforceStrength = 0.2;
fss->attractforceRadius = 0.75;
fss->velocityforceStrength = 0.2;
fss->velocityforceRadius = 0.75;
fss->cpsTimeStart = fss->animStart;
fss->cpsTimeEnd = fss->animEnd;
fss->cpsQuality = 10.0; // 1.0 / 10.0 => means 0.1 width
/*
BAD TODO: this is done in buttons_object.c in the moment
Mesh *mesh = ob->data;
// calculate bounding box
fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
*/
fss->lastgoodframe = -1;
}
return;
}
void fluidsim_free(FluidsimModifierData *fluidmd)
{
if(fluidmd)
{
MEM_freeN(fluidmd->fss);
}
return;
}
DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
{
DerivedMesh *result = NULL;
int framenr;
FluidsimSettings *fss;
framenr= (int)G.scene->r.cfra;
// only handle fluidsim domains
if(fluidmd && fluidmd->fss && (fluidmd->fss->type != OB_FLUIDSIM_DOMAIN))
return dm;
// timescale not supported yet
// clmd->sim_parms->timescale= timescale;
/* try to read from cache */
if((result = fluidsim_read_cache(ob, fluidmd, framenr, useRenderParams))) {
fss->lastgoodframe = framenr;
return result;
}
else
{
// display last known good frame
if(fss->lastgoodframe >= 0)
{
if((result = fluidsim_read_cache(ob, fluidmd, framenr, useRenderParams))) {
return result;
}
}
result = CDDM_copy(dm);
if(!result) {
return dm;
}
}
return result;
}
/* read .bobj.gz file into a fluidsimDerivedMesh struct */
static DerivedMesh *fluidsim_read_obj(char *filename)
{
int wri,i,j;
float wrf;
int gotBytes;
gzFile gzf;
int numverts = 0, numfaces = 0, numedges = 0;
DerivedMesh *dm = NULL;
MFace *mface;
MVert *mvert;
short *normals;
// ------------------------------------------------
// get numverts + numfaces first
// ------------------------------------------------
gzf = gzopen(filename, "rb");
if (!gzf)
{
return NULL;
}
// read numverts
gotBytes = gzread(gzf, &wri, sizeof(wri));
numverts = wri;
// skip verts
for(i=0; i<numverts*3; i++)
{
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
}
// read number of normals
gotBytes = gzread(gzf, &wri, sizeof(wri));
// skip normals
for(i=0; i<numverts*3; i++)
{
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
}
/* get no. of triangles */
gotBytes = gzread(gzf, &wri, sizeof(wri));
numfaces = wri;
gzclose( gzf );
// ------------------------------------------------
// dg - TODO: check for numfaces / numverts = 0
if(!numfaces || !numverts)
return NULL;
gzf = gzopen(filename, "rb");
if (!gzf)
{
return NULL;
}
dm = CDDM_new(numverts, 0, numfaces);
if(!dm)
{
gzclose( gzf );
return NULL;
}
// read numverts
gotBytes = gzread(gzf, &wri, sizeof(wri));
// read vertex position from file
mvert = CDDM_get_verts(dm);
for(i=0; i<numverts; i++)
{
MVert *mv = &mvert[i];
for(j=0; j<3; j++)
{
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
mv->co[j] = wrf;
}
}
// should be the same as numverts
gotBytes = gzread(gzf, &wri, sizeof(wri));
if(wri != numverts)
{
if(dm)
dm->release(dm);
gzclose( gzf );
return NULL;
}
/*
normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" );
if(!normals)
{
if(dm)
dm->release(dm);
gzclose( gzf );
return NULL;
}
*/
// read normals from file (but don't save them yet)
for(i=0; i<numverts*3;i++)
{
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
// normals[i] = (short)(wrf*32767.0f);
}
/* read no. of triangles */
gotBytes = gzread(gzf, &wri, sizeof(wri));
if(wri!=numfaces)
printf("Fluidsim: error in reading data from file.\n");
// read triangles from file
mface = CDDM_get_faces(dm);
for(i=0; i<numfaces; i++)
{
int face[4];
MFace *mf = &mface[i];
gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] ));
gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] ));
gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] ));
face[3] = 0;
// check if 3rd vertex has index 0 (not allowed in blender)
if(face[2])
{
mf->v1 = face[0];
mf->v2 = face[1];
mf->v3 = face[2];
}
else
{
mf->v1 = face[1];
mf->v2 = face[2];
mf->v3 = face[0];
}
mface[i].v4 = face[3];
test_index_face(mf, NULL, 0, 3);
}
gzclose( gzf );
CDDM_calc_edges(dm);
// CDDM_apply_vert_normals(dm, (short (*)[3])normals);
// CDDM_calc_normals(result);
return dm;
}
DerivedMesh *fluidsim_read_cache(Object *ob, FluidsimModifierData *fluidmd, int framenr, int useRenderParams)
{
int displaymode = 0;
int curFrame = G.scene->r.cfra - 1 /*G.scene->r.sfra*/; /* start with 0 at start frame */
char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
FluidsimSettings *fss = fluidmd->fss;
DerivedMesh *dm = NULL;
if(!useRenderParams) {
displaymode = fss->guiDisplayMode;
} else {
displaymode = fss->renderDisplayMode;
}
strncpy(targetDir, fss->surfdataPath, FILE_MAXDIR);
// use preview or final mesh?
if(displaymode==1)
{
// just display original object
return NULL;
}
else if(displaymode==2)
{
strcat(targetDir,"fluidsurface_preview_####");
}
else
{ // 3
strcat(targetDir,"fluidsurface_final_####");
}
BLI_convertstringcode(targetDir, G.sce);
BLI_convertstringframe(targetDir, curFrame); // fixed #frame-no
strcpy(targetFile,targetDir);
strcat(targetFile, ".bobj.gz");
dm = fluidsim_read_obj(targetFile);
if(!dm)
{
// switch, abort background rendering when fluidsim mesh is missing
const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
if(G.background==1) {
if(getenv(strEnvName2)) {
int elevel = atoi(getenv(strEnvName2));
if(elevel>0) {
printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
exit(1);
}
}
}
// display org. object upon failure which is in dm
return NULL;
}
// 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.; }}
}*/
return dm;
}
void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4],
/*RET*/ float start[3], /*RET*/ float size[3] )
{
float bbsx=0.0, bbsy=0.0, bbsz=0.0;
float bbex=1.0, bbey=1.0, bbez=1.0;
int i;
float vec[3];
VECCOPY(vec, mvert[0].co);
Mat4MulVecfl(obmat, vec);
bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
for(i = 1; i < totvert; i++) {
VECCOPY(vec, mvert[i].co);
Mat4MulVecfl(obmat, vec);
if(vec[0] < bbsx){ bbsx= vec[0]; }
if(vec[1] < bbsy){ bbsy= vec[1]; }
if(vec[2] < bbsz){ bbsz= vec[2]; }
if(vec[0] > bbex){ bbex= vec[0]; }
if(vec[1] > bbey){ bbey= vec[1]; }
if(vec[2] > bbez){ bbez= vec[2]; }
}
// return values...
if(start) {
start[0] = bbsx;
start[1] = bbsy;
start[2] = bbsz;
}
if(size) {
size[0] = bbex-bbsx;
size[1] = bbey-bbsy;
size[2] = bbez-bbsz;
}
}
//-------------------------------------------------------------------------------
// old interface
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
// file handling
//-------------------------------------------------------------------------------
/* write .bobj.gz file for a mesh object */
void writeBobjgz(char *filename, struct Object *ob, int useGlobalCoords, int append, float time)
{
int wri,i,j,totvert,totface;
float wrf;
gzFile gzf;
DerivedMesh *dm;
float vec[3];
float rotmat[3][3];
MVert *mvert;
MFace *mface;
//if(append)return; // DEBUG
if(!ob->data || (ob->type!=OB_MESH))
{
return;
}
if((ob->size[0]<0.0) || (ob->size[0]<0.0) || (ob->size[0]<0.0) )
{
return;
}
if(append) gzf = gzopen(filename, "a+b9");
else gzf = gzopen(filename, "wb9");
if (!gzf)
return;
dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
//dm = mesh_create_derived_no_deform(ob,NULL);
mvert = dm->getVertArray(dm);
mface = dm->getFaceArray(dm);
totvert = dm->getNumVerts(dm);
totface = dm->getNumFaces(dm);
// write time value for appended anim mesh
if(append)
{
gzwrite(gzf, &time, sizeof(time));
}
// continue with verts/norms
if(sizeof(wri)!=4) { return; } // paranoia check
wri = dm->getNumVerts(dm);
mvert = dm->getVertArray(dm);
gzwrite(gzf, &wri, sizeof(wri));
for(i=0; i<wri;i++)
{
VECCOPY(vec, mvert[i].co);
if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, vec); }
for(j=0; j<3; j++) {
wrf = vec[j];
gzwrite(gzf, &wrf, sizeof( wrf ));
}
}
// should be the same as Vertices.size
wri = totvert;
gzwrite(gzf, &wri, sizeof(wri));
EulToMat3(ob->rot, rotmat);
for(i=0; i<wri;i++)
{
VECCOPY(vec, mvert[i].no);
Normalize(vec);
if(useGlobalCoords) { Mat3MulVecfl(rotmat, vec); }
for(j=0; j<3; j++) {
wrf = vec[j];
gzwrite(gzf, &wrf, sizeof( wrf ));
}
}
// append only writes verts&norms
if(!append) {
// compute no. of triangles
wri = 0;
for(i=0; i<totface; i++)
{
wri++;
if(mface[i].v4) { wri++; }
}
gzwrite(gzf, &wri, sizeof(wri));
for(i=0; i<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;
gzwrite(gzf, &(face[0]), sizeof( face[0] ));
gzwrite(gzf, &(face[1]), sizeof( face[1] ));
gzwrite(gzf, &(face[2]), sizeof( face[2] ));
if(face[3])
{
gzwrite(gzf, &(face[0]), sizeof( face[0] ));
gzwrite(gzf, &(face[2]), sizeof( face[2] ));
gzwrite(gzf, &(face[3]), sizeof( face[3] ));
} // quad
}
}
gzclose( gzf );
dm->release(dm);
}
void initElbeemMesh(struct Object *ob,
int *numVertices, float **vertices,
int *numTriangles, int **triangles,
int useGlobalCoords)
{
DerivedMesh *dm = NULL;
MVert *mvert;
MFace *mface;
int countTris=0, i, totvert, totface;
float *verts;
int *tris;
dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
//dm = mesh_create_derived_no_deform(ob,NULL);
mvert = dm->getVertArray(dm);
mface = dm->getFaceArray(dm);
totvert = dm->getNumVerts(dm);
totface = dm->getNumFaces(dm);
*numVertices = totvert;
verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices");
for(i=0; i<totvert; i++) {
VECCOPY( &verts[i*3], mvert[i].co);
if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, &verts[i*3]); }
}
*vertices = verts;
for(i=0; i<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<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;
dm->release(dm);
}
/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
void readVelgz(char *filename, Object *srcob)
{
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->domainNovecgen>0) return;
if(len<7)
{
return;
}
// .bobj.gz , correct filename
// 87654321
filename[len-6] = 'v';
filename[len-5] = 'e';
filename[len-4] = 'l';
gzf = gzopen(filename, "rb");
if (!gzf)
return;
gzread(gzf, &wri, sizeof( wri ));
if(wri != mesh->totvert)
{
return;
}
for(i=0; i<mesh->totvert;i++)
{
for(j=0; j<3; j++)
{
gzread(gzf, &wrf, sizeof( wrf ));
vverts[i].co[j] = wrf;
}
}
gzclose(gzf);
}
#endif // DISABLE_ELBEEM

@ -55,7 +55,9 @@
#include "MEM_guardedalloc.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
#include "DNA_cloth_types.h"
#include "DNA_curve_types.h"
#include "DNA_effect_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
@ -66,8 +68,6 @@
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "DNA_curve_types.h"
#include "DNA_camera_types.h"
#include "BLI_editVert.h"
@ -77,29 +77,30 @@
#include "BKE_main.h"
#include "BKE_anim.h"
#include "BKE_bad_level_calls.h"
#include "BKE_bmesh.h"
#include "BKE_booleanops.h"
#include "BKE_cloth.h"
#include "BKE_collision.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_curve.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_DerivedMesh.h"
#include "BKE_booleanops.h"
#include "BKE_displist.h"
#include "BKE_modifier.h"
#include "BKE_fluidsim.h"
#include "BKE_global.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_subsurf.h"
#include "BKE_object.h"
#include "BKE_mesh.h"
#include "BKE_softbody.h"
#include "BKE_cloth.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_softbody.h"
#include "BKE_subsurf.h"
#include "BKE_utildefines.h"
#include "depsgraph_private.h"
#include "BKE_bmesh.h"
#include "LOD_DependKludge.h"
#include "LOD_decimation.h"
@ -6890,6 +6891,49 @@ static DerivedMesh * explodeModifier_applyModifier(
}
return derivedData;
}
/* Fluidsim */
static void fluidsimModifier_initData(ModifierData *md)
{
FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
fluidsim_init(fluidmd);
}
static void fluidsimModifier_freeData(ModifierData *md)
{
FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
fluidsim_free(fluidmd);
}
static DerivedMesh * fluidsimModifier_applyModifier(
ModifierData *md, Object *ob, DerivedMesh *derivedData,
int useRenderParams, int isFinalCalc)
{
FluidsimModifierData *fluidmd= (FluidsimModifierData*) md;
DerivedMesh *result = NULL;
/* check for alloc failing */
if(!fluidmd->fss)
{
fluidsimModifier_initData(md);
if(!fluidmd->fss)
return derivedData;
}
result = fluidsimModifier_do(fluidmd, ob, derivedData, useRenderParams, isFinalCalc);
if(result) { CDDM_calc_normals(result); return result; }
return derivedData;
}
static int fluidsimModifier_dependsOnTime(ModifierData *md)
{
return 1;
}
/* MeshDeform */
static void meshdeformModifier_initData(ModifierData *md)
@ -7522,6 +7566,15 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti->requiredDataMask = explodeModifier_requiredDataMask;
mti->applyModifier = explodeModifier_applyModifier;
mti = INIT_TYPE(Fluidsim);
mti->type = eModifierTypeType_Nonconstructive
| eModifierTypeFlag_RequiresOriginalData;
mti->flags = eModifierTypeFlag_AcceptsMesh;
mti->initData = fluidsimModifier_initData;
mti->freeData = fluidsimModifier_freeData;
mti->dependsOnTime = fluidsimModifier_dependsOnTime;
mti->applyModifier = fluidsimModifier_applyModifier;
typeArrInit = 0;
#undef INIT_TYPE
}

@ -267,7 +267,6 @@ void free_object(Object *ob)
MEM_freeN(ob->pd);
}
if(ob->soft) sbFree(ob->soft);
if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings);
}
static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
@ -1208,15 +1207,6 @@ Object *copy_object(Object *ob)
}
obn->soft= copy_softbody(ob->soft);
/* NT copy fluid sim setting memory */
if(obn->fluidsimSettings) {
obn->fluidsimSettings = fluidsimSettingsCopy(ob->fluidsimSettings);
/* copying might fail... */
if(obn->fluidsimSettings) {
obn->fluidsimSettings->orgMesh = (Mesh *)obn->data;
}
}
copy_object_particlesystems(obn, ob);
obn->derivedDeform = NULL;

@ -4549,94 +4549,98 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra)
/* fluid sim particle import handling, actual loading of particles from file */
#ifndef DISABLE_ELBEEM
if( (1) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && // broken, disabled for now!
(ob->fluidsimSettings)) {
ParticleSettings *part = psys->part;
ParticleData *pa=0;
char *suffix = "fluidsurface_particles_####";
char *suffix2 = ".gz";
char filename[256];
char debugStrBuffer[256];
int curFrame = G.scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading
int p, j, numFileParts, totpart;
int readMask, activeParts = 0, fileParts = 0;
gzFile gzf;
{
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
if(ob==G.obedit) // off...
return;
if( fluidmd && fluidmd->fss) {
FluidsimSettings *fss= fluidmd->fss;
ParticleSettings *part = psys->part;
ParticleData *pa=0;
char *suffix = "fluidsurface_particles_####";
char *suffix2 = ".gz";
char filename[256];
char debugStrBuffer[256];
int curFrame = G.scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading
int p, j, numFileParts, totpart;
int readMask, activeParts = 0, fileParts = 0;
gzFile gzf;
// ok, start loading
strcpy(filename, ob->fluidsimSettings->surfdataPath);
strcat(filename, suffix);
BLI_convertstringcode(filename, G.sce);
BLI_convertstringframe(filename, curFrame); // fixed #frame-no
strcat(filename, suffix2);
if(ob==G.obedit) // off...
return;
gzf = gzopen(filename, "rb");
if (!gzf) {
snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename);
//elbeemDebugOut(debugStrBuffer);
return;
}
// ok, start loading
strcpy(filename, fss->surfdataPath);
strcat(filename, suffix);
BLI_convertstringcode(filename, G.sce);
BLI_convertstringframe(filename, curFrame); // fixed #frame-no
strcat(filename, suffix2);
gzread(gzf, &totpart, sizeof(totpart));
numFileParts = totpart;
totpart = (G.rendering)?totpart:(part->disp*totpart)/100;
part->totpart= totpart;
part->sta=part->end = 1.0f;
part->lifetime = G.scene->r.efra + 1;
/* initialize particles */
realloc_particles(ob, psys, part->totpart);
initialize_all_particles(ob, psys, 0);
// set up reading mask
readMask = ob->fluidsimSettings->typeFlags;
for(p=0, pa=psys->particles; p<totpart; p++, pa++) {
int ptype=0;
gzread(gzf, &ptype, sizeof( ptype ));
if(ptype&readMask) {
activeParts++;
gzread(gzf, &(pa->size), sizeof( float ));
pa->size /= 10.0f;
for(j=0; j<3; j++) {
float wrf;
gzread(gzf, &wrf, sizeof( wrf ));
pa->state.co[j] = wrf;
//fprintf(stderr,"Rj%d ",j);
}
for(j=0; j<3; j++) {
float wrf;
gzread(gzf, &wrf, sizeof( wrf ));
pa->state.vel[j] = wrf;
}
pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0f;
pa->state.rot[0] = 1.0;
pa->state.rot[1] = pa->state.rot[2] = pa->state.rot[3] = 0.0;
pa->alive = PARS_ALIVE;
//if(a<25) 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 );
} else {
// skip...
for(j=0; j<2*3+1; j++) {
float wrf; gzread(gzf, &wrf, sizeof( wrf ));
}
gzf = gzopen(filename, "rb");
if (!gzf) {
snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename);
//elbeemDebugOut(debugStrBuffer);
return;
}
fileParts++;
}
gzclose( gzf );
totpart = psys->totpart = activeParts;
snprintf(debugStrBuffer,256,"readFsPartData::done - particles:%d, active:%d, file:%d, mask:%d \n", psys->totpart,activeParts,fileParts,readMask);
elbeemDebugOut(debugStrBuffer);
} // fluid sim particles done
gzread(gzf, &totpart, sizeof(totpart));
numFileParts = totpart;
totpart = (G.rendering)?totpart:(part->disp*totpart)/100;
part->totpart= totpart;
part->sta=part->end = 1.0f;
part->lifetime = G.scene->r.efra + 1;
/* initialize particles */
realloc_particles(ob, psys, part->totpart);
initialize_all_particles(ob, psys, 0);
// set up reading mask
readMask = fss->typeFlags;
for(p=0, pa=psys->particles; p<totpart; p++, pa++) {
int ptype=0;
gzread(gzf, &ptype, sizeof( ptype ));
if(ptype&readMask) {
activeParts++;
gzread(gzf, &(pa->size), sizeof( float ));
pa->size /= 10.0f;
for(j=0; j<3; j++) {
float wrf;
gzread(gzf, &wrf, sizeof( wrf ));
pa->state.co[j] = wrf;
//fprintf(stderr,"Rj%d ",j);
}
for(j=0; j<3; j++) {
float wrf;
gzread(gzf, &wrf, sizeof( wrf ));
pa->state.vel[j] = wrf;
}
pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0f;
pa->state.rot[0] = 1.0;
pa->state.rot[1] = pa->state.rot[2] = pa->state.rot[3] = 0.0;
pa->alive = PARS_ALIVE;
//if(a<25) 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 );
} else {
// skip...
for(j=0; j<2*3+1; j++) {
float wrf; gzread(gzf, &wrf, sizeof( wrf ));
}
}
fileParts++;
}
gzclose( gzf );
totpart = psys->totpart = activeParts;
snprintf(debugStrBuffer,256,"readFsPartData::done - particles:%d, active:%d, file:%d, mask:%d \n", psys->totpart,activeParts,fileParts,readMask);
elbeemDebugOut(debugStrBuffer);
} // fluid sim particles done
}
#endif // DISABLE_ELBEEM
}

@ -123,6 +123,17 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
pid->cache= clmd->point_cache;
}
void BKE_ptcache_id_from_fluidsim(PTCacheID *pid, Object *ob, FluidsimModifierData *fluidmd)
{
memset(pid, 0, sizeof(PTCacheID));
pid->ob= ob;
pid->data= fluidmd;
pid->type= PTCACHE_TYPE_FLUIDSIM;
pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)fluidmd);
pid->cache= fluidmd->point_cache;
}
void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob)
{
PTCacheID *pid;
@ -155,6 +166,11 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob)
BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md);
BLI_addtail(lb, pid);
}
else if(md->type == eModifierType_Fluidsim) {
pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
BKE_ptcache_id_from_fluidsim(pid, ob, (FluidsimModifierData*)md);
BLI_addtail(lb, pid);
}
}
}

@ -3017,10 +3017,6 @@ 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);
}
/* texture field */
if(ob->pd)
if(ob->pd->tex)
@ -3093,6 +3089,12 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
}
}
else if (md->type==eModifierType_Fluidsim) {
FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
fluidmd->fss= newdataadr(fd, fluidmd->fss);
fluidmd->fss->ipo = newlibadr_us(fd, lb, fluidmd->fss->ipo);
}
else if (md->type==eModifierType_Collision) {
CollisionModifierData *collmd = (CollisionModifierData*) md;
@ -3279,13 +3281,6 @@ static void direct_link_object(FileData *fd, Object *ob)
direct_link_pointcache(fd, sb->pointcache);
}
ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
if(ob->fluidsimSettings) {
// reinit mesh pointers
ob->fluidsimSettings->orgMesh = NULL; //ob->data;
ob->fluidsimSettings->meshSurface = NULL;
ob->fluidsimSettings->meshBB = NULL;
ob->fluidsimSettings->meshSurfNormals = NULL;
}
link_list(fd, &ob->particlesystem);
direct_link_particlesystems(fd,&ob->particlesystem);
@ -7493,8 +7488,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
if(ob->fluidsimSettings && ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)
part->type = PART_FLUID;
{
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
if(fluidmd && fluidmd->fss && fluidmd->fss->type == OB_FLUIDSIM_PARTICLE)
part->type = PART_FLUID;
}
free_effects(&ob->effect);
@ -7664,6 +7663,26 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
// convert fluids to modifier
if(main->versionfile <= 246 && main->subversionfile < 1)
{
Object *ob;
for(ob = main->object.first; ob; ob= ob->id.next) {
if(ob->fluidsimSettings)
{
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifier_new(eModifierType_Fluidsim);
BLI_addhead(&ob->modifiers, (ModifierData *)fluidmd);
MEM_freeN(fluidmd->fss);
fluidmd->fss = MEM_dupallocN(ob->fluidsimSettings);
fluidmd->fss->ipo = newlibadr_us(fd, ob->id.lib, ob->fluidsimSettings->ipo);
MEM_freeN(ob->fluidsimSettings);
}
}
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */

@ -846,6 +846,11 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
writestruct(wd, DATA, "PointCache", 1, clmd->point_cache);
}
else if(md->type==eModifierType_Fluidsim) {
FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
writestruct(wd, DATA, "FluidsimSettings", 1, fluidmd->fss);
}
else if (md->type==eModifierType_Collision) {
/*
@ -911,7 +916,6 @@ static void write_objects(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, "PartDeflect", 1, ob->pd);
writestruct(wd, DATA, "SoftBody", 1, ob->soft);
if(ob->soft) writestruct(wd, DATA, "PointCache", 1, ob->soft->pointcache);
writestruct(wd, DATA, "FluidsimSettings", 1, ob->fluidsimSettings); // NT
write_particlesystems(wd, &ob->particlesystem);
write_modifiers(wd, &ob->modifiers);

@ -35,6 +35,7 @@ typedef enum ModifierType {
eModifierType_Cloth,
eModifierType_Collision,
eModifierType_Bevel,
eModifierType_Fluidsim,
NUM_MODIFIER_TYPES
} ModifierType;
@ -490,4 +491,11 @@ typedef struct ExplodeModifierData {
float protect;
} ExplodeModifierData;
typedef struct FluidsimModifierData {
ModifierData modifier;
struct FluidsimSettings *fss; /* definition is is DNA_object_fluidsim.h */
struct PointCache *point_cache; /* definition is in DNA_object_force.h */
} FluidsimModifierData;
#endif

@ -128,7 +128,7 @@ typedef struct FluidsimSettings {
float velocityforceStrength;
float velocityforceRadius;
int pad;
int lastgoodframe;
} FluidsimSettings;

@ -674,94 +674,6 @@ static void calc_vertexnormals(Render *re, ObjectRen *obr, int do_tangent, int d
MEM_freeN(vtangents);
}
// 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, ObjectRen *obr, int do_nmap_tangent)
{
int a;
/* dont clear vertex normals here */
// OFF for(a=0; a<obr->totvert; a++) { VertRen *ver= RE_findOrAddVert(obr, 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=0; a<obr->totvlak; a++) {
VlakRen *vlr= RE_findOrAddVlak(obr, a);
if(vlr->flag & ME_SMOOTH) {
VertRen *v1= vlr->v1;
VertRen *v2= vlr->v2;
VertRen *v3= vlr->v3;
VertRen *v4= vlr->v4;
float n1[3], n2[3], n3[3], n4[3];
float fac1, fac2, fac3, fac4=0.0f;
if(re->flag & R_GLOB_NOPUNOFLIP)
vlr->flag |= R_NOPUNOFLIP;
VecSubf(n1, v2->co, v1->co);
Normalize(n1);
VecSubf(n2, v3->co, v2->co);
Normalize(n2);
if(v4==NULL) {
VecSubf(n3, v1->co, v3->co);
Normalize(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, v4->co, v3->co);
Normalize(n3);
VecSubf(n4, v1->co, v4->co);
Normalize(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( check_vnormal(vlr->n, v4->n) ) fac4= -fac4;
}
}
//if(do_nmap_tangent)
// calc_tangent_vector(obr, vlr, fac1, fac2, fac3, fac4);
}
if(do_nmap_tangent) {
/* tangents still need to be calculated for flat faces too */
/* weighting removed, they are not vertexnormals */
//calc_tangent_vector(obr, vlr);
}
}
/* do solid faces */
for(a=0; a<obr->totvlak; a++) {
VlakRen *vlr= RE_findOrAddVlak(obr, 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);
}
}
}
/* normalize vertex normals */
for(a=0; a<obr->totvert; a++) {
VertRen *ver= RE_findOrAddVert(obr, a);
Normalize(ver->n);
if(do_nmap_tangent) {
float *tav= RE_vertren_get_tangent(obr, ver, 0);
if(tav) Normalize(tav);
}
}
}
/* ------------------------------------------------------------------------- */
/* Autosmoothing: */
/* ------------------------------------------------------------------------- */
@ -3171,12 +3083,6 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
}
}
if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&&
(ob->fluidsimSettings->meshSurface) ) {
useFluidmeshNormals = 1;
}
mvert= dm->getVertArray(dm);
totvert= dm->getNumVerts(dm);
@ -3199,17 +3105,6 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
if(do_autosmooth==0) /* autosmooth on original unrotated data to prevent differences between frames */
MTC_Mat4MulVecfl(mat, ver->co);
if(useFluidmeshNormals) {
/* normals are inverted in render */
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;
@ -3389,12 +3284,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
autosmooth(re, obr, mat, me->smoothresh);
}
if(useFluidmeshNormals) {
// do not recalculate, only init render data
calc_fluidsimnormals(re, obr, need_tangent||need_nmap_tangent);
} else {
calc_vertexnormals(re, obr, need_tangent, need_nmap_tangent);
}
calc_vertexnormals(re, obr, need_tangent, need_nmap_tangent);
if(need_stress)
calc_edge_stress(re, obr, me);
@ -5273,7 +5163,7 @@ static int load_fluidsimspeedvectors(Render *re, ObjectInstanceRen *obi, float *
//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].co[j];
/* (bad) HACK insert average velocity if none is there (see previous comment */
/* (bad) HACK insert average velocity if none is there (see previous comment) */
if((fsvec[0] == 0.0) && (fsvec[1] == 0.0) && (fsvec[2] == 0.0))
{
fsvec[0] = avgvel[0];
@ -5417,6 +5307,7 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
oldobi= table->first;
for(obi= re->instancetable.first; obi && oldobi; obi= obi->next) {
int ok= 1;
FluidsimModifierData *fluidmd;
if(!(obi->obr->flag & R_NEED_VECTORS))
continue;
@ -5440,7 +5331,8 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
}
// NT check for fluidsim special treatment
if((obi->ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (obi->ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)) {
fluidmd = (FluidsimModifierData *)modifiers_findByType(obi->ob, eModifierType_Fluidsim);
if(fluidmd && fluidmd->fss && (fluidmd->fss->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, obi, oldobi->vectors, step);

@ -985,7 +985,7 @@ static uiBlock *modifiers_add_menu(void *ob_v)
/* Only allow adding through appropriate other interfaces */
if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
if(ELEM(i, eModifierType_Cloth, eModifierType_Collision)) continue;
if(ELEM3(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim)) continue;
if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
(ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
@ -1742,7 +1742,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
// deletion over the deflection panel
// fluid particle modifier can't be deleted here
if(md->type!=eModifierType_Collision && !modifier_is_fluid_particles(md))
if(md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Collision && !modifier_is_fluid_particles(md))
{
but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier");
uiButSetFunc(but, modifiers_del, ob, md);
@ -1826,6 +1826,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
height = 94;
} else if (md->type==eModifierType_Explode) {
height = 94;
} else if (md->type==eModifierType_Fluidsim) {
height = 31;
}
/* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, "");
@ -1843,7 +1845,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiButSetFunc(but, modifiers_applyModifier, ob, md);
}
if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
if (md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
uiButSetFunc(but, modifiers_copyModifier, ob, md);
}

@ -45,6 +45,7 @@
#include "BKE_action.h"
#include "BKE_cloth.h"
#include "BKE_fluidsim.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_library.h"
@ -2240,6 +2241,7 @@ void fluidsimFilesel(char *selection)
char prefix[FILE_MAXFILE];
char *srch, *srchSub, *srchExt, *lastFound;
int isElbeemSurf = 0;
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
// make prefix
strcpy(srcDir, selection);
@ -2274,10 +2276,10 @@ void fluidsimFilesel(char *selection)
}
}
if(ob->fluidsimSettings) {
strcpy(ob->fluidsimSettings->surfdataPath, srcDir);
if(fluidmd && fluidmd->fss) {
strcpy(fluidmd->fss->surfdataPath, srcDir);
//not necessary? strcat(ob->fluidsimSettings->surfdataPath, "/");
strcat(ob->fluidsimSettings->surfdataPath, prefix);
strcat(fluidmd->fss->surfdataPath, prefix);
// redraw view & buttons...
allqueue(REDRAWBUTSOBJECT, 0);
@ -2381,13 +2383,14 @@ void do_object_panels(unsigned short event)
ParticleSystem *psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
ModifierData *md;
ParticleSystemModifierData *psmd;
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
part->type = PART_FLUID;
psys->part = part;
psys->pointcache = BKE_ptcache_add();
psys->flag |= PSYS_ENABLED;
ob->fluidsimSettings->type = OB_FLUIDSIM_PARTICLE;
fluidmd->fss->type = OB_FLUIDSIM_PARTICLE;
BLI_addtail(&ob->particlesystem,psys);
@ -2401,7 +2404,9 @@ void do_object_panels(unsigned short event)
allqueue(REDRAWBUTSOBJECT, 0);
break;
case B_FLUIDSIM_CHANGETYPE:
if(ob && ob->particlesystem.first && ob->fluidsimSettings->type!=OB_FLUIDSIM_PARTICLE){
{
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
if(ob && ob->particlesystem.first && fluidmd->fss->type!=OB_FLUIDSIM_PARTICLE){
ParticleSystem *psys;
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
if(psys->part->type==PART_FLUID) {
@ -2426,20 +2431,16 @@ void do_object_panels(unsigned short event)
}
allqueue(REDRAWBUTSOBJECT, 0);
break;
}
case B_FLUIDSIM_SELDIR:
{
ScrArea *sa = closest_bigger_area();
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
/* choose dir for surface files */
areawinset(sa->win);
activate_fileselect(FILE_SPECIAL, "Select Directory", ob->fluidsimSettings->surfdataPath, fluidsimFilesel);
activate_fileselect(FILE_SPECIAL, "Select Directory", fluidmd->fss->surfdataPath, fluidsimFilesel);
}
break;
case B_FLUIDSIM_FORCEREDRAW:
/* force redraw */
allqueue(REDRAWBUTSOBJECT, 0);
allqueue(REDRAWVIEW3D, 0);
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
break;
case B_GROUP_RELINK:
group_relink_nla_objects(ob);
allqueue(REDRAWVIEW3D, 0);
@ -4914,6 +4915,53 @@ static void object_panel_particle_system(Object *ob)
}
/* NT - Panel for fluidsim settings */
static int _can_fluidsim_at_all(Object *ob)
{
// list of Yes
if ((ob->type==OB_MESH)) return 1;
// else deny
return 0;
}
/* Panel for fluidsim */
static void object_fluidsim__enabletoggle(void *ob_v, void *arg2)
{
Object *ob = ob_v;
ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
if (!md) {
md = modifier_new(eModifierType_Fluidsim);
BLI_addhead(&ob->modifiers, md);
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA|OB_RECALC_OB);
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWVIEW3D, 0);
}
else {
Object *ob = ob_v;
ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
if (!md)
return;
BLI_remlink(&ob->modifiers, md);
modifier_free(md);
BIF_undo_push("Del modifier");
//ob->softflag |= OB_SB_RESET;
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWIMAGE, 0);
allqueue(REDRAWOOPS, 0);
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA|OB_RECALC_OB);
object_handle_update(ob);
countall();
}
}
static void object_panel_fluidsim(Object *ob)
{
#ifndef DISABLE_ELBEEM
@ -4922,336 +4970,382 @@ static void object_panel_fluidsim(Object *ob)
const int lineHeight = 20;
const int separateHeight = 3;
const int objHeight = 20;
char *msg = NULL;
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
int libdata = 0, val = 0;
uiBut *but=NULL;
block= uiNewBlock(&curarea->uiblocks, "object_fluidsim", UI_EMBOSS, UI_HELV, curarea->win);
if(uiNewPanel(curarea, block, "Fluid", "Physics", 1060, 0, 318, 204)==0) return;
uiSetButLock(object_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
libdata= object_is_libdata(ob);
uiSetButLock(libdata, ERROR_LIBDATA_MESSAGE);
if(ob->type==OB_MESH) {
if(((Mesh *)ob->data)->totvert == 0) {
msg = "Mesh has no vertices.";
goto errMessage;
}
uiDefButBitS(block, TOG, OB_FLUIDSIM_ENABLE, REDRAWBUTSOBJECT, "Enable", 0,yline, 75,objHeight,
&ob->fluidsimFlag, 0, 0, 0, 0, "Sets object to participate in fluid simulation");
val = (fluidmd ? 1:0);
if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
FluidsimSettings *fss= ob->fluidsimSettings;
if(fss==NULL) {
fss = ob->fluidsimSettings = fluidsimSettingsNew(ob);
}
if(!_can_fluidsim_at_all(ob))
{
uiDefBut(block, LABEL, 0, "Fluidsim can be activated on mesh only.", 10,200,300,20, NULL, 0.0, 0, 0, 0, "");
}
else
{
but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Fluidsim", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to participate in fluid simulation");
uiButSetFunc(but, object_fluidsim__enabletoggle, ob, NULL);
/*
// no pointcache used in fluidsim *YET*
md = (ModifierData*)clmd;
if(md) {
uiBlockBeginAlign(block);
uiDefButS(block, ROW, B_FLUIDSIM_CHANGETYPE ,"Domain", 90, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_DOMAIN, 20.0, 1.0, "Bounding box of this object represents the computational domain of the fluid simulation.");
uiDefButS(block, ROW, B_FLUIDSIM_CHANGETYPE ,"Fluid", 160, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_FLUID, 20.0, 2.0, "Object represents a volume of fluid in the simulation.");
uiDefButS(block, ROW, B_FLUIDSIM_CHANGETYPE ,"Obstacle", 230, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_OBSTACLE,20.0, 3.0, "Object is a fixed obstacle.");
yline -= lineHeight;
uiDefButS(block, ROW, B_FLUIDSIM_CHANGETYPE ,"Inflow", 90, yline, 52,objHeight, &fss->type, 15.0, OB_FLUIDSIM_INFLOW, 20.0, 4.0, "Object adds fluid to the simulation.");
uiDefButS(block, ROW, B_FLUIDSIM_CHANGETYPE ,"Outflow", 142, yline, 52,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", 194, yline, 52,objHeight, &fss->type, 15.0, OB_FLUIDSIM_PARTICLE,20.0, 3.0, "Object is made a particle system to display particles generated by a fluidsim domain object.");
uiDefButS(block, ROW, B_FLUIDSIM_CHANGETYPE ,"Control", 246, yline, 54,objHeight, &fss->type, 15.0, OB_FLUIDSIM_CONTROL,20.0, 3.0, "Object is made a fluid control mesh, which influences the fluid.");
uiDefIconButBitI(block, TOG, eModifierMode_Render, B_BAKE_CACHE_CHANGE, ICON_SCENE, 145, 200, 20, 20,&md->mode, 0, 0, 1, 0, "Enable fluidsim during rendering");
but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_BAKE_CACHE_CHANGE, VICON_VIEW3D, 165, 200, 20, 20,&md->mode, 0, 0, 1, 0, "Enable fluidsim during interactive display");
uiBlockEndAlign(block);
}
*/
}
if(fluidmd)
{
FluidsimSettings *fss = fluidmd->fss;
if(!fss)
return;
/* GENERAL STUFF */
/*
if(!libdata) {
uiClearButLock();
if(cache->flag & PTCACHE_BAKE_EDIT_ACTIVE)
uiSetButLock(1, "Please leave editmode.");
else if(cache->flag & PTCACHE_BAKED)
uiSetButLock(1, "Simulation frames are baked");
}
*/
uiBlockBeginAlign ( block );
uiDefButS ( block, ROW, B_FLUIDSIM_CHANGETYPE ,"Domain", 90, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_DOMAIN, 20.0, 1.0, "Bounding box of this object represents the computational domain of the fluid simulation." );
uiDefButS ( block, ROW, B_FLUIDSIM_CHANGETYPE ,"Fluid", 160, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_FLUID, 20.0, 2.0, "Object represents a volume of fluid in the simulation." );
uiDefButS ( block, ROW, B_FLUIDSIM_CHANGETYPE ,"Obstacle", 230, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_OBSTACLE,20.0, 3.0, "Object is a fixed obstacle." );
yline -= lineHeight;
uiDefButS ( block, ROW, B_FLUIDSIM_CHANGETYPE ,"Inflow", 90, yline, 52,objHeight, &fss->type, 15.0, OB_FLUIDSIM_INFLOW, 20.0, 4.0, "Object adds fluid to the simulation." );
uiDefButS ( block, ROW, B_FLUIDSIM_CHANGETYPE ,"Outflow", 142, yline, 52,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", 194, yline, 52,objHeight, &fss->type, 15.0, OB_FLUIDSIM_PARTICLE,20.0, 3.0, "Object is made a particle system to display particles generated by a fluidsim domain object." );
uiDefButS ( block, ROW, B_FLUIDSIM_CHANGETYPE ,"Control", 246, yline, 54,objHeight, &fss->type, 15.0, OB_FLUIDSIM_CONTROL,20.0, 3.0, "Object is made a fluid control mesh, which influences the fluid." );
uiBlockEndAlign ( block );
yline -= lineHeight;
yline -= 2*separateHeight;
/* display specific settings for each type */
if ( fss->type == OB_FLUIDSIM_DOMAIN )
{
const int maxRes = 512;
char memString[32];
int i;
Mesh *mesh = ob->data;
// use mesh bounding box and object scaling
// TODO fix redraw issue
fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
elbeemEstimateMemreq ( fss->resolutionxyz,
fss->bbSize[0],fss->bbSize[1],fss->bbSize[2], fss->maxRefine, memString );
uiBlockBeginAlign ( block );
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." );
uiBlockEndAlign ( block );
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;
/* display specific settings for each type */
if(fss->type == OB_FLUIDSIM_DOMAIN) {
const int maxRes = 512;
char memString[32];
if ( fss->show_advancedoptions == 0 )
{
uiDefBut ( block, LABEL, 0, "Req. BAKE Memory:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefBut ( block, LABEL, 0, memString, 200,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "" );
yline -= lineHeight;
// use mesh bounding box and object scaling
// TODO fix redraw issue
elbeemEstimateMemreq(fss->resolutionxyz,
ob->fluidsimSettings->bbSize[0],ob->fluidsimSettings->bbSize[1],ob->fluidsimSettings->bbSize[2], fss->maxRefine, memString);
uiBlockBeginAlign ( block );
uiDefButS ( block, NUM, REDRAWBUTSOBJECT, "Resolution:", 0, yline,150,objHeight, &fss->resolutionxyz, 1, maxRes, 10, 0, "Domain resolution in X, Y and Z direction" );
uiDefButS ( block, NUM, B_DIFF, "Preview-Res.:", 150, yline,150,objHeight, &fss->previewresxyz, 1, 100, 10, 0, "Resolution of the preview meshes to generate, also in X, Y and Z direction" );
uiBlockEndAlign ( block );
yline -= lineHeight;
yline -= 1*separateHeight;
uiBlockBeginAlign(block);
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.");
uiBlockEndAlign(block);
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.");
uiBlockBeginAlign ( block );
uiDefButF ( block, NUM, B_DIFF, "Start time:", 0, yline,150,objHeight, &fss->animStart, 0.0, 100.0, 10, 0, "Simulation time of the first blender frame." );
uiDefButF ( block, NUM, B_DIFF, "End time:", 150, yline,150,objHeight, &fss->animEnd , 0.0, 100.0, 10, 0, "Simulation time of the last blender frame." );
uiBlockEndAlign ( block );
yline -= lineHeight;
yline -= 2*separateHeight;
if(fss->show_advancedoptions == 0) {
uiDefBut(block, LABEL, 0, "Req. BAKE Memory:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefBut(block, LABEL, 0, memString, 200,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "");
yline -= lineHeight;
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, "" );
uiBlockBeginAlign ( block );
uiDefButS ( block, MENU, B_BAKE_CACHE_CHANGE, "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." );
uiDefButS ( block, MENU, B_DIFF, "RenderDisplayMode%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." );
uiBlockEndAlign ( block );
yline -= lineHeight;
yline -= 1*separateHeight;
uiBlockBeginAlign(block);
uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Resolution:", 0, yline,150,objHeight, &fss->resolutionxyz, 1, maxRes, 10, 0, "Domain resolution in X, Y and Z direction");
uiDefButS(block, NUM, B_DIFF, "Preview-Res.:", 150, yline,150,objHeight, &fss->previewresxyz, 1, 100, 10, 0, "Resolution of the preview meshes to generate, also in X, Y and Z direction");
uiBlockEndAlign(block);
yline -= lineHeight;
yline -= 1*separateHeight;
uiBlockBeginAlign(block);
uiDefButF(block, NUM, B_DIFF, "Start time:", 0, yline,150,objHeight, &fss->animStart, 0.0, 100.0, 10, 0, "Simulation time of the first blender frame.");
uiDefButF(block, NUM, B_DIFF, "End time:", 150, yline,150,objHeight, &fss->animEnd , 0.0, 100.0, 10, 0, "Simulation time of the last blender frame.");
uiBlockEndAlign(block);
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, "");
uiBlockBeginAlign(block);
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.");
uiDefButS(block, MENU, B_DIFF, "RenderDisplayMode%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.");
uiBlockEndAlign(block);
yline -= lineHeight;
yline -= 1*separateHeight;
uiBlockBeginAlign(block);
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");
uiBlockEndAlign(block);
// FIXME what is the 79.0 above?
} else if(fss->show_advancedoptions == 1) {
// advanced options
uiDefBut(block, LABEL, 0, "Gravity:", 0, yline, 90,objHeight, NULL, 0.0, 0, 0, 0, "");
uiBlockBeginAlign(block);
uiDefButF(block, NUM, B_DIFF, "X:", 90, yline, 70,objHeight, &fss->gravx, -1000.1, 1000.1, 10, 0, "Gravity in X direction");
uiDefButF(block, NUM, B_DIFF, "Y:", 160, yline, 70,objHeight, &fss->gravy, -1000.1, 1000.1, 10, 0, "Gravity in Y direction");
uiDefButF(block, NUM, B_DIFF, "Z:", 230, yline, 70,objHeight, &fss->gravz, -1000.1, 1000.1, 10, 0, "Gravity in Z direction");
uiBlockEndAlign(block);
yline -= lineHeight;
yline -= 1*separateHeight;
/* viscosity */
if (fss->viscosityMode==1) /*manual*/
uiBlockBeginAlign(block);
uiDefButS(block, MENU, REDRAWVIEW3D, "Viscosity%t|Manual %x1|Water %x2|Oil %x3|Honey %x4",
0,yline, 90,objHeight, &fss->viscosityMode, 0, 0, 0, 0, "Set viscosity of the fluid to a preset value, or use manual input.");
if(fss->viscosityMode==1) {
uiDefButF(block, NUM, B_DIFF, "Value:", 90, yline, 105,objHeight, &fss->viscosityValue, 0.0, 10.0, 10, 0, "Viscosity setting: value that is multiplied by 10 to the power of (exponent*-1).");
uiDefButS(block, NUM, B_DIFF, "Neg-Exp.:", 195, yline, 105,objHeight, &fss->viscosityExponent, 0, 10, 10, 0, "Negative exponent for the viscosity value (to simplify entering small values e.g. 5*10^-6.");
uiBlockEndAlign(block);
} else {
// display preset values
uiDefBut(block, LABEL, 0, fluidsimViscosityPresetString[fss->viscosityMode], 90,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
}
yline -= lineHeight;
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, 10.0, 10, 0, "Size of the simulation domain in meters.");
yline -= lineHeight;
yline -= 2*separateHeight;
uiDefBut(block, LABEL, 0, "Gridlevels:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButI(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->maxRefine, -1, 4, 10, 0, "Number of coarsened Grids to use (set to -1 for automatic selection).");
yline -= lineHeight;
uiDefBut(block, LABEL, 0, "Compressibility:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
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); // domain
uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Noslip", 0, 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.");
uiDefButS(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!");
uiDefButS(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,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButF(block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->partSlipValue, 0.0, 1.0, 10,0, "Amount of mixing between no- and free-slip, 0=stickier, 1=same as free slip.");
yline -= lineHeight;
} else {
//uiDefBut(block, LABEL, 0, "-", 200,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "");
}
// copied from obstacle...
uiDefBut(block, LABEL, 0, "Tracer Particles:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButI(block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->generateTracers, 0.0, 10000.0, 10,0, "Number of tracer particles to generate.");
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, "Surface Subdiv:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButI(block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->surfaceSubdivs, 0.0, 5.0, 10,0, "Number of isosurface subdivisions. This is necessary for the inclusion of particles into the surface generation. Warning - can lead to longer computation times!");
yline -= lineHeight;
uiDefBut(block, LABEL, 0, "Surface Smoothing:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButF(block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->surfaceSmoothing, 0.0, 5.0, 10,0, "Amount of surface smoothing (0=off, 1=normal, >1=stronger smoothing).");
yline -= lineHeight;
// use new variable...
uiDefBut(block, LABEL, 0, "Generate&Use SpeedVecs:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButBitC(block, TOG, 1, REDRAWBUTSOBJECT, "Disable", 200, yline,100,objHeight, &fss->domainNovecgen, 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;
} // domain 3
uiBlockBeginAlign ( block );
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_BAKE_CACHE_CHANGE,"", 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" );
uiBlockEndAlign ( block );
// FIXME what is the 79.0 above?
}
else if(
(fss->type == OB_FLUIDSIM_FLUID)
|| (fss->type == OB_FLUIDSIM_INFLOW)
) {
uiBlockBeginAlign(block); // fluid
uiDefButC(block, ROW, REDRAWBUTSOBJECT ,"Init Volume", 0, yline,100,objHeight, &fss->volumeInitType, 15.0, 1, 20.0, 1.0, "Type of volume init: use only inner region of mesh.");
uiDefButC(block, ROW, REDRAWBUTSOBJECT ,"Init Shell", 100, yline,100,objHeight, &fss->volumeInitType, 15.0, 2, 20.0, 2.0, "Type of volume init: use only the hollow shell defined by the faces of the mesh.");
uiDefButC(block, ROW, REDRAWBUTSOBJECT ,"Init Both", 200, yline,100,objHeight, &fss->volumeInitType, 15.0, 3, 20.0, 3.0, "Type of volume init: use both the inner volume and the outer shell.");
uiBlockEndAlign(block);
else if ( fss->show_advancedoptions == 1 )
{
// advanced options
uiDefBut ( block, LABEL, 0, "Gravity:", 0, yline, 90,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiBlockBeginAlign ( block );
uiDefButF ( block, NUM, B_DIFF, "X:", 90, yline, 70,objHeight, &fss->gravx, -1000.1, 1000.1, 10, 0, "Gravity in X direction" );
uiDefButF ( block, NUM, B_DIFF, "Y:", 160, yline, 70,objHeight, &fss->gravy, -1000.1, 1000.1, 10, 0, "Gravity in Y direction" );
uiDefButF ( block, NUM, B_DIFF, "Z:", 230, yline, 70,objHeight, &fss->gravz, -1000.1, 1000.1, 10, 0, "Gravity in Z direction" );
uiBlockEndAlign ( block );
yline -= lineHeight;
yline -= 1*separateHeight;
yline -= lineHeight + 5; // fluid + inflow
if(fss->type == OB_FLUIDSIM_FLUID) uiDefBut(block, LABEL, 0, "Initial velocity:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
if(fss->type == OB_FLUIDSIM_INFLOW) uiDefBut(block, LABEL, 0, "Inflow velocity:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
yline -= lineHeight;
uiBlockBeginAlign(block);
uiDefButF(block, NUM, B_DIFF, "X:", 0, yline, 100,objHeight, &fss->iniVelx, -1000.1, 1000.1, 10, 0, "Fluid velocity in X direction");
uiDefButF(block, NUM, B_DIFF, "Y:", 100, yline, 100,objHeight, &fss->iniVely, -1000.1, 1000.1, 10, 0, "Fluid velocity in Y direction");
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) { // inflow
uiDefBut(block, LABEL, 0, "Local Inflow Coords", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButBitS(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 {
/* viscosity */
if ( fss->viscosityMode==1 ) /*manual*/
uiBlockBeginAlign ( block );
uiDefButS ( block, MENU, REDRAWVIEW3D, "Viscosity%t|Manual %x1|Water %x2|Oil %x3|Honey %x4",
0,yline, 90,objHeight, &fss->viscosityMode, 0, 0, 0, 0, "Set viscosity of the fluid to a preset value, or use manual input." );
if ( fss->viscosityMode==1 )
{
uiDefButF ( block, NUM, B_DIFF, "Value:", 90, yline, 105,objHeight, &fss->viscosityValue, 0.0, 10.0, 10, 0, "Viscosity setting: value that is multiplied by 10 to the power of (exponent*-1)." );
uiDefButS ( block, NUM, B_DIFF, "Neg-Exp.:", 195, yline, 105,objHeight, &fss->viscosityExponent, 0, 10, 10, 0, "Negative exponent for the viscosity value (to simplify entering small values e.g. 5*10^-6." );
uiBlockEndAlign ( block );
}
else
{
// display preset values
uiDefBut ( block, LABEL, 0, fluidsimViscosityPresetString[fss->viscosityMode], 90,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
}
yline -= lineHeight;
yline -= 1*separateHeight;
// domainNovecgen "misused" here
uiDefBut(block, LABEL, 0, "Animated Mesh:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButBitC(block, TOG, 1, REDRAWBUTSOBJECT, "Export", 200, yline,100,objHeight, &fss->domainNovecgen, 0, 0, 0, 0, "Export this mesh as an animated one. Slower, only use if really necessary (e.g. armatures or parented objects), animated pos/rot/scale IPOs do not require it.");
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, 10.0, 10, 0, "Size of the simulation domain in meters." );
yline -= lineHeight;
yline -= 2*separateHeight;
uiDefBut ( block, LABEL, 0, "Gridlevels:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefButI ( block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->maxRefine, -1, 4, 10, 0, "Number of coarsened Grids to use (set to -1 for automatic selection)." );
yline -= lineHeight;
} // fluid inflow
else if( (fss->type == OB_FLUIDSIM_OUTFLOW) ) {
yline -= lineHeight + 5;
uiBlockBeginAlign(block); // outflow
uiDefButC(block, ROW, REDRAWBUTSOBJECT ,"Init Volume", 0, yline,100,objHeight, &fss->volumeInitType, 15.0, 1, 20.0, 1.0, "Type of volume init: use only inner region of mesh.");
uiDefButC(block, ROW, REDRAWBUTSOBJECT ,"Init Shell", 100, yline,100,objHeight, &fss->volumeInitType, 15.0, 2, 20.0, 2.0, "Type of volume init: use only the hollow shell defined by the faces of the mesh.");
uiDefButC(block, ROW, REDRAWBUTSOBJECT ,"Init Both", 200, yline,100,objHeight, &fss->volumeInitType, 15.0, 3, 20.0, 3.0, "Type of volume init: use both the inner volume and the outer shell.");
uiBlockEndAlign(block);
uiDefBut ( block, LABEL, 0, "Compressibility:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "" );
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;
// domainNovecgen "misused" here
uiDefBut(block, LABEL, 0, "Animated Mesh:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButBitC(block, TOG, 1, REDRAWBUTSOBJECT, "Export", 200, yline,100,objHeight, &fss->domainNovecgen, 0, 0, 0, 0, "Export this mesh as an animated one. Slower, only use if really necessary (e.g. armatures or parented objects), animated pos/rot/scale IPOs do not require it.");
yline -= lineHeight;
//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; // obstacle
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); // obstacle
uiDefButC(block, ROW, REDRAWBUTSOBJECT ,"Init Volume", 0, yline,100,objHeight, &fss->volumeInitType, 15.0, 1, 20.0, 1.0, "Type of volume init: use only inner region of mesh.");
uiDefButC(block, ROW, REDRAWBUTSOBJECT ,"Init Shell", 100, yline,100,objHeight, &fss->volumeInitType, 15.0, 2, 20.0, 2.0, "Type of volume init: use only the hollow shell defined by the faces of the mesh.");
uiDefButC(block, ROW, REDRAWBUTSOBJECT ,"Init Both", 200, yline,100,objHeight, &fss->volumeInitType, 15.0, 3, 20.0, 3.0, "Type of volume init: use both the inner volume and the outer shell.");
uiBlockEndAlign(block);
uiBlockBeginAlign ( block ); // domain
uiDefButS ( block, ROW, REDRAWBUTSOBJECT ,"Noslip", 0, 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." );
uiDefButS ( 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!" );
uiDefButS ( 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;
uiBlockBeginAlign(block); // obstacle
uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Noslip", 0, 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.");
uiDefButS(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!");
uiDefButS(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);
if ( fss->typeFlags&OB_FSBND_PARTSLIP )
{
uiDefBut ( block, LABEL, 0, "PartSlipValue:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefButF ( block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->partSlipValue, 0.0, 1.0, 10,0, "Amount of mixing between no- and free-slip, 0=stickier, 1=same as free slip." );
yline -= lineHeight;
}
else
{
//uiDefBut(block, LABEL, 0, "-", 200,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "");
}
// copied from obstacle...
uiDefBut ( block, LABEL, 0, "Tracer Particles:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefButI ( block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->generateTracers, 0.0, 10000.0, 10,0, "Number of tracer particles to generate." );
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, "Surface Subdiv:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefButI ( block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->surfaceSubdivs, 0.0, 5.0, 10,0, "Number of isosurface subdivisions. This is necessary for the inclusion of particles into the surface generation. Warning - can lead to longer computation times!" );
yline -= lineHeight;
// domainNovecgen "misused" here
uiDefBut(block, LABEL, 0, "Animated Mesh:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButBitC(block, TOG, 1, REDRAWBUTSOBJECT, "Export", 200, yline,100,objHeight, &fss->domainNovecgen, 0, 0, 0, 0, "Export this mesh as an animated one. Slower, only use if really necessary (e.g. armatures or parented objects), animated loc/rot/scale IPOs do not require it.");
uiDefBut ( block, LABEL, 0, "Surface Smoothing:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefButF ( block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->surfaceSmoothing, 0.0, 5.0, 10,0, "Amount of surface smoothing (0=off, 1=normal, >1=stronger smoothing)." );
yline -= lineHeight;
uiDefBut(block, LABEL, 0, "PartSlip Amount:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
if(fss->typeFlags&OB_FSBND_PARTSLIP) {
uiDefButF(block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->partSlipValue, 0.0, 1.0, 10,0, "Amount of mixing between no- and free-slip, 0=stickier, 1=same as free slip.");
} else { uiDefBut(block, LABEL, 0, "-", 200,yline,100,objHeight, NULL, 0.0, 0, 0, 0, ""); }
// use new variable...
uiDefBut ( block, LABEL, 0, "Generate&Use SpeedVecs:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefButBitC ( block, TOG, 1, REDRAWBUTSOBJECT, "Disable", 200, yline,100,objHeight, &fss->domainNovecgen, 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;
} // domain 3
}
else if (
( fss->type == OB_FLUIDSIM_FLUID )
|| ( fss->type == OB_FLUIDSIM_INFLOW )
)
{
uiBlockBeginAlign ( block ); // fluid
uiDefButC ( block, ROW, REDRAWBUTSOBJECT ,"Init Volume", 0, yline,100,objHeight, &fss->volumeInitType, 15.0, 1, 20.0, 1.0, "Type of volume init: use only inner region of mesh." );
uiDefButC ( block, ROW, REDRAWBUTSOBJECT ,"Init Shell", 100, yline,100,objHeight, &fss->volumeInitType, 15.0, 2, 20.0, 2.0, "Type of volume init: use only the hollow shell defined by the faces of the mesh." );
uiDefButC ( block, ROW, REDRAWBUTSOBJECT ,"Init Both", 200, yline,100,objHeight, &fss->volumeInitType, 15.0, 3, 20.0, 3.0, "Type of volume init: use both the inner volume and the outer shell." );
uiBlockEndAlign ( block );
yline -= lineHeight;
// generateParticles "misused" here
uiDefBut(block, LABEL, 0, "Impact Factor:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButF(block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->surfaceSmoothing, -2.0, 10.0, 10,0, "This is an unphysical value for moving objects - it controls the impact an obstacle has on the fluid, =0 behaves a bit like outflow (deleting fluid), =1 is default, while >1 results in high forces. Can be used to tweak total mass.");
yline -= lineHeight + 5; // fluid + inflow
if ( fss->type == OB_FLUIDSIM_FLUID ) uiDefBut ( block, LABEL, 0, "Initial velocity:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
if ( fss->type == OB_FLUIDSIM_INFLOW ) uiDefBut ( block, LABEL, 0, "Inflow velocity:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
yline -= lineHeight;
uiBlockBeginAlign ( block );
uiDefButF ( block, NUM, B_DIFF, "X:", 0, yline, 100,objHeight, &fss->iniVelx, -1000.1, 1000.1, 10, 0, "Fluid velocity in X direction" );
uiDefButF ( block, NUM, B_DIFF, "Y:", 100, yline, 100,objHeight, &fss->iniVely, -1000.1, 1000.1, 10, 0, "Fluid velocity in Y direction" );
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 ) // inflow
{
uiDefBut ( block, LABEL, 0, "Local Inflow Coords", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefButBitS ( 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;
yline -= lineHeight; // obstacle
}
else if(fss->type == OB_FLUIDSIM_PARTICLE) {
else
{
}
//fss->type == 0; // off, broken...
if(1) {
// domainNovecgen "misused" here
uiDefBut ( block, LABEL, 0, "Animated Mesh:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefButBitC ( block, TOG, 1, REDRAWBUTSOBJECT, "Export", 200, yline,100,objHeight, &fss->domainNovecgen, 0, 0, 0, 0, "Export this mesh as an animated one. Slower, only use if really necessary (e.g. armatures or parented objects), animated pos/rot/scale IPOs do not require it." );
yline -= lineHeight;
} // fluid inflow
else if ( ( fss->type == OB_FLUIDSIM_OUTFLOW ) )
{
yline -= lineHeight + 5;
uiBlockBeginAlign ( block ); // outflow
uiDefButC ( block, ROW, REDRAWBUTSOBJECT ,"Init Volume", 0, yline,100,objHeight, &fss->volumeInitType, 15.0, 1, 20.0, 1.0, "Type of volume init: use only inner region of mesh." );
uiDefButC ( block, ROW, REDRAWBUTSOBJECT ,"Init Shell", 100, yline,100,objHeight, &fss->volumeInitType, 15.0, 2, 20.0, 2.0, "Type of volume init: use only the hollow shell defined by the faces of the mesh." );
uiDefButC ( block, ROW, REDRAWBUTSOBJECT ,"Init Both", 200, yline,100,objHeight, &fss->volumeInitType, 15.0, 3, 20.0, 3.0, "Type of volume init: use both the inner volume and the outer shell." );
uiBlockEndAlign ( block );
yline -= lineHeight;
// domainNovecgen "misused" here
uiDefBut ( block, LABEL, 0, "Animated Mesh:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefButBitC ( block, TOG, 1, REDRAWBUTSOBJECT, "Export", 200, yline,100,objHeight, &fss->domainNovecgen, 0, 0, 0, 0, "Export this mesh as an animated one. Slower, only use if really necessary (e.g. armatures or parented objects), animated pos/rot/scale IPOs do not require it." );
yline -= lineHeight;
//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; // obstacle
uiBlockBeginAlign ( block ); // obstacle
uiDefButC ( block, ROW, REDRAWBUTSOBJECT ,"Init Volume", 0, yline,100,objHeight, &fss->volumeInitType, 15.0, 1, 20.0, 1.0, "Type of volume init: use only inner region of mesh." );
uiDefButC ( block, ROW, REDRAWBUTSOBJECT ,"Init Shell", 100, yline,100,objHeight, &fss->volumeInitType, 15.0, 2, 20.0, 2.0, "Type of volume init: use only the hollow shell defined by the faces of the mesh." );
uiDefButC ( block, ROW, REDRAWBUTSOBJECT ,"Init Both", 200, yline,100,objHeight, &fss->volumeInitType, 15.0, 3, 20.0, 3.0, "Type of volume init: use both the inner volume and the outer shell." );
uiBlockEndAlign ( block );
yline -= lineHeight;
uiBlockBeginAlign ( block ); // obstacle
uiDefButS ( block, ROW, REDRAWBUTSOBJECT ,"Noslip", 0, 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." );
uiDefButS ( 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!" );
uiDefButS ( 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;
// domainNovecgen "misused" here
uiDefBut ( block, LABEL, 0, "Animated Mesh:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefButBitC ( block, TOG, 1, REDRAWBUTSOBJECT, "Export", 200, yline,100,objHeight, &fss->domainNovecgen, 0, 0, 0, 0, "Export this mesh as an animated one. Slower, only use if really necessary (e.g. armatures or parented objects), animated loc/rot/scale IPOs do not require it." );
yline -= lineHeight;
uiDefBut ( block, LABEL, 0, "PartSlip Amount:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
if ( fss->typeFlags&OB_FSBND_PARTSLIP )
{
uiDefButF ( block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->partSlipValue, 0.0, 1.0, 10,0, "Amount of mixing between no- and free-slip, 0=stickier, 1=same as free slip." );
}
else { uiDefBut ( block, LABEL, 0, "-", 200,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "" ); }
yline -= lineHeight;
// generateParticles "misused" here
uiDefBut ( block, LABEL, 0, "Impact Factor:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "" );
uiDefButF ( block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->surfaceSmoothing, -2.0, 10.0, 10,0, "This is an unphysical value for moving objects - it controls the impact an obstacle has on the fluid, =0 behaves a bit like outflow (deleting fluid), =1 is default, while >1 results in high forces. Can be used to tweak total mass." );
yline -= lineHeight;
yline -= lineHeight; // obstacle
}
else if ( fss->type == OB_FLUIDSIM_PARTICLE )
{
//fss->type == 0; // off, broken...
if ( 1 )
{
// limited selection, old fixed: fss->typeFlags = (1<<5)|(1<<1);
# define PARTBUT_WIDTH (300/3)
uiDefButBitS(block, TOG, (1<<2) , REDRAWBUTSOBJECT, "Drops", 0*PARTBUT_WIDTH, yline, PARTBUT_WIDTH,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Show drop particles.");
uiDefButBitS(block, TOG, (1<<4) , REDRAWBUTSOBJECT, "Floats", 1*PARTBUT_WIDTH, yline, PARTBUT_WIDTH,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Show floating foam particles.");
uiDefButBitS(block, TOG, (1<<5) , REDRAWBUTSOBJECT, "Tracer", 2*PARTBUT_WIDTH, yline, PARTBUT_WIDTH,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Show tracer particles.");
# define PARTBUT_WIDTH (300/3)
uiDefButBitS ( block, TOG, ( 1<<2 ) , REDRAWBUTSOBJECT, "Drops", 0*PARTBUT_WIDTH, yline, PARTBUT_WIDTH,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Show drop particles." );
uiDefButBitS ( block, TOG, ( 1<<4 ) , REDRAWBUTSOBJECT, "Floats", 1*PARTBUT_WIDTH, yline, PARTBUT_WIDTH,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Show floating foam particles." );
uiDefButBitS ( block, TOG, ( 1<<5 ) , REDRAWBUTSOBJECT, "Tracer", 2*PARTBUT_WIDTH, yline, PARTBUT_WIDTH,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Show tracer particles." );
yline -= lineHeight;
# undef PARTBUT_WIDTH
# undef PARTBUT_WIDTH
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.");
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).");
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
uiBlockBeginAlign(block);
uiDefIconBut(block, BUT, B_FLUIDSIM_SELDIR, ICON_FILESEL, 0, yline, 20, objHeight, 0, 0, 0, 0, 0, "Select fluid simulation bake directory/prefix to load particles from, same as for domain object.");
uiDefBut(block, TEX, B_FLUIDSIM_FORCEREDRAW,"", 20, yline, 280, objHeight, fss->surfdataPath, 0.0,79.0, 0, 0, "Enter fluid simulation bake directory/prefix to load particles from, same as for domain object.");
uiBlockEndAlign(block);
uiBlockBeginAlign ( block );
uiDefIconBut ( block, BUT, B_FLUIDSIM_SELDIR, ICON_FILESEL, 0, yline, 20, objHeight, 0, 0, 0, 0, 0, "Select fluid simulation bake directory/prefix to load particles from, same as for domain object." );
uiDefBut ( block, TEX, B_BAKE_CACHE_CHANGE,"", 20, yline, 280, objHeight, fss->surfdataPath, 0.0,79.0, 0, 0, "Enter fluid simulation bake directory/prefix to load particles from, same as for domain object." );
uiBlockEndAlign ( block );
yline -= lineHeight;
} // disabled for now...
}
else if(fss->type == OB_FLUIDSIM_CONTROL) {
uiDefButF(block, NUM, B_DIFF, "Time Sta:", 0, yline,150,20, &fss->cpsTimeStart, 0.0, 100.0, 10,0, "Specifies time when the control particles are activated.");
uiDefButF(block, NUM, B_DIFF, "Time End:", 150, yline,150,20, &fss->cpsTimeEnd, 0.0, 100.0, 10,0, "Specifies time when the control particles are deactivated.");
yline -= lineHeight;
uiDefBut(block, LABEL, 0, "Attraction force:", 0,yline,300,20, NULL, 0.0, 0, 0, 0, "");
yline -= lineHeight;
uiDefButF(block, NUM, B_DIFF, "Strength:", 0, yline,150,20, &fss->attractforceStrength, 0.0, 2.0, 10,0, "");
uiDefButF(block, NUM, B_DIFF, "Radius:", 150, yline,150,20, &fss->attractforceRadius, 0.0, 2.0, 10,0, "");
yline -= lineHeight;
uiDefBut(block, LABEL, 0, "Velocity force:", 0,yline,300,20, NULL, 0.0, 0, 0, 0, "");
yline -= lineHeight;
uiDefButF(block, NUM, B_DIFF, "Strength:", 0, yline,150,20, &fss->velocityforceStrength, 0.0, 2.0, 10,0, "");
uiDefButF(block, NUM, B_DIFF, "Radius:", 150, yline,150,20, &fss->velocityforceRadius, 0.0, 2.0, 10,0, "");
yline -= lineHeight;
uiDefButF(block, NUM, B_DIFF, "Quality:", 0, yline,150,20, &fss->cpsQuality, 1.0, 100.0, 10,0, "Specifies the quality which is used for object sampling.");
}
else {
yline -= lineHeight + 5;
/* not yet set */
uiDefBut(block, LABEL, 0, "Select object type for simulation", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
yline -= lineHeight;
}
return;
} else {
msg = "Object not enabled for fluid simulation.";
}
} else {
msg = "Only mesh objects can do fluid simulation.";
else if ( fss->type == OB_FLUIDSIM_CONTROL )
{
uiDefButF ( block, NUM, B_DIFF, "Time Sta:", 0, yline,150,20, &fss->cpsTimeStart, 0.0, 100.0, 10,0, "Specifies time when the control particles are activated." );
uiDefButF ( block, NUM, B_DIFF, "Time End:", 150, yline,150,20, &fss->cpsTimeEnd, 0.0, 100.0, 10,0, "Specifies time when the control particles are deactivated." );
yline -= lineHeight;
uiDefBut ( block, LABEL, 0, "Attraction force:", 0,yline,300,20, NULL, 0.0, 0, 0, 0, "" );
yline -= lineHeight;
uiDefButF ( block, NUM, B_DIFF, "Strength:", 0, yline,150,20, &fss->attractforceStrength, -10.0, 10.0, 10,0, "" );
uiDefButF ( block, NUM, B_DIFF, "Radius:", 150, yline,150,20, &fss->attractforceRadius, 0.0, 10.0, 10,0, "" );
yline -= lineHeight;
uiDefBut ( block, LABEL, 0, "Velocity force:", 0,yline,300,20, NULL, 0.0, 0, 0, 0, "" );
yline -= lineHeight;
uiDefButF ( block, NUM, B_DIFF, "Strength:", 0, yline,150,20, &fss->velocityforceStrength, 0.0, 10.0, 10,0, "" );
uiDefButF ( block, NUM, B_DIFF, "Radius:", 150, yline,150,20, &fss->velocityforceRadius, 0.0, 10.0, 10,0, "" );
yline -= lineHeight;
uiDefButF ( block, NUM, B_DIFF, "Quality:", 0, yline,150,20, &fss->cpsQuality, 5.0, 100.0, 10,0, "Specifies the quality which is used for object sampling (higher = better but slower)." );
}
else
{
yline -= lineHeight + 5;
/* not yet set */
uiDefBut ( block, LABEL, 0, "Select object type for simulation", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "" );
yline -= lineHeight;
}
return;
}
errMessage:
yline -= lineHeight + 5;
uiDefBut(block, LABEL, 0, msg, 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
yline -= lineHeight;
#endif // DISABLE_ELBEEM
}

@ -60,6 +60,7 @@
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_object_fluidsim.h"
#include "DNA_particle_types.h"
@ -83,6 +84,7 @@
#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
@ -494,32 +496,31 @@ static void make_fluidsim_editipo(SpaceIpo *si, Object *ob) // NT
EditIpo *ei;
int a;
char *name;
FluidsimSettings *fss= ob->fluidsimSettings;
int numipos = FLUIDSIM_TOTIPO;
int ipo_start_index = 0;
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
FluidsimSettings *fss= fluidmd->fss;
// we don't need all fluid ipos for all types! - dg
/*
if(fss->type == OB_FLUIDSIM_CONTROL)
{
numipos = 4; // there are 4 fluid control ipos
ipo_start_index = 9;
}
else */
if(fss->type == OB_FLUIDSIM_DOMAIN)
else if(fss->type == OB_FLUIDSIM_DOMAIN)
{
numipos = 5; // there are 5 ipos for fluid domains
}/*
}
else
{
numipos = 4; // there are 4 for the rest
ipo_start_index = 5;
}*/
}
ei= si->editipo= MEM_callocN(numipos*sizeof(EditIpo), "fluidsim_editipo");
si->totipo = numipos;
for(a=ipo_start_index; a<numipos; a++) {
for(a=ipo_start_index; a<ipo_start_index+numipos; 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);
@ -1200,10 +1201,14 @@ static void get_ipo_context(short blocktype, ID **from, Ipo **ipo, char *actname
// }
}
else if(blocktype==ID_FLUIDSIM) {
if(ob && ( ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
FluidsimSettings *fss= ob->fluidsimSettings;
*from= (ID *)ob;
if(fss) *ipo= fss->ipo;
if(ob)
{
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
if(fluidmd) {
FluidsimSettings *fss= fluidmd->fss;
*from= (ID *)ob;
if(fss) *ipo= fss->ipo;
}
}
}
else if(blocktype==ID_PA) {
@ -1900,8 +1905,9 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char
}
else if(blocktype== ID_FLUIDSIM) {
Object *ob= (Object *)from;
if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
FluidsimSettings *fss= ob->fluidsimSettings;
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
if(fluidmd) {
FluidsimSettings *fss= fluidmd->fss;
if(fss->ipo==NULL) {
fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM);
//fprintf(stderr,"FSIPO NEW!\n");

@ -1601,15 +1601,6 @@ void separate_mesh(void)
return;
}
/* blender crashes in derivedmesh drawing if I don't do this... but why?
Anyhoo, this function is horrible anyway (ton)
the fluidsimFlag also has to be reset btw. (n_t) */
if(G.obedit->fluidsimSettings) {
fluidsimSettingsFree(G.obedit->fluidsimSettings);
G.obedit->fluidsimSettings = NULL;
G.obedit->fluidsimFlag = 0;
}
if(em->selected.first) BLI_freelistN(&(em->selected)); /* clear the selection order */
EM_selectmode_set(); // enforce full consistant selection flags
@ -1783,13 +1774,6 @@ void separate_mesh_loose(void)
return;
}
/* same problem as in separate_mesh above (n_t) */
if(G.obedit->fluidsimSettings) {
fluidsimSettingsFree(G.obedit->fluidsimSettings);
G.obedit->fluidsimSettings = NULL;
G.obedit->fluidsimFlag = 0;
}
TEST_EDITMESH
if(multires_test()) return;
waitcursor(1);

@ -61,7 +61,9 @@
#include "BKE_customdata.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_fluidsim.h"
#include "BKE_global.h"
#include "BKE_modifier.h"
#include "BKE_main.h"
#include "BKE_key.h"
#include "BKE_scene.h"
@ -102,9 +104,6 @@
#undef main
#endif
// from DerivedMesh.c
void initElbeemMesh(struct Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords);
/* from header info.c */
extern int start_progress_bar(void);
extern void end_progress_bar(void);
@ -128,160 +127,12 @@ char* fluidsimViscosityPresetString[6] = {
"INVALID" /* end */
};
typedef struct {
DerivedMesh dm;
// similar to MeshDerivedMesh
struct Object *ob; // pointer to parent object
float *extverts, *nors; // face normals, colors?
Mesh *fsmesh; // mesh struct to display (either surface, or original one)
char meshFree; // free the mesh afterwards? (boolean)
} fluidsimDerivedMesh;
/* enable/disable overall compilation */
#ifndef DISABLE_ELBEEM
/* ********************** fluid sim settings struct functions ********************** */
/* allocates and initializes general main data */
FluidsimSettings *fluidsimSettingsNew(struct Object *srcob)
{
//char blendDir[FILE_MAXDIR], blendFile[FILE_MAXFILE];
FluidsimSettings *fss;
/* this call uses derivedMesh methods... */
if(srcob->type!=OB_MESH) return NULL;
fss= MEM_callocN( sizeof(FluidsimSettings), "fluidsimsettings memory");
fss->type = 0;
fss->show_advancedoptions = 0;
fss->resolutionxyz = 50;
fss->previewresxyz = 25;
fss->realsize = 0.03;
fss->guiDisplayMode = 2; // preview
fss->renderDisplayMode = 3; // render
fss->viscosityMode = 2; // default to water
fss->viscosityValue = 1.0;
fss->viscosityExponent = 6;
fss->gravx = 0.0;
fss->gravy = 0.0;
fss->gravz = -9.81;
fss->animStart = 0.0;
fss->animEnd = 0.30;
fss->gstar = 0.005; // used as normgstar
fss->maxRefine = -1;
// maxRefine is set according to resolutionxyz during bake
// fluid/inflow settings
fss->iniVelx =
fss->iniVely =
fss->iniVelz = 0.0;
/* elubie: changed this to default to the same dir as the render output
to prevent saving to C:\ on Windows */
BLI_strncpy(fss->surfdataPath, btempdir, FILE_MAX);
fss->orgMesh = (Mesh *)srcob->data;
fss->meshSurface = NULL;
fss->meshBB = NULL;
fss->meshSurfNormals = NULL;
// first init of bounding box
fss->bbStart[0] = 0.0;
fss->bbStart[1] = 0.0;
fss->bbStart[2] = 0.0;
fss->bbSize[0] = 1.0;
fss->bbSize[1] = 1.0;
fss->bbSize[2] = 1.0;
fluidsimGetAxisAlignedBB(srcob->data, srcob->obmat, fss->bbStart, fss->bbSize, &fss->meshBB);
// todo - reuse default init from elbeem!
fss->typeFlags = 0;
fss->domainNovecgen = 0;
fss->volumeInitType = 1; // volume
fss->partSlipValue = 0.0;
fss->generateTracers = 0;
fss->generateParticles = 0.0;
fss->surfaceSmoothing = 1.0;
fss->surfaceSubdivs = 1.0;
fss->particleInfSize = 0.0;
fss->particleInfAlpha = 0.0;
// init fluid control settings
fss->attractforceStrength = 0.2;
fss->attractforceRadius = 0.75;
fss->velocityforceStrength = 0.2;
fss->velocityforceRadius = 0.75;
fss->cpsTimeStart = fss->animStart;
fss->cpsTimeEnd = fss->animEnd;
fss->cpsQuality = 10.0; // 1.0 / 10.0 => means 0.1 width
return fss;
}
/* duplicate struct, analogous to free */
static Mesh *fluidsimCopyMesh(Mesh *me)
{
Mesh *dup = MEM_dupallocN(me);
CustomData_copy(&me->vdata, &dup->vdata, CD_MASK_MESH, CD_DUPLICATE, me->totvert);
CustomData_copy(&me->edata, &dup->edata, CD_MASK_MESH, CD_DUPLICATE, me->totedge);
CustomData_copy(&me->fdata, &dup->fdata, CD_MASK_MESH, CD_DUPLICATE, me->totface);
return dup;
}
FluidsimSettings* fluidsimSettingsCopy(FluidsimSettings *fss)
{
FluidsimSettings *dupfss;
if(!fss) return NULL;
dupfss = MEM_dupallocN(fss);
if(fss->meshSurface)
dupfss->meshSurface = fluidsimCopyMesh(fss->meshSurface);
if(fss->meshBB)
dupfss->meshBB = fluidsimCopyMesh(fss->meshBB);
if(fss->meshSurfNormals) dupfss->meshSurfNormals = MEM_dupallocN(fss->meshSurfNormals);
return dupfss;
}
/* free struct */
static void fluidsimFreeMesh(Mesh *me)
{
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
MEM_freeN(me);
}
void fluidsimSettingsFree(FluidsimSettings *fss)
{
if(fss->meshSurface) {
fluidsimFreeMesh(fss->meshSurface);
fss->meshSurface = NULL;
}
if(fss->meshBB) {
fluidsimFreeMesh(fss->meshBB);
fss->meshBB = NULL;
}
if(fss->meshSurfNormals){ MEM_freeN(fss->meshSurfNormals); fss->meshSurfNormals=NULL; }
MEM_freeN(fss);
}
/* helper function */
void fluidsimGetGeometryObjFilename(struct Object *ob, char *dst) { //, char *srcname) {
//snprintf(dst,FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
@ -542,6 +393,8 @@ void fluidsimBake(struct Object *ob)
float *channelAttractforceRadius[256];
float *channelVelocityforceStrength[256];
float *channelVelocityforceRadius[256];
FluidsimModifierData *fluidmd = NULL;
Mesh *mesh = NULL;
if(getenv(strEnvName)) {
int dlevel = atoi(getenv(strEnvName));
@ -566,12 +419,16 @@ void fluidsimBake(struct Object *ob)
/* no object pointer, find in selected ones.. */
if(!ob) {
for(base=G.scene->base.first; base; base= base->next) {
if ( ((base)->flag & SELECT)
// ignore layer setting for now? && ((base)->lay & G.vd->lay)
) {
if((!ob)&&(base->object->fluidsimFlag & OB_FLUIDSIM_ENABLE)&&(base->object->type==OB_MESH)) {
if(base->object->fluidsimSettings->type == OB_FLUIDSIM_DOMAIN) {
if ((base)->flag & SELECT)
{
FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
if(fluidmdtmp && (base->object->type==OB_MESH))
{
if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN)
{
ob = base->object;
break;
}
}
}
@ -581,13 +438,15 @@ void fluidsimBake(struct Object *ob)
}
channelObjCount = 0;
for(base=G.scene->base.first; base; base= base->next) {
for(base=G.scene->base.first; base; base= base->next)
{
FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
obit = base->object;
//{ 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) ) {
if( fluidmdtmp &&
(obit->type==OB_MESH) &&
(fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH
(fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) )
{
channelObjCount++;
}
}
@ -598,23 +457,54 @@ void fluidsimBake(struct Object *ob)
}
/* check if there's another domain... */
for(base=G.scene->base.first; base; base= base->next) {
for(base=G.scene->base.first; base; base= base->next)
{
FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
obit = base->object;
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);
if( fluidmdtmp &&(obit->type==OB_MESH))
{
if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN)
{
if(obit != ob)
{
pupmenu("Fluidsim Bake Error%t|There should be only one domain object! Aborted%x0");
return;
}
}
}
}
// check if theres any fluid
// abort baking if not...
for(base=G.scene->base.first; base; base= base->next)
{
FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
obit = base->object;
if( fluidmdtmp &&
(obit->type==OB_MESH) &&
((fluidmdtmp->fss->type == OB_FLUIDSIM_FLUID) ||
(fluidmdtmp->fss->type == OB_FLUIDSIM_INFLOW) ))
{
haveSomeFluid = 1;
break;
}
}
if(!haveSomeFluid) {
pupmenu("Fluidsim Bake Error%t|No fluid objects in scene... Aborted%x0");
return;
}
/* these both have to be valid, otherwise we wouldnt be here */
/* dont use ob here after...*/
fsDomain = ob;
domainSettings = ob->fluidsimSettings;
fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
domainSettings = fluidmd->fss;
ob = NULL;
mesh = fsDomain->data;
// calculate bounding box
fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize);
/* rough check of settings... */
if(domainSettings->previewresxyz > domainSettings->resolutionxyz) {
snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz , domainSettings->resolutionxyz);
@ -640,23 +530,6 @@ void fluidsimBake(struct Object *ob)
snprintf(debugStrBuffer,256,"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels );
elbeemDebugOut(debugStrBuffer);
// check if theres any fluid
// abort baking if not...
for(base=G.scene->base.first; base; base= base->next) {
obit = base->object;
if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
(obit->type==OB_MESH) && (
(obit->fluidsimSettings->type == OB_FLUIDSIM_FLUID) ||
(obit->fluidsimSettings->type == OB_FLUIDSIM_INFLOW) )
) {
haveSomeFluid = 1;
}
}
if(!haveSomeFluid) {
pupmenu("Fluidsim Bake Error%t|No fluid objects in scene... Aborted%x0");
return;
}
// prepare names...
strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR);
@ -719,8 +592,8 @@ void fluidsimBake(struct Object *ob)
// dump data for start frame
// CHECK more reasonable to number frames according to blender?
// dump data for frame 0
G.scene->r.cfra = startFrame;
scene_update_for_newframe(G.scene, G.scene->lay);
G.scene->r.cfra = startFrame;
scene_update_for_newframe(G.scene, G.scene->lay);
// init common export vars for both file export and run
for(i=0; i<256; i++) {
@ -743,9 +616,8 @@ void fluidsimBake(struct Object *ob)
calcViscosity = fluidsimViscosityPreset[ domainSettings->viscosityMode ];
}
bbStart = fsDomain->fluidsimSettings->bbStart;
bbSize = fsDomain->fluidsimSettings->bbSize;
fluidsimGetAxisAlignedBB(fsDomain->data, fsDomain->obmat, bbStart, bbSize, &domainSettings->meshBB);
bbStart = domainSettings->bbStart;
bbSize = domainSettings->bbSize;
// always init
{ int timeIcu[1] = { FLUIDSIM_TIME };
@ -791,13 +663,15 @@ void fluidsimBake(struct Object *ob)
// init obj movement channels
channelObjCount=0;
for(base=G.scene->base.first; base; base= base->next) {
for(base=G.scene->base.first; base; base= base->next)
{
FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
obit = base->object;
//{ 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) ) {
if( fluidmdtmp &&
(obit->type==OB_MESH) &&
(fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH
(fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) {
// cant use fluidsimInitChannel for obj channels right now, due
// to the special DXXX channels, and the rotation specialities
@ -824,9 +698,9 @@ void fluidsimBake(struct Object *ob)
int activeIcu[1] = { FLUIDSIM_ACTIVE };
float activeDefs[1] = { 1 }; // default to on
inivelDefs[0] = obit->fluidsimSettings->iniVelx;
inivelDefs[1] = obit->fluidsimSettings->iniVely;
inivelDefs[2] = obit->fluidsimSettings->iniVelz;
inivelDefs[0] = fluidmdtmp->fss->iniVelx;
inivelDefs[1] = fluidmdtmp->fss->iniVely;
inivelDefs[2] = fluidmdtmp->fss->iniVelz;
// check & init loc,rot,size
for(j=0; j<3; j++) {
@ -907,19 +781,19 @@ void fluidsimBake(struct Object *ob)
float velFSDefs[1];
float velFRDefs[1];
attrFSDefs[0] = obit->fluidsimSettings->attractforceStrength;
attrFRDefs[0] = obit->fluidsimSettings->attractforceRadius;
velFSDefs[0] = obit->fluidsimSettings->velocityforceStrength;
velFRDefs[0] = obit->fluidsimSettings->velocityforceRadius;
attrFSDefs[0] = fluidmdtmp->fss->attractforceStrength;
attrFRDefs[0] = fluidmdtmp->fss->attractforceRadius;
velFSDefs[0] = fluidmdtmp->fss->velocityforceStrength;
velFRDefs[0] = fluidmdtmp->fss->velocityforceRadius;
fluidsimInitChannel( &channelAttractforceStrength[o], allchannelSize, timeAtFrame, attrFSIcu,attrFSDefs, obit->fluidsimSettings->ipo, CHANNEL_FLOAT );
fluidsimInitChannel( &channelAttractforceRadius[o], allchannelSize, timeAtFrame, attrFRIcu,attrFRDefs, obit->fluidsimSettings->ipo, CHANNEL_FLOAT );
fluidsimInitChannel( &channelVelocityforceStrength[o], allchannelSize, timeAtFrame, velFSIcu,velFSDefs, obit->fluidsimSettings->ipo, CHANNEL_FLOAT );
fluidsimInitChannel( &channelVelocityforceRadius[o], allchannelSize, timeAtFrame, velFRIcu,velFRDefs, obit->fluidsimSettings->ipo, CHANNEL_FLOAT );
fluidsimInitChannel( &channelAttractforceStrength[o], allchannelSize, timeAtFrame, attrFSIcu,attrFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
fluidsimInitChannel( &channelAttractforceRadius[o], allchannelSize, timeAtFrame, attrFRIcu,attrFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
fluidsimInitChannel( &channelVelocityforceStrength[o], allchannelSize, timeAtFrame, velFSIcu,velFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
fluidsimInitChannel( &channelVelocityforceRadius[o], allchannelSize, timeAtFrame, velFRIcu,velFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
}
fluidsimInitChannel( &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, obit->fluidsimSettings->ipo, CHANNEL_VEC );
fluidsimInitChannel( &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, obit->fluidsimSettings->ipo, CHANNEL_FLOAT );
fluidsimInitChannel( &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, fluidmdtmp->fss->ipo, CHANNEL_VEC );
fluidsimInitChannel( &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
channelObjCount++;
@ -959,6 +833,7 @@ void fluidsimBake(struct Object *ob)
// 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;
@ -1019,22 +894,23 @@ void fluidsimBake(struct Object *ob)
// init objects
channelObjCount = 0;
for(base=G.scene->base.first; base; base= base->next) {
FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
obit = base->object;
//{ 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 has to match 3 places! // CHECKMATCH
(obit->type==OB_MESH) &&
(obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) &&
(obit->fluidsimSettings->type != OB_FLUIDSIM_PARTICLE)
) {
if( fluidmdtmp && // if has to match 3 places! // CHECKMATCH
(obit->type==OB_MESH) &&
(fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&
(fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE))
{
float *verts=NULL;
int *tris=NULL;
int numVerts=0, numTris=0;
int o = channelObjCount;
int deform = (obit->fluidsimSettings->domainNovecgen); // misused value
int deform = (fluidmdtmp->fss->domainNovecgen); // misused value
// todo - use blenderInitElbeemMesh
elbeemMesh fsmesh;
elbeemResetMesh( &fsmesh );
fsmesh.type = obit->fluidsimSettings->type;
fsmesh.type = fluidmdtmp->fss->type;
// get name of object for debugging solver
fsmesh.name = obit->id.name;
@ -1057,24 +933,24 @@ void fluidsimBake(struct Object *ob)
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);
fsmesh.localInivelCoords = ((fluidmdtmp->fss->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0);
}
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;
fsmesh.volumeInitType = obit->fluidsimSettings->volumeInitType;
fsmesh.obstacleImpactFactor = obit->fluidsimSettings->surfaceSmoothing; // misused value
if( (fluidmdtmp->fss->typeFlags&OB_FSBND_NOSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
else if((fluidmdtmp->fss->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
else if((fluidmdtmp->fss->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
fsmesh.obstaclePartslip = fluidmdtmp->fss->partSlipValue;
fsmesh.volumeInitType = fluidmdtmp->fss->volumeInitType;
fsmesh.obstacleImpactFactor = fluidmdtmp->fss->surfaceSmoothing; // misused value
if(fsmesh.type == OB_FLUIDSIM_CONTROL)
{
// control fluids will get exported as whole
deform = 1;
fsmesh.cpsTimeStart = obit->fluidsimSettings->cpsTimeStart;
fsmesh.cpsTimeEnd = obit->fluidsimSettings->cpsTimeEnd;
fsmesh.cpsQuality = obit->fluidsimSettings->cpsQuality;
fsmesh.cpsTimeStart = fluidmdtmp->fss->cpsTimeStart;
fsmesh.cpsTimeEnd = fluidmdtmp->fss->cpsTimeEnd;
fsmesh.cpsQuality = fluidmdtmp->fss->cpsQuality;
fsmesh.channelSizeAttractforceRadius =
fsmesh.channelSizeVelocityforceStrength =

@ -49,6 +49,7 @@
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_object_fluidsim.h"
#include "DNA_particle_types.h"
@ -68,6 +69,7 @@
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
@ -162,12 +164,13 @@ void spaceipo_assign_ipo(SpaceIpo *si, Ipo *ipo)
}
}
else if(si->blocktype==ID_FLUIDSIM) { // NT
if( (ob->fluidsimSettings) &&
(ob->fluidsimSettings->ipo) ) {
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
if( fluidmd && fluidmd->fss &&
(fluidmd->fss->ipo) ) {
// decrement users counter
ob->fluidsimSettings->ipo->id.us--;
fluidmd->fss->ipo->id.us--;
}
ob->fluidsimSettings->ipo = ipo;
fluidmd->fss->ipo = ipo;
}
else if(si->blocktype==ID_PA) {
ParticleSystem *psys=psys_get_current(ob);
@ -974,6 +977,8 @@ static char *ipo_modeselect_pup(void)
str += sprintf(str,formatstring, "Texture",ID_TE, ICON_TEXTURE);
if(ob){
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
if ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_LATTICE)
str += sprintf(str,formatstring, "Shape",ID_KE, ICON_EDIT);
if (ob->type==OB_ARMATURE)
@ -981,7 +986,7 @@ 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) {
if(fluidmd) {
str += sprintf(str,formatstring,"Fluidsim",ID_FLUIDSIM, ICON_WORLD);
}