Index: release/scripts/startup/bl_ui/properties_data_modifier.py =================================================================== --- release/scripts/startup/bl_ui/properties_data_modifier.py (revision 41360) +++ release/scripts/startup/bl_ui/properties_data_modifier.py (working copy) @@ -445,6 +445,9 @@ def PARTICLE_SYSTEM(self, layout, ob, md): layout.label(text="Settings can be found inside the Particle context") + def PARTICLE_SURFACE(self, layout, ob, md): + layout.label(text="Settings can be found inside the Physics context") + def SCREW(self, layout, ob, md): split = layout.split() Index: release/scripts/startup/bl_ui/properties_physics_common.py =================================================================== --- release/scripts/startup/bl_ui/properties_physics_common.py (revision 41360) +++ release/scripts/startup/bl_ui/properties_physics_common.py (working copy) @@ -74,6 +74,9 @@ if(ob.type == 'MESH'): physics_add(self, col, context.fluid, "Fluid", 'FLUID_SIMULATION', 'MOD_FLUIDSIM', True) physics_add(self, col, context.smoke, "Smoke", 'SMOKE', 'MOD_SMOKE', True) + if(ob.type == 'MESH'): + physics_add(self, col, context.ps_collision, "Particle Surface", 'PARTICLE_SURFACE', 'MOD_PHYSICS', True) + # cache-type can be 'PSYS' 'HAIR' 'SMOKE' etc @@ -90,7 +93,7 @@ col.operator("ptcache.remove", icon='ZOOMOUT', text="") row = layout.row() - if cachetype in {'PSYS', 'HAIR', 'SMOKE'}: + if cachetype in {'PSYS', 'HAIR', 'SMOKE', 'PARTICLE_SURFACE'}: row.prop(cache, "use_external") if cache.use_external: @@ -282,5 +285,163 @@ sub.active = field.use_max_distance sub.prop(field, "distance_max", text="Maximum") + + +def ps_panel_enabled(md): + return md.point_cache.is_baked is False + + +def ps_panel_enabled(md): + return md.point_cache.is_baked is False + + +class PhysicButtonsPanel(): + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "physics" + + @classmethod + def poll(cls, context): + rd = context.scene.render + ob = context.object + return (ob and ob.type == 'MESH') and (not rd.use_game_engine) and (context.ps_collision) + + +class PHYSICS_PT_particlesurface(PhysicButtonsPanel, bpy.types.Panel): + bl_label = "Particle Surface" + + def draw(self, context): + layout = self.layout + md = context.ps_collision + ob = context.object + + if md: + particle_surface = md.settings + layout = self.layout + layout.label("Polygonizer version: 1.0a") + + row = layout.row() + row.label(text="Isosurface Extraction:") + row.prop(particle_surface, "isosurface_extraction", text="") + row = layout.row() + row.label(text="Domain Size") + + if particle_surface.isosurface_extraction == 'Function1': + row = layout.row() + row.prop(particle_surface, "isovalue") + + + row = layout.row() + row.prop(particle_surface, "fluidthickness") + row = layout.row() + row.prop(particle_surface, "fluidradius") + row = layout.row() + row.prop(particle_surface, "fluidstiffness") + + md = context.ps_collision + + + ob = context.object + + if md: + particle_surface = md.settings + + if particle_surface.isosurface_extraction == 'Function2': + + + row = layout.row() + row.prop(particle_surface, "isovalue") + + + + + md = context.ps_collision + + ob = context.object + + + + if md: + particle_surface = md.settings + + if particle_surface.isosurface_extraction == 'Function3': + + + row = layout.row() + row.prop(particle_surface, "isovalue") + row.prop(particle_surface, "radius") + + row = layout.row() + row.prop(particle_surface, "smooth") + + row = layout.row() + row.prop(particle_surface, "render_resolution") + row.prop(particle_surface, "display_resolution") + + md = context.ps_collision + + +class PHYSICS_PT_particlesurface_motion_plotting(PhysicButtonsPanel, bpy.types.Panel): + bl_label = "Particle Surface - Motion Plotting" + bl_options = {'DEFAULT_CLOSED'} + + def draw(self, context): + + md = context.ps_collision + + if md: + particle_surface = md.settings + layout = self.layout + row = layout.row() + row.label(text="Motion Plotting") + row.prop(particle_surface, "stretch") + row = layout.row() + row.prop(particle_surface, "size") + row = layout.row() + row.prop(particle_surface, "spread") + +class PHYSICS_PT_particlesurface_cache(PhysicButtonsPanel, bpy.types.Panel): + bl_label = "Particle Surface - Cache" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + return context.ps_collision + + def draw(self, context): + md = context.ps_collision + point_cache_ui(self, context, md.point_cache, ps_panel_enabled(md), 'PARTICLE_SURFACE') + +class PHYSICS_PT_particlesurface_collision(PhysicButtonsPanel, bpy.types.Panel): + bl_label = "Particle Surface - Collision" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + return context.ps_collision + + def draw_header(self, context): + particle_surface = context.ps_collision + ps_coll = particle_surface.collision_settings + self.layout.prop(ps_coll, "use_ps_collision", text="") + + def draw(self, context): + + layout = self.layout + md = context.ps_collision + particle_surface = md.collision_settings + layout.active = particle_surface.use_ps_collision + + split = layout.split() + col = split.column() + + col.label(text="First Value:") + if md: + settings = md.collision_settings + col.label(text="Collision object") + col.prop(settings, "collisiontype") + + + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) Index: release/scripts/startup/bl_ui/space_time.py =================================================================== --- release/scripts/startup/bl_ui/space_time.py (revision 41360) +++ release/scripts/startup/bl_ui/space_time.py (working copy) @@ -134,6 +134,7 @@ col.prop(st, "cache_particles") col.prop(st, "cache_cloth") col.prop(st, "cache_smoke") + col.prop(st, "cache_particlesurface") class TIME_MT_frame(Menu): Index: source/blender/blenkernel/BKE_collision.h =================================================================== --- source/blender/blenkernel/BKE_collision.h (revision 41360) +++ source/blender/blenkernel/BKE_collision.h (working copy) @@ -149,6 +149,7 @@ // used in effect.c ///////////////////////////////////////////////// struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj); +struct Object **get_surfacecollisionobjects(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj); typedef struct ColliderCache { struct ColliderCache *next, *prev; Index: source/blender/blenkernel/BKE_modifier.h =================================================================== --- source/blender/blenkernel/BKE_modifier.h (revision 41360) +++ source/blender/blenkernel/BKE_modifier.h (working copy) @@ -337,6 +337,7 @@ int modifiers_isSoftbodyEnabled(struct Object *ob); int modifiers_isClothEnabled(struct Object *ob); int modifiers_isParticleEnabled(struct Object *ob); +int modifiers_isParticleSurfaceEnabled(struct Object *ob); struct Object *modifiers_isDeformedByArmature(struct Object *ob); struct Object *modifiers_isDeformedByLattice(struct Object *ob); Index: source/blender/blenkernel/BKE_pointcache.h =================================================================== --- source/blender/blenkernel/BKE_pointcache.h (revision 41360) +++ source/blender/blenkernel/BKE_pointcache.h (working copy) @@ -35,6 +35,7 @@ #include "DNA_ID.h" #include "DNA_object_force.h" #include "DNA_boid_types.h" +#include "DNA_particlesurface_types.h" #include /* for FILE */ /* Point cache clearing option, for BKE_ptcache_id_clear, before @@ -65,10 +66,12 @@ #define PTCACHE_TYPE_CLOTH 2 #define PTCACHE_TYPE_SMOKE_DOMAIN 3 #define PTCACHE_TYPE_SMOKE_HIGHRES 4 +#define PTCACHE_TYPE_PARTICLESURFACE 5 /* high bits reserved for flags that need to be stored in file */ #define PTCACHE_TYPEFLAG_COMPRESS (1<<16) #define PTCACHE_TYPEFLAG_EXTRADATA (1<<17) +#define PTCACHE_TYPEFLAG_SECONDEXTRADATA (1<<18) #define PTCACHE_TYPEFLAG_TYPEMASK 0x0000FFFF #define PTCACHE_TYPEFLAG_FLAGMASK 0xFFFF0000 @@ -89,6 +92,7 @@ struct Scene; struct SmokeModifierData; struct SoftBody; +struct ParticleSurfaceModifierData; /* temp structure for read/write */ typedef struct PTCacheData { @@ -141,12 +145,17 @@ void (*read_stream)(PTCacheFile *pf, void *calldata); /* copies custom extradata to cache data */ - void (*write_extra_data)(void *calldata, struct PTCacheMem *pm, int cfra); + int (*write_extra_data)(void *calldata, struct PTCacheMem *pm, int cfra); /* copies custom extradata to cache data */ void (*read_extra_data)(void *calldata, struct PTCacheMem *pm, float cfra); /* copies custom extradata to cache data */ void (*interpolate_extra_data)(void *calldata, struct PTCacheMem *pm, float cfra, float cfra1, float cfra2); + /* copies custom second extradata to cache data */ + int (*write_second_extra_data)(void *calldata, struct PTCacheMem *pm, int cfra); + /* copies custom second extradata to cache data */ + void (*read_second_extra_data)(void *calldata, struct PTCacheMem *pm, float cfra); + /* total number of simulated points (the cfra parameter is just for using same function pointer with totwrite) */ int (*totpoint)(void *calldata, int cfra); /* number of points written for current cache frame */ @@ -254,6 +263,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys); void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd); void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd); +void BKE_ptcache_id_from_particlesurface(PTCacheID *pid, struct Object *ob, struct ParticleSurfaceModifierData *psd); void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis); Index: source/blender/blenkernel/intern/modifier.c =================================================================== --- source/blender/blenkernel/intern/modifier.c (revision 41360) +++ source/blender/blenkernel/intern/modifier.c (working copy) @@ -294,7 +294,13 @@ return cageIndex; } +int modifiers_isParticleSurfaceEnabled(Object *ob) +{ + ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSurface); + return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); +} + int modifiers_isSoftbodyEnabled(Object *ob) { ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody); Index: source/blender/blenkernel/intern/particle_system.c =================================================================== --- source/blender/blenkernel/intern/particle_system.c (revision 41360) +++ source/blender/blenkernel/intern/particle_system.c (working copy) @@ -20,7 +20,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): Raul Fernandez Hernandez (Farsthary), Stephen Swhitehorn. + * Contributor(s): Raul Fernandez Hernandez (Farsthary), Stephen Whitehorn. * * Adaptive time step * Copyright 2011 AutoCRC Index: source/blender/blenkernel/intern/pointcache.c =================================================================== --- source/blender/blenkernel/intern/pointcache.c (revision 41360) +++ source/blender/blenkernel/intern/pointcache.c (working copy) @@ -44,6 +44,7 @@ #include "DNA_particle_types.h" #include "DNA_scene_types.h" #include "DNA_smoke_types.h" +#include "DNA_particlesurface_types.h" #include "BLI_blenlib.h" #include "BLI_threads.h" @@ -114,8 +115,14 @@ static int ptcache_extra_datasize[] = { 0, - sizeof(ParticleSpring) + sizeof(ParticleSpring), + sizeof(Vertlist) }; + +static int ptcache_second_extra_datasize[] = { + 0, + sizeof(Newmeshfacelist) +}; /* forward declerations */ static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len); @@ -210,6 +217,126 @@ SoftBody *soft= soft_v; return soft->totpoint; } + +/* Particle Surface functions */ + +static int ptcache_particlesurface_totpoint(void *surface_v, int cfra) +{ + ParticleSurfaceModifierData *psmd = surface_v; + + if(!psmd->surfaceObject) + return 0; + + if(cfra == 0) + return psmd->surfaceObject->totalpts; + + + return psmd->surfaceObject->totalpts; + +} + + +static int ptcache_particlesurface_write(int index, void *surface_v, void **data, int UNUSED(cfra)) +{ + + return 1; +} + +static void ptcache_particlesurface_read(int index, void *surface_v, void **data, float cfra, float *old_data) +{ + /* DO Nothing */ +} + +static int ptcache_particlesurface_extra_write(void *surface_v, PTCacheMem *pm, int UNUSED(cfra)) +{ + ParticleSurfaceModifierData *psmd= surface_v; + Surface *surface = psmd->surfaceObject; + + PTCacheExtra *extra = NULL; + + if(surface->totalpts && surface->verts) { + + extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: surface extra data"); + + extra->type = BPHYS_EXTRA_VERTICES; + extra->totdata = surface->totalpts; + + extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Point cache: extra data"); + memcpy(extra->data, surface->verts, extra->totdata * ptcache_extra_datasize[extra->type]); + + BLI_addtail(&pm->extradata, extra); + return 1; + } + return 0; +} +static void ptcache_particlesurface_extra_read(void *surface_v, PTCacheMem *pm, float UNUSED(cfra)) +{ + ParticleSurfaceModifierData *psmd= surface_v; + Surface *surface = psmd->surfaceObject; + PTCacheExtra *extra; + + + for(extra = pm->extradata.first; extra; extra=extra->next) { + switch(extra->type) { + case BPHYS_EXTRA_VERTICES: + { + if(surface->verts) + MEM_freeN(surface->verts); + //surface->total = 0; + + surface->verts = MEM_dupallocN(extra->data); + surface->totalpts = extra->totdata; + break; + } + } + } +} + +static int ptcache_particlesurface_second_extra_write(void *surface_v, PTCacheMem *pm, int UNUSED(cfra)) +{ + ParticleSurfaceModifierData *psmd= surface_v; + Surface *surface = psmd->surfaceObject; + + PTCacheSecondExtra *extra = NULL; + + if(surface->totalfaces && surface->faces) { + + extra = MEM_callocN(sizeof(PTCacheSecondExtra), "Point cache: surface extra data"); + + extra->type = BPHYS_SECOND_EXTRA_FACES; + extra->totdata = surface->totalfaces; + + extra->data = MEM_callocN(extra->totdata * ptcache_second_extra_datasize[extra->type], "Point cache: extra data"); + memcpy(extra->data, surface->faces, extra->totdata * ptcache_second_extra_datasize[extra->type]); + + BLI_addtail(&pm->secondextradata, extra); + return 1; + } + return 0; +} +static void ptcache_particlesurface_second_extra_read(void *surface_v, PTCacheMem *pm, float UNUSED(cfra)) +{ + ParticleSurfaceModifierData *psmd= surface_v; + Surface *surface = psmd->surfaceObject; + PTCacheSecondExtra *extra; + + + for(extra = pm->secondextradata.first; extra; extra=extra->next) { + switch(extra->type) { + case BPHYS_SECOND_EXTRA_FACES: + { + if(surface->faces) + MEM_freeN(surface->faces); + //surface->total = 0; + + surface->faces = MEM_dupallocN(extra->data); + surface->totalfaces= extra->totdata; + break; + } + } + } +} + /* Particle functions */ void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time) { @@ -401,7 +528,7 @@ return totwrite; } -static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra)) +static int ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra)) { ParticleSystem *psys = psys_v; PTCacheExtra *extra = NULL; @@ -419,7 +546,9 @@ memcpy(extra->data, psys->fluid_springs, extra->totdata * ptcache_extra_datasize[extra->type]); BLI_addtail(&pm->extradata, extra); + return 1; } + return 0; } static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra)) @@ -681,6 +810,9 @@ pid->read_extra_data = NULL; pid->interpolate_extra_data = NULL; + pid->write_second_extra_data = NULL; + pid->read_second_extra_data = NULL; + pid->write_header = ptcache_basic_header_write; pid->read_header = ptcache_basic_header_read; @@ -718,6 +850,10 @@ pid->read_extra_data = NULL; pid->interpolate_extra_data = NULL; + pid->write_second_extra_data = NULL; + pid->read_second_extra_data = NULL; + + pid->write_header = ptcache_basic_header_write; pid->read_header = ptcache_basic_header_read; @@ -763,6 +899,10 @@ pid->read_extra_data = NULL; pid->interpolate_extra_data = NULL; + pid->write_second_extra_data = NULL; + pid->read_second_extra_data = NULL; + + pid->write_header = ptcache_basic_header_write; pid->read_header = ptcache_basic_header_read; @@ -798,6 +938,10 @@ pid->read_extra_data = NULL; pid->interpolate_extra_data = NULL; + pid->write_second_extra_data = NULL; + pid->read_second_extra_data = NULL; + + pid->write_header = ptcache_basic_header_write; pid->read_header = ptcache_basic_header_read; @@ -809,6 +953,44 @@ if(sds->wt) pid->data_types |= (1<ob= ob; + pid->calldata= psmd; + pid->type= PTCACHE_TYPE_PARTICLESURFACE; + pid->stack_index= psmd->point_cache->index; + pid->cache= psmd->point_cache; + pid->cache_ptr= &psmd->point_cache; + pid->ptcaches= &psmd->ptcaches; + pid->totpoint= pid->totwrite= ptcache_particlesurface_totpoint; + + pid->write_point = ptcache_particlesurface_write; + pid->read_point = ptcache_particlesurface_read; + pid->interpolate_point = NULL; + + pid->write_stream = NULL; + pid->read_stream = NULL; + + pid->write_extra_data = ptcache_particlesurface_extra_write; + pid->read_extra_data = ptcache_particlesurface_extra_read; + pid->interpolate_extra_data = NULL; + + pid->write_second_extra_data = ptcache_particlesurface_second_extra_write; + pid->read_second_extra_data = ptcache_particlesurface_second_extra_read; + + + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; + + pid->data_types= (1<info_types= 0; +} + + + void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis) { PTCacheID *pid; @@ -849,6 +1031,14 @@ BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md); BLI_addtail(lb, pid); } + if(md->type == eModifierType_ParticleSurface) { + ParticleSurfaceModifierData *psmd = (ParticleSurfaceModifierData *)md; + + pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_particlesurface(pid, ob, psmd); + BLI_addtail(lb, pid); + + } if(md->type == eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData *)md; if(smd->type & MOD_SMOKE_TYPE_DOMAIN) @@ -1332,6 +1522,21 @@ BLI_freelistN(&pm->extradata); } } + +static void ptcache_second_extra_free(PTCacheMem *pm) +{ + PTCacheSecondExtra *secondextra = pm->secondextradata.first; + + if(secondextra) { + for(; secondextra; secondextra=secondextra->next) { + if(secondextra->data) + MEM_freeN(secondextra->data); + } + + BLI_freelistN(&pm->secondextradata); + } +} + static int ptcache_old_elemsize(PTCacheID *pid) { if(pid->type==PTCACHE_TYPE_SOFTBODY) @@ -1463,10 +1668,31 @@ BLI_addtail(&pm->extradata, extra); } } + if(!error && pf->flag & PTCACHE_TYPEFLAG_SECONDEXTRADATA) { + unsigned int secondextratype = 0; + while(ptcache_file_read(pf, &secondextratype, 1, sizeof(unsigned int))) { + PTCacheSecondExtra *secondextra = MEM_callocN(sizeof(PTCacheSecondExtra), "Pointcache secondextradata"); + + secondextra->type = secondextratype; + + ptcache_file_read(pf, &secondextra->totdata, 1, sizeof(unsigned int)); + + secondextra->data = MEM_callocN(secondextra->totdata * ptcache_second_extra_datasize[secondextra->type], "Pointcache extradata->data"); + + if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) + ptcache_file_compressed_read(pf, (unsigned char*)(secondextra->data), secondextra->totdata*ptcache_second_extra_datasize[secondextra->type]); + else + ptcache_file_read(pf, secondextra->data, secondextra->totdata, ptcache_second_extra_datasize[secondextra->type]); + + BLI_addtail(&pm->secondextradata, secondextra); + } + } + if(error && pm) { ptcache_data_free(pm); ptcache_extra_free(pm); + ptcache_second_extra_free(pm); MEM_freeN(pm); pm = NULL; } @@ -1501,6 +1727,9 @@ if(pm->extradata.first) pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA; + if(pm->secondextradata.first) + pf->flag |= PTCACHE_TYPEFLAG_SECONDEXTRADATA; + if(pid->cache->compression) pf->flag |= PTCACHE_TYPEFLAG_COMPRESS; @@ -1554,7 +1783,27 @@ } } } + if(!error && pm->secondextradata.first) { + PTCacheSecondExtra *secondextra = pm->secondextradata.first; + for(; secondextra; secondextra=secondextra->next) { + if(secondextra->data == NULL || secondextra->totdata == 0) + continue; + + ptcache_file_write(pf, &secondextra->type, 1, sizeof(unsigned int)); + ptcache_file_write(pf, &secondextra->totdata, 1, sizeof(unsigned int)); + + if(pid->cache->compression) { + unsigned int in_len = secondextra->totdata * ptcache_second_extra_datasize[secondextra->type]; + unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); + ptcache_file_compressed_write(pf, (unsigned char*)(secondextra->data), in_len, out, pid->cache->compression); + MEM_freeN(out); + } + else { + ptcache_file_write(pf, secondextra->data, secondextra->totdata, ptcache_second_extra_datasize[secondextra->type]); + } + } + } ptcache_file_close(pf); if (error && G.f & G_DEBUG) @@ -1635,10 +1884,14 @@ if(pid->read_extra_data && pm->extradata.first) pid->read_extra_data(pid->calldata, pm, (float)pm->frame); + if(pid->read_second_extra_data && pm->secondextradata.first) + pid->read_second_extra_data(pid->calldata, pm, (float)pm->frame); + /* clean up temporary memory cache */ if(pid->cache->flag & PTCACHE_DISK_CACHE) { ptcache_data_free(pm); ptcache_extra_free(pm); + ptcache_second_extra_free(pm); MEM_freeN(pm); } } @@ -1686,6 +1939,7 @@ if(pid->cache->flag & PTCACHE_DISK_CACHE) { ptcache_data_free(pm); ptcache_extra_free(pm); + ptcache_second_extra_free(pm); MEM_freeN(pm); } } @@ -1843,6 +2097,9 @@ if(pid->write_extra_data) pid->write_extra_data(pid->calldata, pm, cfra); + if(pid->write_second_extra_data){ + pid->write_second_extra_data(pid->calldata, pm, cfra); + } pm->frame = cfra; if(cache->flag & PTCACHE_DISK_CACHE) { @@ -1852,6 +2109,7 @@ { ptcache_data_free(pm); ptcache_extra_free(pm); + ptcache_second_extra_free(pm); MEM_freeN(pm); } @@ -1859,6 +2117,7 @@ error += !ptcache_mem_frame_to_disk(pid, pm2); ptcache_data_free(pm2); ptcache_extra_free(pm2); + ptcache_second_extra_free(pm2); MEM_freeN(pm2); } } @@ -1921,38 +2180,39 @@ int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra) { PointCache *cache = pid->cache; - int totpoint = pid->totpoint(pid->calldata, cfra); - int overwrite = 0, error = 0; - - if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0)) - return 0; - - if(ptcache_write_needed(pid, cfra, &overwrite)==0) - return 0; - - if(pid->write_stream) { - ptcache_write_stream(pid, cfra, totpoint); - } - else if(pid->write_point) { - error += ptcache_write(pid, cfra, overwrite); - } - - /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */ - if(cfra - cache->last_exact == 1 || cfra == cache->startframe) { - cache->last_exact = cfra; - cache->flag &= ~PTCACHE_FRAMES_SKIPPED; - } - /* Don't mark skipped when writing info file (frame 0) */ - else if(cfra) - cache->flag |= PTCACHE_FRAMES_SKIPPED; - - /* Update timeline cache display */ - if(cfra && cache->cached_frames) - cache->cached_frames[cfra-cache->startframe] = 1; - - BKE_ptcache_update_info(pid); - - return !error; + int totpoint = pid->totpoint(pid->calldata, cfra); + int overwrite = 0, error = 0; + + /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */ + if(cfra - cache->last_exact == 1 || cfra == cache->startframe) { + cache->last_exact = cfra; + cache->flag &= ~PTCACHE_FRAMES_SKIPPED; + } + /* Don't mark skipped when writing info file (frame 0) */ + else if(cfra) + cache->flag |= PTCACHE_FRAMES_SKIPPED; + + if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0)) + return 0; + + if(ptcache_write_needed(pid, cfra, &overwrite)==0) + return 0; + + if(pid->write_stream) { + ptcache_write_stream(pid, cfra, totpoint); + } + else if(pid->write_point) { + error += ptcache_write(pid, cfra, overwrite); + } + + + /* Update timeline cache display */ + if(cfra && cache->cached_frames) + cache->cached_frames[cfra-cache->startframe] = 1; + + BKE_ptcache_update_info(pid); + + return !error; } /* youll need to close yourself after! * mode - PTCACHE_CLEAR_ALL, @@ -2046,6 +2306,7 @@ for(; pm; pm=pm->next) { ptcache_data_free(pm); ptcache_extra_free(pm); + ptcache_second_extra_free(pm); } BLI_freelistN(&pid->cache->mem_cache); @@ -2060,6 +2321,7 @@ pid->cache->cached_frames[pm->frame-sta] = 0; ptcache_data_free(pm); ptcache_extra_free(pm); + ptcache_second_extra_free(pm); pm = pm->next; BLI_freelinkN(&pid->cache->mem_cache, link); } @@ -2084,6 +2346,7 @@ if(pm->frame == cfra) { ptcache_data_free(pm); ptcache_extra_free(pm); + ptcache_second_extra_free(pm); BLI_freelinkN(&pid->cache->mem_cache, pm); break; } @@ -2234,6 +2497,30 @@ } } } +void particlesurfaceModifier_reset(ParticleSurfaceModifierData *psmd ){ + Surface *sur = NULL; + sur = psmd->surfaceObject; + if ( sur ){ + /* Free the verts */ + if ( sur->verts != NULL ){ + MEM_freeN ( sur->verts ); + sur->verts = NULL; + } + + + /* Free the faces. */ + if ( sur->faces != NULL ){ + MEM_freeN ( sur->faces ); + sur->faces =NULL; + } + + + MEM_freeN ( sur ); + psmd->surfaceObject = NULL; + } +} + + int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) { PointCache *cache; @@ -2288,6 +2575,8 @@ smokeModifier_reset(pid->calldata); else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) smokeModifier_reset_turbulence(pid->calldata); + else if(pid->type == PTCACHE_TYPE_PARTICLESURFACE) + particlesurfaceModifier_reset(pid->calldata); } if(clear) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); @@ -2336,6 +2625,10 @@ BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md); reset |= BKE_ptcache_id_reset(scene, &pid, mode); } + if(md->type == eModifierType_ParticleSurface) { + BKE_ptcache_id_from_particlesurface(&pid, ob, (ParticleSurfaceModifierData*)md); + reset |= BKE_ptcache_id_reset(scene, &pid, mode); + } if(md->type == eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData *)md; if(smd->type & MOD_SMOKE_TYPE_DOMAIN) @@ -2441,6 +2734,7 @@ for(; pm; pm=pm->next) { ptcache_data_free(pm); ptcache_extra_free(pm); + ptcache_second_extra_free(pm); } BLI_freelistN(mem_cache); @@ -3036,6 +3330,7 @@ { PointCache *cache = pid->cache; PTCacheExtra *extra = NULL; + PTCacheSecondExtra *secondextra = NULL; int totframes = 0; char mem_info[64]; @@ -3092,6 +3387,10 @@ bytes += sizeof(PTCacheExtra); } + for(secondextra=pm->secondextradata.first; secondextra; secondextra=secondextra->next) { + bytes += MEM_allocN_len(secondextra->data); + bytes += sizeof(PTCacheSecondExtra); + } bytes += sizeof(PTCacheMem); totframes++; Index: source/blender/blenloader/intern/readfile.c =================================================================== --- source/blender/blenloader/intern/readfile.c (revision 41360) +++ source/blender/blenloader/intern/readfile.c (working copy) @@ -88,6 +88,7 @@ #include "DNA_space_types.h" #include "DNA_vfont_types.h" #include "DNA_world_types.h" +#include "DNA_particlesurface_types.h" #include "MEM_guardedalloc.h" @@ -3099,6 +3100,7 @@ if((cache->flag & PTCACHE_DISK_CACHE)==0) { PTCacheMem *pm; PTCacheExtra *extra; + PTCacheSecondExtra *secondextra; int i; link_list(fd, &cache->mem_cache); @@ -3123,6 +3125,11 @@ for(extra=pm->extradata.first; extra; extra=extra->next) extra->data = newdataadr(fd, extra->data); + + link_list(fd, &pm->secondextradata); + + for(secondextra=pm->secondextradata.first; secondextra; secondextra=secondextra->next) + secondextra->data = newdataadr(fd, secondextra->data); } } else @@ -4009,6 +4016,13 @@ amd->prevCos= NULL; } + else if (md->type==eModifierType_ParticleSurface) { + ParticleSurfaceModifierData *psmd = (ParticleSurfaceModifierData*) md; + + psmd->sim_parms= newdataadr(fd, psmd->sim_parms); + psmd->coll_parms= newdataadr(fd, psmd->coll_parms); + direct_link_pointcache_list(fd, &psmd->ptcaches, &psmd->point_cache, 0); + } else if (md->type==eModifierType_Cloth) { ClothModifierData *clmd = (ClothModifierData*) md; @@ -9311,6 +9325,13 @@ clmd->point_cache= BKE_ptcache_add(&clmd->ptcaches); } } + for(md=ob->modifiers.first; md; md=md->next) { + if(md->type==eModifierType_ParticleSurface) { + ParticleSurfaceModifierData *psmd = (ParticleSurfaceModifierData*) md; + if(!psmd->point_cache) + psmd->point_cache= BKE_ptcache_add(&psmd->ptcaches); + } + } } /* Copy over old per-level multires vertex data @@ -11386,7 +11407,7 @@ /* enable all cache display */ stime->cache_display |= TIME_CACHE_DISPLAY; stime->cache_display |= (TIME_CACHE_SOFTBODY|TIME_CACHE_PARTICLES); - stime->cache_display |= (TIME_CACHE_CLOTH|TIME_CACHE_SMOKE); + stime->cache_display |= (TIME_CACHE_CLOTH|TIME_CACHE_SMOKE|TIME_CACHE_PARTICLESURFACE); } } } Index: source/blender/blenloader/intern/writefile.c =================================================================== --- source/blender/blenloader/intern/writefile.c (revision 41360) +++ source/blender/blenloader/intern/writefile.c (working copy) @@ -128,6 +128,7 @@ #include "DNA_vfont_types.h" #include "DNA_world_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_particlesurface_types.h" #include "MEM_guardedalloc.h" // MEM_freeN #include "BLI_blenlib.h" @@ -851,7 +852,15 @@ static const char *ptcache_extra_struct[] = { "", "ParticleSpring" + "Vertlist" // BPHYS_EXTRA_VERTICES + }; +static const char *ptcache_second_extra_struct[] = { + "", + "Newmeshfacelist" // BPHYS_SECOND_EXTRA_FACES + +}; + static void write_pointcaches(WriteData *wd, ListBase *ptcaches) { PointCache *cache = ptcaches->first; @@ -865,6 +874,7 @@ for(; pm; pm=pm->next) { PTCacheExtra *extra = pm->extradata.first; + PTCacheSecondExtra *secondextra = pm->secondextradata.first; writestruct(wd, DATA, "PTCacheMem", 1, pm); @@ -883,6 +893,13 @@ writestruct(wd, DATA, "PTCacheExtra", 1, extra); writestruct(wd, DATA, ptcache_extra_struct[extra->type], extra->totdata, extra->data); } + for(; secondextra; secondextra=secondextra->next) { + if(strcmp(ptcache_second_extra_struct[secondextra->type], "")==0) + continue; + writestruct(wd, DATA, "PTCacheSecondExtra", 1, secondextra); + writestruct(wd, DATA, ptcache_second_extra_struct[secondextra->type], secondextra->totdata, secondextra->data); + } + } } } @@ -1287,6 +1304,13 @@ writestruct(wd, DATA, "EffectorWeights", 1, clmd->sim_parms->effector_weights); write_pointcaches(wd, &clmd->ptcaches); } + else if(md->type==eModifierType_ParticleSurface) { + ParticleSurfaceModifierData *psmd = (ParticleSurfaceModifierData*) md; + + writestruct(wd, DATA, "ParticleSurfaceSimSettings", 1, psmd->sim_parms); + writestruct(wd, DATA, "ParticleSurfaceCollSettings", 1, psmd->coll_parms); + write_pointcaches(wd, &psmd->ptcaches); + } else if(md->type==eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData*) md; Index: source/blender/CMakeLists.txt =================================================================== --- source/blender/CMakeLists.txt (revision 41360) +++ source/blender/CMakeLists.txt (working copy) @@ -63,6 +63,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_outliner_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_packedFile_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_particle_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_particlesurface_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_property_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_screen_types.h Index: source/blender/editors/space_buttons/buttons_context.c =================================================================== --- source/blender/editors/space_buttons/buttons_context.c (revision 41360) +++ source/blender/editors/space_buttons/buttons_context.c (working copy) @@ -650,7 +650,7 @@ "world", "object", "mesh", "armature", "lattice", "curve", "meta_ball", "lamp", "speaker", "camera", "material", "material_slot", "texture", "texture_slot", "bone", "edit_bone", "pose_bone", "particle_system", "particle_system_editable", - "cloth", "soft_body", "fluid", "smoke", "collision", "brush", NULL}; + "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "ps_collision", NULL}; int buttons_context(const bContext *C, const char *member, bContextDataResult *result) { @@ -825,6 +825,16 @@ return 1; } } + else if(CTX_data_equals(member, "ps_collision")) { + PointerRNA *ptr= get_pointer_type(path, &RNA_Object); + + if(ptr && ptr->data) { + Object *ob= ptr->data; + ModifierData *md= modifiers_findByType(ob, eModifierType_ParticleSurface); + CTX_data_pointer_set(result, &ob->id, &RNA_ParticleSurfaceModifier, md); + return 1; + } + } else if(CTX_data_equals(member, "soft_body")) { PointerRNA *ptr= get_pointer_type(path, &RNA_Object); Index: source/blender/editors/space_outliner/outliner_draw.c =================================================================== --- source/blender/editors/space_outliner/outliner_draw.c (revision 41360) +++ source/blender/editors/space_outliner/outliner_draw.c (working copy) @@ -1012,6 +1012,8 @@ UI_icon_draw(x, y, ICON_MOD_SOLIDIFY); break; case eModifierType_Screw: UI_icon_draw(x, y, ICON_MOD_SCREW); break; + case eModifierType_ParticleSurface: + UI_icon_draw(x, y, ICON_MOD_PHYSICS); break; case eModifierType_WeightVGEdit: case eModifierType_WeightVGMix: case eModifierType_WeightVGProximity: Index: source/blender/editors/space_time/space_time.c =================================================================== --- source/blender/editors/space_time/space_time.c (revision 41360) +++ source/blender/editors/space_time/space_time.c (working copy) @@ -125,6 +125,9 @@ case PTCACHE_TYPE_SMOKE_HIGHRES: if (!(stime->cache_display & TIME_CACHE_SMOKE)) continue; break; + case PTCACHE_TYPE_PARTICLESURFACE: + if (!(stime->cache_display & TIME_CACHE_PARTICLESURFACE)) continue; + break; } if(pid->cache->cached_frames == NULL) @@ -187,6 +190,10 @@ col[0] = 0.2; col[1] = 0.2; col[2] = 0.2; col[3] = 0.1; break; + case PTCACHE_TYPE_PARTICLESURFACE: + col[0] = 1.0; col[1] = 0.1; col[2] = 0.02; + col[3] = 0.1; + break; } glColor4fv(col); @@ -634,7 +641,7 @@ /* enable all cache display */ stime->cache_display |= TIME_CACHE_DISPLAY; stime->cache_display |= (TIME_CACHE_SOFTBODY|TIME_CACHE_PARTICLES); - stime->cache_display |= (TIME_CACHE_CLOTH|TIME_CACHE_SMOKE); + stime->cache_display |= (TIME_CACHE_CLOTH|TIME_CACHE_SMOKE|TIME_CACHE_PARTICLESURFACE); } static SpaceLink *time_duplicate(SpaceLink *sl) Index: source/blender/makesdna/DNA_modifier_types.h =================================================================== --- source/blender/makesdna/DNA_modifier_types.h (revision 41360) +++ source/blender/makesdna/DNA_modifier_types.h (working copy) @@ -28,6 +28,7 @@ #include "DNA_listBase.h" + #define MODSTACK_DEBUG 1 /* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE! */ @@ -74,6 +75,7 @@ eModifierType_WeightVGProximity, eModifierType_EmptySlot, /* keep so DynamicPaint keep loading, can re-use later */ eModifierType_DynamicPaint, /* reserve slot */ + eModifierType_ParticleSurface, NUM_MODIFIER_TYPES } ModifierType; @@ -956,4 +958,102 @@ #define MOD_WVG_MASK_TEX_USE_VAL 7 #define MOD_WVG_MASK_TEX_USE_ALPHA 8 + +/*particle surface modifier */ +#define MOD_SMOOTH_SURFACE (1<<0) +#define MOD_MOTION_PLOTTING_SURFACE (1<<1) + +typedef struct HashBucket +{ + struct LinkNode *listpoints; + +} HashBucket; + +typedef struct SpatialHash +{ + float isolevel; + + float cell_size; /* spatial resolution , UI defined */ + float inv_cell_size; + float radius; + + int cell_resol; //cell subdivision + int totalbuckets; + + + HashBucket *buckets; + struct LinkNode *linked_cubelist; + +}SpatialHash; + +typedef struct HashNearest { + int index; + float dist; + float co[3]; +} HashNearest; + + + +typedef struct XYZ{ + float x,y,z; +}XYZ; + +typedef struct TRIANGLE{ + XYZ p[3]; +} TRIANGLE; +typedef struct GRIDCELL{ + XYZ p[8]; + double val[8]; +} GRIDCELL; + +typedef struct Newmeshfacelist{ + unsigned int index; + int flag; +} Newmeshfacelist; + + +typedef struct Vertlist{ + float coord[3]; +} Vertlist; + +typedef struct Surface{ + struct Newmeshfacelist *faces; + struct Vertlist *verts; + + int totalpts, totalfaces; +} Surface; + +typedef struct ParticleSurfaceModifierData { + ModifierData modifier; + + struct ParticleSurfaceSimSettings *sim_parms; /* definition is in DNA_particlesurface_types.h */ + struct ParticleSurfaceCollSettings *coll_parms; /* definition is in DNA_particlesurface_types.h */ + struct ParticleSystem *psys; + struct Surface *surfaceObject; /* The internal data structure for particle surface. */ + + struct Object *ob; + struct Object *target; /* boundary target */ + struct Scene *scene; /* the context, time etc is here */ + struct KDTree *surface_tree; + + struct PointCache *point_cache; /* definition is in DNA_object_force.h */ + struct ListBase ptcaches; + + int padder; + float pad; +} ParticleSurfaceModifierData; + + + +/* ParticleSurfaceModifierData->isosurface_extraction */ +enum { + ISOSURFACE_EXTRACTION_A, + ISOSURFACE_EXTRACTION_B, + ISOSURFACE_EXTRACTION_C, + + +}; + + + #endif Index: source/blender/makesdna/DNA_object_force.h =================================================================== --- source/blender/makesdna/DNA_object_force.h (revision 41360) +++ source/blender/makesdna/DNA_object_force.h (working copy) @@ -145,13 +145,22 @@ #define BPHYS_TOT_DATA 8 #define BPHYS_EXTRA_FLUID_SPRINGS 1 - +#define BPHYS_EXTRA_VERTICES 2 /* used for particle surface- polygonizer */ + +#define BPHYS_SECOND_EXTRA_FACES 1 /* used for particle surface- polygonizer a second extra was added, for situations where 1 extra isnt enough */ + typedef struct PTCacheExtra { struct PTCacheExtra *next, *prev; unsigned int type, totdata; void *data; } PTCacheExtra; +typedef struct PTCacheSecondExtra { + struct PTCacheSecondExtra *next, *prev; + unsigned int type, totdata; + void *data; +} PTCacheSecondExtra; + typedef struct PTCacheMem { struct PTCacheMem *next, *prev; unsigned int frame, totpoint; @@ -161,6 +170,7 @@ void *cur[8]; /* BPHYS_TOT_DATA */ struct ListBase extradata; + struct ListBase secondextradata; } PTCacheMem; typedef struct PointCache { @@ -406,6 +416,9 @@ #define PTCACHE_COMPRESS_LZO 1 #define PTCACHE_COMPRESS_LZMA 2 +/* ob->sd->collflag*/ +#define OB_PS_ENABLE 1 + /* ob->softflag */ #define OB_SB_ENABLE 1 /* deprecated, use modifier */ #define OB_SB_GOAL 2 Index: source/blender/makesdna/DNA_object_types.h =================================================================== --- source/blender/makesdna/DNA_object_types.h (revision 41360) +++ source/blender/makesdna/DNA_object_types.h (working copy) @@ -265,7 +265,9 @@ ListBase *duplilist; /* for temporary dupli list storage, only for use by RNA API */ float ima_ofs[2]; /* offset for image empties */ - char pad3[8]; + short partsurfaceflag; /* particle surface flag settings*/ + char pad3[10]; + int paddder; } Object; /* Warning, this is not used anymore because hooks are now modifiers */ Index: source/blender/makesdna/DNA_particlesurface_types.h =================================================================== --- source/blender/makesdna/DNA_particlesurface_types.h (revision 0) +++ source/blender/makesdna/DNA_particlesurface_types.h (revision 0) @@ -0,0 +1,73 @@ +/* +* $Id: DNA_particlesurface_types.h 36419 2011-05-01 21:39:13Z joeedh $ +* +* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* The Original Code is Copyright (C) 2006 by NaN Holding BV. +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): Stephen whitehorn +* +* ***** END GPL LICENSE BLOCK ***** +*/ +#ifndef DNA_PARTICLESURFACE_TYPES_H +#define DNA_PARTICLESURFACE_TYPES_H + +/** \file DNA_particlesurface_types.h + * \ingroup DNA + */ + +/* SurfaceDeflect->collisiontype */ +enum { + ADDITION, + SUBTRACTION, + NONE, +}; +/* PARTICLE SURFACE FLAGS */ +#define OB_PS_ENABLE 1 + + + +typedef struct ParticleSurfaceSimSettings +{ + float render_resolution, display_resolution; + float isovalue; + float fluidthickness, fluidstiffness, fluidradius; + float radius; + float thickness; + + int isosurface_extraction; + + float timescale, padding; + /* Motion Plotting */ + float size, stretch; + + int spread; + + short flag, motion_plotting_flag; + int pad; +} ParticleSurfaceSimSettings; + +typedef struct ParticleSurfaceCollSettings +{ + int collisiontype; +} ParticleSurfaceCollSettings; + + +#endif Index: source/blender/makesdna/DNA_space_types.h =================================================================== --- source/blender/makesdna/DNA_space_types.h (revision 41360) +++ source/blender/makesdna/DNA_space_types.h (working copy) @@ -903,6 +903,7 @@ #define TIME_CACHE_PARTICLES 4 #define TIME_CACHE_CLOTH 8 #define TIME_CACHE_SMOKE 16 +#define TIME_CACHE_PARTICLESURFACE 32 /* sseq->mainb */ #define SEQ_DRAW_SEQUENCE 0 Index: source/blender/makesdna/intern/makesdna.c =================================================================== --- source/blender/makesdna/intern/makesdna.c (revision 41360) +++ source/blender/makesdna/intern/makesdna.c (working copy) @@ -131,7 +131,9 @@ "DNA_boid_types.h", "DNA_smoke_types.h", "DNA_speaker_types.h", + "DNA_particlesurface_types.h", + // empty string to indicate end of includefiles "" }; @@ -1196,4 +1198,5 @@ #include "DNA_boid_types.h" #include "DNA_smoke_types.h" #include "DNA_speaker_types.h" +#include "DNA_particlesurface_types.h" /* end of list */ Index: source/blender/makesrna/intern/CMakeLists.txt =================================================================== --- source/blender/makesrna/intern/CMakeLists.txt (revision 41360) +++ source/blender/makesrna/intern/CMakeLists.txt (working copy) @@ -65,6 +65,7 @@ rna_object_force.c rna_packedfile.c rna_particle.c + rna_particlesurface.c rna_pose.c rna_property.c rna_render.c Index: source/blender/makesrna/intern/makesrna.c =================================================================== --- source/blender/makesrna/intern/makesrna.c (revision 41360) +++ source/blender/makesrna/intern/makesrna.c (working copy) @@ -2456,6 +2456,7 @@ {"rna_object_force.c", NULL, RNA_def_object_force}, {"rna_packedfile.c", NULL, RNA_def_packedfile}, {"rna_particle.c", NULL, RNA_def_particle}, + {"rna_particlesurface.c", NULL, RNA_def_particlesurface}, {"rna_pose.c", "rna_pose_api.c", RNA_def_pose}, {"rna_property.c", NULL, RNA_def_gameproperty}, {"rna_render.c", NULL, RNA_def_render}, Index: source/blender/makesrna/intern/rna_internal.h =================================================================== --- source/blender/makesrna/intern/rna_internal.h (revision 41360) +++ source/blender/makesrna/intern/rna_internal.h (working copy) @@ -156,6 +156,7 @@ void RNA_def_object_force(struct BlenderRNA *brna); void RNA_def_packedfile(struct BlenderRNA *brna); void RNA_def_particle(struct BlenderRNA *brna); +void RNA_def_particlesurface(struct BlenderRNA *brna); void RNA_def_pose(struct BlenderRNA *brna); void RNA_def_render(struct BlenderRNA *brna); void RNA_def_rna(struct BlenderRNA *brna); Index: source/blender/makesrna/intern/rna_modifier.c =================================================================== --- source/blender/makesrna/intern/rna_modifier.c (revision 41360) +++ source/blender/makesrna/intern/rna_modifier.c (working copy) @@ -39,6 +39,7 @@ #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_scene_types.h" +#include "DNA_particlesurface_types.h" #include "MEM_guardedalloc.h" @@ -94,6 +95,7 @@ {eModifierType_Smoke, "SMOKE", ICON_MOD_SMOKE, "Smoke", ""}, {eModifierType_Softbody, "SOFT_BODY", ICON_MOD_SOFT, "Soft Body", ""}, {eModifierType_Surface, "SURFACE", ICON_MOD_PHYSICS, "Surface", ""}, + {eModifierType_ParticleSurface, "PARTICLE_SURFACE", ICON_MOD_PHYSICS, "Particle Surface", ""}, {0, NULL, 0, NULL, NULL}}; #ifdef RNA_RUNTIME @@ -192,6 +194,8 @@ return &RNA_VertexWeightMixModifier; case eModifierType_WeightVGProximity: return &RNA_VertexWeightProximityModifier; + case eModifierType_ParticleSurface: + return &RNA_ParticleSurfaceModifier; default: return &RNA_Modifier; } @@ -1808,6 +1812,35 @@ RNA_def_property_ui_text(prop, "Particle System", "Particle System that this modifier controls"); } +static void rna_def_modifier_particlesurface(BlenderRNA *brna) +{ + + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "ParticleSurfaceModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Particle Surface Modifier", "Add a particle system"); + RNA_def_struct_sdna(srna, "ParticleSurfaceModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_PHYSICS); + + + prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "ParticleSurfaceSettings"); + RNA_def_property_pointer_sdna(prop, NULL, "sim_parms"); + RNA_def_property_ui_text(prop, "Surface Settings", ""); + + prop= RNA_def_property(srna, "collision_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "ParticleSurfaceCollisionSettings"); + RNA_def_property_pointer_sdna(prop, NULL, "coll_parms"); + RNA_def_property_ui_text(prop, "Particle Surface Collision Settings", ""); + + prop= RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_ui_text(prop, "Point Cache", ""); +} + static void rna_def_modifier_particleinstance(BlenderRNA *brna) { StructRNA *srna; @@ -2880,6 +2913,7 @@ rna_def_modifier_weightvgedit(brna); rna_def_modifier_weightvgmix(brna); rna_def_modifier_weightvgproximity(brna); + rna_def_modifier_particlesurface(brna); } #endif Index: source/blender/makesrna/intern/rna_object_force.c =================================================================== --- source/blender/makesrna/intern/rna_object_force.c (revision 41360) +++ source/blender/makesrna/intern/rna_object_force.c (working copy) @@ -308,7 +308,7 @@ for(pid=pidlist.first; pid; pid=pid->next) { if(pid->cache == cache) { - if(ELEM3(pid->type, PTCACHE_TYPE_CLOTH, PTCACHE_TYPE_SMOKE_DOMAIN, PTCACHE_TYPE_SMOKE_HIGHRES)) + if(ELEM4(pid->type, PTCACHE_TYPE_CLOTH, PTCACHE_TYPE_SMOKE_DOMAIN, PTCACHE_TYPE_SMOKE_HIGHRES, PTCACHE_TYPE_PARTICLESURFACE)) *max= 1; break; } Index: source/blender/makesrna/intern/rna_particlesurface.c =================================================================== --- source/blender/makesrna/intern/rna_particlesurface.c (revision 0) +++ source/blender/makesrna/intern/rna_particlesurface.c (revision 0) @@ -0,0 +1,322 @@ +/* + * $Id: rna_particlesurface.c 37031 2011-05-31 02:14:25Z campbellbarton $ + * + * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation (2008) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/makesrna/intern/rna_particlesurface.c + * \ingroup RNA + */ + + +#include +#include + +#include "RNA_define.h" + +#include "rna_internal.h" + + +#include "BKE_modifier.h" + + +#include "DNA_particlesurface_types.h" +#include "DNA_particle_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_modifier_types.h" + +#include "WM_api.h" +#include "WM_types.h" + + + + + + + + +#include "DNA_modifier_types.h" + + + + + + + + + + + + + +#ifdef RNA_RUNTIME + +#include "MEM_guardedalloc.h" + +#include "DNA_modifier_types.h" +#include "DNA_object_force.h" + +#include "BKE_context.h" +#include "BKE_modifier.h" + +#include "BKE_depsgraph.h" + + + +#include "ED_object.h" + +static void rna_particlesurface_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + Object *ob= (Object*)ptr->id.data; + + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_main_add_notifier(NC_OBJECT|ND_MODIFIER, ob); +} + +static char *rna_ParticleSurfaceSettings_path(PointerRNA *ptr) +{ + Object *ob= (Object*)ptr->id.data; + ModifierData *md= modifiers_findByType(ob, eModifierType_ParticleSurface); + + return md ? BLI_sprintfN("modifiers[\"%s\"].settings", md->name) : NULL; +} + +static char *rna_ParticleSurfaceCollisionSettings_path(PointerRNA *ptr) +{ + Object *ob= (Object*)ptr->id.data; + ModifierData *md= modifiers_findByType(ob, eModifierType_ParticleSurface); + + return md ? BLI_sprintfN("modifiers[\"%s\"].collision_settings", md->name) : NULL; +} + +static int rna_ParticleSurfaceCollisionSettings_use_collisions_get(PointerRNA *ptr) +{ + Object *data= (Object*)(ptr->id.data); + return (((data->partsurfaceflag) & OB_PS_ENABLE) != 0); +} + +static void rna_ParticleSurfaceCollisionSettings_use_collisions_set(PointerRNA *ptr, int value) +{ + Object *data= (Object*)(ptr->id.data); + if(value) data->partsurfaceflag |= OB_PS_ENABLE; + else data->partsurfaceflag &= ~OB_PS_ENABLE; +} + + +static int rna_ParticleSurfaceCollisionSettings_use_motion_plotting_get(PointerRNA *ptr) +{ + Object *data= (Object*)(ptr->id.data); + return (((data->partsurfaceflag) & OB_PS_ENABLE) != 0); +} + +static void rna_ParticleSurfaceCollisionSettings_use_motion_plotting_set(PointerRNA *ptr, int value) +{ + Object *data= (Object*)(ptr->id.data); + if(value) data->partsurfaceflag |= OB_PS_ENABLE; + else data->partsurfaceflag &= ~OB_PS_ENABLE; +} + + + + +#else + +static void rna_def_particlesurface_sim_settings(BlenderRNA *brna) +{ + + StructRNA* srna; + PropertyRNA* prop; + + static EnumPropertyItem prop_isosurface_extraction_items[] = { + {ISOSURFACE_EXTRACTION_A, "Function1", 0, "Function1", "Function 1: used to extract the scalar values of the grid from the isosurface"}, + {ISOSURFACE_EXTRACTION_B, "Function2", 0, "Function2", "Function 2: used to extract the scalar values of the grid from the isosurface"}, + {ISOSURFACE_EXTRACTION_C, "Function3", 0, "Function3", "Function 3: used to extract the scalar values of the grid from the isosurface"}, + {0, NULL, 0, NULL, NULL} + }; + + + srna = RNA_def_struct(brna, "ParticleSurfaceSettings", NULL); + RNA_def_struct_ui_text(srna, "Particle Surface Settings", "Particle Surface simulation settings for an object"); + RNA_def_struct_sdna(srna, "ParticleSurfaceSimSettings"); + RNA_def_struct_path_func(srna, "rna_ParticleSurfaceSettings_path"); + + prop= RNA_def_property(srna, "isosurface_extraction", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_isosurface_extraction_items); + RNA_def_property_ui_text(prop, "Isosurface Extraction", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + + prop= RNA_def_property(srna, "render_resolution", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "render_resolution"); + RNA_def_property_range(prop, 0.0f, 100.0f); + RNA_def_property_ui_text(prop, "Render Resolution", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "display_resolution", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "display_resolution"); + RNA_def_property_range(prop, 0.0f, 100.0f); + RNA_def_property_ui_text(prop, "Display Resolution", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "isovalue", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "isovalue"); + RNA_def_property_ui_range(prop, 0, 200, 0.1, 4); + RNA_def_property_ui_text(prop, "Isovalue", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "radius", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "radius"); + RNA_def_property_ui_range(prop, 0.0, 100.0, 0.01, 4); + RNA_def_property_ui_text(prop, "Radius", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "fluidthickness", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "fluidthickness"); + RNA_def_property_ui_range(prop, 0.0, 8.0, 0.01, 4); + RNA_def_property_ui_text(prop, "Fluid Thickness", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "fluidradius", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "fluidradius"); + RNA_def_property_ui_range(prop, 0.0, 8.0, 0.01, 4); + RNA_def_property_ui_text(prop, "Fluid Radius", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "fluidstiffness", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "fluidstiffness"); + RNA_def_property_ui_range(prop, 0.0, 8.0, 0.01, 4); + RNA_def_property_ui_text(prop, "Fluid Stiffness", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "thickness", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "thickness"); + RNA_def_property_ui_range(prop, 0.0, 8.0, 0.01, 4); + RNA_def_property_ui_text(prop, "Thickness", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "smooth", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SMOOTH_SURFACE); + RNA_def_property_ui_text(prop, "Smooth", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + + /* Motion Plotting */ + + prop= RNA_def_property(srna, "use_motion_plotting", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "motion_plotting_flag", MOD_MOTION_PLOTTING_SURFACE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Use Motion Plotting", "Use Motion Plotting"); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + + prop= RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "size"); + RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4); + RNA_def_property_ui_text(prop, "Size", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "stretch", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "stretch"); + RNA_def_property_ui_range(prop, 0.0, 100.0, 0.01, 4); + RNA_def_property_ui_text(prop, "Stretch", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "spread", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "spread"); + RNA_def_property_range(prop, 0, 20); + RNA_def_property_ui_text(prop, "Motion Plotting Spread", "Scales the motion"); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + +} + +static void rna_def_particlesurface_collision_settings(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + + static EnumPropertyItem prop_collisiontype_items[] = { + {ADDITION, "Addition", 0, "Addition", "Add function field of colliding particle system surface"}, + {SUBTRACTION, "Subtraction", 0, "Subtraction", "Subtract function field of colliding particle system surface"}, + {NONE, "NONE", 0, "None", "Set to none if you wish to use susrface surface interaction on other object"}, + {0, NULL, 0, NULL, NULL} + }; + + + srna = RNA_def_struct(brna, "ParticleSurfaceCollisionSettings", NULL); + RNA_def_struct_ui_text(srna, "Particle Surface Collision Settings", "Cloth simulation settings for self collision and collision with other objects"); + RNA_def_struct_sdna(srna, "ParticleSurfaceCollSettings"); + RNA_def_struct_path_func(srna, "rna_ParticleSurfaceCollisionSettings_path"); + + prop= RNA_def_property(srna, "use_ps_collision", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_ParticleSurfaceCollisionSettings_use_collisions_get", "rna_ParticleSurfaceCollisionSettings_use_collisions_set"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Use Collisions", "Use Collisions"); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + + + + /*****Surface Interaction***************************/ + + prop= RNA_def_property(srna, "collisiontype", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_collisiontype_items); + RNA_def_property_ui_text(prop, "Collision Type", ""); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + + /* Functions for further work */ + /* + prop= RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "deflect", 1); + RNA_def_property_ui_text(prop, "Enabled", "Enable this objects as a collider for physics systems"); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "stiffness", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "stiffness"); + RNA_def_property_range(prop, 0.0f, 1000.0f); + RNA_def_property_ui_text(prop, "Stiffness:", "NO INFORMATION AS YET"); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "radius", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "radius"); + RNA_def_property_range(prop, 0.0f, 1000.0f); + RNA_def_property_ui_text(prop, "Radius:", "NO INFORMATION AS YET"); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + prop= RNA_def_property(srna, "thickness", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "thickness"); + RNA_def_property_range(prop, 0.0f, 1000.0f); + RNA_def_property_ui_text(prop, "Thickness:", "NO INFORMATION AS YET"); + RNA_def_property_update(prop, 0, "rna_particlesurface_update"); + + */ +} + +void RNA_def_particlesurface(BlenderRNA *brna) +{ + rna_def_particlesurface_sim_settings(brna); + rna_def_particlesurface_collision_settings(brna); +} + +#endif Index: source/blender/makesrna/RNA_access.h =================================================================== --- source/blender/makesrna/RNA_access.h (revision 41360) +++ source/blender/makesrna/RNA_access.h (working copy) @@ -364,6 +364,9 @@ extern StructRNA RNA_ParticleKey; extern StructRNA RNA_ParticleSettings; extern StructRNA RNA_ParticleSettingsTextureSlot; +extern StructRNA RNA_ParticleSurfaceCollisionSettings; +extern StructRNA RNA_ParticleSurfaceModifier; +extern StructRNA RNA_ParticleSurfaceSettings; extern StructRNA RNA_ParticleSystem; extern StructRNA RNA_ParticleSystemModifier; extern StructRNA RNA_ParticleTarget; Index: source/blender/modifiers/CMakeLists.txt =================================================================== --- source/blender/modifiers/CMakeLists.txt (revision 41360) +++ source/blender/modifiers/CMakeLists.txt (working copy) @@ -36,6 +36,9 @@ ../render/extern/include ../../../intern/elbeem/extern ../../../intern/guardedalloc + ../blenlib/intern + + ../render/intern/source ) set(INC_SYS @@ -67,6 +70,7 @@ intern/MOD_multires.c intern/MOD_none.c intern/MOD_particleinstance.c + intern/MOD_particlesurface.c intern/MOD_particlesystem.c intern/MOD_screw.c intern/MOD_shapekey.c @@ -92,6 +96,7 @@ intern/MOD_fluidsim_util.h intern/MOD_util.h intern/MOD_weightvg_util.h + intern/MOD_particlesurface.h ) if(WITH_MOD_BOOLEAN) Index: source/blender/modifiers/intern/MOD_particlesurface.c =================================================================== --- source/blender/modifiers/intern/MOD_particlesurface.c (revision 0) +++ source/blender/modifiers/intern/MOD_particlesurface.c (revision 0) @@ -0,0 +1,2166 @@ +/* +/* +* $Id: MOD_particleinstance.c 34824 2011-02-13 14:16:36Z campbellbarton $ +* +* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* The Original Code is Copyright (C) 2005 by the Blender Foundation. +* All rights reserved. +* +* Contributor(s): Stephen Whitehorn, Raul Fernandez Hernandez (Farsthary) + +* +* ***** END GPL LICENSE BLOCK ***** +* +** \file blender/modifiers/intern/MOD_particlesurface.c +* \ingroup modifiers +*/ +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_particlesurface_types.h" + +#include "BKE_DerivedMesh.h" +#include "BLI_math.h" +#include "math.h" + +#include "BLI_editVert.h" +#include "BKE_collision.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_lattice.h" +#include "BKE_modifier.h" +#include "BKE_deform.h" +#include "BKE_shrinkwrap.h" +#include "BKE_utildefines.h" +#include "BKE_particle.h" +#include "BKE_mesh.h" +#include "BKE_effect.h" +#include "BKE_scene.h" +#include "BKE_texture.h" +#include "BLI_kdtree.h" +#include "depsgraph_private.h" + +#include "MOD_util.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_group_types.h" +#include "DNA_particlesurface_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_force.h" +#include "MOD_particlesurface.h" +#include "BLI_blenlib.h" + +#include "BLI_editVert.h" +#include "BLI_edgehash.h" +#include "BLI_utildefines.h" +#include "BKE_customdata.h" +#include "BLI_math_vector.h" +#include "BKE_global.h" +#include "BLI_linklist.h" +#include "BKE_action.h" +#include "CSG_BooleanOps.h" +#include "BKE_pointcache.h" + + +#ifdef HAVE_CONFIG_H +#include +#endif + +/******************************************************************************************************** +* +* This code uses in some parts adapted algorithms from the website: +* +* Titled: Polygonising a scalar field +* Authors: Paul Bourke +* Website: http://paulbourke.net/geometry/polygonise/ +* +* +* +***********************************************************************************************************/ + + + +//************* Constructing the hash array for polygonalization ************** + +int edgeTable[256]= +{ + 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, +0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, +0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, +0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, +0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, +0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, +0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, +0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, +0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, +0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, +0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, +0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, +0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, +0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, +0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , +0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, +0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, +0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, +0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, +0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, +0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, +0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, +0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, +0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, +0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, +0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, +0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, +0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, +0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, +0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, +0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, +0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 +}; + +int triTable[256][16] = +{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1}, +{3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1}, +{3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1}, +{3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1}, +{9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1}, +{1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1}, +{9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, +{2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1}, +{8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1}, +{9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, +{4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1}, +{3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, +{1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1}, +{4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1}, +{4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1}, +{9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1}, +{1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, +{5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1}, +{2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1}, +{9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, +{0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, +{2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1}, +{10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1}, +{4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1}, +{5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1}, +{5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1}, +{9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1}, +{0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1}, +{1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1}, +{10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1}, +{8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1}, +{2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1}, +{7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1}, +{9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1}, +{2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1}, +{11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1}, +{9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1}, +{5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1}, +{11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1}, +{11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, +{1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1}, +{9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1}, +{5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1}, +{2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, +{0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, +{5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1}, +{6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1}, +{0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1}, +{3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1}, +{6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1}, +{5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1}, +{1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, +{10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1}, +{6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1}, +{1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1}, +{8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1}, +{7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1}, +{3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, +{5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1}, +{0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1}, +{9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1}, +{8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1}, +{5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1}, +{0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1}, +{6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1}, +{10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1}, +{10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1}, +{8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1}, +{1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1}, +{3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1}, +{0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1}, +{10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1}, +{0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1}, +{3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1}, +{6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1}, +{9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1}, +{8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1}, +{3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}, +{6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1}, +{0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1}, +{10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1}, +{10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1}, +{1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1}, +{2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1}, +{7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}, +{7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1}, +{2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1}, +{1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1}, +{11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1}, +{8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1}, +{0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1}, +{7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, +{10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, +{2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, +{6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1}, +{7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1}, +{2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1}, +{1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1}, +{10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1}, +{10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1}, +{0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1}, +{7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1}, +{6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1}, +{8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1}, +{9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1}, +{6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1}, +{1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1}, +{4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1}, +{10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1}, +{8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1}, +{0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1}, +{1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1}, +{8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1}, +{10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1}, +{4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1}, +{10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, +{5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, +{11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1}, +{9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, +{6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1}, +{7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1}, +{3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1}, +{7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, +{9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1}, +{3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1}, +{6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1}, +{9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1}, +{1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1}, +{4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1}, +{7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1}, +{6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}, +{3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1}, +{0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1}, +{6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1}, +{1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1}, +{0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1}, +{11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1}, +{6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1}, +{5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1}, +{9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}, +{1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1}, +{1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1}, +{10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1}, +{0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1}, +{5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1}, +{10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1}, +{11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1}, +{0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1}, +{9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1}, +{7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1}, +{2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1}, +{8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1}, +{9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1}, +{9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1}, +{1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1}, +{9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}, +{9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1}, +{5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1}, +{0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1}, +{10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1}, +{2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1}, +{0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1}, +{0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1}, +{9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1}, +{5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1}, +{3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1}, +{5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1}, +{8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}, +{0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1}, +{9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}, +{0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1}, +{1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1}, +{3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1}, +{4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1}, +{9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1}, +{11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}, +{11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1}, +{2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1}, +{9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1}, +{3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1}, +{1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}, +{4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1}, +{4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1}, +{0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1}, +{3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1}, +{3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1}, +{0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1}, +{9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1}, +{1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}; + + +/* + Linearly interpolate the position where an isosurface cuts + an edge between two vertices, each with their own scalar value +*/ +XYZ VertexInterp(float isolevel,XYZ p1,XYZ p2,float valp1,float valp2) +{ + float mu; + XYZ p; + if (fabs(isolevel-valp1) < 0.00001) + return(p1); + if (fabs(isolevel-valp2) < 0.00001) + return(p2); + if (fabs(valp1-valp2) < 0.00001) + return(p1); + mu = (isolevel - valp1) / (valp2 - valp1); + p.x = p1.x + mu * (p2.x - p1.x); + p.y = p1.y + mu * (p2.y - p1.y); + p.z = p1.z + mu * (p2.z - p1.z); + + return(p); +} +/* + Given a grid cell and an isolevel, calculate the triangular + facets required to represent the isosurface through the cell. + Return the number of triangular facets, the array "triangles" + will be loaded up with the vertices at most 5 triangular facets. + 0 will be returned if the grid cell is either totally above + of totally below the isolevel. +*/ + +int Polygonise(GRIDCELL grid,float isolevel,TRIANGLE *triangles) +{ + int i,ntriang; + int cubeindex; + XYZ vertlist[12]; + + /* + Determine the index into the edge table which + tells us which vertices are inside of the surface + */ + cubeindex = 0; + if (grid.val[0] < isolevel) cubeindex |= 1; + if (grid.val[1] < isolevel) cubeindex |= 2; + if (grid.val[2] < isolevel) cubeindex |= 4; + if (grid.val[3] < isolevel) cubeindex |= 8; + if (grid.val[4] < isolevel) cubeindex |= 16; + if (grid.val[5] < isolevel) cubeindex |= 32; + if (grid.val[6] < isolevel) cubeindex |= 64; + if (grid.val[7] < isolevel) cubeindex |= 128; + + /* Cube is entirely in/out of the surface */ + if (edgeTable[cubeindex] == 0) + return(0); + + /* Find the vertices where the surface intersects the cube */ + if (edgeTable[cubeindex] & 1) + vertlist[0] = VertexInterp(isolevel,grid.p[0],grid.p[1],grid.val[0],grid.val[1]); + if (edgeTable[cubeindex] & 2) + vertlist[1] = VertexInterp(isolevel,grid.p[1],grid.p[2],grid.val[1],grid.val[2]); + if (edgeTable[cubeindex] & 4) + vertlist[2] = VertexInterp(isolevel,grid.p[2],grid.p[3],grid.val[2],grid.val[3]); + if (edgeTable[cubeindex] & 8) + vertlist[3] = VertexInterp(isolevel,grid.p[3],grid.p[0],grid.val[3],grid.val[0]); + if (edgeTable[cubeindex] & 16) + vertlist[4] = VertexInterp(isolevel,grid.p[4],grid.p[5],grid.val[4],grid.val[5]); + if (edgeTable[cubeindex] & 32) + vertlist[5] = VertexInterp(isolevel,grid.p[5],grid.p[6],grid.val[5],grid.val[6]); + if (edgeTable[cubeindex] & 64) + vertlist[6] = VertexInterp(isolevel,grid.p[6],grid.p[7],grid.val[6],grid.val[7]); + if (edgeTable[cubeindex] & 128) + vertlist[7] = VertexInterp(isolevel,grid.p[7],grid.p[4],grid.val[7],grid.val[4]); + if (edgeTable[cubeindex] & 256) + vertlist[8] = VertexInterp(isolevel,grid.p[0],grid.p[4],grid.val[0],grid.val[4]); + if (edgeTable[cubeindex] & 512) + vertlist[9] = VertexInterp(isolevel,grid.p[1],grid.p[5],grid.val[1],grid.val[5]); + if (edgeTable[cubeindex] & 1024) + vertlist[10] = VertexInterp(isolevel,grid.p[2],grid.p[6],grid.val[2],grid.val[6]); + if (edgeTable[cubeindex] & 2048) + vertlist[11] = VertexInterp(isolevel,grid.p[3],grid.p[7],grid.val[3],grid.val[7]); + + /* Create the triangle */ + ntriang = 0; + for (i=0;triTable[cubeindex][i]!=-1;i+=3) { + triangles[ntriang].p[0] = vertlist[triTable[cubeindex][i ]]; + triangles[ntriang].p[1] = vertlist[triTable[cubeindex][i+1]]; + triangles[ntriang].p[2] = vertlist[triTable[cubeindex][i+2]]; + ntriang++; + } + + return(ntriang); +} + +//************************Polygonize tetrahedron******************************************************* +/* + Polygonise a tetrahedron given its vertices within a cube + This is an alternative algorithm to polygonisegrid. + It results in a smoother surface but more triangular facets. + + + 0 + /|\ + / | \ + / | \ + / | \ + / | \ + / | \ + +-------------+ 1 + 3 \ | / + \ | / + \ | / + \ | / + \ | / + \|/ + + 2 + + It's main purpose is still to polygonise a gridded dataset and + would normally be called 6 times, one for each tetrahedron making + up the grid cell. + Given the grid labelling as in PolygniseGrid one would call + PolygoniseTri(grid,iso,triangles,0,2,3,7); + PolygoniseTri(grid,iso,triangles,0,2,6,7); + PolygoniseTri(grid,iso,triangles,0,4,6,7); + PolygoniseTri(grid,iso,triangles,0,6,1,2); + PolygoniseTri(grid,iso,triangles,0,6,1,4); + PolygoniseTri(grid,iso,triangles,5,6,1,4); +*/ +int PolygoniseTri(GRIDCELL g,float iso,TRIANGLE *tri,int v0,int v1,int v2,int v3) +{ + int ntri = 0; + int triindex; + + /* + Determine which of the 16 cases we have given which vertices + are above or below the isosurface + */ + triindex = 0; + if (g.val[v0] < iso) triindex |= 1; + if (g.val[v1] < iso) triindex |= 2; + if (g.val[v2] < iso) triindex |= 4; + if (g.val[v3] < iso) triindex |= 8; + + /* Form the vertices of the triangles for each case */ + switch (triindex) { + case 0x00: + case 0x0F: + break; + case 0x0E: + case 0x01: + tri[0].p[0] = VertexInterp(iso,g.p[v0],g.p[v1],g.val[v0],g.val[v1]); + tri[0].p[1] = VertexInterp(iso,g.p[v0],g.p[v2],g.val[v0],g.val[v2]); + tri[0].p[2] = VertexInterp(iso,g.p[v0],g.p[v3],g.val[v0],g.val[v3]); + ntri++; + break; + case 0x0D: + case 0x02: + tri[0].p[0] = VertexInterp(iso,g.p[v1],g.p[v0],g.val[v1],g.val[v0]); + tri[0].p[1] = VertexInterp(iso,g.p[v1],g.p[v3],g.val[v1],g.val[v3]); + tri[0].p[2] = VertexInterp(iso,g.p[v1],g.p[v2],g.val[v1],g.val[v2]); + ntri++; + break; + case 0x0C: + case 0x03: + tri[0].p[0] = VertexInterp(iso,g.p[v0],g.p[v3],g.val[v0],g.val[v3]); + tri[0].p[1] = VertexInterp(iso,g.p[v0],g.p[v2],g.val[v0],g.val[v2]); + tri[0].p[2] = VertexInterp(iso,g.p[v1],g.p[v3],g.val[v1],g.val[v3]); + ntri++; + tri[1].p[0] = tri[0].p[2]; + tri[1].p[1] = VertexInterp(iso,g.p[v1],g.p[v2],g.val[v1],g.val[v2]); + tri[1].p[2] = tri[0].p[1]; + ntri++; + break; + case 0x0B: + case 0x04: + tri[0].p[0] = VertexInterp(iso,g.p[v2],g.p[v0],g.val[v2],g.val[v0]); + tri[0].p[1] = VertexInterp(iso,g.p[v2],g.p[v1],g.val[v2],g.val[v1]); + tri[0].p[2] = VertexInterp(iso,g.p[v2],g.p[v3],g.val[v2],g.val[v3]); + ntri++; + break; + case 0x0A: + case 0x05: + tri[0].p[0] = VertexInterp(iso,g.p[v0],g.p[v1],g.val[v0],g.val[v1]); + tri[0].p[1] = VertexInterp(iso,g.p[v2],g.p[v3],g.val[v2],g.val[v3]); + tri[0].p[2] = VertexInterp(iso,g.p[v0],g.p[v3],g.val[v0],g.val[v3]); + ntri++; + tri[1].p[0] = tri[0].p[0]; + tri[1].p[1] = VertexInterp(iso,g.p[v1],g.p[v2],g.val[v1],g.val[v2]); + tri[1].p[2] = tri[0].p[1]; + ntri++; + break; + case 0x09: + case 0x06: + tri[0].p[0] = VertexInterp(iso,g.p[v0],g.p[v1],g.val[v0],g.val[v1]); + tri[0].p[1] = VertexInterp(iso,g.p[v1],g.p[v3],g.val[v1],g.val[v3]); + tri[0].p[2] = VertexInterp(iso,g.p[v2],g.p[v3],g.val[v2],g.val[v3]); + ntri++; + tri[1].p[0] = tri[0].p[0]; + tri[1].p[1] = VertexInterp(iso,g.p[v0],g.p[v2],g.val[v0],g.val[v2]); + tri[1].p[2] = tri[0].p[2]; + ntri++; + break; + case 0x07: + case 0x08: + tri[0].p[0] = VertexInterp(iso,g.p[v3],g.p[v0],g.val[v3],g.val[v0]); + tri[0].p[1] = VertexInterp(iso,g.p[v3],g.p[v2],g.val[v3],g.val[v2]); + tri[0].p[2] = VertexInterp(iso,g.p[v3],g.p[v1],g.val[v3],g.val[v1]); + ntri++; + break; + } + + return(ntri); +} + +static void add_surfacecollision_object(Object ***objs, unsigned int *numobj, unsigned int *maxobj, Object *ob, Object *self, int level) +{ + ParticleSurfaceModifierData *cmd= NULL; + + if(ob == self) + return; + + /* only get objects with collision flag modifier */ + if(((ob->partsurfaceflag) & OB_PS_ENABLE) != 0) + cmd= (ParticleSurfaceModifierData *)modifiers_findByType(ob, eModifierType_ParticleSurface); + + if(cmd) { + /* extend array */ + if(*numobj >= *maxobj) { + *maxobj *= 2; + *objs= MEM_reallocN(*objs, sizeof(Object*)*(*maxobj)); + } + + (*objs)[*numobj] = ob; + (*numobj)++; + } + + /* objects in dupli groups, one level only for now */ + if(ob->dup_group && level == 0) { + GroupObject *go; + Group *group= ob->dup_group; + + /* add objects */ + for(go= group->gobject.first; go; go= go->next) + add_surfacecollision_object(objs, numobj, maxobj, go->ob, self, level+1); + } +} + + +// return all particle surface collision objects in scene +// particle surface collision object will exclude self +Object **get_surfacecollisionobjects(Scene *scene, Object *self, Group *group, unsigned int *numcollobj) +{ + Base *base; + Object **objs; + GroupObject *go; + unsigned int numobj= 0, maxobj= 100; + + objs= MEM_callocN(sizeof(Object *)*maxobj, "SurfaceCollisionObjectsArray"); + /* gather all collision objects */ + if(group) { + /* use specified group */ + for(go= group->gobject.first; go; go= go->next) + add_surfacecollision_object(&objs, &numobj, &maxobj, go->ob, self, 0); + } + else { + Scene *sce_iter; + /* add objects in same layer in scene */ + for(SETLOOPER(scene, sce_iter, base)) { + if(base->lay & self->lay) + add_surfacecollision_object(&objs, &numobj, &maxobj, base->object, self, 0); + + } + } + + *numcollobj= numobj; + + return objs; +} + + +DerivedMesh *object_get_derived_def(Object *ob) + { + Mesh *me= ob->data; + EditMesh *em = BKE_mesh_get_editmesh(me); + + if(em) { + DerivedMesh *dm = em->derivedFinal; + BKE_mesh_end_editmesh(me, em); + return dm; + } + + return ob->derivedDeform; + } + + + + +/************** These field functions are interchangable, use and modify as desired ******************* +* +* This field function was taken from paper: An Implicit Formulation for precise Contact Modeling between Flexible Solids +* Author: Marie-Paule Gascuel +* +/******************************************************************************************************/ + +float fluidfieldfunction(ParticleSurfaceModifierData *rvd, float x){ + float thickness, stiffness, radius, Result; + float a, b, c, d, e; + thickness = rvd->sim_parms->fluidthickness; + stiffness = rvd->sim_parms->fluidstiffness; + radius = rvd->sim_parms->fluidradius; + a =0; + b = -stiffness; + c = (stiffness *thickness) + 1; + + + Result = 0; + + d = -(((stiffness*(thickness -radius))+2))/((thickness - radius)*(thickness - radius) * (thickness - radius)); + e = (((stiffness* thickness*(thickness - radius))+ (3 *thickness)-radius))/((thickness-radius)*(thickness-radius)*(thickness-radius)); + + if ((x>0) && (xthickness) && (x alive == PARS_ALIVE){ + + fDx = pos[0] - pa->state.co[0]; + fDy = pos[1] - pa->state.co[1]; + fDz = pos[2] - pa->state.co[2]; + fResult += 1.5/(fDx*fDx + fDy*fDy + fDz*fDz); + } + + + /* Motion Plotting */ + if (sphsurface->sim_parms->spread > 0){ + + + + + for (i=1; i<=sphsurface->sim_parms->spread; i++){ + /* Positive direction */ + mul_v3_v3fl(velvect1, pa->state.vel, sphsurface->sim_parms->stretch*i); + add_v3_v3v3(velvect1, pa->state.co, velvect1); + + fDx = pos[0] - velvect1[0]; + fDy = pos[1] - velvect1[1]; + fDz = pos[2] - velvect1[2]; + motionplotting_pos_val += 1.5/(fDx*fDx + fDy*fDy + fDz*fDz); + + + + + } + for (i=1; i<=sphsurface->sim_parms->spread; i++){ + /* Negative Direction */ + mul_v3_v3fl(velvect2, pa->state.vel, -sphsurface->sim_parms->stretch* i); + add_v3_v3v3(velvect2, pa->state.co, velvect2); + + fDx = pos[0] - velvect2[0]; + fDy = pos[1] - velvect2[1]; + fDz = pos[2] - velvect2[2]; + motionplotting_neg_val += 1.5/(fDx*fDx + fDy*fDy + fDz*fDz); + } + + fResult = fResult + (motionplotting_pos_val*sphsurface->sim_parms->size); + fResult = fResult + (motionplotting_neg_val*sphsurface->sim_parms->size); + } + + + } + + + + + + + + + + + + + + + + return fResult; + +} + +float fluid_field_function2(float radius, float *pos, KDTree *surfacetree) //slow, fix this +{ + KDTree *tree = surfacetree; + KDTreeNearest *ptn = NULL; + + int neighbours,n; + float q,val=0.f; + + neighbours =BLI_kdtree_range_search(tree, radius, pos, NULL, &ptn); + for(n=0; nsim_parms->isovalue); + + + switch(sphsurface->sim_parms->isosurface_extraction) { + case ISOSURFACE_EXTRACTION_A: + + + + LOOP_DYNAMIC_PARTICLES{ + if (pa->alive == PARS_ALIVE){ + val += fluidfieldfunction( sphsurface, len_v3v3(pa->state.co, pos)); + + + /* Motion Plotting */ + if (sphsurface->sim_parms->spread > 0){ + + //val = val * sphsurface->sim_parms->size; + + + + for (i=1; i<=sphsurface->sim_parms->spread; i++){ + /* Positive direction */ + mul_v3_v3fl(velvect1, pa->state.vel, sphsurface->sim_parms->stretch*i); + add_v3_v3v3(velvect1, pa->state.co, velvect1); + motionplotting_pos_val += fluidfieldfunction( sphsurface, len_v3v3(velvect1, pos)); + } + for (i=1; i<=sphsurface->sim_parms->spread; i++){ + /* Negative Direction */ + mul_v3_v3fl(velvect2, pa->state.vel, -sphsurface->sim_parms->stretch* i); + add_v3_v3v3(velvect2, pa->state.co, velvect2); + + motionplotting_pos_val += fluidfieldfunction( sphsurface, len_v3v3(velvect2, pos)); + } + + val = val + (motionplotting_pos_val *sphsurface->sim_parms->size); + val = val + (motionplotting_neg_val *sphsurface->sim_parms->size); + } + } + + } + + + break; + + case ISOSURFACE_EXTRACTION_B: + val = fSample(dm, surfacetree, psys, ob, sphsurface, pos, isovalue); + break; + + case ISOSURFACE_EXTRACTION_C: + val = fluid_field_function2(radius ,pos, surfacetree); + break; + + + + } + + /* Collisions */ + collobjs = get_surfacecollisionobjects(scene, object, NULL, &numcollobj); + + /* Check all collision objects */ + for(i = 0; i < numcollobj; i++) + { + Object *collob= collobjs[i]; + + /* Determine if collisions is enabled */ + if (((collob->partsurfaceflag) & OB_PS_ENABLE) != 0){ + ParticleSystem * psys2= BLI_findlink(&collob->particlesystem, 0); + ParticleSurfaceModifierData *secondmd = (ParticleSurfaceModifierData*)modifiers_findByType(collob, eModifierType_ParticleSurface); + + + + /* Instead of using LOOP_DYNAMIC_PARTICLES for the second particleobjectects particle system */ + for(p=0, pa=psys2->particles; ptotpart; p++, pa++) if(pa->state.time > 0.f){ + if (pa->alive == PARS_ALIVE){ + secondfield += fluidfieldfunction( secondmd, len_v3v3(pa->state.co, pos)); + } + } + + + switch(secondmd->coll_parms->collisiontype) { + case ADDITION: + val = val + secondfield; + break; + + case SUBTRACTION: + val = val - secondfield; + break; + } + } + } + + + if (collobjs){MEM_freeN(collobjs);collobjs =NULL;} + return val; +} + +//-------------- HASH table ------------------------ +#define HASHBIT (5) +#define HASHSIZE (size_t)(1<<(3*HASHBIT)) /*! < hash table size (32768) */ +#define HASH(i,j,k) ((((( (i) & 31)<<5) | ( (j) & 31))<<5 ) | ( (k) & 31) ) + +int hash_cell(float x, float inv_cell_size) +{ +return ((int)(fabs(x)*inv_cell_size)); +} + +/* the hash function is the composition of two functions, + one provided by the client and one by the implementer. + This is because the implementer doesn't understand the element + type, the client doesn't know how many buckets there are, + and the implementer probably doesn't trust the client to achieve diffusion. + The client function hclient first converts the key into an integer + hash code, and the implementation function himpl converts the + hash code into a bucket index. The actual hash function is + the composition of these two functions */ + +int BLI_spatial_hash(float x,float y,float z,SpatialHash *hash) +{ +/* Client Hash function of a double hashing scheme client-implementer */ +int i= hash_cell(x, hash->inv_cell_size); +int j= hash_cell(y, hash->inv_cell_size); +int k= hash_cell(z, hash->inv_cell_size); + +/* Implementer Hash function of a double hashing scheme client-implementer */ +return HASH(i,j,k); +} + +/* Creates or free a Spatial hash */ +SpatialHash* BLI_hash_new(int cell_resol,float cell_size,float isolevel, float radius) +{ + int i; + SpatialHash *hash=MEM_mallocN(sizeof(SpatialHash),"Spatial Hash"); + + hash->cell_size=cell_size; + hash->inv_cell_size=1.f/cell_size; + + hash->isolevel=isolevel; + + hash->cell_resol=cell_resol; + hash->radius=radius; + + + /* preallocate buckets */ + hash->totalbuckets = HASHSIZE; + hash->buckets=MEM_mallocN(hash->totalbuckets*sizeof(HashBucket),"Buckets buffer"); + + hash->linked_cubelist=NULL; + + for (i=0;itotalbuckets;i++) + { + (hash->buckets[i]).listpoints=NULL; + } + + return hash; +} + + + +void BLI_spatialhash_free(SpatialHash *hash) /* check memory issues */ +{ + int i=0; + + + + + + for (i=0;itotalbuckets;i++) + { + if ( (hash->buckets[i]).listpoints != NULL ) + { + LinkNode *search = (hash->buckets[i]).listpoints; + while(search) + { + int *ico = search->link; + + MEM_freeN ( ico ); + search = search->next; + } + BLI_linklist_free((hash->buckets[i]).listpoints,NULL); + (hash->buckets[i]).listpoints=NULL; + + + } + } + if ( hash->linked_cubelist != NULL ) + { + LinkNode *search = hash->linked_cubelist; + while(search) + { + GRIDCELL *cell = search->link; + + MEM_freeN ( cell ); + search = search->next; + } + BLI_linklist_free(hash->linked_cubelist,NULL); + hash->linked_cubelist=NULL; + + + } + + MEM_freeN(hash->buckets); + MEM_freeN(hash); +} + +int is_surface_cell(GRIDCELL *grid, SpatialHash *hash) +{ + int cubeindex; + /* + Determine the index into the edge table which + tells us which vertices are inside of the surface + */ + cubeindex = 0; + if (grid->val[0] < hash->isolevel) cubeindex |= 1; + if (grid->val[1] < hash->isolevel) cubeindex |= 2; + if (grid->val[2] < hash->isolevel) cubeindex |= 4; + if (grid->val[3] < hash->isolevel) cubeindex |= 8; + if (grid->val[4] < hash->isolevel) cubeindex |= 16; + if (grid->val[5] < hash->isolevel) cubeindex |= 32; + if (grid->val[6] < hash->isolevel) cubeindex |= 64; + if (grid->val[7] < hash->isolevel) cubeindex |= 128; + + /* Cube is entirely in/out of the surface */ + if (edgeTable[cubeindex] == 0){ + return 0; + } + + return cubeindex; +} + +int face_offset(int cubeindex) +{ + int faceoffset=0; + /* Find the vertices where the surface intersects the cube */ + if (edgeTable[cubeindex] & 1){ + faceoffset |= 1; faceoffset |= 32; + } + if (edgeTable[cubeindex] & 2){ + faceoffset |= 1; faceoffset |= 8; + } + if (edgeTable[cubeindex] & 4){ + faceoffset |= 1; faceoffset = 32; + } + if (edgeTable[cubeindex] & 8){ + faceoffset |= 1; faceoffset |= 2; + } + if (edgeTable[cubeindex] & 16){ + faceoffset |= 4; faceoffset |= 32; + } + if (edgeTable[cubeindex] & 32){ + faceoffset |= 4; faceoffset |= 8; + } + if (edgeTable[cubeindex] & 64){ + faceoffset |= 16; faceoffset |= 4; + } + if (edgeTable[cubeindex] & 128){ + faceoffset |= 2; faceoffset |= 4; + } + if (edgeTable[cubeindex] & 256){ + faceoffset |= 2; faceoffset |= 32; + } + if (edgeTable[cubeindex] & 512){ + faceoffset |= 8; faceoffset |= 32; + } + if (edgeTable[cubeindex] & 1024){ + faceoffset |= 8; faceoffset |= 16; + } + if (edgeTable[cubeindex] & 2048){ + faceoffset |= 16; faceoffset |= 2; + } + return faceoffset; +} + +int in_bucket_list(int x, int y, int z, int bucket_index, SpatialHash *hash) +{ + int index; + + LinkNode *list = (hash->buckets[bucket_index]).listpoints; + + for (index = 0; list; list= list->next, index++) + { + int *pos = (int *)(list->link); + if (x == pos[0] && y == pos[1] && z == pos[2]) + return 1; + } + + return 0; +} + +void make_cube(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface , KDTree *surfacetree, float *central_pos, float cell_resol, GRIDCELL *cube, float radius, ParticleSystem *psys, float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7) +{ + float pos[3]; + float deltha = 0.5f*cell_resol; + + float x01=central_pos[0]-deltha; + float x02=central_pos[0]+deltha; + + float y01=central_pos[1]-deltha; + float y02=central_pos[1]+deltha; + + float z01=central_pos[2]-deltha; + float z02=central_pos[2]+deltha; + + + /*--------- vertex 0------------------- */ + cube->p[0].x=pos[0]=x01; + cube->p[0].y=pos[1]=y01; + cube->p[0].z=pos[2]=z01; + + if (v0 >= 0) cube->val[0]= v0; + else + cube->val[0]=BLI_surface_eval(dm, scene, ob, sphsurface, surfacetree, radius, pos, central_pos, psys); + + /*--------- vertex 1----------------- */ + cube->p[1].x=pos[0]=x02; + cube->p[1].y=pos[1]=y01; + cube->p[1].z=pos[2]=z01; + + if (v1 >= 0) cube->val[1]=v1; + else + cube->val[1]=BLI_surface_eval(dm, scene, ob, sphsurface, surfacetree, radius, pos, central_pos, psys); + + /*--------- vertex 2----------------- */ + cube->p[2].x=pos[0]=x02; + cube->p[2].y=pos[1]=y01; + cube->p[2].z=pos[2]=z02; + + if (v2 >= 0) cube->val[2]=v2; + else + cube->val[2]=BLI_surface_eval(dm, scene, ob, sphsurface, surfacetree, radius, pos, central_pos, psys); + + /*--------- vertex 3----------------- */ + cube->p[3].x=pos[0]=x01; + cube->p[3].y=pos[1]=y01; + cube->p[3].z=pos[2]=z02; + + if (v3 >= 0) cube->val[3]=v3; + else + cube->val[3]=BLI_surface_eval(dm, scene, ob, sphsurface, surfacetree, radius, pos, central_pos, psys); + + /*--------- vertex 4----------------- */ + cube->p[4].x=pos[0]=x01; + cube->p[4].y=pos[1]=y02; + cube->p[4].z=pos[2]=z01; + + if (v4 >= 0) cube->val[4]=v4; + else + cube->val[4]=BLI_surface_eval(dm, scene, ob, sphsurface, surfacetree, radius, pos, central_pos, psys); + + /*--------- vertex 5----------------- */ + cube->p[5].x=pos[0]=x02; + cube->p[5].y=pos[1]=y02; + cube->p[5].z=pos[2]=z01; + + if (v5 >= 0) cube->val[5]=v5; + else + cube->val[5]=BLI_surface_eval(dm, scene, ob, sphsurface, surfacetree, radius, pos, central_pos, psys); + + /*--------- vertex 6----------------- */ + cube->p[6].x=pos[0]=x02; + cube->p[6].y=pos[1]=y02; + cube->p[6].z=pos[2]=z02; + + if (v6 >= 0) cube->val[6]=v6; + else + cube->val[6]=BLI_surface_eval(dm, scene, ob, sphsurface, surfacetree, radius, pos, central_pos, psys); + + /*--------- vertex 7----------------- */ + cube->p[7].x=pos[0]=x01; + cube->p[7].y=pos[1]=y02; + cube->p[7].z=pos[2]=z02; + + if (v7 >= 0) cube->val[7]=v7; + else + cube->val[7]=BLI_surface_eval(dm, scene, ob, sphsurface, surfacetree, radius, pos, central_pos, psys); + + +} + +int March3D(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface, KDTree *surfacetree, int x, int y, int z, SpatialHash *hash, ParticleSystem *psys, float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7) +{ + int faceoffset, bucket_index, *ico, result, cubeindex = 0; + float pos[3]; + + GRIDCELL *cell=MEM_mallocN(sizeof(GRIDCELL),"spacial hash -March 3d");//allocation? + bucket_index = BLI_spatial_hash(x, y, z, hash); + if (in_bucket_list(x, y, z, bucket_index, hash)){ + if (cell){ MEM_freeN(cell);cell=NULL;} + return 0; + } + pos[0]=x*hash->cell_size; + pos[1]=y*hash->cell_size; + pos[2]=z*hash->cell_size; + + make_cube(dm, scene, ob, sphsurface, surfacetree, pos, hash->cell_size, cell, hash->radius, psys, v0, v1, v2, v3, v4, v5, v6, v7); + cubeindex = is_surface_cell(cell, hash); + + if (!cubeindex){ + if (cell){ MEM_freeN(cell);cell=NULL;} + return 0; + } + + ico=MEM_mallocN(3*sizeof(int), "ico"); //watch this too + ico[0]=x; + ico[1]=y; + ico[2]=z; + BLI_linklist_prepend(&(hash->buckets[bucket_index]).listpoints,ico); + BLI_linklist_prepend(&(hash->linked_cubelist), cell); + + result=1; + + v0=-1; v1=-1; v2=-1; v3=-1; + v4=-1; v5=-1; v6=-1; v7=-1; + + faceoffset=face_offset(cubeindex); + + /* march trough neighbours cells */ + if (faceoffset & 1){ + v5=cell->val[1]; + v7=cell->val[3]; + v4=cell->val[0]; + v6=cell->val[2]; + + result += March3D(dm, scene, ob, sphsurface, surfacetree, x,y-1,z, hash, psys, -1, v1, v2, -1, -1, v5, v6, -1); + } + + if (faceoffset & 2){ + v5=cell->val[4]; + v1=cell->val[0]; + v2=cell->val[3]; + v6=cell->val[7]; + + result += March3D(dm, scene, ob, sphsurface, surfacetree, x-1,y,z, hash, psys, -1, v1, v2, -1, -1, v5, v6, -1); + } + + if (faceoffset & 4){ + v0=cell->val[4]; + v1=cell->val[5]; + v2=cell->val[6]; + v3=cell->val[7]; + + result += March3D(dm, scene, ob, sphsurface, surfacetree, x,y+1,z, hash, psys, v0, v1, v2, v3, -1, -1, -1, -1); + } + + if (faceoffset & 8){ + v0=cell->val[1]; + v7=cell->val[6]; + v4=cell->val[5]; + v3=cell->val[2]; + + result += March3D(dm, scene, ob, sphsurface, surfacetree, x+1,y,z, hash, psys, v0, -1, -1, v3, v4, -1, -1, v7); + } + + if (faceoffset & 16){ + v0=cell->val[3]; + v1=cell->val[2]; + v4=cell->val[7]; + v5=cell->val[6]; + + result += March3D(dm, scene, ob, sphsurface, surfacetree, x,y,z+1, hash, psys, v0, v1, -1, -1, v4, v5, -1, -1); + } + + if (faceoffset & 32){ + v7=cell->val[4]; + v3=cell->val[0]; + v2=cell->val[1]; + v6=cell->val[5]; + + result += March3D(dm, scene, ob, sphsurface, surfacetree, x,y,z-1, hash, psys, -1, -1, v2, v3, -1, -1, v6, v7); + } + + + + return result; +} + +/* Construction: inserted particles have an extention in space that could overlaps several cells */ +int BLI_spatialhash_insert(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface , KDTree *surfacetree, SpatialHash *hash, float *co, ParticleSystem *psys) +{ + int inserted=0; + float tco[3]; + int cell_limit=0; + + GRIDCELL *cell=MEM_mallocN(sizeof(GRIDCELL),"spacial hash"); //free this + + tco[0]=((int)(co[0]*hash->inv_cell_size)+0.5f)*hash->cell_size; + tco[1]=((int)(co[1]*hash->inv_cell_size)+0.5f)*hash->cell_size; + tco[2]=((int)(co[2]*hash->inv_cell_size)+0.5f)*hash->cell_size; + + make_cube(dm, scene, ob, sphsurface, surfacetree, tco, hash->cell_size, cell, hash->radius, psys, -1, -1, -1, -1, -1, -1, -1, -1); + + while(!is_surface_cell(cell, hash) && cell_limit<20) + { + //march toward the normal (implement) + + tco[1]-=hash->cell_size; + + make_cube(dm, scene ,ob, sphsurface, surfacetree, tco, hash->cell_size, cell, hash->radius, psys, -1, -1, -1, -1, -1, -1, -1, -1); + + cell_limit++; + } + + if (cell_limit < 20) { /* if found a surface cell seed */ + int ico[3]; + /* find bucket index where should be inserted */ + ico[0]=(int)(tco[0]*hash->inv_cell_size); + ico[1]=(int)(tco[1]*hash->inv_cell_size); + ico[2]=(int)(tco[2]*hash->inv_cell_size); + + /* iterates to the neighbours cells that probably contains surface also */ + inserted += March3D(dm, scene, ob, sphsurface, surfacetree, ico[0], ico[1], ico[2], hash, psys, -1, -1, -1, -1, -1, -1, -1, -1); + + } + + + if (cell){ MEM_freeN(cell);cell=NULL;} + + return inserted; +} + + + + +void make_cubelist_linked(SpatialHash *hash, GRIDCELL *cubelist, int inserted_cells) +{ + int i; + GRIDCELL *cell= NULL; + LinkNode *linklist= hash->linked_cubelist; + struct LinkNode *index; + index = linklist; + for (i=0; ilink); + + cubelist[i]=*cell; + + index = index->next; + } + +} + + + + +//***************************************************************************** +float squared_distance(float *co1, float *co2) +{ + return (co1[0]-co2[0])*(co1[0]-co2[0]) + (co1[1]-co2[1])*(co1[1]-co2[1]) + (co1[2]-co2[2])*(co1[2]-co2[2]); +} + + +/* for now only insert points */ + void BLI_hash_insert(SpatialHash *hash, int index, float *co, float *nor) + { + int bucket_index = BLI_spatial_hash(co[0], co[1], co[2], hash); + BLI_linklist_prepend(&(hash->buckets[bucket_index]).listpoints,co); + } + + + /* XXX This function fixes bad merging code, in some cases removing vertices creates indices > maxvert */ + +static int test_index_face_maxvert1(MFace *mface, CustomData *fdata, int mfindex, int nr, int maxvert) +{ + if(mface->v1 >= maxvert) { + // printf("bad index in array\n"); + mface->v1= maxvert - 1; + } + if(mface->v2 >= maxvert) { + // printf("bad index in array\n"); + mface->v2= maxvert - 1; + } + if(mface->v3 >= maxvert) { + // printf("bad index in array\n"); + mface->v3= maxvert - 1; + } + if(mface->v4 >= maxvert) { + // printf("bad index in array\n"); + mface->v4= maxvert - 1; + } + + return test_index_face(mface, fdata, mfindex, nr); +} + + + + + + +static DerivedMesh *Simulation_do(ParticleSurfaceModifierData *psd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams) { + + ParticleSurfaceModifierData *sphsurface= (ParticleSurfaceModifierData*) psd; + + ParticleSystem * psys= BLI_findlink(&ob->particlesystem, 0); + DerivedMesh *result = NULL; + ParticleData *pi=NULL; + SpatialHash *hash; + KDTree *surfacetree = sphsurface->surface_tree; + + + PARTICLE_P; + GRIDCELL *cubelist; + + + MVert *newmvert, *newmvert2; + Newmeshfacelist *facelist; + Vertlist *coordinates; + TRIANGLE triangles[100]; + TRIANGLE *tris = NULL; + + int facecounter; + int cell_resol, inserted_cells; + int flag1, flag2, flag3; + int l,total; + int counter; + float cell_size, radius_search, isolevel; + float tempco[3]; + int i, j; + int totpart, numFaces; + int facelistcounter; + int verts; + verts=0; + facelistcounter=0; + counter = 0; + flag1=0; + flag2=0; + flag3=0; + facecounter = 0; + numFaces =0; + facelist = (Newmeshfacelist*)MEM_callocN(sizeof(Newmeshfacelist), "modifier face list surface"); + coordinates = (Vertlist*)MEM_callocN(sizeof(Vertlist), "List of coordinates for mesh memory"); + tris = (TRIANGLE*)MEM_callocN(sizeof(TRIANGLE), "Memory block for TRIANGLES"); + surfacetree = BLI_kdtree_new(psys->totpart); + + + LOOP_DYNAMIC_PARTICLES{ + if (pa->alive == PARS_ALIVE){ + BLI_kdtree_insert(surfacetree, p, pa->state.co, NULL); + } + } + BLI_kdtree_balance(surfacetree); + cell_resol = 1; + + cubelist = NULL; + cell_size= (useRenderParams)? (1.0f/sphsurface->sim_parms->render_resolution) *3.0f: (1.0f/sphsurface->sim_parms->display_resolution) *3.0f; + + radius_search= sphsurface->sim_parms->radius; + isolevel=1.0f/sphsurface->sim_parms->isovalue; + + inserted_cells = 0; + total=0; + + totpart = psys->totpart; + hash=BLI_hash_new(cell_resol, cell_size, isolevel, radius_search); + + LOOP_DYNAMIC_PARTICLES{ + if (pa->alive == PARS_ALIVE){ + inserted_cells+=BLI_spatialhash_insert(dm, scene, ob, sphsurface, surfacetree, hash, pa->state.co, psys); + } + } + + inserted_cells*=hash->cell_resol*hash->cell_resol*hash->cell_resol; + + /* Build the cube list */ + cubelist=(GRIDCELL *)(MEM_callocN(inserted_cells*sizeof(GRIDCELL), "Hash cube")); + make_cubelist_linked(hash, cubelist, inserted_cells); + + /* Feed the polygonizer, marching cubes */ + for (i=0;isurfaceObject->verts = (Vertlist*)MEM_reallocN( sphsurface->surfaceObject->verts, counter * sizeof(Vertlist)); + + + + result = CDDM_new(counter, 0, facecounter/3); + newmvert = CDDM_get_verts(result); + newmvert2 = CDDM_get_verts(result); + + + + for (i = 0; i < counter; i++){ + MVert *mv; + mv = CDDM_get_vert(result, i); + copy_v3_v3(mv->co, coordinates[i].coord); + } + + + sphsurface->surfaceObject->faces = (Newmeshfacelist*)MEM_reallocN( sphsurface->surfaceObject->faces, facecounter* sizeof(Newmeshfacelist)); + + + //coordinates = (Vertlist*)MEM_reallocN( coordinates , (verts-counter) * sizeof(Vertlist)); + //sphsurface->surfaceObject->verts = (Vertlist*)MEM_reallocN( sphsurface->surfaceObject->verts, (verts-counter) * sizeof(Vertlist)); + + memcpy(sphsurface->surfaceObject->faces, facelist, facecounter * sizeof(Newmeshfacelist)); + memcpy(sphsurface->surfaceObject->verts, coordinates, counter * sizeof(Vertlist)); + + for (i = 0; isim_parms->flag == MOD_SMOOTH_SURFACE){ + mface->flag = ME_SMOOTH; + } + else + mface->flag = ME_FACE_SEL; + + /* Cant have index 0 as 3rd corner */ + if(sphsurface->surfaceObject->faces[a+2].index) + { + mface->v1 =sphsurface->surfaceObject->faces[a].index; + mface->v2 = sphsurface->surfaceObject->faces[a+1].index; + mface->v3 = sphsurface->surfaceObject->faces[a+2].index; + } + else if(sphsurface->surfaceObject->faces[a].index) + { + mface->v1 =sphsurface->surfaceObject->faces[a+1].index; + mface->v2 = sphsurface->surfaceObject->faces[a+2].index; + mface->v3 = sphsurface->surfaceObject->faces[a].index; + } + else { + mface->v1 =sphsurface->surfaceObject->faces[a].index; + mface->v2 = sphsurface->surfaceObject->faces[a+2].index; + mface->v3 = sphsurface->surfaceObject->faces[a+1].index; + } + mface->v4 = 0; + + + + numFaces++; + + /* if the face has fewer than 3 vertices, don't create it */ + if(test_index_face_maxvert1(mface, &result->faceData, numFaces-1, 3, counter) < 3) { + numFaces--; + DM_free_face_data(result, numFaces, 1); + } + /* if the face has fewer than 3 vertices, don't create it */ + else test_index_face(mface, NULL, 0, 3); + + } + + CDDM_calc_edges(result); + CDDM_calc_normals(result); + + + sphsurface->surfaceObject->totalfaces = facecounter; + sphsurface->surfaceObject->totalpts = counter; + + if(facelist){MEM_freeN(facelist); facelist = NULL;}; + if(coordinates){MEM_freeN(coordinates); coordinates=NULL;} + + BLI_kdtree_free(surfacetree); + BLI_spatialhash_free(hash); + MEM_freeN(cubelist); + MEM_freeN(tris); + return result; +} + + + + +static DerivedMesh *implicit_set_positions_surface(ParticleSurfaceModifierData *psmd) +{ + + ParticleSurfaceModifierData *surfacedata = psmd; + MVert *newmvert; + + DerivedMesh *result = NULL; + int j, i; + int numfaces = surfacedata->surfaceObject->totalfaces; + int numverts = surfacedata->surfaceObject->totalpts; + int numFaces; + + + numfaces= numfaces/3; + numFaces =0; + result = CDDM_new(numverts, 0, numfaces); + newmvert = CDDM_get_verts(result); + if(!result){ + return NULL; + } + + + for(i = 0; ico, surfacedata->surfaceObject->verts[i].coord); + + } + + + + + for(j=0; jsim_parms->flag == MOD_SMOOTH_SURFACE){ + mface->flag = ME_SMOOTH; + } + else + mface->flag = ME_FACE_SEL; + + + /* Cant have index 0 as 3rd corner */ + if(surfacedata->surfaceObject->faces[a+2].index) + { + mface->v1 =surfacedata->surfaceObject->faces[a].index; + mface->v2 = surfacedata->surfaceObject->faces[a+1].index; + mface->v3 = surfacedata->surfaceObject->faces[a+2].index; + } + else if(surfacedata->surfaceObject->faces[a].index) + { + mface->v1 =surfacedata->surfaceObject->faces[a+1].index; + mface->v2 = surfacedata->surfaceObject->faces[a+2].index; + mface->v3 = surfacedata->surfaceObject->faces[a].index; + } + else { + mface->v1 =surfacedata->surfaceObject->faces[a].index; + mface->v2 = surfacedata->surfaceObject->faces[a+2].index; + mface->v3 = surfacedata->surfaceObject->faces[a+1].index; + } + mface->v4 = 0; + + + + + + numFaces++; + + /* if the face has fewer than 3 vertices, don't create it */ + if(test_index_face_maxvert1(mface, &result->faceData, numFaces-1, 3, numverts) < 3) { + numFaces--; + DM_free_face_data(result, numFaces, 1); + } + /* if the face has fewer than 3 vertices, don't create it */ + else test_index_face(mface, NULL, 0, 3); + + } + + + CDDM_calc_edges(result); + CDDM_calc_normals(result); + + return result; +} + +void init_particlesurfacemodifierdata(ParticleSurfaceModifierData *psd){ + + + if (psd->surfaceObject == NULL){ + psd->surfaceObject = (Surface*)MEM_callocN(sizeof(Surface), "Surface"); + psd->surfaceObject->faces = (Newmeshfacelist*)MEM_callocN(sizeof(Newmeshfacelist), "sphfurface face memory "); + psd->surfaceObject->verts = (Vertlist*)MEM_callocN(sizeof(Vertlist), "sphsurface verts coordinates memomory2"); + + + } + +} + +void free_particlesurfacemodifierdata(ParticleSurfaceModifierData *psd){ + ParticleSurfaceModifierData *psd_md = (ParticleSurfaceModifierData *)psd; + + if(psd_md->surfaceObject){ + MEM_freeN(psd_md->surfaceObject->verts); + psd_md->surfaceObject->verts = NULL; + } + if(psd_md->surfaceObject){ + MEM_freeN(psd_md->surfaceObject->faces); + psd_md->surfaceObject->faces = NULL; + } + if(psd_md->surfaceObject){ + MEM_freeN(psd_md->surfaceObject); + psd_md->surfaceObject = NULL; + } + +} + +static DerivedMesh *ParticleSurfaceModifier_do(ParticleSurfaceModifierData *psd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams) { + /* Ive Seperated out the simulation step into its own function for future pointcache implementation. */ + + PointCache *cache; + + float timescale; + int framenr, startframe, endframe; + int cache_result; + int flag; + PTCacheID pid; + DerivedMesh *result = NULL; + + framenr= (int)scene->r.cfra; + + cache= psd->point_cache; + + + flag = 0; + + + BKE_ptcache_id_from_particlesurface(&pid, ob, psd); + BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); + + /* initialize simulation data if it didn't exist already */ + if(psd->surfaceObject == NULL){ + init_particlesurfacemodifierdata(psd); + + flag = 1; + return result; + } + + /* clear everythin on start frame */ + if(((framenr == startframe) && (cache->flag != PTCACHE_BAKED)) && (flag == 1 || cache->flag & PTCACHE_OUTDATED)){ + cache->flag |= PTCACHE_OUTDATED; + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + BKE_ptcache_validate(cache, startframe); + cache->last_exact= 0; + cache->flag &= ~PTCACHE_REDO_NEEDED; + + return result; + } + + + /* For the play button */ + if(BKE_ptcache_get_continue_physics()){ + + /* initialize simulation data if it didn't exist already */ + if(psd->surfaceObject == NULL){ + init_particlesurfacemodifierdata(psd); + + } + + result = Simulation_do(psd, scene, ob, dm, useRenderParams); + + + free_particlesurfacemodifierdata(psd); + return result; + } + + + + + + /* simulation is only active during a specific period */ + if(framenr < startframe) { + + BKE_ptcache_invalidate(cache); + free_particlesurfacemodifierdata(psd); + return result; + } + else if(framenr > endframe) { + framenr= endframe; + } + + if(&pid){ + + /* try to read from cache */ + cache_result = BKE_ptcache_read(&pid, (float)framenr); + + if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED){ + + result = implicit_set_positions_surface(psd); + + BKE_ptcache_validate(cache, framenr); + + if(cache->flag & PTCACHE_REDO_NEEDED){ + + BKE_ptcache_write(&pid, framenr); + + + } + return result; + } + + /* Cache is supposed to be baked, but no data was found so bail out */ + else if(cache->flag & PTCACHE_BAKED) { + result = Simulation_do(psd, scene, ob, dm, useRenderParams); + BKE_ptcache_validate(cache, framenr); + if(framenr != startframe){ + BKE_ptcache_write(&pid, framenr); + } + return result; + } + + if(cache_result==PTCACHE_READ_OLD) { + + result = implicit_set_positions_surface(psd); + + BKE_ptcache_validate(cache, framenr); + + free_particlesurfacemodifierdata(psd); + return result; + } + + /* if on second frame, write cache for first frame */ + if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)){ + + + BKE_ptcache_write(&pid, framenr); + + + } + } + else{ + BKE_ptcache_invalidate(cache); + } + result = Simulation_do(psd, scene, ob, dm, useRenderParams); + + if(&pid){ + + BKE_ptcache_validate(cache, framenr); + if(framenr != startframe){ + + + BKE_ptcache_write(&pid, framenr); + + + + } + } + + + + + + return result; +} + + + + + + + + + + + + +/* ParticleSurface Modifier */ +static void initData(ModifierData *md) { + ParticleSurfaceModifierData *psd = (ParticleSurfaceModifierData*) md; + + psd->sim_parms = MEM_callocN(sizeof(ParticleSurfaceSimSettings), "particle surface sim parms"); + psd->coll_parms = MEM_callocN(sizeof(ParticleSurfaceCollSettings), "particle surface coll parms"); + psd->point_cache = BKE_ptcache_add(&psd->ptcaches); + + /* check for alloc failing */ + if(!psd->sim_parms || !psd->coll_parms || !psd->point_cache) + return; + + + + psd->sim_parms->spread = 0; + psd->sim_parms->size = 1.0f; + psd->sim_parms->stretch = 0.05f; + psd->sim_parms->render_resolution = 2; + psd->sim_parms->display_resolution = 2; + psd->sim_parms->isovalue = 1.0f; + psd->sim_parms->radius = 1.0f; + psd->sim_parms->fluidradius = 1.5f; + psd->sim_parms->fluidstiffness = 1.0f; + psd->sim_parms->fluidthickness = 0.03f; + psd->sim_parms->isosurface_extraction = ISOSURFACE_EXTRACTION_A; + + if(psd->point_cache) + psd->point_cache->step = 1; +} + +static void copyData(ModifierData *md, ModifierData *target) +{ + ParticleSurfaceModifierData *psd_md = (ParticleSurfaceModifierData*) md; + ParticleSurfaceModifierData *psd_target = (ParticleSurfaceModifierData*) target; + + + psd_target->sim_parms->render_resolution = psd_md->sim_parms->render_resolution; + psd_target->sim_parms->display_resolution = psd_md->sim_parms->display_resolution; + psd_target->sim_parms->isovalue = psd_md->sim_parms->isovalue; + psd_target->sim_parms->radius = psd_md->sim_parms->radius; + psd_target->sim_parms->isosurface_extraction = psd_md->sim_parms->isosurface_extraction; + + + + psd_target->point_cache = BKE_ptcache_copy_list(&psd_target->ptcaches, &psd_md->ptcaches); + psd_target->surfaceObject = NULL; + +} +static void freeData(ModifierData *md) +{ + ParticleSurfaceModifierData *psd_md = (ParticleSurfaceModifierData*) md; + + if(psd_md->sim_parms) { + MEM_freeN(psd_md->sim_parms); + } + if(psd_md->coll_parms) + MEM_freeN(psd_md->coll_parms); + + + BLI_kdtree_free(psd_md->surface_tree); + if(psd_md->surfaceObject){ + MEM_freeN(psd_md->surfaceObject->faces); + psd_md->surfaceObject->faces = NULL; + } + if(psd_md->surfaceObject){ + MEM_freeN(psd_md->surfaceObject->verts); + psd_md->surfaceObject->verts = NULL; + + } + + if(psd_md->surfaceObject){ + MEM_freeN(psd_md->surfaceObject); + psd_md->surfaceObject = NULL; + } + BKE_ptcache_free_list(&psd_md->ptcaches); + psd_md->point_cache = NULL; +} +static DerivedMesh *applyModifier(ModifierData *md, Object *ob, + DerivedMesh *derivedData, + int useRenderParams, + int UNUSED(isFinalCalc)) +{ + unsigned int numverts, i; + float global_pos[3]; + float imat[4][4]; + MVert *verts = NULL; + DerivedMesh *result = NULL; + /* Check for particle system if none just return derived mesh data*/ + ParticleSurfaceModifierData *psd_md = (ParticleSurfaceModifierData*) md; + if (BLI_findlink(&ob->particlesystem, 0)){ + result = ParticleSurfaceModifier_do((ParticleSurfaceModifierData*) md, md->scene, ob, derivedData, useRenderParams); + //free_particlesurfacemodifierdata(psd_md); + + + } + if(result) + { + /* Convert to 3d space */ + + verts = result->getVertArray(result); + + invert_m4_m4(imat, ob->obmat); + numverts = result->getNumVerts(result); + for( i = 0; i< numverts; i++){ + mul_v3_m4v3(global_pos, imat, verts[i].co); + copy_v3_v3(verts[i].co, global_pos); + } + + + return result; + } + + + + return derivedData; +} + + +static int dependsOnTime(ModifierData *UNUSED(md)) +{ + return 1; +} + + + + + + + + + + +ModifierTypeInfo modifierType_ParticleSurface = { + /* name */ "Surface Construction", + /* structName */ "ParticleSurfaceModifierData", + /* structSize */ sizeof(ParticleSurfaceModifierData), + /* type */ eModifierTypeType_Nonconstructive, + + /* flags */ eModifierTypeFlag_RequiresOriginalData + | eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_UsesPointCache + | eModifierTypeFlag_Single, + + + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ NULL, + /* initData */ initData, + /* requiredDataMask */ NULL, + /* freeData */ freeData, + /* isDisabled */ NULL, + /* updateDepgraph */ NULL, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, +}; Index: source/blender/modifiers/intern/MOD_particlesurface.h =================================================================== --- source/blender/modifiers/intern/MOD_particlesurface.h (revision 0) +++ source/blender/modifiers/intern/MOD_particlesurface.h (revision 0) @@ -0,0 +1,234 @@ +/** + * blenlib/BKE_isosurface.h (dic-2009 nzc) + * + * $Id: BKE_isosurface.h 22181 2009-12-19 14:40:10Z farsthary $ + * + * ***** 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) 2001-2002 by Raúl Fernández Hernández (farsthary). + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Raúl Fernádez Hernández. + * + ** \file blender/modifiers/intern/MOD_particlesurface.h + * \ingroup modifiers + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef BKE_ISOSURFACE_H +#define BKE_ISOSURFACE_H + +#include "DNA_modifier_types.h" + + +#define ISO_UPDATE_ALWAYS 0 +#define ISO_UPDATE_HALFRES 1 +#define ISO_UPDATE_FAST 2 +#define ISO_UPDATE_NEVER 3 + +struct HashBucket; +struct SpatialHash; +struct HashNearest; +struct XYZ; +struct TRIANGLE; +struct GRIDCELL; +struct FluidsimModifierData; + + +void make_cube(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface , KDTree *surfacetree, float *central_pos, float cell_resol, GRIDCELL *cube, float radius, ParticleSystem *psys, float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7); + +static DerivedMesh *Simulation_do(ParticleSurfaceModifierData *psd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams); +static DerivedMesh *implicit_set_positions_surface(ParticleSurfaceModifierData *psd); +void init_particlesurfacemodifierdata(ParticleSurfaceModifierData *psd); +void free_particlesurfacemodifierdata(ParticleSurfaceModifierData *psd); + +float BLI_surface_eval(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface , KDTree *surfacetree, float radius, float *pos, float *centerpos, ParticleSystem *psys); + +SpatialHash* BLI_hash_new(int cell_resol, float cell_size, float isolevel, float radius); + +int BLI_spatialhash_insert(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface , KDTree *surfacetree, SpatialHash *hash, float *co, ParticleSystem *psys); /* This is used in surface generation */ +void BLI_spatialhash_free(SpatialHash *hash); +int BLI_spatial_hash(float x, float y, float z, SpatialHash *hash); + +//------- NN search ------ +/* Construction: first insert points. Normal is optional. */ +void BLI_hash_insert(SpatialHash *hash, int index, float *co, float *nor); + +/* Range search returns number of points found, with results in nearest */ +/* Normal is optional, but if given will limit results to points in normal direction from co. */ +/* Remember to free nearest after use! */ +int BLI_hash_range_search(SpatialHash *hash, float range, float *co, float *nor, HashNearest **nearest); + + +#endif +/** + * blenlib/BKE_isosurface.h (dic-2009 nzc) + * + * $Id: BKE_isosurface.h 22181 2009-12-19 14:40:10Z farsthary $ + * + * ***** 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) 2001-2002 by Raúl Fernández Hernández (farsthary). + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Raúl Fernádez Hernández. + * + ** \file blender/modifiers/intern/MOD_particlesurface.h + * \ingroup modifiers + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef BKE_ISOSURFACE_H +#define BKE_ISOSURFACE_H + +#include "DNA_modifier_types.h" + + +#define ISO_UPDATE_ALWAYS 0 +#define ISO_UPDATE_HALFRES 1 +#define ISO_UPDATE_FAST 2 +#define ISO_UPDATE_NEVER 3 + +struct HashBucket; +struct SpatialHash; +struct HashNearest; +struct XYZ; +struct TRIANGLE; +struct GRIDCELL; +struct FluidsimModifierData; + + +void make_cube(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface , KDTree *surfacetree, float *central_pos, float cell_resol, GRIDCELL *cube, float radius, ParticleSystem *psys, float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7); + +static DerivedMesh *Simulation_do(ParticleSurfaceModifierData *psd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams); +static DerivedMesh *implicit_set_positions_surface(ParticleSurfaceModifierData *psd, Object *ob); +void init_particlesurfacemodifierdata(ParticleSurfaceModifierData *psd); +void free_particlesurfacemodifierdata(ParticleSurfaceModifierData *psd); + +float BLI_surface_eval(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface , KDTree *surfacetree, float radius, float *pos, float *centerpos, ParticleSystem *psys); + +SpatialHash* BLI_hash_new(int cell_resol, float cell_size, float isolevel, float radius); + +int BLI_spatialhash_insert(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface , KDTree *surfacetree, SpatialHash *hash, float *co, ParticleSystem *psys); /* This is used in surface generation */ +void BLI_spatialhash_free(SpatialHash *hash); +int BLI_spatial_hash(float x, float y, float z, SpatialHash *hash); + +//------- NN search ------ +/* Construction: first insert points. Normal is optional. */ +void BLI_hash_insert(SpatialHash *hash, int index, float *co, float *nor); + +/* Range search returns number of points found, with results in nearest */ +/* Normal is optional, but if given will limit results to points in normal direction from co. */ +/* Remember to free nearest after use! */ +int BLI_hash_range_search(SpatialHash *hash, float range, float *co, float *nor, HashNearest **nearest); + + +#endif +/** + * blenlib/BKE_isosurface.h (dic-2009 nzc) + * + * $Id: BKE_isosurface.h 22181 2009-12-19 14:40:10Z farsthary $ + * + * ***** 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) 2001-2002 by Raúl Fernández Hernández (farsthary). + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Raúl Fernádez Hernández. + * + ** \file blender/modifiers/intern/MOD_particlesurface.h + * \ingroup modifiers + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef BKE_ISOSURFACE_H +#define BKE_ISOSURFACE_H + +#include "DNA_modifier_types.h" + + +#define ISO_UPDATE_ALWAYS 0 +#define ISO_UPDATE_HALFRES 1 +#define ISO_UPDATE_FAST 2 +#define ISO_UPDATE_NEVER 3 + +struct HashBucket; +struct SpatialHash; +struct HashNearest; +struct XYZ; +struct TRIANGLE; +struct GRIDCELL; +struct FluidsimModifierData; + + +void make_cube(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface , KDTree *surfacetree, float *central_pos, float cell_resol, GRIDCELL *cube, float radius, ParticleSystem *psys, float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7); + +static DerivedMesh *Simulation_do(ParticleSurfaceModifierData *psd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams); +static DerivedMesh *implicit_set_positions_surface(ParticleSurfaceModifierData *psd); +void init_particlesurfacemodifierdata(ParticleSurfaceModifierData *psd); +void free_particlesurfacemodifierdata(ParticleSurfaceModifierData *psd); + +float BLI_surface_eval(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface , KDTree *surfacetree, float radius, float *pos, float *centerpos, ParticleSystem *psys); + +SpatialHash* BLI_hash_new(int cell_resol, float cell_size, float isolevel, float radius); + +int BLI_spatialhash_insert(DerivedMesh *dm, Scene *scene, Object *ob, ParticleSurfaceModifierData *sphsurface , KDTree *surfacetree, SpatialHash *hash, float *co, ParticleSystem *psys); /* This is used in surface generation */ +void BLI_spatialhash_free(SpatialHash *hash); +int BLI_spatial_hash(float x, float y, float z, SpatialHash *hash); + +//------- NN search ------ +/* Construction: first insert points. Normal is optional. */ +void BLI_hash_insert(SpatialHash *hash, int index, float *co, float *nor); + +/* Range search returns number of points found, with results in nearest */ +/* Normal is optional, but if given will limit results to points in normal direction from co. */ +/* Remember to free nearest after use! */ +int BLI_hash_range_search(SpatialHash *hash, float range, float *co, float *nor, HashNearest **nearest); + + +#endif Index: source/blender/modifiers/intern/MOD_util.c =================================================================== --- source/blender/modifiers/intern/MOD_util.c (revision 41360) +++ source/blender/modifiers/intern/MOD_util.c (working copy) @@ -296,5 +296,6 @@ INIT_TYPE(WeightVGEdit); INIT_TYPE(WeightVGMix); INIT_TYPE(WeightVGProximity); + INIT_TYPE(ParticleSurface); #undef INIT_TYPE } Index: source/blender/modifiers/MOD_modifiertypes.h =================================================================== --- source/blender/modifiers/MOD_modifiertypes.h (revision 41360) +++ source/blender/modifiers/MOD_modifiertypes.h (working copy) @@ -74,6 +74,8 @@ extern ModifierTypeInfo modifierType_WeightVGEdit; extern ModifierTypeInfo modifierType_WeightVGMix; extern ModifierTypeInfo modifierType_WeightVGProximity; +extern ModifierTypeInfo modifierType_ParticleSurface; +extern ModifierTypeInfo modifierType_ParticleSurfaceCol; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); Index: source/creator/buildinfo.h.rule =================================================================== --- source/creator/buildinfo.h.rule (revision 0) +++ source/creator/buildinfo.h.rule (revision 0) @@ -0,0 +1,24 @@ +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake +# generated from CMake