Fix [#22469] Crashes with "segmentation fault" when opening an image for Voxel Data...
authorMatt Ebb <matt@mke3.net>
Tue, 1 Jun 2010 06:07:22 +0000 (06:07 +0000)
committerMatt Ebb <matt@mke3.net>
Tue, 1 Jun 2010 06:07:22 +0000 (06:07 +0000)
Cleaned up the code here, made it more efficient and more reliable with threaded render.

release/scripts/ui/properties_texture.py
source/blender/blenkernel/intern/texture.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_texture_types.h
source/blender/makesrna/intern/rna_texture.c
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/voxeldata.c

index 39c6bdf1d9f32c96e1e90304d2487260b4edaa0b..eb1c547e4191ef86d6bb3bc30b44d0dd00a4e8a2 100644 (file)
@@ -961,7 +961,9 @@ class TEXTURE_PT_voxeldata(TextureButtonsPanel):
             layout.prop(vd, "domain_object")
             layout.prop(vd, "smoke_data_type")
         elif vd.file_format == 'IMAGE_SEQUENCE':
-            layout.template_image(tex, "image", tex.image_user)
+            layout.template_ID(tex, "image", open="image.open")
+            layout.template_image(tex, "image", tex.image_user, compact=True)
+            #layout.prop(vd, "frames")
 
         layout.prop(vd, "still")
         row = layout.row()
index 873a4103e3eabea30a60e61fcac216097fc79303..6d8c339d2b98e8cbf45728013532b044c91943b8 100644 (file)
@@ -1149,7 +1149,8 @@ void BKE_free_pointdensity(PointDensity *pd)
 void BKE_free_voxeldatadata(struct VoxelData *vd)
 {
        if (vd->dataset) {
-               MEM_freeN(vd->dataset);
+               if(vd->file_format != TEX_VD_SMOKE)
+                       MEM_freeN(vd->dataset);
                vd->dataset = NULL;
        }
 
@@ -1173,6 +1174,8 @@ struct VoxelData *BKE_add_voxeldata(void)
        vd->int_multiplier = 1.0;
        vd->extend = TEX_CLIP;
        vd->object = NULL;
+       vd->cachedframe = -1;
+       vd->ok = 0;
        
        return vd;
  }
index 61685ccefcee8ed6b636e1961212398e94acad7d..b0256159e14d6a1aa9a53c9f857f9aa86ec2c25b 100644 (file)
@@ -2839,6 +2839,7 @@ static void direct_link_texture(FileData *fd, Tex *tex)
        tex->vd= newdataadr(fd, tex->vd);
        if(tex->vd) {
                tex->vd->dataset = NULL;
+               tex->vd->ok = 0;
        }
        
        tex->nodetree= newdataadr(fd, tex->nodetree);
index 2c5c50d7dc2cbdbd6e57bf136160069caf870a0d..b6f72875c29882c0df9659b4eb3032a344febc72 100644 (file)
@@ -190,8 +190,12 @@ typedef struct VoxelData {
        float int_multiplier;   
        int still_frame;
        char source_path[240];
+
+       /* temporary data */
        float *dataset;
+       int cachedframe;
+       int ok;
+       
 } VoxelData;
 
 typedef struct Tex {
index 5e58403e41b398a50686619ab53b941c89c93fc2..32221e51cb9a76b0a2bef727424393bcbfbe1956 100644 (file)
@@ -75,6 +75,7 @@ EnumPropertyItem texture_type_items[] = {
 #include "RNA_access.h"
 
 #include "BKE_depsgraph.h"
+#include "BKE_image.h"
 #include "BKE_texture.h"
 #include "BKE_main.h"
 
@@ -131,6 +132,22 @@ static void rna_Texture_update(Main *bmain, Scene *scene, PointerRNA *ptr)
        WM_main_add_notifier(NC_TEXTURE, tex);
 }
 
+static void rna_Texture_voxeldata_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+       Tex *tex= ptr->id.data;
+       
+       tex->vd->ok = 0;
+       rna_Texture_update(bmain, scene, ptr);
+}
+
+static void rna_Texture_voxeldata_image_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+       Tex *tex= ptr->id.data;
+       
+       tex->ima->source = IMA_SRC_SEQUENCE;
+       rna_Texture_voxeldata_update(bmain, scene, ptr);
+}
+
 /* Used for Texture Properties, used (also) for/in Nodes */
 static void rna_Texture_nodes_update(Main *bmain, Scene *scene, PointerRNA *ptr)
 {
@@ -1593,7 +1610,7 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna)
        RNA_def_property_enum_sdna(prop, NULL, "smoked_type");
        RNA_def_property_enum_items(prop, smoked_type_items);
        RNA_def_property_ui_text(prop, "Source", "Simulation value to be used as a texture");
