diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2018-06-05 18:02:50 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2018-06-05 18:02:50 +0300 |
commit | f0d9dbae0dae4deae84824833096c38e625073cb (patch) | |
tree | a9fa826eb5860e9b62d16c3498703bde1bb5d4aa /source/blender/render | |
parent | ce6db959c7d96792edad3a6d606e3662a4ef0798 (diff) | |
parent | 481cdb08ed6f33a09d0e6843d1024db93c301178 (diff) |
Merge branch 'master' into blender2.8
Conflicts:
source/blender/blenkernel/intern/blendfile.c
source/blender/blenloader/intern/readfile.h
source/blender/blenloader/intern/versioning_250.c
source/blender/blenloader/intern/versioning_260.c
source/blender/blenloader/intern/versioning_270.c
source/blender/blenloader/intern/versioning_legacy.c
source/blender/editors/render/render_shading.c
source/blender/makesrna/intern/rna_movieclip.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/voxeldata.c
Diffstat (limited to 'source/blender/render')
-rw-r--r-- | source/blender/render/intern/source/pipeline.c | 6 | ||||
-rw-r--r-- | source/blender/render/intern/source/render_result.c | 9 | ||||
-rw-r--r-- | source/blender/render/intern/source/voxeldata.c | 571 |
3 files changed, 579 insertions, 7 deletions
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 595640489c8..e71cc6d063e 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2208,7 +2208,7 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, ViewLayer *single_la else { char name[FILE_MAX]; BKE_image_path_from_imformat( - name, scene->r.pic, bmain->name, scene->r.cfra, + name, scene->r.pic, BKE_main_blendfile_path(bmain), scene->r.cfra, &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL); /* reports only used for Movie */ @@ -2467,7 +2467,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie BLI_strncpy(name, name_override, sizeof(name)); else BKE_image_path_from_imformat( - name, scene->r.pic, bmain->name, scene->r.cfra, + name, scene->r.pic, BKE_main_blendfile_path(bmain), scene->r.cfra, &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL); /* write images as individual images or stereo */ @@ -2647,7 +2647,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri if (is_movie == false) { if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH)) BKE_image_path_from_imformat( - name, scene->r.pic, bmain->name, scene->r.cfra, + name, scene->r.pic, BKE_main_blendfile_path(bmain), scene->r.cfra, &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL); if (scene->r.mode & R_NO_OVERWRITE) { diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index a6f1ecd5405..5fd897219c4 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -1130,7 +1130,7 @@ void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart, const void render_result_exr_file_path(Scene *scene, const char *layname, int sample, char *filepath) { char name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100]; - const char *fi = BLI_path_basename(G.main->name); + const char *fi = BLI_path_basename(BKE_main_blendfile_path_from_global()); if (sample == 0) { BLI_snprintf(name, sizeof(name), "%s_%s_%s.exr", fi, scene->id.name + 2, layname); @@ -1224,10 +1224,11 @@ static void render_result_exr_file_cache_path(Scene *sce, const char *root, char char path_hexdigest[33]; /* If root is relative, use either current .blend file dir, or temp one if not saved. */ - if (G.main->name[0]) { - BLI_split_dirfile(G.main->name, dirname, filename, sizeof(dirname), sizeof(filename)); + const char *blendfile_path = BKE_main_blendfile_path_from_global(); + if (blendfile_path[0] != '\0') { + BLI_split_dirfile(blendfile_path, dirname, filename, sizeof(dirname), sizeof(filename)); BLI_replace_extension(filename, sizeof(filename), ""); /* strip '.blend' */ - BLI_hash_md5_buffer(G.main->name, strlen(G.main->name), path_digest); + BLI_hash_md5_buffer(blendfile_path, strlen(blendfile_path), path_digest); } else { BLI_strncpy(dirname, BKE_tempdir_base(), sizeof(dirname)); diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c new file mode 100644 index 00000000000..0d9f7b197e1 --- /dev/null +++ b/source/blender/render/intern/source/voxeldata.c @@ -0,0 +1,571 @@ +/* + * ***** 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Raul Fernandez Hernandez (Farsthary), Matt Ebb. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/render/intern/source/voxeldata.c + * \ingroup render + */ + + +#include <math.h> +#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 "BLT_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 "BKE_modifier.h" + +#include "smoke_API.h" +#include "BPH_mass_spring.h" + +#include "DNA_texture_types.h" +#include "DNA_object_force_types.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 "texture.h" +#include "voxeldata.h" + +static bool is_vd_res_ok(VoxelData *vd) +{ + /* arbitrary large value so corrupt headers don't break */ + const int min = 1, max = 100000; + return (vd->resol[0] >= min && vd->resol[0] <= max) && + (vd->resol[1] >= min && vd->resol[1] <= max) && + (vd->resol[2] >= min && vd->resol[2] <= max); +} + +/* use size_t because the result may exceed INT_MAX */ +static size_t vd_resol_size(VoxelData *vd) +{ + return (size_t)vd->resol[0] * (size_t)vd->resol[1] * (size_t)vd->resol[2]; +} + +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) + return 0; + + vd->dataset = MEM_mapallocN(sizeof(float) * size, "voxel dataset"); + if (vd->dataset == NULL) return 0; + + if (fseek(fp, frame * size * sizeof(float) + offset, 0) == -1) + return 0; + if (fread(vd->dataset, sizeof(float), size, fp) != size) + return 0; + + vd->cachedframe = frame; + vd->ok = 1; + return 1; +} + +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; + + if (is_vd_res_ok(vd) == false) + return 0; + + vd->dataset = MEM_mapallocN(sizeof(float) * size, "voxel dataset"); + if (vd->dataset == NULL) return 0; + data_c = (char *)MEM_mallocN(sizeof(char) * size, "temporary voxel file reading storage"); + if (data_c == NULL) { + MEM_freeN(vd->dataset); + vd->dataset = NULL; + return 0; + } + + if (fseek(fp, (frame - 1) * size * sizeof(char), 0) == -1) { + MEM_freeN(data_c); + MEM_freeN(vd->dataset); + vd->dataset = NULL; + return 0; + } + if (fread(data_c, sizeof(char), size, fp) != size) { + MEM_freeN(data_c); + MEM_freeN(vd->dataset); + vd->dataset = NULL; + return 0; + } + + for (i = 0; i < size; i++) { + vd->dataset[i] = (float)data_c[i] / 255.f; + } + MEM_freeN(data_c); + + vd->cachedframe = frame; + vd->ok = 1; + return 1; +} + +static void load_frame_image_sequence(VoxelData *vd, Tex *tex) +{ + ImBuf *ibuf; + Image *ima = tex->ima; + ImageUser *tiuser = &tex->iuser; + ImageUser iuser = *(tiuser); + int x = 0, y = 0, z = 0; + const float *rf; + + if (!ima) return; + if (iuser.frames == 0) return; + + ima->source = IMA_SRC_SEQUENCE; + iuser.framenr = 1 + iuser.offset; + + /* 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_acquire_ibuf(ima, &iuser, NULL); + while (!ibuf && (iuser.framenr < iuser.frames)) { + iuser.framenr++; + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); + } + if (!ibuf) return; + if (!ibuf->rect_float) IMB_float_from_rect(ibuf); + + vd->flag |= TEX_VD_STILL; + vd->resol[0] = ibuf->x; + vd->resol[1] = ibuf->y; + vd->resol[2] = iuser.frames; + vd->dataset = MEM_mapallocN(sizeof(float) * vd_resol_size(vd), "voxel dataset"); + + for (z = 0; z < iuser.frames; z++) { + /* get a new ibuf for each frame */ + if (z > 0) { + iuser.framenr++; + 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); + } + rf = ibuf->rect_float; + + 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]) / 3.0f; + rf += 4; + } + } + + BKE_image_free_anim_ibufs(ima, iuser.framenr); + } + + BKE_image_release_ibuf(ima, ibuf, NULL); + + vd->ok = 1; + return; +} + +static int read_voxeldata_header(FILE *fp, struct VoxelData *vd) +{ + VoxelDataHeader *h = (VoxelDataHeader *)MEM_mallocN(sizeof(VoxelDataHeader), "voxel data header"); + + rewind(fp); + if (fread(h, sizeof(VoxelDataHeader), 1, fp) != 1) { + MEM_freeN(h); + return 0; + } + + vd->resol[0] = h->resolX; + vd->resol[1] = h->resolY; + vd->resol[2] = h->resolZ; + + MEM_freeN(h); + return 1; +} + +static void init_frame_smoke(VoxelData *vd, int cfra) +{ +#ifdef WITH_SMOKE + Object *ob; + ModifierData *md; + + vd->dataset = NULL; + if (vd->object == NULL) return; + ob = vd->object; + + /* draw code for smoke */ + if ((md = (ModifierData *)modifiers_findByType(ob, eModifierType_Smoke))) { + SmokeModifierData *smd = (SmokeModifierData *)md; + 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) { + size_t totRes; + size_t i; + float *heat; + + 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); + vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data"); + /* get heat data */ + heat = smoke_get_heat(sds->fluid); + + /* scale heat values from -2.0-2.0 to 0.0-1.0 */ + for (i = 0; i < totRes; i++) { + vd->dataset[i] = (heat[i] + 2.0f) / 4.0f; + } + } + else if (vd->smoked_type == TEX_VD_SMOKEVEL) { + size_t totRes; + size_t i; + float *xvel, *yvel, *zvel; + + copy_v3_v3_int(vd->resol, sds->res); + totRes = vd_resol_size(vd); + vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data"); + /* get velocity data */ + xvel = smoke_get_velocity_x(sds->fluid); + yvel = smoke_get_velocity_y(sds->fluid); + zvel = smoke_get_velocity_z(sds->fluid); + + /* map velocities between 0 and 0.3f */ + for (i = 0; i < totRes; i++) { + vd->dataset[i] = sqrtf(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f; + } + + } + else if (vd->smoked_type == TEX_VD_SMOKEFLAME) { + size_t totRes; + float *flame; + + if (sds->flags & MOD_SMOKE_HIGHRES) { + 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)) { + 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); + vd->dataset = MEM_mapallocN(sizeof(float)*(totRes), "smoke data"); + memcpy(vd->dataset, flame, sizeof(float)*totRes); + } + else { + size_t totCells; + int depth = 4; + vd->data_type = TEX_VD_RGBA_PREMUL; + + /* data resolution */ + if (sds->flags & MOD_SMOKE_HIGHRES) { + smoke_turbulence_get_res(sds->wt, vd->resol); + } + else { + copy_v3_v3_int(vd->resol, sds->res); + } + + /* TODO: is_vd_res_ok(rvd) doesnt check this resolution */ + totCells = vd_resol_size(vd) * depth; + /* always store copy, as smoke internal data can change */ + vd->dataset = MEM_mapallocN(sizeof(float) * totCells, "smoke data"); + + if (sds->flags & MOD_SMOKE_HIGHRES) { + if (smoke_turbulence_has_colors(sds->wt)) { + smoke_turbulence_get_rgba(sds->wt, vd->dataset, 1); + } + else { + smoke_turbulence_get_rgba_from_density(sds->wt, sds->active_color, vd->dataset, 1); + } + } + else { + if (smoke_has_colors(sds->fluid)) { + smoke_get_rgba(sds->fluid, vd->dataset, 1); + } + else { + smoke_get_rgba_from_density(sds->fluid, sds->active_color, vd->dataset, 1); + } + } + } /* end of fluid condition */ + + BLI_rw_mutex_unlock(sds->fluid_mutex); + } + } + + vd->ok = 1; + +#else // WITH_SMOKE + (void)vd; + (void)cfra; + + vd->dataset = NULL; +#endif +} + +static void init_frame_hair(VoxelData *vd, int UNUSED(cfra)) +{ + Object *ob; + ModifierData *md; + + 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) { + vd->ok |= BPH_cloth_solver_get_texture_data(ob, pmd->psys->clmd, vd); + } + } +} + +void cache_voxeldata(Tex *tex, int scene_frame) +{ + VoxelData *vd = tex->vd; + FILE *fp; + int curframe; + char path[sizeof(vd->source_path)]; + + /* only re-cache if dataset needs updating */ + if ((vd->flag & TEX_VD_STILL) || (vd->cachedframe == scene_frame)) + if (vd->ok) return; + + /* clear out old cache, ready for new */ + if (vd->dataset) { + MEM_freeN(vd->dataset); + vd->dataset = NULL; + } + /* reset data_type */ + vd->data_type = TEX_VD_INTENSITY; + + if (vd->flag & TEX_VD_STILL) + curframe = vd->still_frame; + else + curframe = scene_frame; + + BLI_strncpy(path, vd->source_path, sizeof(path)); + + /* each type is responsible for setting to true */ + vd->ok = false; + + switch (vd->file_format) { + case TEX_VD_IMAGE_SEQUENCE: + load_frame_image_sequence(vd, tex); + return; + 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, BKE_main_blendfile_path_from_global()); + fp = BLI_fopen(path, "rb"); + if (!fp) return; + + if (read_voxeldata_header(fp, vd)) + load_frame_blendervoxel(vd, fp, curframe - 1); + + fclose(fp); + return; + case TEX_VD_RAW_8BIT: + BLI_path_abs(path, BKE_main_blendfile_path_from_global()); + fp = BLI_fopen(path, "rb"); + if (!fp) return; + + load_frame_raw8(vd, fp, curframe); + fclose(fp); + return; + } +} + +void make_voxeldata(struct Render *re) +{ + Tex *tex; + + re->i.infostr = IFACE_("Loading voxel datasets"); + re->stats_draw(re->sdh, &re->i); + + /* XXX: should be doing only textures used in this render */ + for (tex = re->main->tex.first; tex; tex = tex->id.next) { + if (tex->id.us && tex->type == TEX_VOXELDATA) { + cache_voxeldata(tex, re->r.cfra); + } + } + + re->i.infostr = NULL; + re->stats_draw(re->sdh, &re->i); + +} + +int voxeldatatex(struct Tex *tex, const float texvec[3], struct TexResult *texres) +{ + 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; + int ch; + + if (vd->dataset == NULL) { + texres->tin = 0.0f; + return 0; + } + + /* scale lookup from 0.0-1.0 (original location) to -1.0, 1.0, consistent with image texture tex coords */ + /* in implementation this works backwards, bringing sample locations from -1.0, 1.0 + * to the range 0.0, 1.0, before looking up in the voxel structure. */ + copy_v3_v3(co, texvec); + mul_v3_fl(co, 0.5f); + add_v3_v3(co, offset); + + /* co is now in the range 0.0, 1.0 */ + switch (vd->extend) { + case TEX_CLIP: + { + if ((co[0] < 0.f || co[0] > 1.f) || (co[1] < 0.f || co[1] > 1.f) || (co[2] < 0.f || co[2] > 1.f)) { + texres->tin = 0.f; + return retval; + } + break; + } + case TEX_REPEAT: + { + co[0] = co[0] - floorf(co[0]); + co[1] = co[1] - floorf(co[1]); + co[2] = co[2] - floorf(co[2]); + break; + } + case TEX_EXTEND: + { + CLAMP(co[0], 0.f, 1.f); + CLAMP(co[1], 0.f, 1.f); + CLAMP(co[2], 0.f, 1.f); + break; + } + } + + for (ch = 0; ch < depth; ch++) { + float *dataset = vd->dataset + ch*vd->resol[0]*vd->resol[1]*vd->resol[2]; + float *result = &texres->tin; + + if (vd->data_type == TEX_VD_RGBA_PREMUL) { + switch (ch) { + case 0: + result = &texres->tr; + break; + case 1: + result = &texres->tg; + break; + case 2: + result = &texres->tb; + break; + } + } + + switch (vd->interp_type) { + case TEX_VD_NEARESTNEIGHBOR: + *result = BLI_voxel_sample_nearest(dataset, vd->resol, co); + break; + case TEX_VD_LINEAR: + *result = BLI_voxel_sample_trilinear(dataset, vd->resol, co); + break; + case TEX_VD_QUADRATIC: + *result = BLI_voxel_sample_triquadratic(dataset, vd->resol, co); + break; + case TEX_VD_TRICUBIC_CATROM: + case TEX_VD_TRICUBIC_BSPLINE: + *result = BLI_voxel_sample_tricubic(dataset, vd->resol, co, (vd->interp_type == TEX_VD_TRICUBIC_BSPLINE)); + break; + } + } + + a = texres->tin; + texres->tin *= vd->int_multiplier; + BRICONT; + + if (vd->data_type == TEX_VD_RGBA_PREMUL) { + /* unmultiply */ + if (a>0.001f) { + texres->tr /= a; + texres->tg /= a; + texres->tb /= a; + } + texres->talpha = 1; + } + else { + texres->tr = texres->tin; + texres->tg = texres->tin; + texres->tb = texres->tin; + } + + texres->ta = texres->tin; + BRICONTRGB; + + return retval; +} |