Moved the cloth solver code into a new subfolder/library inside Blender
[blender.git] / source / blender / render / intern / source / voxeldata.c
index 7eccacb816da87e1599bed2030f257d071a75aad..6f3c50bca62a61cdf134361d5d4ca10498dfd358 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
 
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
 #include "MEM_guardedalloc.h"
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
+#include "BLI_threads.h"
 #include "BLI_voxel.h"
 #include "BLI_utildefines.h"
 
+#include "BLF_translation.h"
+
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 
+#include "BKE_cloth.h"
 #include "BKE_global.h"
 #include "BKE_image.h"
 #include "BKE_main.h"
 #include "DNA_texture_types.h"
 #include "DNA_object_force.h"
 #include "DNA_object_types.h"
+#include "DNA_particle_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_smoke_types.h"
 
 
 #include "render_types.h"
-#include "renderdatabase.h"
 #include "texture.h"
 #include "voxeldata.h"
 
-static int is_vd_res_ok(VoxelData *vd)
+static bool is_vd_res_ok(VoxelData *vd)
 {
        /* arbitrary large value so corrupt headers don't break */
        const int min = 1, max = 100000;
@@ -83,7 +91,7 @@ static int load_frame_blendervoxel(VoxelData *vd, FILE *fp, int frame)
        const size_t size = vd_resol_size(vd);
        size_t offset = sizeof(VoxelDataHeader);
        
-       if (is_vd_res_ok(vd) == FALSE)
+       if (is_vd_res_ok(vd) == false)
                return 0;
 
        vd->dataset = MEM_mapallocN(sizeof(float) * size, "voxel dataset");
@@ -102,10 +110,10 @@ static int load_frame_blendervoxel(VoxelData *vd, FILE *fp, int frame)
 static int load_frame_raw8(VoxelData *vd, FILE *fp, int frame)
 {
        const size_t size = vd_resol_size(vd);
+       size_t i;
        char *data_c;
-       int i;
 
-       if (is_vd_res_ok(vd) == FALSE)
+       if (is_vd_res_ok(vd) == false)
                return 0;
 
        vd->dataset = MEM_mapallocN(sizeof(float) * size, "voxel dataset");
@@ -147,9 +155,9 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex)
        ImageUser *tiuser = &tex->iuser;
        ImageUser iuser = *(tiuser);
        int x = 0, y = 0, z = 0;
-       float *rf;
+       const float *rf;
 
-       if (!ima || !tiuser) return;
+       if (!ima) return;
        if (iuser.frames == 0) return;
        
        ima->source = IMA_SRC_SEQUENCE;
@@ -157,10 +165,10 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex)
 
        /* find the first valid ibuf and use it to initialize the resolution of the data set */
        /* need to do this in advance so we know how much memory to allocate */
-       ibuf = BKE_image_get_ibuf(ima, &iuser);
+       ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
        while (!ibuf && (iuser.framenr < iuser.frames)) {
                iuser.framenr++;
-               ibuf = BKE_image_get_ibuf(ima, &iuser);
+               ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
        }
        if (!ibuf) return;
        if (!ibuf->rect_float) IMB_float_from_rect(ibuf);
@@ -175,7 +183,8 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex)
                /* get a new ibuf for each frame */
                if (z > 0) {
                        iuser.framenr++;
-                       ibuf = BKE_image_get_ibuf(ima, &iuser);
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                       ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
                        if (!ibuf) break;
                        if (!ibuf->rect_float) IMB_float_from_rect(ibuf);
                }
@@ -184,14 +193,16 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex)
                for (y = 0; y < ibuf->y; y++) {
                        for (x = 0; x < ibuf->x; x++) {
                                /* currently averaged to monchrome */
-                               vd->dataset[BLI_VOXEL_INDEX(x, y, z, vd->resol)] = (rf[0] + rf[1] + rf[2]) * 0.333f;
+                               vd->dataset[BLI_VOXEL_INDEX(x, y, z, vd->resol)] = (rf[0] + rf[1] + rf[2]) / 3.0f;
                                rf += 4;
                        }
                }
                
                BKE_image_free_anim_ibufs(ima, iuser.framenr);
        }
-       
+
+       BKE_image_release_ibuf(ima, ibuf, NULL);
+
        vd->ok = 1;
        return;
 }
@@ -214,7 +225,7 @@ static int read_voxeldata_header(FILE *fp, struct VoxelData *vd)
        return 1;
 }
 