-       RNA_def_property_update(prop, 0, "rna_Texture_update");
+       RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_update");
        
        prop= RNA_def_property(srna, "extension", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "extend");
@@ -1611,34 +1628,34 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna)
        RNA_def_property_enum_sdna(prop, NULL, "file_format");
        RNA_def_property_enum_items(prop, file_format_items);
        RNA_def_property_ui_text(prop, "File Format", "Format of the source data set to render  ");
-       RNA_def_property_update(prop, 0, "rna_Texture_update");
+       RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_update");
        
        prop= RNA_def_property(srna, "source_path", PROP_STRING, PROP_FILEPATH);
        RNA_def_property_string_sdna(prop, NULL, "source_path");
        RNA_def_property_ui_text(prop, "Source Path", "The external source data file to use");
-       RNA_def_property_update(prop, 0, "rna_Texture_update");
+       RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_update");
        
        prop= RNA_def_property(srna, "resolution", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "resol");
        RNA_def_property_ui_text(prop, "Resolution", "Resolution of the voxel grid");
-       RNA_def_property_update(prop, 0, "rna_Texture_update");
+       RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_update");
        
        prop= RNA_def_property(srna, "still", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", TEX_VD_STILL);
        RNA_def_property_ui_text(prop, "Still Frame Only", "Always render a still frame from the voxel data sequence");
-       RNA_def_property_update(prop, 0, "rna_Texture_update");
+       RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_update");
        
        prop= RNA_def_property(srna, "still_frame_number", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "still_frame");
        RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
        RNA_def_property_ui_text(prop, "Still Frame Number", "The frame number to always use");
-       RNA_def_property_update(prop, 0, "rna_Texture_update");
+       RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_update");
        
        prop= RNA_def_property(srna, "domain_object", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "object");
        RNA_def_property_ui_text(prop, "Domain Object", "Object used as the smoke simulation domain");
        RNA_def_property_flag(prop, PROP_EDITABLE);
-       RNA_def_property_update(prop, 0, "rna_Texture_update");
+       RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_update");
 
        
        srna= RNA_def_struct(brna, "VoxelDataTexture", "Texture");
@@ -1656,12 +1673,12 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna)
        RNA_def_property_struct_type(prop, "Image");
        RNA_def_property_flag(prop, PROP_EDITABLE);
        RNA_def_property_ui_text(prop, "Image", "");
-       RNA_def_property_update(prop, 0, "rna_Texture_update");
+       RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_image_update");
        
        prop= RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NEVER_NULL);
        RNA_def_property_pointer_sdna(prop, NULL, "iuser");
        RNA_def_property_ui_text(prop, "Image User", "Parameters defining which layer, pass and frame of the image is displayed");
-       RNA_def_property_update(prop, 0, "rna_Texture_update");
+       RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_update");
 }
 
 static void rna_def_texture(BlenderRNA *brna)
index 86c6a325bcdc260d245a4bd2dadfff70d0c66d07..deb3d99f9edd245ce51877d7495962a3c4582759 100644 (file)
@@ -4595,7 +4595,6 @@ void RE_Database_Free(Render *re)
        end_render_textures();
        
        free_pointdensities(re);
-       free_voxeldata(re);
        
        free_camera_inside_volumes(re);
        
index 3ac806f320ac05cdb0218917a13888e85efbfe83..64ba206bb8697626c38160e0089ec28fc2239e22 100644 (file)
 #include "texture.h"
 #include "voxeldata.h"
 
-static int load_frame_blendervoxel(FILE *fp, float *F, int size, int frame, int offset)
+static int load_frame_blendervoxel(VoxelData *vd, FILE *fp, int frame)
 {      
-       if(fseek(fp,frame*size*sizeof(float)+offset,0) == -1)
+       size_t offset = sizeof(VoxelDataHeader);
+       int size = (vd->resol[0])*(vd->resol[1])*(vd->resol[2]);
+       
+       vd->dataset = MEM_mapallocN(sizeof(float)*size, "voxel dataset");
+       
+       if(fseek(fp, frame*size*sizeof(float)+offset, 0) == -1)
                return 0;
-       if(fread(F,sizeof(float),size,fp) != size)
+       if(fread(vd->dataset, sizeof(float), size, fp) != size)
                return 0;
        
+       vd->cachedframe = frame;
+       vd->ok = 1;
        return 1;
 }
 
