Fix [#22469] Crashes with "segmentation fault" when opening an image for Voxel Data texture of type Image sequence

Cleaned up the code here, made it more efficient and more reliable with threaded render.
This commit is contained in:
Matt Ebb 2010-06-01 06:07:22 +00:00
parent 80a89d2de5
commit eab7f6d3c2
7 changed files with 125 additions and 93 deletions

@ -961,7 +961,9 @@ class TEXTURE_PT_voxeldata(TextureButtonsPanel):
layout.prop(vd, "domain_object") layout.prop(vd, "domain_object")
layout.prop(vd, "smoke_data_type") layout.prop(vd, "smoke_data_type")
elif vd.file_format == 'IMAGE_SEQUENCE': 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") layout.prop(vd, "still")
row = layout.row() row = layout.row()

@ -1149,7 +1149,8 @@ void BKE_free_pointdensity(PointDensity *pd)
void BKE_free_voxeldatadata(struct VoxelData *vd) void BKE_free_voxeldatadata(struct VoxelData *vd)
{ {
if (vd->dataset) { if (vd->dataset) {
MEM_freeN(vd->dataset); if(vd->file_format != TEX_VD_SMOKE)
MEM_freeN(vd->dataset);
vd->dataset = NULL; vd->dataset = NULL;
} }
@ -1173,6 +1174,8 @@ struct VoxelData *BKE_add_voxeldata(void)
vd->int_multiplier = 1.0; vd->int_multiplier = 1.0;
vd->extend = TEX_CLIP; vd->extend = TEX_CLIP;
vd->object = NULL; vd->object = NULL;
vd->cachedframe = -1;
vd->ok = 0;
return vd; return vd;
} }

@ -2839,6 +2839,7 @@ static void direct_link_texture(FileData *fd, Tex *tex)
tex->vd= newdataadr(fd, tex->vd); tex->vd= newdataadr(fd, tex->vd);
if(tex->vd) { if(tex->vd) {
tex->vd->dataset = NULL; tex->vd->dataset = NULL;
tex->vd->ok = 0;
} }
tex->nodetree= newdataadr(fd, tex->nodetree); tex->nodetree= newdataadr(fd, tex->nodetree);

@ -190,7 +190,11 @@ typedef struct VoxelData {
float int_multiplier; float int_multiplier;
int still_frame; int still_frame;
char source_path[240]; char source_path[240];
/* temporary data */
float *dataset; float *dataset;
int cachedframe;
int ok;
} VoxelData; } VoxelData;

