2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2017-06-06 22:47:41 +02:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2017-06-06 22:47:41 +02:00
|
|
|
*/
|
|
|
|
|
|
2023-07-22 11:27:25 +10:00
|
|
|
#include <cstring>
|
2019-09-12 04:34:55 +10:00
|
|
|
|
2020-05-13 19:39:47 +02:00
|
|
|
#include "DNA_collection_types.h"
|
2019-09-12 04:34:55 +10:00
|
|
|
#include "DNA_defaults.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_lightprobe_types.h"
|
|
|
|
|
#include "DNA_object_types.h"
|
2017-06-06 22:47:41 +02:00
|
|
|
|
2023-04-17 17:12:19 +02:00
|
|
|
#include "BLI_math_base.h"
|
|
|
|
|
#include "BLI_span.hh"
|
2017-06-06 22:47:41 +02:00
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
2020-09-10 17:47:04 +02:00
|
|
|
#include "BKE_anim_data.h"
|
2020-03-06 11:51:17 +01:00
|
|
|
#include "BKE_idtype.h"
|
2020-02-10 12:58:59 +01:00
|
|
|
#include "BKE_lib_id.h"
|
2020-05-13 19:32:45 +02:00
|
|
|
#include "BKE_lib_query.h"
|
2017-06-12 20:59:54 +10:00
|
|
|
#include "BKE_lightprobe.h"
|
2018-11-07 15:37:31 +01:00
|
|
|
#include "BKE_main.h"
|
2017-06-06 22:47:41 +02:00
|
|
|
|
2020-03-06 11:51:17 +01:00
|
|
|
#include "BLT_translation.h"
|
|
|
|
|
|
2023-08-28 15:01:05 +02:00
|
|
|
#include "BLO_read_write.hh"
|
2020-09-10 17:47:04 +02:00
|
|
|
|
2020-03-06 11:51:17 +01:00
|
|
|
static void lightprobe_init_data(ID *id)
|
2017-06-06 22:47:41 +02:00
|
|
|
{
|
2020-03-06 11:51:17 +01:00
|
|
|
LightProbe *probe = (LightProbe *)id;
|
2019-03-12 16:59:04 +11:00
|
|
|
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(probe, id));
|
2017-06-06 22:47:41 +02:00
|
|
|
|
2019-09-12 04:34:55 +10:00
|
|
|
MEMCPY_STRUCT_AFTER(probe, DNA_struct_default_get(LightProbe), id);
|
2017-06-06 22:47:41 +02:00
|
|
|
}
|
|
|
|
|
|
2020-05-13 19:39:47 +02:00
|
|
|
static void lightprobe_foreach_id(ID *id, LibraryForeachIDData *data)
|
|
|
|
|
{
|
|
|
|
|
LightProbe *probe = (LightProbe *)id;
|
|
|
|
|
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, probe->visibility_grp, IDWALK_CB_NOP);
|
2020-05-13 19:39:47 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-10 17:47:04 +02:00
|
|
|
static void lightprobe_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
|
|
|
|
{
|
|
|
|
|
LightProbe *prb = (LightProbe *)id;
|
2021-08-19 11:13:55 +02:00
|
|
|
|
|
|
|
|
/* write LibData */
|
|
|
|
|
BLO_write_id_struct(writer, LightProbe, id_address, &prb->id);
|
|
|
|
|
BKE_id_blend_write(writer, &prb->id);
|
2020-09-10 17:47:04 +02:00
|
|
|
}
|
|
|
|
|
|
2020-05-13 19:32:45 +02:00
|
|
|
IDTypeInfo IDType_ID_LP = {
|
2023-04-06 18:40:58 +02:00
|
|
|
/*id_code*/ ID_LP,
|
|
|
|
|
/*id_filter*/ FILTER_ID_LP,
|
|
|
|
|
/*main_listbase_index*/ INDEX_ID_LP,
|
|
|
|
|
/*struct_size*/ sizeof(LightProbe),
|
|
|
|
|
/*name*/ "LightProbe",
|
2023-10-22 08:47:26 +02:00
|
|
|
/*name_plural*/ N_("lightprobes"),
|
2023-04-06 18:40:58 +02:00
|
|
|
/*translation_context*/ BLT_I18NCONTEXT_ID_LIGHTPROBE,
|
|
|
|
|
/*flags*/ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
|
|
|
|
|
/*asset_type_info*/ nullptr,
|
|
|
|
|
|
|
|
|
|
/*init_data*/ lightprobe_init_data,
|
|
|
|
|
/*copy_data*/ nullptr,
|
|
|
|
|
/*free_data*/ nullptr,
|
|
|
|
|
/*make_local*/ nullptr,
|
|
|
|
|
/*foreach_id*/ lightprobe_foreach_id,
|
|
|
|
|
/*foreach_cache*/ nullptr,
|
|
|
|
|
/*foreach_path*/ nullptr,
|
|
|
|
|
/*owner_pointer_get*/ nullptr,
|
|
|
|
|
|
|
|
|
|
/*blend_write*/ lightprobe_blend_write,
|
2023-08-14 16:26:11 +02:00
|
|
|
/*blend_read_data*/ nullptr,
|
2023-03-11 18:07:59 +01:00
|
|
|
/*blend_read_after_liblink*/ nullptr,
|
2023-04-06 18:40:58 +02:00
|
|
|
|
|
|
|
|
/*blend_read_undo_preserve*/ nullptr,
|
|
|
|
|
|
|
|
|
|
/*lib_override_apply_post*/ nullptr,
|
2020-05-13 19:32:45 +02:00
|
|
|
};
|
|
|
|
|
|
2020-01-20 17:54:38 +11:00
|
|
|
void BKE_lightprobe_type_set(LightProbe *probe, const short lightprobe_type)
|
2020-01-17 19:14:23 +01:00
|
|
|
{
|
|
|
|
|
probe->type = lightprobe_type;
|
|
|
|
|
|
|
|
|
|
switch (probe->type) {
|
2023-10-11 19:38:42 +02:00
|
|
|
case LIGHTPROBE_TYPE_VOLUME:
|
2020-01-17 19:14:23 +01:00
|
|
|
probe->distinf = 0.3f;
|
|
|
|
|
probe->falloff = 1.0f;
|
|
|
|
|
probe->clipsta = 0.01f;
|
|
|
|
|
break;
|
2023-10-11 19:38:42 +02:00
|
|
|
case LIGHTPROBE_TYPE_PLANE:
|
2020-01-17 19:14:23 +01:00
|
|
|
probe->distinf = 0.1f;
|
|
|
|
|
probe->falloff = 0.5f;
|
|
|
|
|
probe->clipsta = 0.001f;
|
|
|
|
|
break;
|
2023-10-11 19:38:42 +02:00
|
|
|
case LIGHTPROBE_TYPE_SPHERE:
|
2020-01-17 19:14:23 +01:00
|
|
|
probe->attenuation_type = LIGHTPROBE_SHAPE_ELIPSOID;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2021-07-15 18:23:28 +10:00
|
|
|
BLI_assert_msg(0, "LightProbe type not configured.");
|
2020-01-17 19:14:23 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-12 20:59:54 +10:00
|
|
|
void *BKE_lightprobe_add(Main *bmain, const char *name)
|
2017-06-06 22:47:41 +02:00
|
|
|
{
|
2017-06-12 20:59:54 +10:00
|
|
|
LightProbe *probe;
|
2017-06-06 22:47:41 +02:00
|
|
|
|
2023-04-06 17:41:13 +02:00
|
|
|
probe = static_cast<LightProbe *>(BKE_id_new(bmain, ID_LP, name));
|
2017-06-06 22:47:41 +02:00
|
|
|
|
|
|
|
|
return probe;
|
|
|
|
|
}
|
2023-04-17 17:12:19 +02:00
|
|
|
|
|
|
|
|
static void lightprobe_grid_cache_frame_blend_write(BlendWriter *writer,
|
|
|
|
|
const LightProbeGridCacheFrame *cache)
|
|
|
|
|
{
|
|
|
|
|
BLO_write_struct_array(writer, LightProbeGridCacheFrame, cache->block_len, cache->block_infos);
|
|
|
|
|
|
|
|
|
|
int64_t sample_count = BKE_lightprobe_grid_cache_frame_sample_count(cache);
|
|
|
|
|
|
|
|
|
|
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L0);
|
|
|
|
|
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L1_a);
|
|
|
|
|
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L1_b);
|
|
|
|
|
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L1_c);
|
|
|
|
|
|
|
|
|
|
BLO_write_float_array(writer, sample_count, cache->visibility.L0);
|
|
|
|
|
BLO_write_float_array(writer, sample_count, cache->visibility.L1_a);
|
|
|
|
|
BLO_write_float_array(writer, sample_count, cache->visibility.L1_b);
|
|
|
|
|
BLO_write_float_array(writer, sample_count, cache->visibility.L1_c);
|
|
|
|
|
|
2023-08-03 15:48:33 +02:00
|
|
|
BLO_write_int8_array(writer, sample_count, (int8_t *)cache->connectivity.validity);
|
2023-04-17 17:12:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void lightprobe_grid_cache_frame_blend_read(BlendDataReader *reader,
|
|
|
|
|
LightProbeGridCacheFrame *cache)
|
|
|
|
|
{
|
|
|
|
|
if (!ELEM(
|
|
|
|
|
cache->data_layout, LIGHTPROBE_CACHE_ADAPTIVE_RESOLUTION, LIGHTPROBE_CACHE_UNIFORM_GRID))
|
|
|
|
|
{
|
|
|
|
|
/* Do not try to read data from incompatible layout. Clear all pointers. */
|
|
|
|
|
memset(cache, 0, sizeof(*cache));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &cache->block_infos);
|
|
|
|
|
|
|
|
|
|
int64_t sample_count = BKE_lightprobe_grid_cache_frame_sample_count(cache);
|
|
|
|
|
|
|
|
|
|
/* Baking data is not stored. */
|
|
|
|
|
cache->baking.L0 = nullptr;
|
|
|
|
|
cache->baking.L1_a = nullptr;
|
|
|
|
|
cache->baking.L1_b = nullptr;
|
|
|
|
|
cache->baking.L1_c = nullptr;
|
2023-08-03 16:47:05 +02:00
|
|
|
cache->baking.virtual_offset = nullptr;
|
2023-08-03 15:48:33 +02:00
|
|
|
cache->baking.validity = nullptr;
|
2023-04-17 17:12:19 +02:00
|
|
|
cache->surfels = nullptr;
|
|
|
|
|
cache->surfels_len = 0;
|
|
|
|
|
|
|
|
|
|
BLO_read_float3_array(reader, sample_count, (float **)&cache->irradiance.L0);
|
|
|
|
|
BLO_read_float3_array(reader, sample_count, (float **)&cache->irradiance.L1_a);
|
|
|
|
|
BLO_read_float3_array(reader, sample_count, (float **)&cache->irradiance.L1_b);
|
|
|
|
|
BLO_read_float3_array(reader, sample_count, (float **)&cache->irradiance.L1_c);
|
|
|
|
|
|
|
|
|
|
BLO_read_float_array(reader, sample_count, &cache->visibility.L0);
|
|
|
|
|
BLO_read_float_array(reader, sample_count, &cache->visibility.L1_a);
|
|
|
|
|
BLO_read_float_array(reader, sample_count, &cache->visibility.L1_b);
|
|
|
|
|
BLO_read_float_array(reader, sample_count, &cache->visibility.L1_c);
|
|
|
|
|
|
2023-08-03 15:48:33 +02:00
|
|
|
BLO_read_data_address(reader, &cache->connectivity.validity);
|
2023-04-17 17:12:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_lightprobe_cache_blend_write(BlendWriter *writer, LightProbeObjectCache *cache)
|
|
|
|
|
{
|
|
|
|
|
if (cache->grid_static_cache != nullptr) {
|
|
|
|
|
BLO_write_struct(writer, LightProbeGridCacheFrame, cache->grid_static_cache);
|
|
|
|
|
lightprobe_grid_cache_frame_blend_write(writer, cache->grid_static_cache);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_lightprobe_cache_blend_read(BlendDataReader *reader, LightProbeObjectCache *cache)
|
|
|
|
|
{
|
|
|
|
|
if (cache->grid_static_cache != nullptr) {
|
|
|
|
|
BLO_read_data_address(reader, &cache->grid_static_cache);
|
|
|
|
|
lightprobe_grid_cache_frame_blend_read(reader, cache->grid_static_cache);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T> static void spherical_harmonic_free(T &data)
|
|
|
|
|
{
|
|
|
|
|
MEM_SAFE_FREE(data.L0);
|
|
|
|
|
MEM_SAFE_FREE(data.L1_a);
|
|
|
|
|
MEM_SAFE_FREE(data.L1_b);
|
|
|
|
|
MEM_SAFE_FREE(data.L1_c);
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-06 21:30:30 +02:00
|
|
|
template<typename DataT, typename T> static void spherical_harmonic_copy(T &dst, T &src)
|
|
|
|
|
{
|
|
|
|
|
dst.L0 = (DataT *)MEM_dupallocN(src.L0);
|
|
|
|
|
dst.L1_a = (DataT *)MEM_dupallocN(src.L1_a);
|
|
|
|
|
dst.L1_b = (DataT *)MEM_dupallocN(src.L1_b);
|
|
|
|
|
dst.L1_c = (DataT *)MEM_dupallocN(src.L1_c);
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-17 17:12:19 +02:00
|
|
|
LightProbeGridCacheFrame *BKE_lightprobe_grid_cache_frame_create()
|
|
|
|
|
{
|
|
|
|
|
LightProbeGridCacheFrame *cache = static_cast<LightProbeGridCacheFrame *>(
|
|
|
|
|
MEM_callocN(sizeof(LightProbeGridCacheFrame), "LightProbeGridCacheFrame"));
|
|
|
|
|
return cache;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-06 21:30:30 +02:00
|
|
|
LightProbeGridCacheFrame *BKE_lightprobe_grid_cache_frame_copy(LightProbeGridCacheFrame *src)
|
|
|
|
|
{
|
|
|
|
|
LightProbeGridCacheFrame *dst = static_cast<LightProbeGridCacheFrame *>(MEM_dupallocN(src));
|
|
|
|
|
dst->block_infos = static_cast<LightProbeBlockData *>(MEM_dupallocN(src->block_infos));
|
|
|
|
|
spherical_harmonic_copy<float[3]>(dst->irradiance, src->irradiance);
|
|
|
|
|
spherical_harmonic_copy<float>(dst->visibility, src->visibility);
|
|
|
|
|
dst->connectivity.validity = static_cast<uint8_t *>(MEM_dupallocN(src->connectivity.validity));
|
|
|
|
|
/* NOTE: Don't copy baking since it wouldn't be freed nor updated after completion. */
|
|
|
|
|
dst->baking.L0 = nullptr;
|
|
|
|
|
dst->baking.L1_a = nullptr;
|
|
|
|
|
dst->baking.L1_b = nullptr;
|
|
|
|
|
dst->baking.L1_c = nullptr;
|
|
|
|
|
dst->baking.virtual_offset = nullptr;
|
|
|
|
|
dst->baking.validity = nullptr;
|
|
|
|
|
dst->surfels = nullptr;
|
|
|
|
|
return dst;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-17 17:12:19 +02:00
|
|
|
void BKE_lightprobe_grid_cache_frame_free(LightProbeGridCacheFrame *cache)
|
|
|
|
|
{
|
|
|
|
|
MEM_SAFE_FREE(cache->block_infos);
|
|
|
|
|
spherical_harmonic_free(cache->baking);
|
|
|
|
|
spherical_harmonic_free(cache->irradiance);
|
|
|
|
|
spherical_harmonic_free(cache->visibility);
|
2023-08-03 15:48:33 +02:00
|
|
|
MEM_SAFE_FREE(cache->baking.validity);
|
|
|
|
|
MEM_SAFE_FREE(cache->connectivity.validity);
|
2023-04-17 17:12:19 +02:00
|
|
|
MEM_SAFE_FREE(cache->surfels);
|
2023-08-03 16:47:05 +02:00
|
|
|
MEM_SAFE_FREE(cache->baking.virtual_offset);
|
2023-04-17 17:12:19 +02:00
|
|
|
|
|
|
|
|
MEM_SAFE_FREE(cache);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_lightprobe_cache_create(Object *object)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(object->lightprobe_cache == nullptr);
|
|
|
|
|
|
|
|
|
|
object->lightprobe_cache = static_cast<LightProbeObjectCache *>(
|
|
|
|
|
MEM_callocN(sizeof(LightProbeObjectCache), "LightProbeObjectCache"));
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-06 21:30:30 +02:00
|
|
|
LightProbeObjectCache *BKE_lightprobe_cache_copy(LightProbeObjectCache *src_cache)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(src_cache != nullptr);
|
|
|
|
|
|
|
|
|
|
LightProbeObjectCache *dst_cache = static_cast<LightProbeObjectCache *>(
|
|
|
|
|
MEM_dupallocN(src_cache));
|
|
|
|
|
|
|
|
|
|
if (src_cache->grid_static_cache) {
|
|
|
|
|
dst_cache->grid_static_cache = BKE_lightprobe_grid_cache_frame_copy(
|
|
|
|
|
src_cache->grid_static_cache);
|
|
|
|
|
}
|
|
|
|
|
return dst_cache;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-17 17:12:19 +02:00
|
|
|
void BKE_lightprobe_cache_free(Object *object)
|
|
|
|
|
{
|
|
|
|
|
if (object->lightprobe_cache == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LightProbeObjectCache *cache = object->lightprobe_cache;
|
|
|
|
|
|
|
|
|
|
if (cache->shared == false) {
|
|
|
|
|
if (cache->grid_static_cache != nullptr) {
|
|
|
|
|
BKE_lightprobe_grid_cache_frame_free(cache->grid_static_cache);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEM_SAFE_FREE(object->lightprobe_cache);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t BKE_lightprobe_grid_cache_frame_sample_count(const LightProbeGridCacheFrame *cache)
|
|
|
|
|
{
|
|
|
|
|
if (cache->data_layout == LIGHTPROBE_CACHE_ADAPTIVE_RESOLUTION) {
|
|
|
|
|
return cache->block_len * cube_i(cache->block_size);
|
|
|
|
|
}
|
|
|
|
|
/* LIGHTPROBE_CACHE_UNIFORM_GRID */
|
|
|
|
|
return cache->size[0] * cache->size[1] * cache->size[2];
|
|
|
|
|
}
|