-static int load_frame_raw8(FILE *fp, float *F, int size, int frame)
+static int load_frame_raw8(VoxelData *vd, FILE *fp, int frame)
 {
-       char *tmp;
+       int size = (vd->resol[0])*(vd->resol[1])*(vd->resol[2]);
+       char *data_c;
        int i;
        
-       tmp = (char *)MEM_mallocN(sizeof(char)*size, "temporary voxel file reading storage");
+       vd->dataset = MEM_mapallocN(sizeof(float)*size, "voxel dataset");
+       data_c = (char *)MEM_mallocN(sizeof(char)*size, "temporary voxel file reading storage");
        
        if(fseek(fp,(frame-1)*size*sizeof(char),0) == -1) {
-               MEM_freeN(tmp);
+               MEM_freeN(data_c);
                return 0;
        }
-       if(fread(tmp, sizeof(char), size, fp) != size) {
-               MEM_freeN(tmp);
+       if(fread(data_c, sizeof(char), size, fp) != size) {
+               MEM_freeN(data_c);
                return 0;
        }
        
        for (i=0; i<size; i++) {
-               F[i] = (float)tmp[i] / 256.f;
+               vd->dataset[i] = (float)data_c[i] / 255.f;
        }
-       MEM_freeN(tmp);
+       MEM_freeN(data_c);
+       
+       vd->cachedframe = frame;
+       vd->ok = 1;
        return 1;
 }
 
-static void load_frame_image_sequence(Render *re, VoxelData *vd, Tex *tex)
+static void load_frame_image_sequence(VoxelData *vd, Tex *tex)
 {
        ImBuf *ibuf;
        Image *ima = tex->ima;
-       ImageUser *iuser = &tex->iuser;
+       ImageUser *tiuser = &tex->iuser;
+       ImageUser iuser = *(tiuser);
        int x=0, y=0, z=0;
        float *rf;
 
-       if (!ima || !iuser) return;
+       if (!ima || !tiuser) return;
+       if (iuser.frames == 0) return;
        
        ima->source = IMA_SRC_SEQUENCE;
-       iuser->framenr = 1 + iuser->offset;
+       iuser.framenr = 1 + iuser.offset;
 
        /* find the first valid ibuf and use it to initialise 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);
-       while (!ibuf && (iuser->framenr < iuser->frames)) {
-               iuser->framenr++;
-               ibuf= BKE_image_get_ibuf(ima, iuser);
+       ibuf= BKE_image_get_ibuf(ima, &iuser);
+       while (!ibuf && (iuser.framenr < iuser.frames)) {
+               iuser.framenr++;
+               ibuf= BKE_image_get_ibuf(ima, &iuser);
        }
        if (!ibuf) return;
        if (!ibuf->rect_float) IMB_float_from_rect(ibuf);
@@ -116,15 +130,15 @@ static void load_frame_image_sequence(Render *re, VoxelData *vd, Tex *tex)
        vd->flag |= TEX_VD_STILL;
        vd->resol[0] = ibuf->x;
        vd->resol[1] = ibuf->y;
-       vd->resol[2] = iuser->frames;
+       vd->resol[2] = iuser.frames;
        vd->dataset = MEM_mapallocN(sizeof(float)*(vd->resol[0])*(vd->resol[1])*(vd->resol[2]), "voxel dataset");
        
-       for (z=0; z < iuser->frames; z++)
+       for (z=0; z < iuser.frames; z++)
        {       
                /* get a new ibuf for each frame */
                if (z > 0) {
-                       iuser->framenr++;
-                       ibuf= BKE_image_get_ibuf(ima, iuser);
+                       iuser.framenr++;
+                       ibuf= BKE_image_get_ibuf(ima, &iuser);
                        if (!ibuf) break;
                        if (!ibuf->rect_float) IMB_float_from_rect(ibuf);
                }
@@ -134,14 +148,17 @@ static void load_frame_image_sequence(Render *re, VoxelData *vd, Tex *tex)
                {
                        for (x=0; x < ibuf->x; x++)
                        {
-                               /* currently converted to monchrome */
+                               /* currently averaged to monchrome */
                                vd->dataset[ V_I(x, y, z, vd->resol) ] = (rf[0] + rf[1] + rf[2])*0.333f;
                                rf +=4;
                        }
                }
                
-               BKE_image_free_anim_ibufs(ima, iuser->framenr);
+               BKE_image_free_anim_ibufs(ima, iuser.framenr);
        }
+       
+       vd->ok = 1;
+       return;
 }
 
 static int read_voxeldata_header(FILE *fp, struct VoxelData *vd)