-static void init_frame_smoke(VoxelData *vd, float cfra)
+static void init_frame_smoke(VoxelData *vd, int cfra)
 {
 #ifdef WITH_SMOKE
        Object *ob;
@@ -230,6 +241,13 @@ static void init_frame_smoke(VoxelData *vd, float cfra)
                SmokeDomainSettings *sds = smd->domain;
                
                if (sds && sds->fluid) {
+                       BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
+
+                       if (!sds->fluid) {
+                               BLI_rw_mutex_unlock(sds->fluid_mutex);
+                               return;
+                       }
+
                        if (cfra < sds->point_cache[0]->startframe)
                                ;  /* don't show smoke before simulation starts, this could be made an option in the future */
                        else if (vd->smoked_type == TEX_VD_SMOKEHEAT) {
@@ -237,7 +255,10 @@ static void init_frame_smoke(VoxelData *vd, float cfra)
                                size_t i;
                                float *heat;
 
-                               if (!smoke_has_heat(sds->fluid)) return;
+                               if (!smoke_has_heat(sds->fluid)) {
+                                       BLI_rw_mutex_unlock(sds->fluid_mutex);
+                                       return;
+                               }
 
                                copy_v3_v3_int(vd->resol, sds->res);
                                totRes = vd_resol_size(vd);
@@ -265,7 +286,7 @@ static void init_frame_smoke(VoxelData *vd, float cfra)
 
                                /* map velocities between 0 and 0.3f */
                                for (i = 0; i < totRes; i++) {
-                                       vd->dataset[i] = sqrt(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f;
+                                       vd->dataset[i] = sqrtf(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f;
                                }
 
                        }
@@ -274,18 +295,24 @@ static void init_frame_smoke(VoxelData *vd, float cfra)
                                float *flame;
 
                                if (sds->flags & MOD_SMOKE_HIGHRES) {
-                                       if (!smoke_turbulence_has_fuel(sds->wt)) return;
+                                       if (!smoke_turbulence_has_fuel(sds->wt)) {
+                                               BLI_rw_mutex_unlock(sds->fluid_mutex);
+                                               return;
+                                       }
                                        smoke_turbulence_get_res(sds->wt, vd->resol);
                                        flame = smoke_turbulence_get_flame(sds->wt);
                                }
                                else {
-                                       if (!smoke_has_fuel(sds->fluid)) return;
+                                       if (!smoke_has_fuel(sds->fluid)) {
+                                               BLI_rw_mutex_unlock(sds->fluid_mutex);
+                                               return;
+                                       }
                                        copy_v3_v3_int(vd->resol, sds->res);
                                        flame = smoke_get_flame(sds->fluid);
                                }
 
                                /* always store copy, as smoke internal data can change */
-                               totRes= vd_resol_size(vd);
+                               totRes = vd_resol_size(vd);
                                vd->dataset = MEM_mapallocN(sizeof(float)*(totRes), "smoke data");
                                memcpy(vd->dataset, flame, sizeof(float)*totRes);
                        }
@@ -324,6 +351,8 @@ static void init_frame_smoke(VoxelData *vd, float cfra)
                                        }
                                }
                        }  /* end of fluid condition */
+
+                       BLI_rw_mutex_unlock(sds->fluid_mutex);
                }
        }
        
@@ -337,6 +366,28 @@ static void init_frame_smoke(VoxelData *vd, float cfra)
 #endif
 }
 
+static void init_frame_hair(VoxelData *vd, int UNUSED(cfra))
+{
+       Object *ob;
+       ModifierData *md;
+       bool found = false;
+       
+       vd->dataset = NULL;
+       if (vd->object == NULL) return;
+       ob = vd->object;
+       
+       if ((md = (ModifierData *)modifiers_findByType(ob, eModifierType_ParticleSystem))) {
+               ParticleSystemModifierData *pmd = (ParticleSystemModifierData *)md;
+               
+               if (pmd->psys && pmd->psys->clmd) {
+                       // XXX TODO was moved into own subfolder, figure out how to handle this (perhaps make a wrapper in BKE)
+//                     found |= implicit_hair_volume_get_texture_data(ob, pmd->psys->clmd, NULL, vd);
+               }
+       }
+       
+       vd->ok = found;
+}
+
 void cache_voxeldata(Tex *tex, int scene_frame)
 {      
        VoxelData *vd = tex->vd;
@@ -370,6 +421,9 @@ void cache_voxeldata(Tex *tex, int scene_frame)
                case TEX_VD_SMOKE:
                        init_frame_smoke(vd, scene_frame);
                        return;
+               case TEX_VD_HAIR:
+                       init_frame_hair(vd, scene_frame);
+                       return;
                case TEX_VD_BLENDERVOXEL:
                        BLI_path_abs(path, G.main->name);
                        if (!BLI_exists(path)) return;
@@ -397,7 +451,7 @@ void make_voxeldata(struct Render *re)
 {
        Tex *tex;
        
-       re->i.infostr = "Loading voxel datasets";
+       re->i.infostr = IFACE_("Loading voxel datasets");
        re->stats_draw(re->sdh, &re->i);
        
        /* XXX: should be doing only textures used in this render */
@@ -414,7 +468,7 @@ void make_voxeldata(struct Render *re)
 
 int voxeldatatex(struct Tex *tex, const float texvec[3], struct TexResult *texres)
 {       
-       VoxelData *vd = tex->vd;        
+       VoxelData *vd = tex->vd;
        float co[3], offset[3] = {0.5, 0.5, 0.5}, a;
        int retval = (vd->data_type == TEX_VD_RGBA_PREMUL) ? TEX_RGB : TEX_INT;
        int depth = (vd->data_type == TEX_VD_RGBA_PREMUL) ? 4 : 1;
@@ -482,7 +536,7 @@ int voxeldatatex(struct Tex *tex, const float texvec[3], struct TexResult *texre
                                break;  
                        case TEX_VD_LINEAR:
                                *result = BLI_voxel_sample_trilinear(dataset, vd->resol, co);
-                               break;                                  
+                               break;
                        case TEX_VD_QUADRATIC:
                                *result = BLI_voxel_sample_triquadratic(dataset, vd->resol, co);
                                break;
@@ -515,5 +569,5 @@ int voxeldatatex(struct Tex *tex, const float texvec[3], struct TexResult *texre
        texres->ta = texres->tin;
        BRICONTRGB;
        
-       return retval;  
+       return retval;
 }