diff options
Diffstat (limited to 'source/blender/blenkernel')
23 files changed, 1815 insertions, 1277 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index fe25ada3962..263b17151e7 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -432,7 +432,10 @@ DerivedMesh *mesh_create_derived_for_modifier(struct Object *ob, struct Modifier DerivedMesh *mesh_create_derived_render(struct Object *ob, CustomDataMask dataMask); -/* same as above but wont use render settings */ + +DerivedMesh *mesh_create_derived_index_render(struct Object *ob, CustomDataMask dataMask, int index); + + /* same as above but wont use render settings */ DerivedMesh *mesh_create_derived_view(struct Object *ob, CustomDataMask dataMask); DerivedMesh *mesh_create_derived_no_deform(struct Object *ob, diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 0591937ea4c..14270d3a7c9 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 247 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 7 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 45d8193b16f..25d6d78c4aa 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -39,9 +39,12 @@ struct ListBase; struct BezTriple; struct BevList; -#define KNOTSU(nu) ( (nu)->orderu+ (nu)->pntsu+ (nu->orderu-1)*((nu)->flagu & CU_CYCLIC) ) -#define KNOTSV(nu) ( (nu)->orderv+ (nu)->pntsv+ (nu->orderv-1)*((nu)->flagv & CU_CYCLIC) ) +#define KNOTSU(nu) ( (nu)->orderu+ (nu)->pntsu+ (((nu)->flagu & CU_CYCLIC) ? (nu->orderu-1) : 0) ) +#define KNOTSV(nu) ( (nu)->orderv+ (nu)->pntsv+ (((nu)->flagv & CU_CYCLIC) ? (nu->orderv-1) : 0) ) +/* Non cyclic nurbs have 1 less segment */ +#define SEGMENTSU(nu) ( ((nu)->flagu & CU_CYCLIC) ? (nu)->pntsu : (nu)->pntsu-1 ) +#define SEGMENTSV(nu) ( ((nu)->flagv & CU_CYCLIC) ? (nu)->pntsv : (nu)->pntsv-1 ) void unlink_curve( struct Curve *cu); void free_curve( struct Curve *cu); @@ -62,15 +65,14 @@ void minmaxNurb( struct Nurb *nu, float *min, float *max); void makeknots( struct Nurb *nu, short uv, short type); -void makeNurbfaces( struct Nurb *nu, float *data, int rowstride); -void makeNurbcurve( struct Nurb *nu, float *data, int resolu, int dim); +void makeNurbfaces(struct Nurb *nu, float *coord_array, int rowstride); +void makeNurbcurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, int resolu); void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride); float *make_orco_curve( struct Object *ob); float *make_orco_surf( struct Object *ob); void makebevelcurve( struct Object *ob, struct ListBase *disp); void makeBevelList( struct Object *ob); -float calc_curve_subdiv_radius( struct Curve *cu, struct Nurb *nu, int cursubdiv); void calchandleNurb( struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, int mode); void calchandlesNurb( struct Nurb *nu); diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h new file mode 100644 index 00000000000..33c706da82b --- /dev/null +++ b/source/blender/blenkernel/BKE_fluidsim.h @@ -0,0 +1,55 @@ +/** + * 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(Object *srcob); + +void initElbeemMesh(Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords, int modifierIndex); + + +/* new fluid-modifier interface */ +void fluidsim_init(FluidsimModifierData *fluidmd); +void fluidsim_free(FluidsimModifierData *fluidmd); + +DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams); +DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc); + +// get bounding box of mesh +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_property.h b/source/blender/blenkernel/BKE_property.h index f1587790c4a..6af1deda727 100644 --- a/source/blender/blenkernel/BKE_property.h +++ b/source/blender/blenkernel/BKE_property.h @@ -41,7 +41,8 @@ struct bProperty *copy_property(struct bProperty *prop); void copy_properties(struct ListBase *lbn, struct ListBase *lbo); void init_property(struct bProperty *prop); struct bProperty *new_property(int type); -struct bProperty *get_property(struct Object *ob, char *name); +struct bProperty *get_ob_property(struct Object *ob, char *name); +void set_ob_property(struct Object *ob, struct bProperty *propc); int compare_property(struct bProperty *prop, char *str); void set_property(struct bProperty *prop, char *str); void add_property(struct bProperty *prop, char *str); diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index d647a74c6e2..9662d6fbff8 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -102,6 +102,8 @@ #define AVG2(x, y) ( 0.5 * ((x) + (y)) ) +#define FTOCHAR(val) (val<=0.0f)? 0 : ((val>(1.0f-0.5f/255.0f))? 255 : (char)((255.0f*val)+0.5f)) + #define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);} #define VECCOPY2D(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1);} #define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);} diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index a5eb1f258f1..e090168592c 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" @@ -67,6 +65,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" @@ -93,11 +92,6 @@ #include "GPU_extensions.h" #include "GPU_material.h" -// headers for fluidsim bobj meshes -#include <stdlib.h> -#include "LBM_fluidsim.h" -#include "elbeem.h" - /////////////////////////////////// /////////////////////////////////// @@ -425,35 +419,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; } @@ -2128,7 +2102,7 @@ static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh * static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParams, int useDeform, - int needMapping, CustomDataMask dataMask) + int needMapping, CustomDataMask dataMask, int index) { Mesh *me = ob->data; ModifierData *firstmd, *md; @@ -2137,7 +2111,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); @@ -2153,21 +2126,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; @@ -2176,7 +2134,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], deformedVerts = mesh_getVertexCos(me, &numVerts); /* Apply all leading deforming modifiers */ - for(; md; md = md->next, curr = curr->next) { + for(;md; md = md->next, curr = curr->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); if((md->mode & required_mode) != required_mode) continue; @@ -2190,6 +2148,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], } else { break; } + + /* grab modifiers until index i */ + if((index >= 0) && (modifiers_indexInObject(ob, md) >= index)) + break; } /* Result of all leading deforming modifiers is cached for @@ -2215,18 +2177,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); } @@ -2243,7 +2198,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], if(me->vnode) dm = derivedmesh_from_versemesh(me->vnode, deformedVerts); #endif - for(; md; md = md->next, curr = curr->next) { + for(;md; md = md->next, curr = curr->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); if((md->mode & required_mode) != required_mode) continue; @@ -2349,6 +2304,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], } } } + + /* grab modifiers until index i */ + if((index >= 0) && (modifiers_indexInObject(ob, md) >= index)) + break; } for(md=firstmd; md; md=md->next) @@ -2404,9 +2363,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] @@ -2759,13 +2715,13 @@ static void mesh_build_data(Object *ob, CustomDataMask dataMask) mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1, - needMapping, dataMask); + needMapping, dataMask, -1); CustomData_free_layer_active(&me->fdata, CD_MCOL, me->totface); } else { mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, G.rendering, 1, - needMapping, dataMask); + needMapping, dataMask, -1); } INIT_MINMAX(min, max); @@ -2936,7 +2892,21 @@ DerivedMesh *mesh_create_derived_render(Object *ob, CustomDataMask dataMask) int orig_lvl= 0; vert_copy= multires_render_pin(ob, me, &orig_lvl); - mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0, dataMask); + mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1); + multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask); + + return final; +} + +DerivedMesh *mesh_create_derived_index_render(Object *ob, CustomDataMask dataMask, int index) +{ + DerivedMesh *final; + Mesh *me= get_mesh(ob); + float *vert_copy= NULL; + int orig_lvl= 0; + + vert_copy= multires_render_pin(ob, me, &orig_lvl); + mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0, dataMask, index); multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask); return final; @@ -2946,7 +2916,7 @@ DerivedMesh *mesh_create_derived_view(Object *ob, CustomDataMask dataMask) { DerivedMesh *final; - mesh_calc_modifiers(ob, NULL, NULL, &final, 0, 1, 0, dataMask); + mesh_calc_modifiers(ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1); return final; } @@ -2956,7 +2926,7 @@ DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3], { DerivedMesh *final; - mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0, 0, dataMask); + mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0, 0, dataMask, -1); return final; } @@ -2971,7 +2941,7 @@ DerivedMesh *mesh_create_derived_no_deform_render(Object *ob, int orig_lvl= 0; vert_copy= multires_render_pin(ob, me, &orig_lvl); - mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0, 0, dataMask); + mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1); multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask); return final; @@ -3331,582 +3301,3 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, } } -/* ************************* 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/action.c b/source/blender/blenkernel/intern/action.c index d65a99f23f0..e0afdec5e23 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1048,7 +1048,7 @@ static float nla_time(float cfra, float unit) static float stridechannel_frame(Object *ob, float sizecorr, bActionStrip *strip, Path *path, float pathdist, float *stride_offset) { bAction *act= strip->act; - char *name= strip->stridechannel; + const char *name= strip->stridechannel; bActionChannel *achan= get_action_channel(act, name); int stride_axis= strip->stride_axis; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index ceb0e132ff9..731c2a18c55 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -52,6 +52,7 @@ #include "DNA_vfont_types.h" #include "BKE_anim.h" +#include "BKE_curve.h" #include "BKE_DerivedMesh.h" #include "BKE_displist.h" #include "BKE_effect.h" @@ -118,7 +119,7 @@ void calc_curvepath(Object *ob) path->len= tot+1; /* exception: vector handle paths and polygon paths should be subdivided at least a factor resolu */ - if(path->len<nu->resolu*nu->pntsu) path->len= nu->resolu*nu->pntsu; + if(path->len<nu->resolu*SEGMENTSU(nu)) path->len= nu->resolu*SEGMENTSU(nu); dist= (float *)MEM_mallocN((tot+1)*4, "calcpathdist"); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 6ea470a2263..1c53af97dbb 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -359,7 +359,6 @@ void brush_sample_tex(Brush *brush, float *xy, float *rgba) rgba[0]= rgba[1]= rgba[2]= rgba[3]= 1.0f; } -#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **outbuf) { diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 9d5dcb8109b..c30d86431b1 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -898,10 +898,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/colortools.c b/source/blender/blenkernel/intern/colortools.c index 45b8bb7935c..1bc34aea9a1 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -650,7 +650,6 @@ void curvemapping_evaluate_premulRGBF(CurveMapping *cumap, float *vecout, const vecout[2]= curvemap_evaluateF(cumap->cm+2, fac); } -#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf) { diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 396bdda9c10..457bfe20915 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -247,7 +247,7 @@ void tex_space_curve(Curve *cu) { DispList *dl; BoundBox *bb; - float *data, min[3], max[3], loc[3], size[3]; + float *fp, min[3], max[3], loc[3], size[3]; int tot, doit= 0; if(cu->bb==NULL) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); @@ -262,10 +262,10 @@ void tex_space_curve(Curve *cu) else tot= dl->nr*dl->parts; if(tot) doit= 1; - data= dl->verts; + fp= dl->verts; while(tot--) { - DO_MINMAX(data, min, max); - data+= 3; + DO_MINMAX(fp, min, max); + fp += 3; } dl= dl->next; } @@ -650,8 +650,8 @@ static void basisNurb(float t, short order, short pnts, float *knots, float *bas } -void makeNurbfaces(Nurb *nu, float *data, int rowstride) -/* data has to be 3*4*resolu*resolv in size, and zero-ed */ +void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride) +/* coord_array has to be 3*4*resolu*resolv in size, and zero-ed */ { BPoint *bp; float *basisu, *basis, *basisv, *sum, *fp, *in; @@ -662,7 +662,7 @@ void makeNurbfaces(Nurb *nu, float *data, int rowstride) if(nu->knotsu==NULL || nu->knotsv==NULL) return; if(nu->orderu>nu->pntsu) return; if(nu->orderv>nu->pntsv) return; - if(data==0) return; + if(coord_array==NULL) return; /* allocate and initialize */ len= nu->pntsu*nu->pntsv; @@ -722,7 +722,7 @@ void makeNurbfaces(Nurb *nu, float *data, int rowstride) if(nu->flagu & CU_CYCLIC) cycl= nu->orderu-1; else cycl= 0; - in= data; + in= coord_array; u= ustart; while(resolu--) { @@ -809,24 +809,26 @@ void makeNurbfaces(Nurb *nu, float *data, int rowstride) MEM_freeN(jend); } -void makeNurbcurve(Nurb *nu, float *data, int resolu, int dim) -/* data has to be dim*4*pntsu*resolu in size and zero-ed */ +void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, int resolu) +/* coord_array has to be 3*4*pntsu*resolu in size and zero-ed + * tilt_array and radius_array will be written to if valid */ { BPoint *bp; float u, ustart, uend, ustep, sumdiv; - float *basisu, *sum, *fp, *in; + float *basisu, *sum, *fp; + float *coord_fp= coord_array, *tilt_fp= tilt_array, *radius_fp= radius_array; int i, len, istart, iend, cycl; if(nu->knotsu==NULL) return; if(nu->orderu>nu->pntsu) return; - if(data==0) return; + if(coord_array==0) return; /* allocate and initialize */ len= nu->pntsu; if(len==0) return; sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1"); - - resolu*= nu->pntsu; + + resolu= (resolu*SEGMENTSU(nu))+1; if(resolu==0) { MEM_freeN(sum); return; @@ -836,13 +838,12 @@ void makeNurbcurve(Nurb *nu, float *data, int resolu, int dim) ustart= fp[nu->orderu-1]; if(nu->flagu & CU_CYCLIC) uend= fp[nu->pntsu+nu->orderu-1]; else uend= fp[nu->pntsu]; - ustep= (uend-ustart)/(resolu-1+(nu->flagu & CU_CYCLIC)); + ustep= (uend-ustart)/(resolu-1); basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbcurve3"); if(nu->flagu & CU_CYCLIC) cycl= nu->orderu-1; else cycl= 0; - in= data; u= ustart; while(resolu--) { @@ -877,17 +878,24 @@ void makeNurbcurve(Nurb *nu, float *data, int resolu, int dim) if(*fp!=0.0) { - in[0]+= (*fp) * bp->vec[0]; - in[1]+= (*fp) * bp->vec[1]; - if(dim>=3) { - in[2]+= (*fp) * bp->vec[2]; - if(dim==4) in[3]+= (*fp) * bp->alfa; - } + coord_fp[0]+= (*fp) * bp->vec[0]; + coord_fp[1]+= (*fp) * bp->vec[1]; + coord_fp[2]+= (*fp) * bp->vec[2]; + + if (tilt_fp) + (*tilt_fp) += (*fp) * bp->alfa; + + if (radius_fp) + (*radius_fp) += (*fp) * bp->radius; + } } - in+= dim; - + coord_fp+= 3; + + if (tilt_fp) tilt_fp++; + if (radius_fp) radius_fp++; + u+= ustep; } @@ -932,7 +940,7 @@ float *make_orco_surf(Object *ob) Nurb *nu; int a, b, tot=0; int sizeu, sizev; - float *data, *orco; + float *fp, *coord_array; /* first calculate the size of the datablock */ nu= cu->nurb.first; @@ -955,7 +963,7 @@ float *make_orco_surf(Object *ob) nu= nu->next; } /* makeNurbfaces wants zeros */ - data= orco= MEM_callocN(3*sizeof(float)*tot, "make_orco"); + fp= coord_array= MEM_callocN(3*sizeof(float)*tot, "make_orco"); nu= cu->nurb.first; while(nu) { @@ -969,15 +977,15 @@ float *make_orco_surf(Object *ob) for(b=0; b< sizeu; b++) { for(a=0; a< sizev; a++) { - if(sizev <2) data[0]= 0.0f; - else data[0]= -1.0f + 2.0f*((float)a)/(sizev - 1); + if(sizev <2) fp[0]= 0.0f; + else fp[0]= -1.0f + 2.0f*((float)a)/(sizev - 1); - if(sizeu <2) data[1]= 0.0f; - else data[1]= -1.0f + 2.0f*((float)b)/(sizeu - 1); + if(sizeu <2) fp[1]= 0.0f; + else fp[1]= -1.0f + 2.0f*((float)b)/(sizeu - 1); - data[2]= 0.0; + fp[2]= 0.0; - data+= 3; + fp+= 3; } } } @@ -999,10 +1007,10 @@ float *make_orco_surf(Object *ob) tdata = _tdata + 3 * (use_b * nu->resolv + use_a); - data[0]= (tdata[0]-cu->loc[0])/cu->size[0]; - data[1]= (tdata[1]-cu->loc[1])/cu->size[1]; - data[2]= (tdata[2]-cu->loc[2])/cu->size[2]; - data+= 3; + fp[0]= (tdata[0]-cu->loc[0])/cu->size[0]; + fp[1]= (tdata[1]-cu->loc[1])/cu->size[1]; + fp[2]= (tdata[2]-cu->loc[2])/cu->size[2]; + fp+= 3; } } @@ -1012,7 +1020,7 @@ float *make_orco_surf(Object *ob) nu= nu->next; } - return orco; + return coord_array; } @@ -1024,7 +1032,7 @@ float *make_orco_curve(Object *ob) Curve *cu = ob->data; DispList *dl; int u, v, numVerts; - float *fp, *orco; + float *fp, *coord_array; int remakeDisp = 0; if (!(cu->flag&CU_UV_ORCO) && cu->key && cu->key->refkey) { @@ -1052,7 +1060,7 @@ float *make_orco_curve(Object *ob) } } - fp= orco= MEM_mallocN(3*sizeof(float)*numVerts, "cu_orco"); + fp= coord_array= MEM_mallocN(3*sizeof(float)*numVerts, "cu_orco"); for (dl=cu->disp.first; dl; dl=dl->next) { if (dl->type==DL_INDEX3) { for (u=0; u<dl->nr; u++, fp+=3) { @@ -1102,7 +1110,7 @@ float *make_orco_curve(Object *ob) makeDispListCurveTypes(ob, 0); } - return orco; + return coord_array; } @@ -1429,7 +1437,7 @@ static void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *si } -static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *data_a, int resolu) +static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *tilt_array, float *radius_array, int resolu) { BezTriple *pprev, *next, *last; float fac, dfac, t[4]; @@ -1455,10 +1463,30 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float * dfac= 1.0f/(float)resolu; for(a=0; a<resolu; a++, fac+= dfac) { + if (tilt_array) { + if (nu->tilt_interp==3) { /* May as well support for tilt also 2.47 ease interp */ + tilt_array[a] = prevbezt->alfa + (bezt->alfa - prevbezt->alfa)*(3.0f*fac*fac - 2.0f*fac*fac*fac); + } else { + set_four_ipo(fac, t, nu->tilt_interp); + tilt_array[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa; + } + } - set_four_ipo(fac, t, nu->tilt_interp); - - data_a[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa; + if (radius_array) { + if (nu->radius_interp==3) { + /* Support 2.47 ease interp + * Note! - this only takes the 2 points into account, + * giving much more localized results to changes in radius, sometimes you want that */ + radius_array[a] = prevbezt->radius + (bezt->radius - prevbezt->radius)*(3.0f*fac*fac - 2.0f*fac*fac*fac); + } else { + + /* reuse interpolation from tilt if we can */ + if (tilt_array==NULL || nu->tilt_interp != nu->radius_interp) { + set_four_ipo(fac, t, nu->radius_interp); + } + radius_array[a]= t[0]*pprev->radius + t[1]*prevbezt->radius + t[2]*bezt->radius + t[3]*next->radius; + } + } } } @@ -1476,13 +1504,19 @@ void makeBevelList(Object *ob) BPoint *bp; BevList *bl, *blnew, *blnext; BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0; - float *data, *data_a, *v1, *v2, min, inp, x1, x2, y1, y2, vec[3]; + float min, inp, x1, x2, y1, y2, vec[3]; + float *coord_array, *tilt_array=NULL, *radius_array=NULL, *coord_fp, *tilt_fp=NULL, *radius_fp; + float *v1, *v2; struct bevelsort *sortdata, *sd, *sd1; int a, b, nr, poly, resolu, len=0; - + int do_tilt, do_radius; + /* this function needs an object, because of tflag and upflag */ cu= ob->data; + /* do we need to calculate the radius for each point? */ + /* do_radius = (cu->bevobj || cu->taperobj || (cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ? 0 : 1; */ + /* STEP 1: MAKE POLYS */ BLI_freelistN(&(cu->bev)); @@ -1490,10 +1524,15 @@ void makeBevelList(Object *ob) else nu= cu->nurb.first; while(nu) { + + /* check if we will calculate tilt data */ + do_tilt = ((nu->type & CU_2D) && (cu->flag & CU_3D)==0) ? 0 : 1; + do_radius = do_tilt; /* normal display uses the radius, better just to calculate them */ + /* check we are a single point? also check we are not a surface and that the orderu is sane, * enforced in the UI but can go wrong possibly */ if(!check_valid_nurb_u(nu)) { - bl= MEM_callocN(sizeof(BevList)+1*sizeof(BevPoint), "makeBevelList"); + bl= MEM_callocN(sizeof(BevList)+1*sizeof(BevPoint), "makeBevelList1"); BLI_addtail(&(cu->bev), bl); bl->nr= 0; } else { @@ -1504,7 +1543,7 @@ void makeBevelList(Object *ob) if((nu->type & 7)==CU_POLY) { len= nu->pntsu; - bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList"); + bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList2"); BLI_addtail(&(cu->bev), bl); if(nu->flagu & CU_CYCLIC) bl->poly= 0; @@ -1519,7 +1558,8 @@ void makeBevelList(Object *ob) bevp->y= bp->vec[1]; bevp->z= bp->vec[2]; bevp->alfa= bp->alfa; - bevp->f1= 1; + bevp->radius= bp->radius; + bevp->f1= SELECT; bevp++; bp++; } @@ -1527,7 +1567,7 @@ void makeBevelList(Object *ob) else if((nu->type & 7)==CU_BEZIER) { len= resolu*(nu->pntsu+ (nu->flagu & CU_CYCLIC) -1)+1; /* in case last point is not cyclic */ - bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList"); + bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelBPoints"); BLI_addtail(&(cu->bev), bl); if(nu->flagu & CU_CYCLIC) bl->poly= 0; @@ -1545,8 +1585,13 @@ void makeBevelList(Object *ob) bezt++; } - data= MEM_mallocN(3*sizeof(float)*(resolu+1), "makeBevelList2"); - data_a= MEM_callocN(sizeof(float)*(resolu+1), "data_a"); + coord_array= coord_fp= MEM_mallocN(3*sizeof(float)*(resolu+1), "makeBevelCoords"); + + if(do_tilt) + tilt_array= tilt_fp= MEM_callocN(sizeof(float)*(resolu+1), "makeBevelTilt"); + + if (do_radius) + radius_array= radius_fp= MEM_callocN(sizeof(float)*(resolu+1), "nakeBevelRadius"); while(a--) { if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) { @@ -1555,6 +1600,7 @@ void makeBevelList(Object *ob) bevp->y= prevbezt->vec[1][1]; bevp->z= prevbezt->vec[1][2]; bevp->alfa= prevbezt->alfa; + bevp->radius= prevbezt->radius; bevp->f1= SELECT; bevp->f2= 0; bevp++; @@ -1566,38 +1612,44 @@ void makeBevelList(Object *ob) v2= bezt->vec[0]; /* always do all three, to prevent data hanging around */ - forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], data, resolu, 3); - forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], data+1, resolu, 3); - forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], data+2, resolu, 3); - - if((nu->type & CU_2D)==0) { - if(cu->flag & CU_3D) { - alfa_bezpart(prevbezt, bezt, nu, data_a, resolu); - } - } + forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], coord_array, resolu, 3); + forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], coord_array+1, resolu, 3); + forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], coord_array+2, resolu, 3); + if (do_tilt || do_radius) + alfa_bezpart(prevbezt, bezt, nu, tilt_array, radius_array, resolu); /* indicate with handlecodes double points */ if(prevbezt->h1==prevbezt->h2) { - if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= 1; + if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= SELECT; } else { - if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= 1; - else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->f1= 1; + if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= SELECT; + else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->f1= SELECT; } - v1= data; - v2= data_a; nr= resolu; + coord_fp = coord_array; + tilt_fp = tilt_array; + radius_fp = radius_array; + while(nr--) { - bevp->x= v1[0]; - bevp->y= v1[1]; - bevp->z= v1[2]; - bevp->alfa= v2[0]; + bevp->x= coord_fp[0]; + bevp->y= coord_fp[1]; + bevp->z= coord_fp[2]; + coord_fp+=3; + + if (do_tilt) { + bevp->alfa= *tilt_fp; + tilt_fp++; + } + + if (do_radius) { + bevp->radius= *radius_fp; + radius_fp++; + } bevp++; - v1+=3; - v2++; } bl->nr+= resolu; @@ -1606,22 +1658,24 @@ void makeBevelList(Object *ob) bezt++; } - MEM_freeN(data); - MEM_freeN(data_a); + MEM_freeN(coord_array); + if (do_tilt) MEM_freeN(tilt_array); + if (do_radius) MEM_freeN(radius_array); + coord_array = tilt_array = radius_array = NULL; if((nu->flagu & CU_CYCLIC)==0) { /* not cyclic: endpoint */ bevp->x= prevbezt->vec[1][0]; bevp->y= prevbezt->vec[1][1]; bevp->z= prevbezt->vec[1][2]; bevp->alfa= prevbezt->alfa; + bevp->radius= prevbezt->radius; bl->nr++; } - } else if((nu->type & 7)==CU_NURBS) { if(nu->pntsv==1) { - len= resolu*nu->pntsu; - bl= MEM_mallocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3"); + len= (resolu*SEGMENTSU(nu))+1; + bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3"); BLI_addtail(&(cu->bev), bl); bl->nr= len; bl->flag= 0; @@ -1629,21 +1683,40 @@ void makeBevelList(Object *ob) else bl->poly= -1; bevp= (BevPoint *)(bl+1); - data= MEM_callocN(4*sizeof(float)*len, "makeBevelList4"); /* has to be zero-ed */ - makeNurbcurve(nu, data, resolu, 4); + coord_array= coord_fp= MEM_callocN(3*sizeof(float)*len, "makeBevelCoords"); /* has to be zero-ed */ + + if(do_tilt) + tilt_array= tilt_fp= MEM_callocN(sizeof(float)*len, "makeBevelTilt"); + + if (do_radius) + radius_array= radius_fp= MEM_callocN(sizeof(float)*len, "nakeBevelRadius"); + + makeNurbcurve(nu, coord_array, tilt_array, radius_array, resolu); - v1= data; while(len--) { - bevp->x= v1[0]; - bevp->y= v1[1]; - bevp->z= v1[2]; - bevp->alfa= v1[3]; + bevp->x= coord_fp[0]; + bevp->y= coord_fp[1]; + bevp->z= coord_fp[2]; + coord_fp+=3; + + if (do_tilt) { + bevp->alfa= *tilt_fp; + tilt_fp++; + } + + if (do_radius) { + bevp->radius= *radius_fp; + radius_fp++; + } + bevp->f1= bevp->f2= 0; bevp++; - v1+=4; } - MEM_freeN(data); + MEM_freeN(coord_array); + if (do_tilt) MEM_freeN(tilt_array); + if (do_radius) MEM_freeN(radius_array); + coord_array = tilt_array = radius_array = NULL; } } } @@ -1678,7 +1751,7 @@ void makeBevelList(Object *ob) blnext= bl->next; if(bl->nr && bl->flag) { nr= bl->nr- bl->flag+1; /* +1 because vectorbezier sets flag too */ - blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList"); + blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList4"); memcpy(blnew, bl, sizeof(BevList)); blnew->nr= 0; BLI_remlink(&(cu->bev), bl); @@ -1886,137 +1959,6 @@ void makeBevelList(Object *ob) } } -/* calculates a bevel width (radius) for a particular subdivided curve part, - * based on the radius value of the surrounding CVs */ -float calc_curve_subdiv_radius(Curve *cu, Nurb *nu, int cursubdiv) -{ - BezTriple *bezt, *beztfirst, *beztlast, *beztnext, *beztprev; - BPoint *bp, *bpfirst, *bplast; - int resolu; - float prevrad=0.0, nextrad=0.0, rad=0.0, ratio=0.0; - int vectseg=0, subdivs=0; - - if((nu==NULL) || (nu->pntsu<=1)) return 1.0; - bezt= nu->bezt; - bp = nu->bp; - - if(G.rendering && cu->resolu_ren!=0) resolu= cu->resolu_ren; - else resolu= nu->resolu; - - if(((nu->type & 7)==CU_BEZIER) && (bezt != NULL)) { - beztfirst = nu->bezt; - beztlast = nu->bezt + (nu->pntsu - 1); - - /* loop through the CVs to end up with a pointer to the CV before the subdiv in question, and a ratio - * of how far that subdiv is between this CV and the next */ - while(bezt<=beztlast) { - beztnext = bezt+1; - beztprev = bezt-1; - vectseg=0; - - if (subdivs==cursubdiv) { - ratio= 0.0; - break; - } - - /* check to see if we're looking at a vector segment (no subdivisions) */ - if (nu->flagu & CU_CYCLIC) { - if (bezt == beztfirst) { - if ((beztlast->h2==HD_VECT) && (bezt->h1==HD_VECT)) vectseg = 1; - } else { - if ((beztprev->h2==HD_VECT) && (bezt->h1==HD_VECT)) vectseg = 1; - } - } else if ((bezt->h2==HD_VECT) && (beztnext->h1==HD_VECT)) vectseg = 1; - - - if (vectseg==0) { - /* if it's NOT a vector segment, check to see if the subdiv falls within the segment */ - subdivs += resolu; - - if (cursubdiv < subdivs) { - ratio = 1.0 - ((subdivs - cursubdiv)/(float)resolu); - break; - } - } else { - /* must be a vector segment.. loop again! */ - subdivs += 1; - } - - bezt++; - } - - /* Now we have a nice bezt pointer to the CV that we want. But cyclic messes it up, so must correct for that.. - * (cyclic goes last-> first -> first+1 -> first+2 -> ...) */ - if (nu->flagu & CU_CYCLIC) { - if (bezt == beztfirst) bezt = beztlast; - else bezt--; - } - - /* find the radii at the bounding CVs and interpolate between them based on ratio */ - rad = prevrad = bezt->radius; - - if ((bezt == beztlast) && (nu->flagu & CU_CYCLIC)) { /* loop around */ - bezt= beztfirst; - } else if (bezt != beztlast) { - bezt++; - } - nextrad = bezt->radius; - - } - else if( ( ((nu->type & 7)==CU_NURBS) || ((nu->type & 7)==CU_POLY)) && (bp != NULL)) { - /* follows similar algo as for bezt above */ - bpfirst = nu->bp; - bplast = nu->bp + (nu->pntsu - 1); - - if ((nu->type & 7)==CU_POLY) resolu=1; - - while(bp<=bplast) { - if (subdivs==cursubdiv) { - ratio= 0.0; - break; - } - - subdivs += resolu; - - if (cursubdiv < subdivs) { - ratio = 1.0 - ((subdivs - cursubdiv)/(float)resolu); - break; - } - - bp++; - } - - if ( ((nu->type & 7)==CU_NURBS) && (nu->flagu & CU_CYCLIC)) { - if (bp >= bplast) bp = bpfirst; - else bp++; - } else if ( bp > bplast ) { - /* this can happen in rare cases, refer to bug [#8596] */ - bp = bplast; - } - - rad = prevrad = bp->radius; - - if ((bp == bplast) && (nu->flagu & CU_CYCLIC)) { /* loop around */ - bp= bpfirst; - } else if (bp < bplast) { - bp++; - } - nextrad = bp->radius; - - } - - - if (nextrad != prevrad) { - /* smooth interpolation */ - rad = prevrad + (nextrad-prevrad)*(3.0f*ratio*ratio - 2.0f*ratio*ratio*ratio); - } - - if (rad > 0.0) - return rad; - else - return 1.0; -} - /* ****************** HANDLES ************** */ /* @@ -2385,9 +2327,9 @@ void sethandlesNurb(short code) bezt= nu->bezt; a= nu->pntsu; while(a--) { - if(bezt->f1 || bezt->f3) { - if(bezt->f1) bezt->h1= code; - if(bezt->f3) bezt->h2= code; + if((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) { + if(bezt->f1 & SELECT) bezt->h1= code; + if(bezt->f3 & SELECT) bezt->h2= code; if(bezt->h1!=bezt->h2) { if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE; if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE; @@ -2415,8 +2357,8 @@ void sethandlesNurb(short code) bezt= nu->bezt; a= nu->pntsu; while(a--) { - if(bezt->f1 && bezt->h1) ok= 1; - if(bezt->f3 && bezt->h2) ok= 1; + if((bezt->f1 & SELECT) && bezt->h1) ok= 1; + if((bezt->f3 & SELECT) && bezt->h2) ok= 1; if(ok) break; bezt++; } @@ -2432,8 +2374,8 @@ void sethandlesNurb(short code) bezt= nu->bezt; a= nu->pntsu; while(a--) { - if(bezt->f1) bezt->h1= ok; - if(bezt->f3 ) bezt->h2= ok; + if(bezt->f1 & SELECT) bezt->h1= ok; + if(bezt->f3 & SELECT) bezt->h2= ok; bezt++; } diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index d958c43aa40..7f4910a9765 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -865,12 +865,12 @@ DagNode * dag_get_sub_node (DagForest *forest,void * fob) return node; } -void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, char *name) +static void dag_add_parent_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, char *name) { - DagAdjList *itA = fob1->child; + DagAdjList *itA = fob2->parent; while (itA) { /* search if relation exist already */ - if (itA->node == fob2) { + if (itA->node == fob1) { itA->type |= rel; itA->count += 1; return; @@ -879,20 +879,23 @@ void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel } /* create new relation and insert at head. MALLOC alert! */ itA = MEM_mallocN(sizeof(DagAdjList),"DAG adj list"); - itA->node = fob2; + itA->node = fob1; itA->type = rel; itA->count = 1; - itA->next = fob1->child; + itA->next = fob2->parent; itA->name = name; - fob1->child = itA; + fob2->parent = itA; } -static void dag_add_parent_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, char *name) +void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, char *name) { - DagAdjList *itA = fob2->parent; + DagAdjList *itA = fob1->child; + /* parent relation is for cycle checking */ + dag_add_parent_relation(forest, fob1, fob2, rel, name); + while (itA) { /* search if relation exist already */ - if (itA->node == fob1) { + if (itA->node == fob2) { itA->type |= rel; itA->count += 1; return; @@ -901,12 +904,12 @@ static void dag_add_parent_relation(DagForest *forest, DagNode *fob1, DagNode *f } /* create new relation and insert at head. MALLOC alert! */ itA = MEM_mallocN(sizeof(DagAdjList),"DAG adj list"); - itA->node = fob1; + itA->node = fob2; itA->type = rel; itA->count = 1; - itA->next = fob2->parent; + itA->next = fob1->child; itA->name = name; - fob2->parent = itA; + fob1->child = itA; } static char *dag_node_name(DagNode *node) @@ -966,6 +969,63 @@ static void dag_node_print_dependency_cycle(DagForest *dag, DagNode *startnode, printf("\n"); } +static int dag_node_recurs_level(DagNode *node, int level) +{ + DagAdjList *itA; + int newlevel; + + node->color= DAG_BLACK; /* done */ + newlevel= ++level; + + for(itA= node->parent; itA; itA= itA->next) { + if(itA->node->color==DAG_WHITE) { + itA->node->ancestor_count= dag_node_recurs_level(itA->node, level); + newlevel= MAX2(newlevel, level+itA->node->ancestor_count); + } + else + newlevel= MAX2(newlevel, level+itA->node->ancestor_count); + } + + return newlevel; +} + +static void dag_check_cycle(DagForest *dag) +{ + DagNode *node; + DagAdjList *itA; + + /* tag nodes unchecked */ + for(node = dag->DagNode.first; node; node= node->next) + node->color= DAG_WHITE; + + for(node = dag->DagNode.first; node; node= node->next) { + if(node->color==DAG_WHITE) { + node->ancestor_count= dag_node_recurs_level(node, 0); + } + } + + /* check relations, and print errors */ + for(node = dag->DagNode.first; node; node= node->next) { + for(itA= node->parent; itA; itA= itA->next) { + if(itA->node->ancestor_count > node->ancestor_count) { + if(node->ob && itA->node->ob) { + printf("Dependency cycle detected:\n"); + dag_node_print_dependency_cycle(dag, itA->node, node, itA->name); + } + } + } + } + + /* parent relations are only needed for cycle checking, so free now */ + for(node = dag->DagNode.first; node; node= node->next) { + while (node->parent) { + itA = node->parent->next; + MEM_freeN(node->parent); + node->parent = itA; + } + } +} + /* * MainDAG is the DAG of all objects in current scene * used only for drawing there is one also in each scene @@ -1603,6 +1663,8 @@ void DAG_scene_sort(struct Scene *sce) build_dag(sce, DAG_RL_ALL_BUT_DATA); + dag_check_cycle(sce->theDag); + nqueue = queue_create(DAGQUEUEALLOC); for(node = sce->theDag->DagNode.first; node; node= node->next) { @@ -1969,12 +2031,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; @@ -2212,57 +2268,6 @@ void DAG_object_update_flags(Scene *sce, Object *ob, unsigned int lay) /* ******************* DAG FOR ARMATURE POSE ***************** */ -static int node_recurs_level(DagNode *node, int level) -{ - DagAdjList *itA; - int newlevel; - - node->color= DAG_BLACK; /* done */ - newlevel= ++level; - - for(itA= node->parent; itA; itA= itA->next) { - if(itA->node->color==DAG_WHITE) { - itA->node->ancestor_count= node_recurs_level(itA->node, level); - newlevel= MAX2(newlevel, level+itA->node->ancestor_count); - } - else - newlevel= MAX2(newlevel, level+itA->node->ancestor_count); - } - - return newlevel; -} - -static void pose_check_cycle(DagForest *dag) -{ - DagNode *node; - DagAdjList *itA; - - /* tag nodes unchecked */ - for(node = dag->DagNode.first; node; node= node->next) - node->color= DAG_WHITE; - - for(node = dag->DagNode.first; node; node= node->next) { - if(node->color==DAG_WHITE) { - node->ancestor_count= node_recurs_level(node, 0); - } - } - - /* check relations, and print errors */ - for(node = dag->DagNode.first; node; node= node->next) { - for(itA= node->parent; itA; itA= itA->next) { - if(itA->node->ancestor_count > node->ancestor_count) { - bPoseChannel *pchan= (bPoseChannel *)node->ob; - bPoseChannel *parchan= (bPoseChannel *)itA->node->ob; - - if(pchan && parchan) { - printf("Cycle detected:\n"); - dag_node_print_dependency_cycle(dag, itA->node, node, itA->name); - } - } - } - } -} - /* we assume its an armature with pose */ void DAG_pose_sort(Object *ob) { @@ -2292,7 +2297,6 @@ void DAG_pose_sort(Object *ob) if(pchan->parent) { node2 = dag_get_node(dag, pchan->parent); dag_add_relation(dag, node2, node, 0, "Parent Relation"); - dag_add_parent_relation(dag, node2, node, 0, "Parent Relation"); addtoroot = 0; } for (con = pchan->constraints.first; con; con=con->next) { @@ -2311,7 +2315,6 @@ void DAG_pose_sort(Object *ob) if(target) { node2 = dag_get_node(dag, target); dag_add_relation(dag, node2, node, 0, "Ipo Driver"); - dag_add_parent_relation(dag, node2, node, 0, "Ipo Driver"); /* uncommented this line, results in dependencies * not being added properly for this constraint, @@ -2331,7 +2334,6 @@ void DAG_pose_sort(Object *ob) if (target) { node2= dag_get_node(dag, target); dag_add_relation(dag, node2, node, 0, "IK Constraint"); - dag_add_parent_relation(dag, node2, node, 0, "IK Constraint"); if (con->type==CONSTRAINT_TYPE_KINEMATIC) { bKinematicConstraint *data = (bKinematicConstraint *)con->data; @@ -2348,7 +2350,6 @@ void DAG_pose_sort(Object *ob) while (parchan) { node3= dag_get_node(dag, parchan); dag_add_relation(dag, node2, node3, 0, "IK Constraint"); - dag_add_parent_relation(dag, node2, node3, 0, "IK Constraint"); segcount++; if (segcount==data->rootbone || segcount>255) break; // 255 is weak @@ -2365,11 +2366,10 @@ void DAG_pose_sort(Object *ob) } if (addtoroot == 1 ) { dag_add_relation(dag, rootnode, node, 0, "Root Bone Relation"); - dag_add_parent_relation(dag, rootnode, node, 0, "Root Bone Relation"); } } - pose_check_cycle(dag); + dag_check_cycle(dag); /* now we try to sort... */ tempbase.first= tempbase.last= NULL; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 3b79f6689c0..598973d6974 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -757,7 +757,10 @@ void reshadeall_displist(void) for(base= G.scene->base.first; base; base= base->next) { ob= base->object; - freedisplist(&ob->disp); + + if(ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) + freedisplist(&ob->disp); + if(base->lay & G.scene->lay) { /* Metaballs have standard displist at the Object */ if(ob->type==OB_MBALL) shadeDispList(base); @@ -855,7 +858,8 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) } } else if((nu->type & 7)==CU_NURBS) { - len= nu->pntsu*resolu; + len= (resolu*SEGMENTSU(nu))+1; + dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); BLI_addtail(dispbase, dl); @@ -867,7 +871,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) data= dl->verts; if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; - makeNurbcurve(nu, data, resolu, 3); + makeNurbcurve(nu, data, NULL, NULL, resolu); } else if((nu->type & 7)==CU_POLY) { len= nu->pntsu; @@ -1319,7 +1323,7 @@ void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender) for (nu=nubase->first; nu; nu=nu->next) { if(forRender || nu->hide==0) { if(nu->pntsv==1) { - len= nu->pntsu*nu->resolu; + len= nu->resolu*SEGMENTSU(nu)+1; dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); @@ -1335,7 +1339,7 @@ void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender) if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; - makeNurbcurve(nu, data, nu->resolu, 3); + makeNurbcurve(nu, data, NULL, NULL, nu->resolu); } else { len= nu->resolu*nu->resolv; @@ -1482,7 +1486,7 @@ void makeDispListCurveTypes(Object *ob, int forOrco) float fac=1.0; if (cu->taperobj==NULL) { if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ) - fac = calc_curve_subdiv_radius(cu, nu, a); + fac = bevp->radius; } else { fac = calc_taper(cu->taperobj, a, bl->nr); } diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c new file mode 100644 index 00000000000..9c1b3ee5a8d --- /dev/null +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -0,0 +1,642 @@ +/** + * 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 **************************** */ + +// ----------------------------------------- +// forward decleration +// ----------------------------------------- + +// ----------------------------------------- + +void fluidsim_init(FluidsimModifierData *fluidmd) +{ +#ifndef DISABLE_ELBEEM + 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; + + fss->flag = 0; + + } +#endif + return; +} + +void fluidsim_free(FluidsimModifierData *fluidmd) +{ +#ifndef DISABLE_ELBEEM + if(fluidmd) + { + MEM_freeN(fluidmd->fss); + } +#endif + return; +} + +DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) +{ +#ifndef DISABLE_ELBEEM + DerivedMesh *result = NULL; + int framenr; + FluidsimSettings *fss = NULL; + + framenr= (int)G.scene->r.cfra; + + // only handle fluidsim domains + if(fluidmd && fluidmd->fss && (fluidmd->fss->type != OB_FLUIDSIM_DOMAIN)) + return dm; + + // sanity check + if(!fluidmd || (fluidmd && !fluidmd->fss)) + return dm; + + fss = fluidmd->fss; + + // timescale not supported yet + // clmd->sim_parms->timescale= timescale; + + // support reversing of baked fluid frames here + if((fss->flag & OB_FLUIDSIM_REVERSE) && (fss->lastgoodframe >= 0)) + { + framenr = fss->lastgoodframe - framenr + 1; + CLAMP(framenr, 1, fss->lastgoodframe); + } + + /* try to read from cache */ + if(((fss->lastgoodframe >= framenr) || (fss->lastgoodframe < 0)) && (result = fluidsim_read_cache(ob, dm, fluidmd, framenr, useRenderParams))) + { + // fss->lastgoodframe = framenr; // set also in src/fluidsim.c + return result; + } + else + { + // display last known good frame + if(fss->lastgoodframe >= 0) + { + if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams))) + { + return result; + } + + // it was supposed to be a valid frame but it isn't! + fss->lastgoodframe = framenr - 1; + + + // this could be likely the case when you load an old fluidsim + if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams))) + { + return result; + } + } + + result = CDDM_copy(dm); + + if(result) + { + return result; + } + } + + return dm; +#else + return NULL; +#endif +} + +#ifndef DISABLE_ELBEEM +/* 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; + 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 ); + // ------------------------------------------------ + + 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]; + } + mf->v4 = face[3]; + + test_index_face(mf, NULL, 0, 3); + } + + gzclose( gzf ); + + CDDM_calc_edges(dm); + + CDDM_apply_vert_normals(dm, (short (*)[3])normals); + MEM_freeN(normals); + + // CDDM_calc_normals(result); + + return dm; +} + +DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams) +{ + int displaymode = 0; + int curFrame = framenr - 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; + MFace *mface; + int numfaces; + int mat_nr, flag, i; + + 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; + } + + // assign material + flags to new dm + mface = orgdm->getFaceArray(orgdm); + mat_nr = mface[0].mat_nr; + flag = mface[0].flag; + + mface = dm->getFaceArray(dm); + numfaces = dm->getNumFaces(dm); + for(i=0; i<numfaces; i++) + { + mface[i].mat_nr = mat_nr; + mface[i].flag = flag; + } + + // 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 +//------------------------------------------------------------------------------- + +void initElbeemMesh(struct Object *ob, + int *numVertices, float **vertices, + int *numTriangles, int **triangles, + int useGlobalCoords, int modifierIndex) +{ + DerivedMesh *dm = NULL; + MVert *mvert; + MFace *mface; + int countTris=0, i, totvert, totface; + float *verts; + int *tris; + + dm = mesh_create_derived_index_render(ob, CD_MASK_BAREMESH, modifierIndex); + //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/ipo.c b/source/blender/blenkernel/intern/ipo.c index e8a25aaaf80..1448ff8e417 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -175,7 +175,9 @@ int fluidsim_ar[FLUIDSIM_TOTIPO]= { FLUIDSIM_VISC, FLUIDSIM_TIME, FLUIDSIM_GRAV_X , FLUIDSIM_GRAV_Y , FLUIDSIM_GRAV_Z , FLUIDSIM_VEL_X , FLUIDSIM_VEL_Y , FLUIDSIM_VEL_Z , - FLUIDSIM_ACTIVE + FLUIDSIM_ACTIVE, + FLUIDSIM_ATTR_FORCE_STR, FLUIDSIM_ATTR_FORCE_RADIUS, + FLUIDSIM_VEL_FORCE_STR, FLUIDSIM_VEL_FORCE_RADIUS, }; int part_ar[PART_TOTIPO]= { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 6f52f923a08..5ef7f985435 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -54,8 +54,11 @@ #include "MEM_guardedalloc.h" +#include "DNA_action_types.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 +69,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,30 +78,31 @@ #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_texture.h" #include "BKE_utildefines.h" + #include "depsgraph_private.h" -#include "BKE_bmesh.h" #include "BKE_deform.h" #include "BKE_shrinkwrap.h" #include "BKE_simple_deform.h" @@ -587,6 +589,361 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob, return result; } +/* Mask */ + +static void maskModifier_copyData(ModifierData *md, ModifierData *target) +{ + MaskModifierData *mmd = (MaskModifierData*) md; + MaskModifierData *tmmd = (MaskModifierData*) target; + + strcpy(tmmd->vgroup, mmd->vgroup); +} + +static CustomDataMask maskModifier_requiredDataMask(ModifierData *md) +{ + return (1 << CD_MDEFORMVERT); +} + +static void maskModifier_foreachObjectLink( + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) +{ + MaskModifierData *mmd = (MaskModifierData *)md; + walk(userData, ob, &mmd->ob_arm); +} + +static void maskModifier_updateDepgraph(ModifierData *md, DagForest *forest, + Object *ob, DagNode *obNode) +{ + MaskModifierData *mmd = (MaskModifierData *)md; + + if (mmd->ob_arm) + { + DagNode *armNode = dag_get_node(forest, mmd->ob_arm); + + dag_add_relation(forest, armNode, obNode, + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mask Modifier"); + } +} + +static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob, + DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) +{ + MaskModifierData *mmd= (MaskModifierData *)md; + DerivedMesh *dm= derivedData, *result= NULL; + GHash *vertHash=NULL, *edgeHash, *faceHash; + GHashIterator *hashIter; + MDeformVert *dvert= NULL; + int numFaces=0, numEdges=0, numVerts=0; + int maxVerts, maxEdges, maxFaces; + int i; + + /* Overview of Method: + * 1. Get the vertices that are in the vertexgroup of interest + * 2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices + * 3. Make a new mesh containing only the mapping data + */ + + /* get original number of verts, edges, and faces */ + maxVerts= dm->getNumVerts(dm); + maxEdges= dm->getNumEdges(dm); + maxFaces= dm->getNumFaces(dm); + + /* check if we can just return the original mesh + * - must have verts and therefore verts assigned to vgroups to do anything useful + */ + if ( !(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || + (maxVerts == 0) || (ob->defbase.first == NULL) ) + { + return derivedData; + } + + /* if mode is to use selected armature bones, aggregate the bone groups */ + if (mmd->mode == MOD_MASK_MODE_ARM) /* --- using selected bones --- */ + { + GHash *vgroupHash, *boneHash; + Object *oba= mmd->ob_arm; + bPoseChannel *pchan; + bDeformGroup *def; + + /* check that there is armature object with bones to use, otherwise return original mesh */ + if (ELEM(NULL, mmd->ob_arm, mmd->ob_arm->pose)) + return derivedData; + + /* hashes for finding mapping of: + * - vgroups to indicies -> vgroupHash (string, int) + * - bones to vgroup indices -> boneHash (index of vgroup, dummy) + */ + vgroupHash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp); + boneHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* build mapping of names of vertex groups to indices */ + for (i = 0, def = ob->defbase.first; def; def = def->next, i++) + BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i)); + + /* get selected-posechannel <-> vertexgroup index mapping */ + for (pchan= oba->pose->chanbase.first; pchan; pchan= pchan->next) + { + /* check if bone is selected */ + // TODO: include checks for visibility too? + // FIXME: the depsgraph needs extensions to make this work in realtime... + if ( (pchan->bone) && (pchan->bone->flag & BONE_SELECTED) ) + { + /* check if hash has group for this bone */ + if (BLI_ghash_haskey(vgroupHash, pchan->name)) + { + int defgrp_index= GET_INT_FROM_POINTER(BLI_ghash_lookup(vgroupHash, pchan->name)); + + /* add index to hash (store under key only) */ + BLI_ghash_insert(boneHash, SET_INT_IN_POINTER(defgrp_index), pchan); + } + } + } + + /* if no bones selected, free hashes and return original mesh */ + if (BLI_ghash_size(boneHash) == 0) + { + BLI_ghash_free(vgroupHash, NULL, NULL); + BLI_ghash_free(boneHash, NULL, NULL); + + return derivedData; + } + + /* repeat the previous check, but for dverts */ + dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT); + if (dvert == NULL) + { + BLI_ghash_free(vgroupHash, NULL, NULL); + BLI_ghash_free(boneHash, NULL, NULL); + + return derivedData; + } + + /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ + vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* add vertices which exist in vertexgroups into vertHash for filtering */ + for (i = 0; i < maxVerts; i++) + { + MDeformWeight *def_weight = NULL; + int j; + + for (j= 0; j < dvert[i].totweight; j++) + { + if (BLI_ghash_haskey(boneHash, SET_INT_IN_POINTER(dvert[i].dw[j].def_nr))) + { + def_weight = &dvert[i].dw[j]; + break; + } + } + + /* check if include vert in vertHash */ + if (mmd->flag & MOD_MASK_INV) { + /* if this vert is in the vgroup, don't include it in vertHash */ + if (def_weight) continue; + } + else { + /* if this vert isn't in the vgroup, don't include it in vertHash */ + if (!def_weight) continue; + } + + /* add to ghash for verts (numVerts acts as counter for mapping) */ + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); + numVerts++; + } + + /* free temp hashes */ + BLI_ghash_free(vgroupHash, NULL, NULL); + BLI_ghash_free(boneHash, NULL, NULL); + } + else /* --- Using Nominated VertexGroup only --- */ + { + int defgrp_index = -1; + + /* get index of vertex group */ + if (mmd->vgroup[0]) + { + bDeformGroup *def; + + /* find index by comparing names - SLOW... */ + for (i = 0, def = ob->defbase.first; def; def = def->next, i++) + { + if (!strcmp(def->name, mmd->vgroup)) + { + defgrp_index = i; + break; + } + } + } + + /* get dverts */ + if (defgrp_index >= 0) + dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + + /* if no vgroup (i.e. dverts) found, return the initial mesh */ + if ((defgrp_index < 0) || (dvert == NULL)) + return dm; + + /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ + vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* add vertices which exist in vertexgroup into ghash for filtering */ + for (i = 0; i < maxVerts; i++) + { + MDeformWeight *def_weight = NULL; + int j; + + for (j= 0; j < dvert[i].totweight; j++) + { + if (dvert[i].dw[j].def_nr == defgrp_index) + { + def_weight = &dvert[i].dw[j]; + break; + } + } + + /* check if include vert in vertHash */ + if (mmd->flag & MOD_MASK_INV) { + /* if this vert is in the vgroup, don't include it in vertHash */ + if (def_weight) continue; + } + else { + /* if this vert isn't in the vgroup, don't include it in vertHash */ + if (!def_weight) continue; + } + + /* add to ghash for verts (numVerts acts as counter for mapping) */ + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); + numVerts++; + } + } + + /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ + edgeHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + faceHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* loop over edges and faces, and do the same thing to + * ensure that they only reference existing verts + */ + for (i = 0; i < maxEdges; i++) + { + MEdge me; + dm->getEdge(dm, i, &me); + + /* only add if both verts will be in new mesh */ + if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) && + BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)) ) + { + BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges)); + numEdges++; + } + } + for (i = 0; i < maxFaces; i++) + { + MFace mf; + dm->getFace(dm, i, &mf); + + /* all verts must be available */ + if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)) && + BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)) && + BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)) && + (mf.v4==0 || BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4))) ) + { + BLI_ghash_insert(faceHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numFaces)); + numFaces++; + } + } + + + /* now we know the number of verts, edges and faces, + * we can create the new (reduced) mesh + */ + result = CDDM_from_template(dm, numVerts, numEdges, numFaces); + + + /* using ghash-iterators, map data into new mesh */ + /* vertices */ + for ( hashIter = BLI_ghashIterator_new(vertHash); + !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_step(hashIter) ) + { + MVert source; + MVert *dest; + int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); + int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); + + dm->getVert(dm, oldIndex, &source); + dest = CDDM_get_vert(result, newIndex); + + DM_copy_vert_data(dm, result, oldIndex, newIndex, 1); + *dest = source; + } + BLI_ghashIterator_free(hashIter); + + /* edges */ + for ( hashIter = BLI_ghashIterator_new(edgeHash); + !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_step(hashIter) ) + { + MEdge source; + MEdge *dest; + int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); + int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); + + dm->getEdge(dm, oldIndex, &source); + dest = CDDM_get_edge(result, newIndex); + + source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); + source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); + + DM_copy_edge_data(dm, result, oldIndex, newIndex, 1); + *dest = source; + } + BLI_ghashIterator_free(hashIter); + + /* faces */ + for ( hashIter = BLI_ghashIterator_new(faceHash); + !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_step(hashIter) ) + { + MFace source; + MFace *dest; + int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); + int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); + int orig_v4; + + dm->getFace(dm, oldIndex, &source); + dest = CDDM_get_face(result, newIndex); + + orig_v4 = source.v4; + + source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); + source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); + source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3))); + if (source.v4) + source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4))); + + DM_copy_face_data(dm, result, oldIndex, newIndex, 1); + *dest = source; + + test_index_face(dest, &result->faceData, newIndex, (orig_v4 ? 4 : 3)); + } + BLI_ghashIterator_free(hashIter); + + /* recalculate normals */ + CDDM_calc_normals(result); + + /* free hashes */ + BLI_ghash_free(vertHash, NULL, NULL); + BLI_ghash_free(edgeHash, NULL, NULL); + BLI_ghash_free(faceHash, NULL, NULL); + + /* return the new mesh */ + return result; +} + /* Array */ /* Array modifier: duplicates the object multiple times along an axis */ @@ -6922,6 +7279,93 @@ 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 void fluidsimModifier_copyData(ModifierData *md, ModifierData *target) +{ + FluidsimModifierData *fluidmd= (FluidsimModifierData*) md; + FluidsimModifierData *tfluidmd= (FluidsimModifierData*) target; + + if(tfluidmd->fss) + MEM_freeN(tfluidmd->fss); + + tfluidmd->fss = MEM_dupallocN(fluidmd->fss); +} + +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) + { + return result; + } + + return derivedData; +} + +static void fluidsimModifier_updateDepgraph( + ModifierData *md, DagForest *forest, + Object *ob, DagNode *obNode) +{ + FluidsimModifierData *fluidmd= (FluidsimModifierData*) md; + Base *base; + + if(fluidmd && fluidmd->fss) + { + if(fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) + { + for(base = G.scene->base.first; base; base= base->next) + { + Object *ob1= base->object; + if(ob1 != ob) + { + FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob1, eModifierType_Fluidsim); + + // only put dependancies from NON-DOMAIN fluids in here + if(fluidmdtmp && fluidmdtmp->fss && (fluidmdtmp->fss->type!=OB_FLUIDSIM_DOMAIN)) + { + DagNode *curNode = dag_get_node(forest, ob1); + dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Fluidsim Object"); + } + } + } + } + } +} + +static int fluidsimModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + /* MeshDeform */ static void meshdeformModifier_initData(ModifierData *md) @@ -7535,6 +7979,15 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->copyData = buildModifier_copyData; mti->dependsOnTime = buildModifier_dependsOnTime; mti->applyModifier = buildModifier_applyModifier; + + mti = INIT_TYPE(Mask); + mti->type = eModifierTypeType_Nonconstructive; + mti->flags = eModifierTypeFlag_AcceptsMesh; + mti->copyData = maskModifier_copyData; + mti->requiredDataMask= maskModifier_requiredDataMask; + mti->foreachObjectLink = maskModifier_foreachObjectLink; + mti->updateDepgraph = maskModifier_updateDepgraph; + mti->applyModifier = maskModifier_applyModifier; mti = INIT_TYPE(Array); mti->type = eModifierTypeType_Constructive; @@ -7778,6 +8231,17 @@ 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->copyData = fluidsimModifier_copyData; + mti->dependsOnTime = fluidsimModifier_dependsOnTime; + mti->applyModifier = fluidsimModifier_applyModifier; + mti->updateDepgraph = fluidsimModifier_updateDepgraph; mti = INIT_TYPE(Shrinkwrap); mti->type = eModifierTypeType_OnlyDeform; @@ -8230,3 +8694,4 @@ void modifier_freeTemporaryData(ModifierData *md) } + diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 9bc7fe28f44..259a4e0de04 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -208,7 +208,7 @@ static void multires_get_edge(MultiresEdge *e, EditEdge *eed, MEdge *m, short *f } } -static void multires_get_face(MultiresFace *f, EditFace *efa, MFace *m) +static void multires_get_face(MultiresFace *f, CustomData *fdata, int findex, EditFace *efa, MFace *m) { if(efa) { MFace tmp; @@ -218,7 +218,7 @@ static void multires_get_face(MultiresFace *f, EditFace *efa, MFace *m) tmp.v3= efa->v3->tmp.l; tmp.v4= 0; if(efa->v4) tmp.v4= efa->v4->tmp.l; - test_index_face(&tmp, NULL, 0, efa->v4?4:3); + test_index_face(&tmp, fdata, findex, efa->v4?4:3); for(j=0; j<4; ++j) f->v[j]= (&tmp.v1)[j]; /* Flags */ @@ -388,7 +388,7 @@ void multires_create(Object *ob, Mesh *me) &me->mr->fdata, CD_MTFACE); if(em) efa= em->faces.first; for(i=0; i<lvl->totface; ++i) { - multires_get_face(&lvl->faces[i], efa, &me->mface[i]); + multires_get_face(&lvl->faces[i], &me->mr->fdata, i, efa, &me->mface[i]); if(em) efa= efa->next; } @@ -765,7 +765,7 @@ static void multires_update_faces(Mesh *me, EditMesh *em) if(em) efa= em->faces.first; for(i=0; i<cr_lvl->totface; ++i) { MultiresFace mftmp; - multires_get_face(&mftmp, efa, &me->mface[i]); + multires_get_face(&mftmp, &me->mr->fdata, i, efa, &me->mface[i]); if(cr_lvl->faces[i].flag != mftmp.flag) cr_flag_damaged[i]= 1; if(cr_lvl->faces[i].mat_nr != mftmp.mat_nr) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6cbcba65f56..7b53d770861 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -269,7 +269,6 @@ void free_object(Object *ob) MEM_freeN(ob->pd); } if(ob->soft) sbFree(ob->soft); - if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings); if(ob->gpulamp.first) GPU_lamp_free(ob); } @@ -748,6 +747,9 @@ void *add_lamp(char *name) la->atm_extinction_factor = 1.0; la->atm_distance_factor = 1.0; la->sun_intensity = 1.0; + la->skyblendtype= MA_RAMP_ADD; + la->skyblendfac= 1.0f; + curvemapping_initialize(la->curfalloff); return la; } @@ -962,7 +964,7 @@ Object *add_only_object(int type, char *name) ob->anisotropicFriction[2] = 1.0f; ob->gameflag= OB_PROP|OB_COLLISION; ob->margin = 0.0; - + /* NT fluid sim defaults */ ob->fluidsimFlag = 0; ob->fluidsimSettings = NULL; @@ -1180,7 +1182,9 @@ Object *copy_object(Object *ob) BPY_copy_scriptlink(&ob->scriptlink); + obn->prop.first = obn->prop.last = NULL; copy_properties(&obn->prop, &ob->prop); + copy_sensors(&obn->sensors, &ob->sensors); copy_controllers(&obn->controllers, &ob->controllers); copy_actuators(&obn->actuators, &ob->actuators); @@ -1214,15 +1218,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.c b/source/blender/blenkernel/intern/particle.c index 3ff57f55992..878cb08c950 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1674,7 +1674,6 @@ int do_guide(ParticleKey *state, int pa_num, float time, ListBase *lb) /* TODO */ //else{ ///* curve size*/ - // calc_curve_subdiv_radius(cu,cu->nurb.first,((Nurb*)cu->nurb.first)-> //} par.co[0]=par.co[1]=par.co[2]=0.0f; VECCOPY(key.co,pa_loc); @@ -3721,6 +3720,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey float cfra; int totpart=psys->totpart, between=0; + /* negative time means "use current time" */ if(state->time>0) cfra=state->time; else @@ -3796,7 +3796,45 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey } else{ if (pa) { /* TODO PARTICLE - should this ever be NULL? - Campbell */ - copy_particle_key(state,&pa->state,0); + if(pa->state.time==state->time) + copy_particle_key(state, &pa->state, 1); + else if(pa->prev_state.time==state->time) + copy_particle_key(state, &pa->prev_state, 1); + else { + /* let's interpolate to try to be as accurate as possible */ + if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) { + ParticleKey keys[4]; + float dfra, keytime, frs_sec = G.scene->r.frs_sec; + + if(pa->prev_state.time >= pa->state.time) { + /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */ + copy_particle_key(state, &pa->state, 1); + + VECADDFAC(state->co, state->co, state->vel, (state->time-pa->state.time)/frs_sec); + } + else { + copy_particle_key(keys+1, &pa->prev_state, 1); + copy_particle_key(keys+2, &pa->state, 1); + + dfra = keys[2].time - keys[1].time; + + keytime = (state->time - keys[1].time) / dfra; + + /* convert velocity to timestep size */ + VecMulf(keys[1].vel, dfra / frs_sec); + VecMulf(keys[2].vel, dfra / frs_sec); + + interpolate_particle(-1, keys, keytime, state, 1); + + /* convert back to real velocity */ + VecMulf(state->vel, frs_sec / dfra); + } + } + else { + /* extrapolating over big ranges is not accurate so let's just give something close to reasonable back */ + copy_particle_key(state, &pa->state, 0); + } + } if(pa->alive==PARS_DEAD && part->flag&PART_STICKY && pa->flag&PARS_STICKY && pa->stick_ob){ key_from_object(pa->stick_ob,state); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 11e69262bbe..e4b8077cd4e 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1714,10 +1714,8 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi tob=ob; tpsys=BLI_findlink(&tob->particlesystem,psys->target_psys-1); - - /*TODO: get precise location of particle at birth*/ - state.time=cfra; + state.time = pa->time; if(pa->num == -1) memset(&state, 0, sizeof(state)); else @@ -1809,6 +1807,12 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi } /* conversion done so now we apply new: */ /* -velocity from: */ + + /* *reactions */ + if(dtime>0.0f){ + VECSUB(vel,pa->state.vel,pa->prev_state.vel); + } + /* *emitter velocity */ if(dtime!=0.0 && part->obfac!=0.0){ VECSUB(vel,loc,pa->state.co); @@ -2204,6 +2208,8 @@ static int get_particles_from_cache(Object *ob, ParticleSystem *psys, int cfra) /* assuming struct consists of tightly packed floats */ for(i=0, pa=psys->particles; i<totpart; i++, pa++) { + if(cfra!=pa->state.time) + copy_particle_key(&pa->prev_state,&pa->state,1); if(!BKE_ptcache_file_read_floats(pf, (float*)&pa->state, sizeof(ParticleKey)/sizeof(float))) { BKE_ptcache_file_close(pf); return 0; @@ -2489,14 +2495,12 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo Object *eob = ec->ob; ParticleSystem *epsys = BLI_findlink(&eob->particlesystem,ec->psys_nbr); ParticleSettings *epart = epsys->part; - ParticleData *epa = epsys->particles; - int totepart = epsys->totpart; + ParticleData *epa; + int p, totepart = epsys->totpart; if(psys->part->phystype==PART_PHYS_BOIDS){ - ParticleData *epa; ParticleKey state; PartDeflect *pd; - int p; pd= epart->pd; if(pd->forcefield==PFIELD_FORCE && totepart){ @@ -2512,6 +2516,7 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo BLI_kdtree_balance(tree); } } + } else if(ec->type==PSYS_EC_DEFLECT) { CollisionModifierData *collmd = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); @@ -2573,7 +2578,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P } else { do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance, falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part, - pa->state.vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size); + state->vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size); } } if(ec->type & PSYS_EC_PARTICLE){ @@ -2602,7 +2607,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P if(epsys==psys && p == pa_no) continue; epa = epsys->particles + p; - estate.time=-1.0; + estate.time=cfra; if(psys_get_particle_state(eob,epsys,p,&estate,0)){ VECSUB(vec_to_part, state->co, estate.co); distance = VecLength(vec_to_part); @@ -2641,7 +2646,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P /* Newtonian physics */ /************************************************/ /* gathers all forces that effect particles and calculates a new state for the particle */ -static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, float timestep, float dfra, float cfra, ParticleKey *state) +static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, float timestep, float dfra, float cfra) { ParticleKey states[5], tkey; float force[3],tvel[3],dx[4][3],dv[4][3]; @@ -2649,7 +2654,7 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti int i, steps=1; /* maintain angular velocity */ - VECCOPY(state->ave,pa->state.ave); + VECCOPY(pa->state.ave,pa->prev_state.ave); if(part->flag & PART_SIZEMASS) pa_mass*=pa->size; @@ -2699,8 +2704,8 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti switch(part->integrator){ case PART_INT_EULER: - VECADDFAC(state->co,states->co,states->vel,dtime); - VECADDFAC(state->vel,states->vel,force,dtime); + VECADDFAC(pa->state.co,states->co,states->vel,dtime); + VECADDFAC(pa->state.vel,states->vel,force,dtime); break; case PART_INT_MIDPOINT: if(i==0){ @@ -2709,8 +2714,8 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti fra=psys->cfra+0.5f*dfra; } else{ - VECADDFAC(state->co,states->co,states[1].vel,dtime); - VECADDFAC(state->vel,states->vel,force,dtime); + VECADDFAC(pa->state.co,states->co,states[1].vel,dtime); + VECADDFAC(pa->state.vel,states->vel,force,dtime); } break; case PART_INT_RK4: @@ -2750,15 +2755,15 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti VECCOPY(dv[3],force); VecMulf(dv[3],dtime); - VECADDFAC(state->co,states->co,dx[0],1.0f/6.0f); - VECADDFAC(state->co,state->co,dx[1],1.0f/3.0f); - VECADDFAC(state->co,state->co,dx[2],1.0f/3.0f); - VECADDFAC(state->co,state->co,dx[3],1.0f/6.0f); + VECADDFAC(pa->state.co,states->co,dx[0],1.0f/6.0f); + VECADDFAC(pa->state.co,pa->state.co,dx[1],1.0f/3.0f); + VECADDFAC(pa->state.co,pa->state.co,dx[2],1.0f/3.0f); + VECADDFAC(pa->state.co,pa->state.co,dx[3],1.0f/6.0f); - VECADDFAC(state->vel,states->vel,dv[0],1.0f/6.0f); - VECADDFAC(state->vel,state->vel,dv[1],1.0f/3.0f); - VECADDFAC(state->vel,state->vel,dv[2],1.0f/3.0f); - VECADDFAC(state->vel,state->vel,dv[3],1.0f/6.0f); + VECADDFAC(pa->state.vel,states->vel,dv[0],1.0f/6.0f); + VECADDFAC(pa->state.vel,pa->state.vel,dv[1],1.0f/3.0f); + VECADDFAC(pa->state.vel,pa->state.vel,dv[2],1.0f/3.0f); + VECADDFAC(pa->state.vel,pa->state.vel,dv[3],1.0f/6.0f); } break; } @@ -2766,62 +2771,62 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti /* damp affects final velocity */ if(part->dampfac!=0.0) - VecMulf(state->vel,1.0f-part->dampfac); + VecMulf(pa->state.vel,1.0f-part->dampfac); /* finally we do guides */ time=(cfra-pa->time)/pa->lifetime; CLAMP(time,0.0,1.0); - VECCOPY(tkey.co,state->co); - VECCOPY(tkey.vel,state->vel); - tkey.time=state->time; + VECCOPY(tkey.co,pa->state.co); + VECCOPY(tkey.vel,pa->state.vel); + tkey.time=pa->state.time; if(part->type != PART_HAIR) { if(do_guide(&tkey,pa_no,time,&psys->effectors)) { - VECCOPY(state->co,tkey.co); + VECCOPY(pa->state.co,tkey.co); /* guides don't produce valid velocity */ - VECSUB(state->vel,tkey.co,pa->state.co); - VecMulf(state->vel,1.0f/dtime); - state->time=tkey.time; + VECSUB(pa->state.vel,tkey.co,pa->prev_state.co); + VecMulf(pa->state.vel,1.0f/dtime); + pa->state.time=tkey.time; } } } -static void rotate_particle(ParticleSettings *part, ParticleData *pa, float dfra, float timestep, ParticleKey *state) +static void rotate_particle(ParticleSettings *part, ParticleData *pa, float dfra, float timestep) { float rotfac, rot1[4], rot2[4]={1.0,0.0,0.0,0.0}, dtime=dfra*timestep; if((part->flag & PART_ROT_DYN)==0){ if(part->avemode==PART_AVE_SPIN){ float angle; - float len1 = VecLength(pa->state.vel); - float len2 = VecLength(state->vel); + float len1 = VecLength(pa->prev_state.vel); + float len2 = VecLength(pa->state.vel); if(len1==0.0f || len2==0.0f) - state->ave[0]=state->ave[1]=state->ave[2]=0.0f; + pa->state.ave[0]=pa->state.ave[1]=pa->state.ave[2]=0.0f; else{ - Crossf(state->ave,pa->state.vel,state->vel); - Normalize(state->ave); - angle=Inpf(pa->state.vel,state->vel)/(len1*len2); - VecMulf(state->ave,saacos(angle)/dtime); + Crossf(pa->state.ave,pa->prev_state.vel,pa->state.vel); + Normalize(pa->state.ave); + angle=Inpf(pa->prev_state.vel,pa->state.vel)/(len1*len2); + VecMulf(pa->state.ave,saacos(angle)/dtime); } - VecRotToQuat(state->vel,dtime*part->avefac,rot2); + VecRotToQuat(pa->state.vel,dtime*part->avefac,rot2); } } - rotfac=VecLength(state->ave); + rotfac=VecLength(pa->state.ave); if(rotfac==0.0){ /* QuatOne (in VecRotToQuat) doesn't give unit quat [1,0,0,0]?? */ rot1[0]=1.0; rot1[1]=rot1[2]=rot1[3]=0; } else{ - VecRotToQuat(state->ave,rotfac*dtime,rot1); + VecRotToQuat(pa->state.ave,rotfac*dtime,rot1); } - QuatMul(state->rot,rot1,pa->state.rot); - QuatMul(state->rot,rot2,state->rot); + QuatMul(pa->state.rot,rot1,pa->prev_state.rot); + QuatMul(pa->state.rot,rot2,pa->state.rot); /* keep rotation quat in good health */ - NormalQuat(state->rot); + NormalQuat(pa->state.rot); } /* convert from triangle barycentric weights to quad mean value weights */ @@ -2856,7 +2861,7 @@ int psys_intersect_dm(Object *ob, DerivedMesh *dm, float *vert_cos, float *co1, dm=mesh_get_derived_final(ob,0); if(dm==0) - mesh_get_derived_deform(ob,0); + dm=mesh_get_derived_deform(ob,0); psys_enable_all(ob); @@ -3055,7 +3060,7 @@ static void particle_intersect_face(void *userdata, int index, const BVHTreeRay /* angular momentum <-> linear momentum and swept sphere - mesh collisions */ /* 1. check for all possible deflectors for closest intersection on particle path */ /* 2. if deflection was found kill the particle or calculate new coordinates */ -static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra, ParticleKey *state){ +static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra){ Object *ob; ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; @@ -3067,8 +3072,8 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f); int deflections=0, max_deflections=10; - VECCOPY(col.co1, pa->state.co); - VECCOPY(col.co2, state->co); + VECCOPY(col.co1, pa->prev_state.co); + VECCOPY(col.co2, pa->state.co); col.t = 0.0f; /* 10 iterations to catch multiple deflections */ @@ -3126,16 +3131,16 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part /* we have to add this for dying particles too so that reactors work correctly */ VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); - VECCOPY(state->co, co); - VecLerpf(state->vel, pa->state.vel, state->vel, dt); - QuatInterpol(state->rot, pa->state.rot, state->rot, dt); - VecLerpf(state->ave, pa->state.ave, state->ave, dt); + VECCOPY(pa->state.co, co); + VecLerpf(pa->state.vel, pa->prev_state.vel, pa->state.vel, dt); + QuatInterpol(pa->state.rot, pa->prev_state.rot, pa->state.rot, dt); + VecLerpf(pa->state.ave, pa->prev_state.ave, pa->state.ave, dt); /* particle is dead so we don't need to calculate further */ deflections=max_deflections; /* store for reactors */ - copy_particle_key(&reaction_state,state,0); + copy_particle_key(&reaction_state,&pa->state,0); if(part->flag & PART_STICKY){ pa->stick_ob=ob; @@ -3183,7 +3188,7 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part VECSUB(surface_vel, tan_vec, tan_vel); /* direction of rolling friction */ - Crossf(rot_vel, state->ave, col.nor); + Crossf(rot_vel, pa->state.ave, col.nor); /* convert to current dt */ VecMulf(rot_vel, (timestep*dfra) * (1.0f - col.t)); VecMulf(rot_vel, pa->size); @@ -3213,8 +3218,8 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part /* convert back to normal time */ VecMulf(dave, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); - VecMulf(state->ave, 1.0 - frict*0.01); - VECADD(state->ave, state->ave, dave); + VecMulf(pa->state.ave, 1.0 - frict*0.01); + VECADD(pa->state.ave, pa->state.ave, dave); } /* combine components together again */ @@ -3229,8 +3234,8 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part /* store state for reactors */ VECCOPY(reaction_state.co, co); - VecLerpf(reaction_state.vel, pa->state.vel, state->vel, dt); - QuatInterpol(reaction_state.rot, pa->state.rot, state->rot, dt); + VecLerpf(reaction_state.vel, pa->prev_state.vel, pa->state.vel, dt); + QuatInterpol(reaction_state.rot, pa->prev_state.rot, pa->state.rot, dt); /* set coordinates for next iteration */ VECCOPY(col.co1, co); @@ -3239,15 +3244,15 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part if(VecLength(vec) < 0.001 && VecLength(pa->state.vel) < 0.001) { /* kill speed to stop slipping */ - VECCOPY(state->vel,zerovec); - VECCOPY(state->co, co); + VECCOPY(pa->state.vel,zerovec); + VECCOPY(pa->state.co, co); if(part->flag & PART_ROT_DYN) { - VECCOPY(state->ave,zerovec); + VECCOPY(pa->state.ave,zerovec); } } else { - VECCOPY(state->co, col.co2); - VECCOPY(state->vel, vel); + VECCOPY(pa->state.co, col.co2); + VECCOPY(pa->state.vel, vel); } } deflections++; @@ -3314,7 +3319,9 @@ static int boid_see_mesh(ListBase *lb, Object *pob, ParticleSystem *psys, float else{ psys_disable_all(ob); - dm=mesh_get_derived_deform(ob,0); + dm=mesh_get_derived_final(ob,0); + if(dm==0) + dm=mesh_get_derived_deform(ob,0); psys_enable_all(ob); } @@ -3448,18 +3455,18 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS switch(part->boidrule[i]){ case BOID_COLLIDE: /* collision avoidance */ - bvf->Copyf(dvec,pa->state.vel); + bvf->Copyf(dvec,pa->prev_state.vel); bvf->Mulf(dvec,5.0f); - bvf->Addf(dvec,dvec,pa->state.co); - if(boid_see_mesh(&psys->effectors,ob,psys,pa->state.co,dvec,ob_co,ob_nor,cfra)){ + bvf->Addf(dvec,dvec,pa->prev_state.co); + if(boid_see_mesh(&psys->effectors,ob,psys,pa->prev_state.co,dvec,ob_co,ob_nor,cfra)){ float probelen = bvf->Length(dvec); float proj; float oblen; Normalize(ob_nor); - proj = bvf->Inpf(ob_nor,pa->state.vel); + proj = bvf->Inpf(ob_nor,pa->prev_state.vel); - bvf->Subf(dvec,pa->state.co,ob_co); + bvf->Subf(dvec,pa->prev_state.co,ob_co); oblen=bvf->Length(dvec); bvf->Copyf(dvec,ob_nor); @@ -3479,7 +3486,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0){ float distance; - VECSUB(dvec,eob->obmat[3],pa->state.co); + VECSUB(dvec,eob->obmat[3],pa->prev_state.co); distance=Normalize(dvec); @@ -3514,11 +3521,11 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS totepart= epsys->totpart; if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0 && ec->tree){ - count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2); + count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->prev_state.co,NULL,ptn2); for(p=0; p<count; p++){ state.time=-1.0; if(psys_get_particle_state(eob,epsys,ptn2[p].index,&state,0)){ - VECSUB(dvec, state.co, pa->state.co); + VECSUB(dvec, state.co, pa->prev_state.co); distance = Normalize(dvec); @@ -3549,7 +3556,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS for(n=1; n<neighbours; n++){ if(ptn[n].dist<2.0f*pa->size){ if(ptn[n].dist!=0.0f) { - bvf->Subf(dvec,pa->state.co,pars[ptn[n].index].state.co); + bvf->Subf(dvec,pa->prev_state.co,pars[ptn[n].index].state.co); bvf->Mulf(dvec,(2.0f*pa->size-ptn[n].dist)/ptn[n].dist); bvf->Addf(avoid,avoid,dvec); near++; @@ -3572,7 +3579,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS } bvf->Mulf(center,1.0f/((float)neighbours-1.0f)); - bvf->Subf(dvec,center,pa->state.co); + bvf->Subf(dvec,center,pa->prev_state.co); bvf->Mulf(dvec,part->boidfac[BOID_CENTER]*2.0f); @@ -3581,9 +3588,9 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS break; case BOID_AV_VEL: /* average velocity */ - cur_vel=bvf->Length(pa->state.vel); + cur_vel=bvf->Length(pa->prev_state.vel); if(cur_vel>0.0){ - bvf->Copyf(dvec,pa->state.vel); + bvf->Copyf(dvec,pa->prev_state.vel); bvf->Mulf(dvec,part->boidfac[BOID_AV_VEL]*(avg_vel-cur_vel)/cur_vel); not_finished=add_boid_acc(bvf,max_lat_acc,max_tan_acc,&lat_accu,&tan_accu,acc,dvec,0); } @@ -3598,7 +3605,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS } bvf->Mulf(velocity,1.0f/((float)neighbours-1.0f)); - bvf->Subf(dvec,velocity,pa->state.vel); + bvf->Subf(dvec,velocity,pa->prev_state.vel); bvf->Mulf(dvec,part->boidfac[BOID_VEL_MATCH]); @@ -3616,7 +3623,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0){ float distance; - VECSUB(dvec,eob->obmat[3],pa->state.co); + VECSUB(dvec,eob->obmat[3],pa->prev_state.co); distance=Normalize(dvec); @@ -3633,7 +3640,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS where_on_path(eob, (cfra-pa->time)/pa->lifetime, temp, dvec); - VECSUB(dvec,temp,pa->state.co); + VECSUB(dvec,temp,pa->prev_state.co); distance=Normalize(dvec); @@ -3661,11 +3668,11 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS totepart= epsys->totpart; if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0 && ec->tree){ - count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2); + count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->prev_state.co,NULL,ptn2); for(p=0; p<count; p++){ state.time=-1.0; if(psys_get_particle_state(eob,epsys,ptn2[p].index,&state,0)){ - VECSUB(dvec, state.co, pa->state.co); + VECSUB(dvec, state.co, pa->prev_state.co); distance = Normalize(dvec); @@ -3687,7 +3694,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS /* level flight */ if((part->flag & PART_BOIDS_2D)==0){ dvec[0]=dvec[1]=0.0; - dvec[2]=-pa->state.vel[2]; + dvec[2]=-pa->prev_state.vel[2]; VecMulf(dvec,part->boidfac[BOID_LEVEL]); not_finished=add_boid_acc(bvf,max_lat_acc,max_tan_acc,&lat_accu,&tan_accu,acc,dvec,0); @@ -3697,7 +3704,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS } } /* tries to realize the wanted acceleration */ -static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, ParticleSettings *part, float timestep, float *acc, ParticleKey *state) +static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, ParticleSettings *part, float timestep, float *acc) { float dvec[3], bvec[3], length, max_vel=part->max_vel; float q2[4], q[4]; @@ -3705,7 +3712,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, float yvec[3]={0.0,1.0,0.0}, zvec[3]={0.0,0.0,-1.0}, bank; /* apply new velocity, location & rotation */ - copy_particle_key(state,&pa->state,0); + copy_particle_key(&pa->state,&pa->prev_state,0); if(part->flag & PART_SIZEMASS) pa_mass*=pa->size; @@ -3717,10 +3724,10 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, bvf->Copyf(dvec,acc); bvf->Mulf(dvec,timestep*timestep*0.5f); - bvf->Copyf(bvec,state->vel); + bvf->Copyf(bvec,pa->state.vel); bvf->Mulf(bvec,timestep); bvf->Addf(dvec,dvec,bvec); - bvf->Addf(state->co,state->co,dvec); + bvf->Addf(pa->state.co,pa->state.co,dvec); /* air speed from wind and vortex effectors */ if(psys->effectors.first) { @@ -3734,7 +3741,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, if(pd->f_strength != 0.0f) { VecCopyf(direction, eob->obmat[2]); - VecSubf(vec_to_part, state->co, eob->obmat[3]); + VecSubf(vec_to_part, pa->state.co, eob->obmat[3]); falloff=effector_falloff(pd, direction, vec_to_part); @@ -3745,7 +3752,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, else { Normalize(direction); VecMulf(direction, pd->f_strength * falloff); - bvf->Addf(state->co, state->co, direction); + bvf->Addf(pa->state.co, pa->state.co, direction); } break; case PFIELD_VORTEX: @@ -3757,7 +3764,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, distance = VecLength(vec_to_part); VecMulf(mag_vec, pd->f_strength * distance * falloff); - bvf->Addf(state->co, state->co, mag_vec); + bvf->Addf(pa->state.co, pa->state.co, mag_vec); break; } } @@ -3767,8 +3774,8 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, } - if((part->flag & PART_BOIDS_2D)==0 && pa->state.vel[0]!=0.0 && pa->state.vel[0]!=0.0 && pa->state.vel[0]!=0.0){ - Crossf(yvec,state->vel,zvec); + if((part->flag & PART_BOIDS_2D)==0 && pa->prev_state.vel[0]!=0.0 && pa->prev_state.vel[0]!=0.0 && pa->prev_state.vel[0]!=0.0){ + Crossf(yvec,pa->state.vel,zvec); Normalize(yvec); @@ -3795,27 +3802,27 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, } - VecRotToQuat(state->vel,bank,q); + VecRotToQuat(pa->state.vel,bank,q); - VECCOPY(dvec,state->vel); + VECCOPY(dvec,pa->state.vel); VecMulf(dvec,-1.0f); vectoquat(dvec, OB_POSX, OB_POSZ, q2); - QuatMul(state->rot,q,q2); + QuatMul(pa->state.rot,q,q2); bvf->Mulf(acc,timestep); - bvf->Addf(state->vel,state->vel,acc); + bvf->Addf(pa->state.vel,pa->state.vel,acc); if(part->flag & PART_BOIDS_2D){ - state->vel[2]=0.0; - state->co[2]=part->groundz; + pa->state.vel[2]=0.0; + pa->state.co[2]=part->groundz; if(psys->keyed_ob && (psys->keyed_ob->type == OB_MESH)){ Object *zob=psys->keyed_ob; int min_face; float co1[3],co2[3],min_d=2.0,min_w[4],imat[4][4]; - VECCOPY(co1,state->co); - VECCOPY(co2,state->co); + VECCOPY(co1,pa->state.co); + VECCOPY(co2,pa->state.co); co1[2]=1000.0f; co2[2]=-1000.0f; @@ -3846,7 +3853,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, Normalize(nor); - VECCOPY(state->co,loc); + VECCOPY(pa->state.co,loc); zvec[2]=1.0; @@ -3858,17 +3865,17 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, VecRotToQuat(loc,bank,q); - QUATCOPY(q1,state->rot); + QUATCOPY(q1,pa->state.rot); - QuatMul(state->rot,q,q1); + QuatMul(pa->state.rot,q,q1); } } } } - length=bvf->Length(state->vel); + length=bvf->Length(pa->state.vel); if(length > max_vel) - bvf->Mulf(state->vel,max_vel/length); + bvf->Mulf(pa->state.vel,max_vel/length); } /************************************************/ /* Hair */ @@ -3925,7 +3932,6 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi float *vg_vel, float *vg_tan, float *vg_rot, float *vg_size) { ParticleData *pa; - ParticleKey *outstate, *key; ParticleSettings *part=psys->part; KDTree *tree=0; BoidVecFunc bvf; @@ -3995,15 +4001,9 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi if(vg_size) MEM_freeN(vg_size); - - //if(part->phystype==PART_PHYS_SOLID) - // reset_to_first_fragment(psys); } else{ BLI_srandom(31415926 + (int)cfra + psys->seed); - - /* outstate is used so that particles are updated in parallel */ - outstate=MEM_callocN(totpart*sizeof(ParticleKey),"Particle Outstates"); /* update effectors */ if(psys->effectors.first) @@ -4028,10 +4028,10 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } /* main loop: calculate physics for all particles */ - for(p=0, pa=psys->particles, key=outstate; p<totpart; p++,pa++,key++){ + for(p=0, pa=psys->particles; p<totpart; p++,pa++){ if(pa->flag & PARS_UNEXIST) continue; - copy_particle_key(key,&pa->state,1); + copy_particle_key(&pa->prev_state,&pa->state,1); /* set correct ipo timing */ if((part->flag&PART_ABS_TIME)==0 && part->ipo){ @@ -4041,7 +4041,12 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + /* reactions can change birth time so they need to be checked first */ + if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) + react_to_events(psys,p); + birthtime = pa->time + pa->loop * pa->lifetime; + dietime = birthtime + pa->lifetime; /* allways reset particles to emitter before birth */ if(pa->alive==PARS_UNBORN @@ -4049,91 +4054,72 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) || birthtime >= cfra){ reset_particle(pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); - copy_particle_key(key,&pa->state,1); } - if(1) { - - if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) - react_to_events(psys,p); - - pa_dfra = dfra; - pa_dtime = dtime; + pa_dfra = dfra; + pa_dtime = dtime; - /* we need to calculate this once again because reactions might have changed pa->time */ - birthtime = pa->time + pa->loop * pa->lifetime; - dietime = birthtime + pa->lifetime; - - if(birthtime <= cfra && birthtime >= psys->cfra){ - /* particle is born some time between this and last step*/ - pa->alive = PARS_ALIVE; - pa_dfra = cfra - birthtime; - pa_dtime = pa_dfra*timestep; - } - else if(dietime <= cfra && psys->cfra < dietime){ - /* particle dies some time between this and last step */ - pa_dfra = dietime - psys->cfra; - pa_dtime = pa_dfra * timestep; - pa->alive = PARS_DYING; - } - else if(dietime < cfra){ - /* nothing to be done when particle is dead */ - } + if(birthtime <= cfra && birthtime >= psys->cfra){ + /* particle is born some time between this and last step*/ + pa->alive = PARS_ALIVE; + pa_dfra = cfra - birthtime; + pa_dtime = pa_dfra*timestep; + } + else if(dietime <= cfra && psys->cfra < dietime){ + /* particle dies some time between this and last step */ + pa_dfra = dietime - psys->cfra; + pa_dtime = pa_dfra * timestep; + pa->alive = PARS_DYING; + } + else if(dietime < cfra){ + /* nothing to be done when particle is dead */ + } - copy_particle_key(key,&pa->state,1); - if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ - switch(part->phystype){ - case PART_PHYS_NEWTON: - /* do global forces & effectors */ - apply_particle_forces(p,pa,ob,psys,part,timestep,pa_dfra,cfra,key); - - /* deflection */ - deflect_particle(ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra,key); + if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ + switch(part->phystype){ + case PART_PHYS_NEWTON: + /* do global forces & effectors */ + apply_particle_forces(p,pa,ob,psys,part,timestep,pa_dfra,cfra); + + /* deflection */ + deflect_particle(ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra); - /* rotations */ - rotate_particle(part,pa,pa_dfra,timestep,key); - break; - case PART_PHYS_BOIDS: - { - float acc[3]; - boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc); - if(pa->alive != PARS_DYING) - boid_body(&bvf,pa,psys,part,timestep,acc,key); - break; - } + /* rotations */ + rotate_particle(part,pa,pa_dfra,timestep); + break; + case PART_PHYS_BOIDS: + { + float acc[3]; + boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc); + if(pa->alive != PARS_DYING) + boid_body(&bvf,pa,psys,part,timestep,acc); + break; } + } - if(pa->alive == PARS_DYING){ - push_reaction(ob,psys,p,PART_EVENT_DEATH,key); - - if(part->flag & PART_LOOP && part->type!=PART_HAIR){ - pa->loop++; - reset_particle(pa,psys,psmd,ob,0.0,cfra,vg_vel,vg_tan,vg_rot); - copy_particle_key(key,&pa->state,1); - pa->alive=PARS_ALIVE; - } - else{ - pa->alive=PARS_DEAD; - key->time=pa->dietime; + if(pa->alive == PARS_DYING){ + push_reaction(ob,psys,p,PART_EVENT_DEATH,&pa->state); - if(pa->flag&PARS_STICKY) - psys_key_to_object(pa->stick_ob,key,0); - } + if(part->flag & PART_LOOP && part->type!=PART_HAIR){ + pa->loop++; + reset_particle(pa,psys,psmd,ob,0.0,cfra,vg_vel,vg_tan,vg_rot); + pa->alive=PARS_ALIVE; } - else - key->time=cfra; + else{ + pa->alive=PARS_DEAD; + pa->state.time=pa->dietime; - push_reaction(ob,psys,p,PART_EVENT_NEAR,key); + if(pa->flag&PARS_STICKY) + psys_key_to_object(pa->stick_ob,&pa->state,0); + } } + else + pa->state.time=cfra; + + push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state); } } - - /* apply outstates to particles */ - for(p=0, pa=psys->particles, key=outstate; p<totpart; p++,pa++,key++) - copy_particle_key(&pa->state,key,1); - - MEM_freeN(outstate); } if(psys->reactevents.first) BLI_freelistN(&psys->reactevents); @@ -4334,7 +4320,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; @@ -4343,94 +4329,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; - - 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; + { + FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); - 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/property.c b/source/blender/blenkernel/intern/property.c index f55bdd15279..d2eb058a9a0 100644 --- a/source/blender/blenkernel/intern/property.c +++ b/source/blender/blenkernel/intern/property.c @@ -83,8 +83,7 @@ bProperty *copy_property(bProperty *prop) void copy_properties(ListBase *lbn, ListBase *lbo) { bProperty *prop, *propn; - - lbn->first= lbn->last= 0; + free_properties( lbn ); /* incase we are copying to an object with props */ prop= lbo->first; while(prop) { propn= copy_property(prop); @@ -139,7 +138,7 @@ bProperty *new_property(int type) return prop; } -bProperty *get_property(Object *ob, char *name) +bProperty *get_ob_property(Object *ob, char *name) { bProperty *prop; @@ -151,6 +150,17 @@ bProperty *get_property(Object *ob, char *name) return NULL; } +void set_ob_property(Object *ob, bProperty *propc) +{ + bProperty *prop; + prop= get_ob_property(ob, propc->name); + if(prop) { + free_property(prop); + BLI_remlink(&ob->prop, prop); + } + BLI_addtail(&ob->prop, copy_property(propc)); +} + /* negative: prop is smaller * positive: prop is larger */ |