@@ -162,7 +179,7 @@ static int read_voxeldata_header(FILE *fp, struct VoxelData *vd)
        return 1;
 }
 
-static void init_frame_smoke(Render *re, VoxelData *vd, Tex *tex)
+static void init_frame_smoke(VoxelData *vd, Tex *tex)
 {
        Object *ob;
        ModifierData *md;
@@ -232,53 +249,65 @@ static void init_frame_smoke(Render *re, VoxelData *vd, Tex *tex)
                        } // end of fluid condition
                }
        }
+       
+       vd->ok = 1;
+       return;
 }
 
 static void cache_voxeldata(struct Render *re,Tex *tex)
 {      
        VoxelData *vd = tex->vd;
        FILE *fp;
-       int size;
        int curframe;
        
        if (!vd) return;
        
-       /* image sequence gets special treatment */
-       if (vd->file_format == TEX_VD_IMAGE_SEQUENCE) {
-               load_frame_image_sequence(re, vd, tex);
-               return;
-       } else if (vd->file_format == TEX_VD_SMOKE) {
-               init_frame_smoke(re, vd, tex);
-               return;
+       /* only re-cache if dataset needs updating */
+       if ((vd->flag & TEX_VD_STILL) || (vd->cachedframe == re->r.cfra))
+               if (vd->ok) return;
+       
+       /* clear out old cache, ready for new */
+       if (vd->dataset) {
+               if(vd->file_format != TEX_VD_SMOKE)
+                       MEM_freeN(vd->dataset);
+               vd->dataset = NULL;
        }
 
-       if (!BLI_exists(vd->source_path)) return;
-       fp = fopen(vd->source_path,"rb");
-       if (!fp) return;
-
-       if (vd->file_format == TEX_VD_BLENDERVOXEL) {
-               if(!read_voxeldata_header(fp, vd)) {
-                       fclose(fp);
-                       return;
-               }
-       }
-       
-       size = (vd->resol[0])*(vd->resol[1])*(vd->resol[2]);
-       vd->dataset = MEM_mapallocN(sizeof(float)*size, "voxel dataset");
-               
-       if (vd->flag & TEX_VD_STILL) curframe = vd->still_frame;
-       else curframe = re->r.cfra;
+       if (vd->flag & TEX_VD_STILL)
+               curframe = vd->still_frame;
+       else
+               curframe = re->r.cfra;
        
        switch(vd->file_format) {
+               case TEX_VD_IMAGE_SEQUENCE:
+                       load_frame_image_sequence(vd, tex);
+                       return;
+               case TEX_VD_SMOKE:
+                       init_frame_smoke(vd, tex);
+                       return;
                case TEX_VD_BLENDERVOXEL:
-                       load_frame_blendervoxel(fp, vd->dataset, size, curframe-1, sizeof(VoxelDataHeader));
-                       break;
+                       if (!BLI_exists(vd->source_path)) return;
+                       fp = fopen(vd->source_path,"rb");
+                       if (!fp) return;
+                       
+                       if(read_voxeldata_header(fp, vd))
+                               load_frame_blendervoxel(vd, fp, curframe-1);
+                       else
+                               fclose(fp);
+                       
+                       return;
                case TEX_VD_RAW_8BIT:
-                       load_frame_raw8(fp, vd->dataset, size, curframe);
-                       break;
+                       if (!BLI_exists(vd->source_path)) return;
+                       fp = fopen(vd->source_path,"rb");
+                       if (!fp) return;
+                       
+                       if (load_frame_raw8(vd, fp, curframe))
+                               ;
+                       else    
+                               fclose(fp);
+                       
+                       return;
        }
-       
-       fclose(fp);
 }
 
 void make_voxeldata(struct Render *re)
@@ -300,29 +329,6 @@ void make_voxeldata(struct Render *re)
        
 }
 
-static void free_voxeldata_one(Render *re, Tex *tex)
-{
-       VoxelData *vd = tex->vd;
-       
-       if (vd->dataset) {
-               if(vd->file_format != TEX_VD_SMOKE)
-                       MEM_freeN(vd->dataset);
-               vd->dataset = NULL;
-       }
-}
-
-
-void free_voxeldata(Render *re)
-{
-       Tex *tex;
-       
-       for (tex= G.main->tex.first; tex; tex= tex->id.next) {
-               if(tex->id.us && tex->type==TEX_VOXELDATA) {
-                       free_voxeldata_one(re, tex);
-               }
-       }
-}
-
 int voxeldatatex(struct Tex *tex, float *texvec, struct TexResult *texres)
 {       
        int retval = TEX_INT;