@ -75,6 +75,7 @@ EnumPropertyItem texture_type_items[] = {
#include "RNA_access.h" #include "RNA_access.h"
#include "BKE_depsgraph.h" #include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BKE_texture.h" #include "BKE_texture.h"
#include "BKE_main.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); 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 */ /* Used for Texture Properties, used (also) for/in Nodes */
static void rna_Texture_nodes_update(Main *bmain, Scene *scene, PointerRNA *ptr) 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_sdna(prop, NULL, "smoked_type");
RNA_def_property_enum_items(prop, smoked_type_items); 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_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); prop= RNA_def_property(srna, "extension", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "extend"); 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_sdna(prop, NULL, "file_format");
RNA_def_property_enum_items(prop, file_format_items); 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_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); prop= RNA_def_property(srna, "source_path", PROP_STRING, PROP_FILEPATH);
RNA_def_property_string_sdna(prop, NULL, "source_path"); 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_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); prop= RNA_def_property(srna, "resolution", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "resol"); RNA_def_property_int_sdna(prop, NULL, "resol");
RNA_def_property_ui_text(prop, "Resolution", "Resolution of the voxel grid"); 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); prop= RNA_def_property(srna, "still", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", TEX_VD_STILL); 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_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); prop= RNA_def_property(srna, "still_frame_number", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "still_frame"); RNA_def_property_int_sdna(prop, NULL, "still_frame");
RNA_def_property_range(prop, -MAXFRAME, MAXFRAME); 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_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); prop= RNA_def_property(srna, "domain_object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "object"); 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_ui_text(prop, "Domain Object", "Object used as the smoke simulation domain");
RNA_def_property_flag(prop, PROP_EDITABLE); 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"); 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_struct_type(prop, "Image");
RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Image", ""); 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); prop= RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "iuser"); 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_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) static void rna_def_texture(BlenderRNA *brna)

@ -4595,7 +4595,6 @@ void RE_Database_Free(Render *re)
end_render_textures(); end_render_textures();
free_pointdensities(re); free_pointdensities(re);
free_voxeldata(re);
free_camera_inside_volumes(re); free_camera_inside_volumes(re);

@ -57,58 +57,72 @@
#include "texture.h" #include "texture.h"
#include "voxeldata.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; return 0;
if(fread(F,sizeof(float),size,fp) != size) if(fread(vd->dataset, sizeof(float), size, fp) != size)
return 0; return 0;
vd->cachedframe = frame;
vd->ok = 1;
return 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; 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) { if(fseek(fp,(frame-1)*size*sizeof(char),0) == -1) {
MEM_freeN(tmp); MEM_freeN(data_c);
return 0; return 0;
} }
if(fread(tmp, sizeof(char), size, fp) != size) { if(fread(data_c, sizeof(char), size, fp) != size) {
MEM_freeN(tmp); MEM_freeN(data_c);
return 0; return 0;
} }
for (i=0; i<size; i++) { 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; 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; ImBuf *ibuf;
Image *ima = tex->ima; Image *ima = tex->ima;
ImageUser *iuser = &tex->iuser; ImageUser *tiuser = &tex->iuser;
ImageUser iuser = *(tiuser);
int x=0, y=0, z=0; int x=0, y=0, z=0;
float *rf; float *rf;
if (!ima || !iuser) return; if (!ima || !tiuser) return;
if (iuser.frames == 0) return;
ima->source = IMA_SRC_SEQUENCE; 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 */ /* 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 */ /* need to do this in advance so we know how much memory to allocate */
ibuf= BKE_image_get_ibuf(ima, iuser); ibuf= BKE_image_get_ibuf(ima, &iuser);
while (!ibuf && (iuser->framenr < iuser->frames)) { while (!ibuf && (iuser.framenr < iuser.frames)) {
iuser->framenr++; iuser.framenr++;
ibuf= BKE_image_get_ibuf(ima, iuser); ibuf= BKE_image_get_ibuf(ima, &iuser);
} }
if (!ibuf) return; if (!ibuf) return;
if (!ibuf->rect_float) IMB_float_from_rect(ibuf); 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->flag |= TEX_VD_STILL;
vd->resol[0] = ibuf->x; vd->resol[0] = ibuf->x;
vd->resol[1] = ibuf->y; 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"); 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 */ /* get a new ibuf for each frame */
if (z > 0) { if (z > 0) {
iuser->framenr++; iuser.framenr++;
ibuf= BKE_image_get_ibuf(ima, iuser); ibuf= BKE_image_get_ibuf(ima, &iuser);
if (!ibuf) break; if (!ibuf) break;
if (!ibuf->rect_float) IMB_float_from_rect(ibuf); 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++) 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; vd->dataset[ V_I(x, y, z, vd->resol) ] = (rf[0] + rf[1] + rf[2])*0.333f;
rf +=4; 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) 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; return 1;
} }
static void init_frame_smoke(Render *re, VoxelData *vd, Tex *tex) static void init_frame_smoke(VoxelData *vd, Tex *tex)
{ {
Object *ob; Object *ob;
ModifierData *md; ModifierData *md;
@ -232,53 +249,65 @@ static void init_frame_smoke(Render *re, VoxelData *vd, Tex *tex)
} // end of fluid condition } // end of fluid condition
} }
} }
vd->ok = 1;
return;
} }
static void cache_voxeldata(struct Render *re,Tex *tex) static void cache_voxeldata(struct Render *re,Tex *tex)
{ {
VoxelData *vd = tex->vd; VoxelData *vd = tex->vd;
FILE *fp; FILE *fp;
int size;
int curframe; int curframe;
if (!vd) return; if (!vd) return;
/* image sequence gets special treatment */ /* only re-cache if dataset needs updating */
if (vd->file_format == TEX_VD_IMAGE_SEQUENCE) { if ((vd->flag & TEX_VD_STILL) || (vd->cachedframe == re->r.cfra))
load_frame_image_sequence(re, vd, tex); if (vd->ok) return;
return;
} else if (vd->file_format == TEX_VD_SMOKE) { /* clear out old cache, ready for new */
init_frame_smoke(re, vd, tex); if (vd->dataset) {
return; if(vd->file_format != TEX_VD_SMOKE)
MEM_freeN(vd->dataset);
vd->dataset = NULL;
} }
if (!BLI_exists(vd->source_path)) return; if (vd->flag & TEX_VD_STILL)
fp = fopen(vd->source_path,"rb"); curframe = vd->still_frame;
if (!fp) return; else
curframe = re->r.cfra;
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;
switch(vd->file_format) { 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: case TEX_VD_BLENDERVOXEL:
load_frame_blendervoxel(fp, vd->dataset, size, curframe-1, sizeof(VoxelDataHeader)); if (!BLI_exists(vd->source_path)) return;
break; fp = fopen(vd->source_path,"rb");
case TEX_VD_RAW_8BIT: if (!fp) return;
load_frame_raw8(fp, vd->dataset, size, curframe);
break;
}
fclose(fp); if(read_voxeldata_header(fp, vd))
load_frame_blendervoxel(vd, fp, curframe-1);
else
fclose(fp);
return;
case TEX_VD_RAW_8BIT:
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;
}
} }
void make_voxeldata(struct Render *re) 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 voxeldatatex(struct Tex *tex, float *texvec, struct TexResult *texres)
{ {
int retval = TEX_INT; int retval = TEX_INT;