diff options
author | Daniel Genrich <daniel.genrich@gmx.net> | 2008-07-25 22:57:16 +0400 |
---|---|---|
committer | Daniel Genrich <daniel.genrich@gmx.net> | 2008-07-25 22:57:16 +0400 |
commit | d7fecc9e963d8823d3e6a045c96d3a166ac031a6 (patch) | |
tree | 80f91447a2112454b2651d12fbf2bedada2d9076 | |
parent | 9bf0bfcae74f27e5bc2d5b20a70b21c3668542e4 (diff) |
Fluid control: WIP commit before weekend, not working is crashing on the first 3 frames
29 files changed, 1584 insertions, 1477 deletions
diff --git a/config/linux2-config.py b/config/linux2-config.py index 6bde0664fe5..46611b80f3b 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -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 diff --git a/intern/elbeem/extern/elbeem.h b/intern/elbeem/extern/elbeem.h index 2cee22a62a4..e29890aba44 100644 --- a/intern/elbeem/extern/elbeem.h +++ b/intern/elbeem/extern/elbeem.h @@ -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*); diff --git a/intern/elbeem/intern/controlparticles.cpp b/intern/elbeem/intern/controlparticles.cpp index 75b7e9bfd80..90bc99cada7 100644 --- a/intern/elbeem/intern/controlparticles.cpp +++ b/intern/elbeem/intern/controlparticles.cpp @@ -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); diff --git a/intern/elbeem/intern/elbeem.cpp b/intern/elbeem/intern/elbeem.cpp index 0deed5082b0..c9e6bc7989b 100644 --- a/intern/elbeem/intern/elbeem.cpp +++ b/intern/elbeem/intern/elbeem.cpp @@ -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 { diff --git a/intern/elbeem/intern/ntl_ray.cpp b/intern/elbeem/intern/ntl_ray.cpp index d6593b6b335..242b82085be 100644 --- a/intern/elbeem/intern/ntl_ray.cpp +++ b/intern/elbeem/intern/ntl_ray.cpp @@ -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() ); diff --git a/intern/elbeem/intern/ntl_world.cpp b/intern/elbeem/intern/ntl_world.cpp index 21d9d63aac0..c7aa3495c93 100644 --- a/intern/elbeem/intern/ntl_world.cpp +++ b/intern/elbeem/intern/ntl_world.cpp @@ -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; + + } diff --git a/intern/elbeem/intern/solver_control.cpp b/intern/elbeem/intern/solver_control.cpp index ee032f17f8a..6b4c31b8f3e 100644 --- a/intern/elbeem/intern/solver_control.cpp +++ b/intern/elbeem/intern/solver_control.cpp @@ -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); @@ -581,6 +584,12 @@ LbmFsgrSolver::handleCpdata() for(int cpssi=0; cpssi<(int)mpControl->mCons.size(); cpssi++) { 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); diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index f76cdbc64b7..d951c8401e3 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -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 diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h new file mode 100644 index 00000000000..12df42e85c1 --- /dev/null +++ b/source/blender/blenkernel/BKE_fluidsim.h @@ -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] ); + + + diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 5bc467465a8..e4ce502e142 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -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); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 4d3f9143b85..bfd47f14009 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -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 (vertCos && !dofluidsim) + + if(!dm) + return NULL; + + 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 diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 472df3d0f26..4bc3c3a3883 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -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); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 80f450000bb..9dc89a49196 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -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; diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c new file mode 100644 index 00000000000..63be80f90f9 --- /dev/null +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -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 + diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index f13f8ef0298..ded13611683 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -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) @@ -7521,6 +7565,15 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->dependsOnTime = explodeModifier_dependsOnTime; 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 diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 7b36e46d45e..08845fb1a53 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -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; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index f70648965f4..6973ad51e43 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -4540,7 +4540,7 @@ void psys_changed_type(ParticleSystem *psys) } static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) -{ +{ if(psys->particles){ MEM_freeN(psys->particles); psys->particles = 0; @@ -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; - - if(ob==G.obedit) // off... - return; - - // 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); - - gzf = gzopen(filename, "rb"); - if (!gzf) { - snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename); - //elbeemDebugOut(debugStrBuffer); - return; - } - - gzread(gzf, &totpart, sizeof(totpart)); - numFileParts = totpart; - totpart = (G.rendering)?totpart:(part->disp*totpart)/100; + { + FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); - 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 )); + 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; + + if(ob==G.obedit) // off... + 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); + + gzf = gzopen(filename, "rb"); + if (!gzf) { + snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename); + //elbeemDebugOut(debugStrBuffer); + return; + } + + 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++; } - 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 + 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 } diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 43805959e62..c406e57872d 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -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); + } } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 3c629818b2d..c7927f7d4eb 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3016,10 +3016,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) @@ -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); @@ -7663,6 +7662,26 @@ static void do_versions(FileData *fd, Library *lib, Main *main) la->sun_intensity = 1.0; } } + + // 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! */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index ca91f1dc346..b47642b6a6f 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.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); diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index a44d9793062..53b6e12a309 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -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 diff --git a/source/blender/makesdna/DNA_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim.h index a8c4d216f26..30257bb9b17 100644 --- a/source/blender/makesdna/DNA_object_fluidsim.h +++ b/source/blender/makesdna/DNA_object_fluidsim.h @@ -128,7 +128,7 @@ typedef struct FluidsimSettings { float velocityforceStrength; float velocityforceRadius; - int pad; + int lastgoodframe; } FluidsimSettings; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index faa7a68f754..ec50b3ee1bc 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -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); diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 529a795a101..f058db9e835 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -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); } diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 724201234b4..b63933f7abf 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -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"); - - if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) { - FluidsimSettings *fss= ob->fluidsimSettings; + val = (fluidmd ? 1:0); - if(fss==NULL) { - fss = ob->fluidsimSettings = fluidsimSettingsNew(ob); - } - - 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; + 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); - 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."); + /* + // no pointcache used in fluidsim *YET* + md = (ModifierData*)clmd; + if(md) { + uiBlockBeginAlign(block); + 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]; - - // 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, 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."); + + 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; - 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; - - 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 - } - 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); + + 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 -= 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 -= 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; - 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 -= 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_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; - - 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 { + 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_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->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, "" ); } - - // 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 -= 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; - - // 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 -= 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, "No additional settings as of now...", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, ""); + + 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->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); + 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; - - 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; - - // 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, "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, "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, ""); } + 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; - - // 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."); + + 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; - - yline -= lineHeight; // obstacle + + // 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; + + 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 + { + } + + // 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 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."); + 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." ); yline -= lineHeight; -# 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."); + # 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." ); 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."; - } -errMessage: - yline -= lineHeight + 5; - uiDefBut(block, LABEL, 0, msg, 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, ""); - yline -= lineHeight; + 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; + } #endif // DISABLE_ELBEEM } diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index 393aa90f715..6f532e5d3d2 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -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"); diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 188f7476728..487f5f80bfc 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -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 @@ -1782,13 +1773,6 @@ void separate_mesh_loose(void) error("Can't separate a mesh with vertex keys"); 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; diff --git a/source/blender/src/fluidsim.c b/source/blender/src/fluidsim.c index b28e41722f3..429e648fb07 100644 --- a/source/blender/src/fluidsim.c +++ b/source/blender/src/fluidsim.c @@ -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; } } } @@ -579,15 +436,17 @@ void fluidsimBake(struct Object *ob) // no domains found? if(!ob) return; } - + 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); @@ -639,23 +529,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); @@ -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 = diff --git a/source/blender/src/header_ipo.c b/source/blender/src/header_ipo.c index 15caf325ec6..8fa42810816 100644 --- a/source/blender/src/header_ipo.c +++ b/source/blender/src/header_ipo.c @@ -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); } |