Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
Diffstat (limited to 'intern')
-rw-r--r--intern/CMakeLists.txt1
-rw-r--r--intern/clog/clog.c29
-rw-r--r--intern/cycles/app/CMakeLists.txt2
-rw-r--r--intern/cycles/blender/addon/engine.py27
-rw-r--r--intern/cycles/blender/addon/properties.py37
-rw-r--r--intern/cycles/blender/addon/ui.py11
-rw-r--r--intern/cycles/blender/blender_camera.cpp17
-rw-r--r--intern/cycles/blender/blender_id_map.h2
-rw-r--r--intern/cycles/blender/blender_mesh.cpp77
-rw-r--r--intern/cycles/blender/blender_object.cpp4
-rw-r--r--intern/cycles/blender/blender_python.cpp1
-rw-r--r--intern/cycles/blender/blender_session.cpp29
-rw-r--r--intern/cycles/blender/blender_shader.cpp7
-rw-r--r--intern/cycles/blender/blender_sync.cpp71
-rw-r--r--intern/cycles/blender/blender_sync.h2
-rw-r--r--intern/cycles/blender/blender_util.h6
-rw-r--r--intern/cycles/blender/blender_volume.cpp75
-rw-r--r--intern/cycles/cmake/external_libs.cmake4
-rw-r--r--intern/cycles/device/cuda/device_cuda_impl.cpp25
-rw-r--r--intern/cycles/device/device.cpp4
-rw-r--r--intern/cycles/device/device.h4
-rw-r--r--intern/cycles/device/device_cpu.cpp235
-rw-r--r--intern/cycles/device/device_denoising.cpp52
-rw-r--r--intern/cycles/device/device_denoising.h8
-rw-r--r--intern/cycles/device/device_multi.cpp47
-rw-r--r--intern/cycles/device/device_optix.cpp395
-rw-r--r--intern/cycles/device/device_task.h21
-rw-r--r--intern/cycles/device/opencl/device_opencl_impl.cpp2
-rw-r--r--intern/cycles/kernel/CMakeLists.txt4
-rw-r--r--intern/cycles/kernel/bvh/bvh.h23
-rw-r--r--intern/cycles/kernel/geom/geom_curve_intersect.h9
-rw-r--r--intern/cycles/kernel/kernel_camera.h2
-rw-r--r--intern/cycles/kernel/kernel_light_background.h2
-rw-r--r--intern/cycles/kernel/kernel_path.h14
-rw-r--r--intern/cycles/kernel/kernel_shader.h31
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h2
-rw-r--r--intern/cycles/kernel/kernels/optix/kernel_optix.cu48
-rw-r--r--intern/cycles/kernel/shaders/node_sky_texture.osl50
-rw-r--r--intern/cycles/kernel/svm/svm_sky.h21
-rw-r--r--intern/cycles/render/CMakeLists.txt2
-rw-r--r--intern/cycles/render/buffers.h46
-rw-r--r--intern/cycles/render/camera.cpp40
-rw-r--r--intern/cycles/render/denoising.cpp64
-rw-r--r--intern/cycles/render/denoising.h4
-rw-r--r--intern/cycles/render/graph.cpp4
-rw-r--r--intern/cycles/render/image.cpp6
-rw-r--r--intern/cycles/render/image.h2
-rw-r--r--intern/cycles/render/image_sky.cpp33
-rw-r--r--intern/cycles/render/image_sky.h4
-rw-r--r--intern/cycles/render/light.cpp14
-rw-r--r--intern/cycles/render/nodes.cpp58
-rw-r--r--intern/cycles/render/nodes.h3
-rw-r--r--intern/cycles/render/object.cpp6
-rw-r--r--intern/cycles/render/session.cpp81
-rw-r--r--intern/cycles/render/session.h4
-rw-r--r--intern/cycles/test/CMakeLists.txt1
-rw-r--r--intern/cycles/test/util_transform_test.cpp53
-rw-r--r--intern/cycles/util/CMakeLists.txt5
-rw-r--r--intern/cycles/util/util_avxb.h2
-rw-r--r--intern/cycles/util/util_avxi.h2
-rw-r--r--intern/cycles/util/util_debug.cpp1
-rw-r--r--intern/cycles/util/util_debug.h3
-rw-r--r--intern/cycles/util/util_math.h10
-rw-r--r--intern/cycles/util/util_math_fast.h20
-rw-r--r--intern/cycles/util/util_math_float4.h18
-rw-r--r--intern/cycles/util/util_sseb.h2
-rw-r--r--intern/cycles/util/util_ssei.h2
-rw-r--r--intern/cycles/util/util_tbb.h5
-rw-r--r--intern/cycles/util/util_transform.cpp28
-rw-r--r--intern/cycles/util/util_transform.h11
-rw-r--r--intern/ghost/CMakeLists.txt1
-rw-r--r--intern/ghost/GHOST_C-api.h9
-rw-r--r--intern/ghost/GHOST_IContext.h5
-rw-r--r--intern/ghost/GHOST_IEvent.h5
-rw-r--r--intern/ghost/GHOST_IEventConsumer.h5
-rw-r--r--intern/ghost/GHOST_ISystem.h5
-rw-r--r--intern/ghost/GHOST_ISystemPaths.h5
-rw-r--r--intern/ghost/GHOST_ITimerTask.h5
-rw-r--r--intern/ghost/GHOST_IWindow.h9
-rw-r--r--intern/ghost/GHOST_IXrContext.h5
-rw-r--r--intern/ghost/GHOST_Path-api.h5
-rw-r--r--intern/ghost/GHOST_Rect.h5
-rw-r--r--intern/ghost/GHOST_Types.h5
-rw-r--r--intern/ghost/intern/GHOST_Buttons.h5
-rw-r--r--intern/ghost/intern/GHOST_CallbackEventConsumer.h5
-rw-r--r--intern/ghost/intern/GHOST_Context.h5
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.h5
-rw-r--r--intern/ghost/intern/GHOST_ContextD3D.h5
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.cpp2
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.h5
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.h5
-rw-r--r--intern/ghost/intern/GHOST_ContextNone.h5
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.h5
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.h5
-rw-r--r--intern/ghost/intern/GHOST_Debug.h5
-rw-r--r--intern/ghost/intern/GHOST_DisplayManager.h5
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCocoa.h5
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerNULL.h5
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerSDL.h5
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.h5
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerX11.h5
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.h5
-rw-r--r--intern/ghost/intern/GHOST_DropTargetX11.h5
-rw-r--r--intern/ghost/intern/GHOST_Event.h5
-rw-r--r--intern/ghost/intern/GHOST_EventButton.h5
-rw-r--r--intern/ghost/intern/GHOST_EventCursor.h5
-rw-r--r--intern/ghost/intern/GHOST_EventDragnDrop.h5
-rw-r--r--intern/ghost/intern/GHOST_EventKey.h5
-rw-r--r--intern/ghost/intern/GHOST_EventManager.h5
-rw-r--r--intern/ghost/intern/GHOST_EventNDOF.h5
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.h5
-rw-r--r--intern/ghost/intern/GHOST_EventString.h5
-rw-r--r--intern/ghost/intern/GHOST_EventTrackpad.h5
-rw-r--r--intern/ghost/intern/GHOST_EventWheel.h5
-rw-r--r--intern/ghost/intern/GHOST_IXrGraphicsBinding.h5
-rw-r--r--intern/ghost/intern/GHOST_IconX11.h5
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.h4
-rw-r--r--intern/ghost/intern/GHOST_ModifierKeys.h5
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h5
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerCocoa.h5
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerUnix.h5
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerWin32.h5
-rw-r--r--intern/ghost/intern/GHOST_System.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemNULL.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemPaths.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsCocoa.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsUnix.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsWin32.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp6
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h4
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp33
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h5
-rw-r--r--intern/ghost/intern/GHOST_TaskbarWin32.h5
-rw-r--r--intern/ghost/intern/GHOST_TaskbarX11.h5
-rw-r--r--intern/ghost/intern/GHOST_TimerManager.h5
-rw-r--r--intern/ghost/intern/GHOST_TimerTask.h5
-rw-r--r--intern/ghost/intern/GHOST_Window.h9
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h5
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.h5
-rw-r--r--intern/ghost/intern/GHOST_WindowNULL.h5
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.h5
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.cpp21
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.h9
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h5
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h5
-rw-r--r--intern/ghost/intern/GHOST_XrContext.h5
-rw-r--r--intern/ghost/intern/GHOST_XrException.h5
-rw-r--r--intern/ghost/intern/GHOST_XrSession.h5
-rw-r--r--intern/ghost/intern/GHOST_XrSwapchain.h5
-rw-r--r--intern/ghost/intern/GHOST_Xr_intern.h5
-rw-r--r--intern/ghost/intern/GHOST_Xr_openxr_includes.h5
-rw-r--r--intern/guardedalloc/CMakeLists.txt1
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h9
-rw-r--r--intern/guardedalloc/intern/leak_detector.cc61
-rw-r--r--intern/guardedalloc/intern/mallocn_guarded_impl.c165
-rw-r--r--intern/guardedalloc/intern/mallocn_inline.h8
-rw-r--r--intern/guardedalloc/intern/mallocn_intern.h11
-rw-r--r--intern/guardedalloc/intern/mallocn_lockfree_impl.c4
-rw-r--r--intern/guardedalloc/test/simpletest/memtest.c2
-rw-r--r--intern/itasc/Scene.cpp1079
-rw-r--r--intern/libc_compat/libc_compat.c12
-rw-r--r--intern/libmv/CMakeLists.txt2
-rw-r--r--intern/libmv/libmv/simple_pipeline/pipeline.cc4
-rw-r--r--intern/mantaflow/extern/manta_fluid_API.h85
-rw-r--r--intern/mantaflow/intern/MANTA_main.cpp543
-rw-r--r--intern/mantaflow/intern/MANTA_main.h170
-rw-r--r--intern/mantaflow/intern/manta_fluid_API.cpp229
-rw-r--r--intern/mantaflow/intern/strings/fluid_script.h23
-rw-r--r--intern/mantaflow/intern/strings/liquid_script.h6
-rw-r--r--intern/mantaflow/intern/strings/smoke_script.h8
-rw-r--r--intern/opencolorio/ocio_impl_glsl.cc141
-rw-r--r--intern/rigidbody/RBI_api.h8
-rw-r--r--intern/rigidbody/rb_bullet_api.cpp69
-rw-r--r--intern/sky/CMakeLists.txt39
-rw-r--r--intern/sky/include/sky_model.h (renamed from intern/cycles/util/util_sky_model.h)110
-rw-r--r--intern/sky/source/sky_float3.h157
-rw-r--r--intern/sky/source/sky_model.cpp (renamed from intern/cycles/util/util_sky_model.cpp)30
-rw-r--r--intern/sky/source/sky_model_data.h (renamed from intern/cycles/util/util_sky_model_data.h)4
-rw-r--r--intern/sky/source/sky_nishita.cpp (renamed from intern/cycles/util/util_sky_nishita.cpp)187
182 files changed, 3250 insertions, 2324 deletions
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index fa18f4d793a..0758567bb78 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -30,6 +30,7 @@ add_subdirectory(opensubdiv)
add_subdirectory(mikktspace)
add_subdirectory(glew-mx)
add_subdirectory(eigen)
+add_subdirectory(sky)
if(WITH_AUDASPACE)
add_subdirectory(audaspace)
diff --git a/intern/clog/clog.c b/intern/clog/clog.c
index 921ee17a672..d384b9a89e6 100644
--- a/intern/clog/clog.c
+++ b/intern/clog/clog.c
@@ -153,7 +153,6 @@ static void clg_str_reserve(CLogStringBuf *cstr, const uint len)
cstr->data = data;
cstr->is_alloc = true;
}
- cstr->len_alloc = len;
}
}
@@ -179,26 +178,34 @@ static void clg_str_vappendf(CLogStringBuf *cstr, const char *fmt, va_list args)
{
/* Use limit because windows may use '-1' for a formatting error. */
const uint len_max = 65535;
- uint len_avail = (cstr->len_alloc - cstr->len);
- if (len_avail == 0) {
- len_avail = CLOG_BUF_LEN_INIT;
- clg_str_reserve(cstr, len_avail);
- }
while (true) {
+ uint len_avail = cstr->len_alloc - cstr->len;
+
va_list args_cpy;
va_copy(args_cpy, args);
int retval = vsnprintf(cstr->data + cstr->len, len_avail, fmt, args_cpy);
va_end(args_cpy);
- if (retval != -1) {
- cstr->len += retval;
+
+ if (retval < 0) {
+ /* Some encoding error happened, not much we can do here, besides skipping/cancelling this
+ * message. */
+ break;
+ }
+ else if ((uint)retval <= len_avail) {
+ /* Copy was successful. */
+ cstr->len += (uint)retval;
break;
}
else {
- len_avail *= 2;
- if (len_avail >= len_max) {
+ /* vsnprintf was not successful, due to lack of allocated space, retval contains expected
+ * length of the formated string, use it to allocate required amount of memory. */
+ uint len_alloc = cstr->len + (uint)retval;
+ if (len_alloc >= len_max) {
+ /* Safe upper-limit, just in case... */
break;
}
- clg_str_reserve(cstr, len_avail);
+ clg_str_reserve(cstr, len_alloc);
+ len_avail = cstr->len_alloc - cstr->len;
}
}
}
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index ef374f91a65..a2b0ed03925 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -35,7 +35,7 @@ if(WITH_CYCLES_OSL)
endif()
if(NOT CYCLES_STANDALONE_REPOSITORY)
- list(APPEND LIBRARIES bf_intern_glew_mx bf_intern_guardedalloc bf_intern_numaapi)
+ list(APPEND LIBRARIES bf_intern_glew_mx bf_intern_guardedalloc bf_intern_numaapi bf_intern_sky)
endif()
if(WITH_CYCLES_LOGGING)
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 7566ca28dd7..67e448db859 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -224,7 +224,7 @@ def system_info():
import _cycles
return _cycles.system_info()
-def list_render_passes(srl):
+def list_render_passes(scene, srl):
# Builtin Blender passes.
yield ("Combined", "RGBA", 'COLOR')
@@ -279,14 +279,17 @@ def list_render_passes(srl):
yield ("Denoising Normal", "XYZ", 'VECTOR')
yield ("Denoising Albedo", "RGB", 'COLOR')
yield ("Denoising Depth", "Z", 'VALUE')
- yield ("Denoising Shadowing", "X", 'VALUE')
- yield ("Denoising Variance", "RGB", 'COLOR')
- yield ("Denoising Intensity", "X", 'VALUE')
- clean_options = ("denoising_diffuse_direct", "denoising_diffuse_indirect",
- "denoising_glossy_direct", "denoising_glossy_indirect",
- "denoising_transmission_direct", "denoising_transmission_indirect")
- if any(getattr(crl, option) for option in clean_options):
- yield ("Denoising Clean", "RGB", 'COLOR')
+
+ if scene.cycles.denoiser == 'NLM':
+ yield ("Denoising Shadowing", "X", 'VALUE')
+ yield ("Denoising Variance", "RGB", 'COLOR')
+ yield ("Denoising Intensity", "X", 'VALUE')
+
+ clean_options = ("denoising_diffuse_direct", "denoising_diffuse_indirect",
+ "denoising_glossy_direct", "denoising_glossy_indirect",
+ "denoising_transmission_direct", "denoising_transmission_indirect")
+ if any(getattr(crl, option) for option in clean_options):
+ yield ("Denoising Clean", "RGB", 'COLOR')
# Custom AOV passes.
for aov in crl.aovs:
@@ -298,15 +301,15 @@ def list_render_passes(srl):
def register_passes(engine, scene, view_layer):
# Detect duplicate render pass names, first one wins.
listed = set()
- for name, channelids, channeltype in list_render_passes(view_layer):
+ for name, channelids, channeltype in list_render_passes(scene, view_layer):
if name not in listed:
engine.register_pass(scene, view_layer, name, len(channelids), channelids, channeltype)
listed.add(name)
-def detect_conflicting_passes(view_layer):
+def detect_conflicting_passes(scene, view_layer):
# Detect conflicting render pass names for UI.
counter = {}
- for name, _, _ in list_render_passes(view_layer):
+ for name, _, _ in list_render_passes(scene, view_layer):
counter[name] = counter.get(name, 0) + 1
for aov in view_layer.cycles.aovs:
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index da706451f88..45d25720aff 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -182,6 +182,7 @@ enum_aov_types = (
('COLOR', "Color", "Write a Color pass", 1),
)
+
def enum_openimagedenoise_denoiser(self, context):
if _cycles.with_openimagedenoise:
return [('OPENIMAGEDENOISE', "OpenImageDenoise", "Use Intel OpenImageDenoise AI denoiser running on the CPU", 4)]
@@ -208,14 +209,23 @@ def enum_preview_denoiser(self, context):
def enum_denoiser(self, context):
items = [('NLM', "NLM", "Cycles native non-local means denoiser, running on any compute device", 1)]
items += enum_optix_denoiser(self, context)
+ items += enum_openimagedenoise_denoiser(self, context)
return items
-enum_denoising_optix_input_passes = (
+enum_denoising_input_passes = (
('RGB', "Color", "Use only color as input", 1),
('RGB_ALBEDO', "Color + Albedo", "Use color and albedo data as input", 2),
('RGB_ALBEDO_NORMAL', "Color + Albedo + Normal", "Use color, albedo and normal data as input", 3),
)
+
+def update_render_passes(self, context):
+ scene = context.scene
+ view_layer = context.view_layer
+ view_layer.update_render_passes()
+ engine.detect_conflicting_passes(scene, view_layer)
+
+
class CyclesRenderSettings(bpy.types.PropertyGroup):
device: EnumProperty(
@@ -261,9 +271,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
denoiser: EnumProperty(
name="Denoiser",
- description="Denoise the image with the selected denoiser",
+ description="Denoise the image with the selected denoiser. "
+ "For denoising the image after rendering, denoising data render passes "
+ "also adapt to the selected denoiser",
items=enum_denoiser,
default=1,
+ update=update_render_passes,
)
preview_denoiser: EnumProperty(
name="Viewport Denoiser",
@@ -818,6 +831,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
debug_use_cuda_split_kernel: BoolProperty(name="Split Kernel", default=False)
debug_optix_cuda_streams: IntProperty(name="CUDA Streams", default=1, min=1)
+ debug_optix_curves_api: BoolProperty(name="Native OptiX Curve Primitive", default=False)
debug_opencl_kernel_type: EnumProperty(
name="OpenCL Kernel Type",
@@ -1291,12 +1305,6 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
del bpy.types.Scene.cycles_curves
-def update_render_passes(self, context):
- view_layer = context.view_layer
- view_layer.update_render_passes()
- engine.detect_conflicting_passes(view_layer)
-
-
class CyclesAOVPass(bpy.types.PropertyGroup):
name: StringProperty(
name="Name",
@@ -1430,7 +1438,7 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
)
denoising_store_passes: BoolProperty(
name="Store Denoising Passes",
- description="Store the denoising feature passes and the noisy image",
+ description="Store the denoising feature passes and the noisy image. The passes adapt to the denoiser selected for rendering",
default=False,
update=update_render_passes,
)
@@ -1443,11 +1451,18 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
denoising_optix_input_passes: EnumProperty(
name="Input Passes",
- description="Passes handed over to the OptiX denoiser (this can have different effects on the denoised image)",
- items=enum_denoising_optix_input_passes,
+ description="Passes used by the denoiser to distinguish noise from shader and geometry detail",
+ items=enum_denoising_input_passes,
default='RGB_ALBEDO',
)
+ denoising_openimagedenoise_input_passes: EnumProperty(
+ name="Input Passes",
+ description="Passes used by the denoiser to distinguish noise from shader and geometry detail",
+ items=enum_denoising_input_passes,
+ default='RGB_ALBEDO_NORMAL',
+ )
+
use_pass_crypto_object: BoolProperty(
name="Cryptomatte Object",
description="Render cryptomatte object pass, for isolating objects in compositing",
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 129f16b0357..03b1675c309 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -265,7 +265,12 @@ class CYCLES_RENDER_PT_sampling_denoising(CyclesButtonsPanel, Panel):
row = heading.row(align=True)
row.prop(cscene, "use_denoising", text="")
sub = row.row()
+
sub.active = cscene.use_denoising
+ for view_layer in scene.view_layers:
+ if view_layer.cycles.denoising_store_passes:
+ sub.active = True
+
sub.prop(cscene, "denoiser", text="")
heading = layout.column(align=False, heading="Viewport")
@@ -777,10 +782,6 @@ class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel):
col.prop(view_layer, "use_solid", text="Surfaces")
col.prop(view_layer, "use_strand", text="Hair")
col.prop(view_layer, "use_volumes", text="Volumes")
- if with_freestyle:
- sub = col.row(align=True)
- sub.prop(view_layer, "use_freestyle", text="Freestyle")
- sub.active = rd.use_freestyle
class CYCLES_RENDER_PT_override(CyclesButtonsPanel, Panel):
@@ -1007,6 +1008,7 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
col.prop(cycles_view_layer, "denoising_optix_input_passes")
return
elif denoiser == 'OPENIMAGEDENOISE':
+ col.prop(cycles_view_layer, "denoising_openimagedenoise_input_passes")
return
col.prop(cycles_view_layer, "denoising_radius", text="Radius")
@@ -2026,6 +2028,7 @@ class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
col = layout.column()
col.label(text="OptiX Flags:")
col.prop(cscene, "debug_optix_cuda_streams")
+ col.prop(cscene, "debug_optix_curves_api")
col.separator()
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index 011678a7a65..e1ab3b3fbc1 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -76,6 +76,9 @@ struct BlenderCamera {
int full_width;
int full_height;
+ int render_width;
+ int render_height;
+
BoundBox2D border;
BoundBox2D pano_viewplane;
BoundBox2D viewport_camera_border;
@@ -126,8 +129,10 @@ static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings &b_rende
bcam->matrix = transform_identity();
/* render resolution */
- bcam->full_width = render_resolution_x(b_render);
- bcam->full_height = render_resolution_y(b_render);
+ bcam->render_width = render_resolution_x(b_render);
+ bcam->render_height = render_resolution_y(b_render);
+ bcam->full_width = bcam->render_width;
+ bcam->full_height = bcam->render_height;
}
static float blender_camera_focal_distance(BL::RenderEngine &b_engine,
@@ -398,8 +403,8 @@ static void blender_camera_sync(Camera *cam,
/* panorama sensor */
if (bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) {
- float fit_xratio = (float)bcam->full_width * bcam->pixelaspect.x;
- float fit_yratio = (float)bcam->full_height * bcam->pixelaspect.y;
+ float fit_xratio = (float)bcam->render_width * bcam->pixelaspect.x;
+ float fit_yratio = (float)bcam->render_height * bcam->pixelaspect.y;
bool horizontal_fit;
float sensor_size;
@@ -709,6 +714,10 @@ static void blender_camera_from_view(BlenderCamera *bcam,
/* 3d view transform */
bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix()));
+
+ /* dimensions */
+ bcam->full_width = width;
+ bcam->full_height = height;
}
static void blender_camera_view_subset(BL::RenderEngine &b_engine,
diff --git a/intern/cycles/blender/blender_id_map.h b/intern/cycles/blender/blender_id_map.h
index 3bc42e349ae..b5f6aaa67a8 100644
--- a/intern/cycles/blender/blender_id_map.h
+++ b/intern/cycles/blender/blender_id_map.h
@@ -200,7 +200,7 @@ template<typename K, typename T> class id_map {
* To uniquely identify instances, we use the parent, object and persistent instance ID.
* We also export separate object for a mesh and its particle hair. */
-enum { OBJECT_PERSISTENT_ID_SIZE = 16 };
+enum { OBJECT_PERSISTENT_ID_SIZE = 8 /* MAX_DUPLI_RECUR in Blender. */ };
struct ObjectKey {
void *parent;
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 49407799fcd..f4354d5166e 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -923,6 +923,74 @@ static void create_subd_mesh(Scene *scene,
/* Sync */
+static BL::MeshSequenceCacheModifier object_mesh_cache_find(BL::Object &b_ob,
+ BL::Scene /*b_scene*/)
+{
+ BL::Object::modifiers_iterator b_mod;
+
+ for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
+ if (!b_mod->is_a(&RNA_MeshSequenceCacheModifier)) {
+ continue;
+ }
+
+ BL::MeshSequenceCacheModifier mesh_cache = BL::MeshSequenceCacheModifier(*b_mod);
+
+ if (MeshSequenceCacheModifier_has_velocity_get(&mesh_cache.ptr)) {
+ return mesh_cache;
+ }
+ }
+
+ return BL::MeshSequenceCacheModifier(PointerRNA_NULL);
+}
+
+static void sync_mesh_cached_velocities(BL::Object &b_ob,
+ BL::Scene b_scene,
+ Scene *scene,
+ Mesh *mesh)
+{
+ if (scene->need_motion() == Scene::MOTION_NONE)
+ return;
+
+ BL::MeshSequenceCacheModifier b_mesh_cache = object_mesh_cache_find(b_ob, b_scene);
+
+ if (!b_mesh_cache) {
+ return;
+ }
+
+ /* Find or add attribute */
+ float3 *P = &mesh->verts[0];
+ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (!attr_mP) {
+ attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
+ }
+
+ if (!MeshSequenceCacheModifier_read_velocity_get(&b_mesh_cache.ptr)) {
+ return;
+ }
+
+ const size_t numverts = mesh->verts.size();
+
+ if (b_mesh_cache.vertex_velocities.length() != numverts) {
+ return;
+ }
+
+ /* Only export previous and next frame, we don't have any in between data. */
+ float motion_times[2] = {-1.0f, 1.0f};
+ for (int step = 0; step < 2; step++) {
+ const float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f;
+ float3 *mP = attr_mP->data_float3() + step * numverts;
+
+ BL::MeshSequenceCacheModifier::vertex_velocities_iterator vvi;
+ int i = 0;
+
+ for (b_mesh_cache.vertex_velocities.begin(vvi); vvi != b_mesh_cache.vertex_velocities.end();
+ ++vvi, ++i) {
+ mP[i] = P[i] + get_float3(vvi->velocity()) * relative_time;
+ }
+ }
+}
+
static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
{
if (scene->need_motion() == Scene::MOTION_NONE)
@@ -1002,6 +1070,9 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph,
}
}
+ /* cached velocities (e.g. from alembic archive) */
+ sync_mesh_cached_velocities(b_ob, b_depsgraph.scene(), scene, mesh);
+
/* mesh fluid motion mantaflow */
sync_mesh_fluid_motion(b_ob, scene, mesh);
@@ -1023,6 +1094,12 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
return;
}
+ /* Cached motion blur already exported. */
+ BL::MeshSequenceCacheModifier mesh_cache = object_mesh_cache_find(b_ob, b_scene);
+ if (mesh_cache) {
+ return;
+ }
+
/* Skip if no vertices were exported. */
size_t numverts = mesh->verts.size();
if (numverts == 0) {
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index d3a37563ef4..3ea6892a349 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -59,7 +59,7 @@ bool BlenderSync::BKE_object_is_modified(BL::Object &b_ob)
return false;
}
-bool BlenderSync::object_is_mesh(BL::Object &b_ob)
+bool BlenderSync::object_is_geometry(BL::Object &b_ob)
{
BL::ID b_ob_data = b_ob.data();
@@ -143,7 +143,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
}
/* only interested in object that we can create meshes from */
- if (!object_is_mesh(b_ob)) {
+ if (!object_is_geometry(b_ob)) {
return NULL;
}
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 3e595c3ee52..25c77b74ce3 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -92,6 +92,7 @@ bool debug_flags_sync_from_scene(BL::Scene b_scene)
flags.cuda.split_kernel = get_boolean(cscene, "debug_use_cuda_split_kernel");
/* Synchronize OptiX flags. */
flags.optix.cuda_streams = get_int(cscene, "debug_optix_cuda_streams");
+ flags.optix.curves_api = get_boolean(cscene, "debug_optix_curves_api");
/* Synchronize OpenCL device type. */
switch (get_enum(cscene, "debug_opencl_device_type")) {
case 0:
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 391a1b8f473..a06030c8b7d 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -59,6 +59,7 @@ BlenderSession::BlenderSession(BL::RenderEngine &b_engine,
BL::BlendData &b_data,
bool preview_osl)
: session(NULL),
+ scene(NULL),
sync(NULL),
b_engine(b_engine),
b_userpref(b_userpref),
@@ -88,6 +89,7 @@ BlenderSession::BlenderSession(BL::RenderEngine &b_engine,
int width,
int height)
: session(NULL),
+ scene(NULL),
sync(NULL),
b_engine(b_engine),
b_userpref(b_userpref),
@@ -492,27 +494,15 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
/* Update denoising parameters. */
session->set_denoising(session_params.denoising);
- bool use_denoising = session_params.denoising.use;
- bool store_denoising_passes = session_params.denoising.store_passes;
-
- buffer_params.denoising_data_pass = use_denoising || store_denoising_passes;
- buffer_params.denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES);
- buffer_params.denoising_prefiltered_pass = store_denoising_passes &&
- session_params.denoising.type == DENOISER_NLM;
-
- scene->film->denoising_data_pass = buffer_params.denoising_data_pass;
- scene->film->denoising_clean_pass = buffer_params.denoising_clean_pass;
- scene->film->denoising_prefiltered_pass = buffer_params.denoising_prefiltered_pass;
-
- /* Add passes */
+ /* Compute render passes and film settings. */
vector<Pass> passes = sync->sync_render_passes(
b_rlay, b_view_layer, session_params.adaptive_sampling, session_params.denoising);
- buffer_params.passes = passes;
- scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold();
- scene->film->tag_passes_update(scene, passes);
- scene->film->tag_update(scene);
- scene->integrator->tag_update(scene);
+ /* Set buffer params, using film settings from sync_render_passes. */
+ buffer_params.passes = passes;
+ buffer_params.denoising_data_pass = scene->film->denoising_data_pass;
+ buffer_params.denoising_clean_pass = scene->film->denoising_clean_pass;
+ buffer_params.denoising_prefiltered_pass = scene->film->denoising_prefiltered_pass;
BL::RenderResult::views_iterator b_view_iter;
@@ -982,7 +972,8 @@ void BlenderSession::update_status_progress()
remaining_time = (1.0 - (double)progress) * (render_time / (double)progress);
if (background) {
- scene_status += " | " + scene->name;
+ if (scene)
+ scene_status += " | " + scene->name;
if (b_rlay_name != "")
scene_status += ", " + b_rlay_name;
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 19d2730dc93..ae681432a43 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -678,7 +678,7 @@ static ShaderNode *add_node(Scene *scene,
* builtin names for packed images and movies
*/
int scene_frame = b_scene.frame_current();
- int image_frame = image_user_frame_number(b_image_user, scene_frame);
+ int image_frame = image_user_frame_number(b_image_user, b_image, scene_frame);
image->handle = scene->image_manager->add_image(
new BlenderImageLoader(b_image, image_frame), image->image_params());
}
@@ -713,7 +713,7 @@ static ShaderNode *add_node(Scene *scene,
if (is_builtin) {
int scene_frame = b_scene.frame_current();
- int image_frame = image_user_frame_number(b_image_user, scene_frame);
+ int image_frame = image_user_frame_number(b_image_user, b_image, scene_frame);
env->handle = scene->image_manager->add_image(new BlenderImageLoader(b_image, image_frame),
env->image_params());
}
@@ -815,9 +815,10 @@ static ShaderNode *add_node(Scene *scene,
sky->ground_albedo = b_sky_node.ground_albedo();
sky->sun_disc = b_sky_node.sun_disc();
sky->sun_size = b_sky_node.sun_size();
+ sky->sun_intensity = b_sky_node.sun_intensity();
sky->sun_elevation = b_sky_node.sun_elevation();
sky->sun_rotation = b_sky_node.sun_rotation();
- sky->altitude = b_sky_node.altitude();
+ sky->altitude = 1000.0f * b_sky_node.altitude();
sky->air_density = b_sky_node.air_density();
sky->dust_density = b_sky_node.dust_density();
sky->ozone_density = b_sky_node.ozone_density();
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index bf065cc5492..511061db08a 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -147,30 +147,43 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
/* Object */
else if (b_id.is_a(&RNA_Object)) {
BL::Object b_ob(b_id);
- const bool updated_geometry = b_update->is_updated_geometry();
+ const bool is_geometry = object_is_geometry(b_ob);
+ const bool is_light = !is_geometry && object_is_light(b_ob);
- if (b_update->is_updated_transform() || b_update->is_updated_shading()) {
- object_map.set_recalc(b_ob);
- light_map.set_recalc(b_ob);
- }
+ if (is_geometry || is_light) {
+ const bool updated_geometry = b_update->is_updated_geometry();
- if (object_is_mesh(b_ob)) {
- if (updated_geometry ||
- (object_subdivision_type(b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE)) {
- BL::ID key = BKE_object_is_modified(b_ob) ? b_ob : b_ob.data();
- geometry_map.set_recalc(key);
- }
- }
- else if (object_is_light(b_ob)) {
- if (updated_geometry) {
- light_map.set_recalc(b_ob);
+ /* Geometry (mesh, hair, volume). */
+ if (is_geometry) {
+ if (b_update->is_updated_transform() || b_update->is_updated_shading()) {
+ object_map.set_recalc(b_ob);
+ }
+
+ if (updated_geometry ||
+ (object_subdivision_type(b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE)) {
+ BL::ID key = BKE_object_is_modified(b_ob) ? b_ob : b_ob.data();
+ geometry_map.set_recalc(key);
+ }
+
+ if (updated_geometry) {
+ BL::Object::particle_systems_iterator b_psys;
+ for (b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end();
+ ++b_psys) {
+ particle_system_map.set_recalc(b_ob);
+ }
+ }
}
- }
+ /* Light */
+ else if (is_light) {
+ if (b_update->is_updated_transform() || b_update->is_updated_shading()) {
+ object_map.set_recalc(b_ob);
+ light_map.set_recalc(b_ob);
+ }
- if (updated_geometry) {
- BL::Object::particle_systems_iterator b_psys;
- for (b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys)
- particle_system_map.set_recalc(b_ob);
+ if (updated_geometry) {
+ light_map.set_recalc(b_ob);
+ }
+ }
}
}
/* Mesh */
@@ -684,6 +697,16 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
}
RNA_END;
+ scene->film->denoising_data_pass = denoising.use || denoising.store_passes;
+ scene->film->denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES);
+ scene->film->denoising_prefiltered_pass = denoising.store_passes &&
+ denoising.type == DENOISER_NLM;
+
+ scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold();
+ scene->film->tag_passes_update(scene, passes);
+ scene->film->tag_update(scene);
+ scene->integrator->tag_update(scene);
+
return passes;
}
@@ -941,7 +964,13 @@ DenoiseParams BlenderSync::get_denoise_params(BL::Scene &b_scene,
denoising.strength = get_float(clayer, "denoising_strength");
denoising.feature_strength = get_float(clayer, "denoising_feature_strength");
denoising.relative_pca = get_boolean(clayer, "denoising_relative_pca");
- denoising.optix_input_passes = get_enum(clayer, "denoising_optix_input_passes");
+
+ denoising.input_passes = (DenoiserInput)get_enum(
+ clayer,
+ (denoising.type == DENOISER_OPTIX) ? "denoising_optix_input_passes" :
+ "denoising_openimagedenoise_input_passes",
+ DENOISER_INPUT_NUM,
+ DENOISER_INPUT_RGB_ALBEDO_NORMAL);
denoising.store_passes = get_boolean(clayer, "denoising_store_passes");
}
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 0214d9eb3b8..a551ec31e04 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -208,7 +208,7 @@ class BlenderSync {
/* util */
void find_shader(BL::ID &id, vector<Shader *> &used_shaders, Shader *default_shader);
bool BKE_object_is_modified(BL::Object &b_ob);
- bool object_is_mesh(BL::Object &b_ob);
+ bool object_is_geometry(BL::Object &b_ob);
bool object_is_light(BL::Object &b_ob);
/* variables */
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index ad90a5f8d52..1ea34b41aa2 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -238,7 +238,7 @@ static inline string image_user_file_path(BL::ImageUser &iuser,
{
char filepath[1024];
iuser.tile(0);
- BKE_image_user_frame_calc(NULL, iuser.ptr.data, cfra);
+ BKE_image_user_frame_calc(ima.ptr.data, iuser.ptr.data, cfra);
BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath);
string filepath_str = string(filepath);
@@ -248,9 +248,9 @@ static inline string image_user_file_path(BL::ImageUser &iuser,
return filepath_str;
}
-static inline int image_user_frame_number(BL::ImageUser &iuser, int cfra)
+static inline int image_user_frame_number(BL::ImageUser &iuser, BL::Image &ima, int cfra)
{
- BKE_image_user_frame_calc(NULL, iuser.ptr.data, cfra);
+ BKE_image_user_frame_calc(ima.ptr.data, iuser.ptr.data, cfra);
return iuser.frame_current();
}
diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp
index 80591e0eec8..d0e1e4d6131 100644
--- a/intern/cycles/blender/blender_volume.cpp
+++ b/intern/cycles/blender/blender_volume.cpp
@@ -217,43 +217,29 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float
class BlenderVolumeLoader : public VDBImageLoader {
public:
BlenderVolumeLoader(BL::BlendData &b_data, BL::Volume &b_volume, const string &grid_name)
- : VDBImageLoader(grid_name), b_data(b_data), b_volume(b_volume), unload(false)
- {
- }
-
- bool load_metadata(ImageMetaData &metadata) override
+ : VDBImageLoader(grid_name), b_volume(b_volume)
{
b_volume.grids.load(b_data.ptr.data);
- BL::VolumeGrid b_volume_grid = find_grid();
-
- if (!b_volume_grid) {
- return false;
- }
-
- unload = !b_volume_grid.is_loaded();
#ifdef WITH_OPENVDB
- Volume *volume = (Volume *)b_volume.ptr.data;
- VolumeGrid *volume_grid = (VolumeGrid *)b_volume_grid.ptr.data;
- grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
-#endif
+ BL::Volume::grids_iterator b_grid_iter;
+ for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) {
+ BL::VolumeGrid b_volume_grid(*b_grid_iter);
+ if (b_volume_grid.name() == grid_name) {
+ const bool unload = !b_volume_grid.is_loaded();
- return VDBImageLoader::load_metadata(metadata);
- }
+ Volume *volume = (Volume *)b_volume.ptr.data;
+ VolumeGrid *volume_grid = (VolumeGrid *)b_volume_grid.ptr.data;
+ grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
- bool load_pixels(const ImageMetaData &metadata,
- void *pixels,
- const size_t pixel_size,
- const bool associate_alpha) override
- {
- b_volume.grids.load(b_data.ptr.data);
- BL::VolumeGrid b_volume_grid = find_grid();
+ if (unload) {
+ b_volume_grid.unload();
+ }
- if (!b_volume_grid) {
- return false;
+ break;
+ }
}
-
- return VDBImageLoader::load_pixels(metadata, pixels, pixel_size, associate_alpha);
+#endif
}
bool equals(const ImageLoader &other) const override
@@ -263,36 +249,7 @@ class BlenderVolumeLoader : public VDBImageLoader {
return b_volume == other_loader.b_volume && grid_name == other_loader.grid_name;
}
- void cleanup() override
- {
- VDBImageLoader::cleanup();
-
- BL::VolumeGrid b_volume_grid = find_grid();
- if (b_volume_grid && unload) {
- b_volume_grid.unload();
- }
- }
-
- /* Find grid with matching name. Grid point not stored in the class since
- * grids may be unloaded before we load the pixels, for example for motion
- * blur where we move between frames. */
- BL::VolumeGrid find_grid()
- {
-#ifdef WITH_OPENVDB
- BL::Volume::grids_iterator b_grid_iter;
- for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) {
- if (b_grid_iter->name() == grid_name) {
- return *b_grid_iter;
- }
- }
-#endif
-
- return BL::VolumeGrid(PointerRNA_NULL);
- }
-
- BL::BlendData b_data;
BL::Volume b_volume;
- bool unload;
};
static void sync_volume_object(BL::BlendData &b_data, BL::Object &b_ob, Scene *scene, Mesh *mesh)
@@ -342,7 +299,7 @@ static void sync_volume_object(BL::BlendData &b_data, BL::Object &b_ob, Scene *s
ImageParams params;
params.frame = b_volume.grids.frame();
- attr->data_voxel() = scene->image_manager->add_image(loader, params);
+ attr->data_voxel() = scene->image_manager->add_image(loader, params, false);
}
}
}
diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake
index 0b082b11cf7..b09f442bd16 100644
--- a/intern/cycles/cmake/external_libs.cmake
+++ b/intern/cycles/cmake/external_libs.cmake
@@ -133,9 +133,9 @@ if(CYCLES_STANDALONE_REPOSITORY)
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
####
- # embree
+ # Embree
if(WITH_CYCLES_EMBREE)
- find_package(embree 3.8.0 REQUIRED)
+ find_package(Embree 3.8.0 REQUIRED)
endif()
####
diff --git a/intern/cycles/device/cuda/device_cuda_impl.cpp b/intern/cycles/device/cuda/device_cuda_impl.cpp
index b9bbeb9a25b..3a2eb8df95b 100644
--- a/intern/cycles/device/cuda/device_cuda_impl.cpp
+++ b/intern/cycles/device/cuda/device_cuda_impl.cpp
@@ -383,11 +383,24 @@ string CUDADevice::compile_kernel(const DeviceRequestedFeatures &requested_featu
}
}
- const string ptx = path_get(string_printf("lib/%s_compute_%d%d.ptx", name, major, minor));
- VLOG(1) << "Testing for pre-compiled kernel " << ptx << ".";
- if (path_exists(ptx)) {
- VLOG(1) << "Using precompiled kernel.";
- return ptx;
+ /* The driver can JIT-compile PTX generated for older generations, so find the closest one. */
+ int ptx_major = major, ptx_minor = minor;
+ while (ptx_major >= 3) {
+ const string ptx = path_get(
+ string_printf("lib/%s_compute_%d%d.ptx", name, ptx_major, ptx_minor));
+ VLOG(1) << "Testing for pre-compiled kernel " << ptx << ".";
+ if (path_exists(ptx)) {
+ VLOG(1) << "Using precompiled kernel.";
+ return ptx;
+ }
+
+ if (ptx_minor > 0) {
+ ptx_minor--;
+ }
+ else {
+ ptx_major--;
+ ptx_minor = 9;
+ }
}
}
@@ -1760,7 +1773,7 @@ void CUDADevice::denoise(RenderTile &rtile, DenoisingTask &denoising)
denoising.render_buffer.samples = rtile.sample;
denoising.buffer.gpu_temporary_mem = true;
- denoising.run_denoising(&rtile);
+ denoising.run_denoising(rtile);
}
void CUDADevice::adaptive_sampling_filter(uint filter_sample,
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 9dbb33980b4..407f73e8451 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -209,13 +209,13 @@ bool Device::bind_fallback_display_space_shader(const float width, const float h
glUseProgram(fallback_shader_program);
image_texture_location = glGetUniformLocation(fallback_shader_program, "image_texture");
if (image_texture_location < 0) {
- LOG(ERROR) << "Shader doesn't containt the 'image_texture' uniform.";
+ LOG(ERROR) << "Shader doesn't contain the 'image_texture' uniform.";
return false;
}
fullscreen_location = glGetUniformLocation(fallback_shader_program, "fullscreen");
if (fullscreen_location < 0) {
- LOG(ERROR) << "Shader doesn't containt the 'fullscreen' uniform.";
+ LOG(ERROR) << "Shader doesn't contain the 'fullscreen' uniform.";
return false;
}
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index a5833369a17..115b05e3911 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -439,10 +439,10 @@ class Device {
{
return 0;
}
- virtual void map_neighbor_tiles(Device * /*sub_device*/, RenderTile * /*tiles*/)
+ virtual void map_neighbor_tiles(Device * /*sub_device*/, RenderTileNeighbors & /*neighbors*/)
{
}
- virtual void unmap_neighbor_tiles(Device * /*sub_device*/, RenderTile * /*tiles*/)
+ virtual void unmap_neighbor_tiles(Device * /*sub_device*/, RenderTileNeighbors & /*neighbors*/)
{
}
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index 8f68e66a1b4..ee3a3ddea64 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -182,6 +182,7 @@ class CPUDevice : public Device {
oidn::DeviceRef oidn_device;
oidn::FilterRef oidn_filter;
#endif
+ thread_spin_lock oidn_task_lock;
bool use_split_kernel;
@@ -948,12 +949,25 @@ class CPUDevice : public Device {
}
}
- void denoise_openimagedenoise(DeviceTask &task, RenderTile &rtile)
+ void denoise_openimagedenoise_buffer(DeviceTask &task,
+ float *buffer,
+ const size_t offset,
+ const size_t stride,
+ const size_t x,
+ const size_t y,
+ const size_t w,
+ const size_t h,
+ const float scale)
{
#ifdef WITH_OPENIMAGEDENOISE
assert(openimagedenoise_supported());
- /* Only one at a time, since OpenImageDenoise itself is multithreaded. */
+ /* Only one at a time, since OpenImageDenoise itself is multithreaded for full
+ * buffers, and for tiled rendering because creating multiple devices and filters
+ * is slow and memory hungry as well.
+ *
+ * TODO: optimize tiled rendering case, by batching together denoising of many
+ * tiles somehow? */
static thread_mutex mutex;
thread_scoped_lock lock(mutex);
@@ -964,54 +978,192 @@ class CPUDevice : public Device {
}
if (!oidn_filter) {
oidn_filter = oidn_device.newFilter("RT");
+ oidn_filter.set("hdr", true);
+ oidn_filter.set("srgb", false);
}
- /* Copy pixels from compute device to CPU (no-op for CPU device). */
- rtile.buffers->buffer.copy_from_device();
-
/* Set images with appropriate stride for our interleaved pass storage. */
- const struct {
+ struct {
const char *name;
- int offset;
- } passes[] = {{"color", task.pass_denoising_data + DENOISING_PASS_COLOR},
- {"normal", task.pass_denoising_data + DENOISING_PASS_NORMAL},
- {"albedo", task.pass_denoising_data + DENOISING_PASS_ALBEDO},
- {"output", 0},
+ const int offset;
+ const bool scale;
+ const bool use;
+ array<float> scaled_buffer;
+ } passes[] = {{"color", task.pass_denoising_data + DENOISING_PASS_COLOR, false, true},
+ {"albedo",
+ task.pass_denoising_data + DENOISING_PASS_ALBEDO,
+ true,
+ task.denoising.input_passes >= DENOISER_INPUT_RGB_ALBEDO},
+ {"normal",
+ task.pass_denoising_data + DENOISING_PASS_NORMAL,
+ true,
+ task.denoising.input_passes >= DENOISER_INPUT_RGB_ALBEDO_NORMAL},
+ {"output", 0, false, true},
{ NULL,
0 }};
for (int i = 0; passes[i].name; i++) {
- const int64_t offset = rtile.offset + rtile.x + rtile.y * rtile.stride;
- const int64_t buffer_offset = (offset * task.pass_stride + passes[i].offset) * sizeof(float);
- const int64_t pixel_stride = task.pass_stride * sizeof(float);
- const int64_t row_stride = rtile.stride * pixel_stride;
+ if (!passes[i].use) {
+ continue;
+ }
- oidn_filter.setImage(passes[i].name,
- (char *)rtile.buffer + buffer_offset,
- oidn::Format::Float3,
- rtile.w,
- rtile.h,
- 0,
- pixel_stride,
- row_stride);
+ const int64_t pixel_offset = offset + x + y * stride;
+ const int64_t buffer_offset = (pixel_offset * task.pass_stride + passes[i].offset);
+ const int64_t pixel_stride = task.pass_stride;
+ const int64_t row_stride = stride * pixel_stride;
+
+ if (passes[i].scale && scale != 1.0f) {
+ /* Normalize albedo and normal passes as they are scaled by the number of samples.
+ * For the color passes OIDN will perform auto-exposure making it unnecessary. */
+ array<float> &scaled_buffer = passes[i].scaled_buffer;
+ scaled_buffer.resize(w * h * 3);
+
+ for (int y = 0; y < h; y++) {
+ const float *pass_row = buffer + buffer_offset + y * row_stride;
+ float *scaled_row = scaled_buffer.data() + y * w * 3;
+
+ for (int x = 0; x < w; x++) {
+ scaled_row[x * 3 + 0] = pass_row[x * pixel_stride + 0] * scale;
+ scaled_row[x * 3 + 1] = pass_row[x * pixel_stride + 1] * scale;
+ scaled_row[x * 3 + 2] = pass_row[x * pixel_stride + 2] * scale;
+ }
+ }
+
+ oidn_filter.setImage(
+ passes[i].name, scaled_buffer.data(), oidn::Format::Float3, w, h, 0, 0, 0);
+ }
+ else {
+ oidn_filter.setImage(passes[i].name,
+ buffer + buffer_offset,
+ oidn::Format::Float3,
+ w,
+ h,
+ 0,
+ pixel_stride * sizeof(float),
+ row_stride * sizeof(float));
+ }
}
/* Execute filter. */
- oidn_filter.set("hdr", true);
- oidn_filter.set("srgb", false);
oidn_filter.commit();
oidn_filter.execute();
-
- /* todo: it may be possible to avoid this copy, but we have to ensure that
- * when other code copies data from the device it doesn't overwrite the
- * denoiser buffers. */
- rtile.buffers->buffer.copy_to_device();
#else
(void)task;
- (void)rtile;
+ (void)buffer;
+ (void)offset;
+ (void)stride;
+ (void)x;
+ (void)y;
+ (void)w;
+ (void)h;
+ (void)scale;
#endif
}
+ void denoise_openimagedenoise(DeviceTask &task, RenderTile &rtile)
+ {
+ if (task.type == DeviceTask::DENOISE_BUFFER) {
+ /* Copy pixels from compute device to CPU (no-op for CPU device). */
+ rtile.buffers->buffer.copy_from_device();
+
+ denoise_openimagedenoise_buffer(task,
+ (float *)rtile.buffer,
+ rtile.offset,
+ rtile.stride,
+ rtile.x,
+ rtile.y,
+ rtile.w,
+ rtile.h,
+ 1.0f / rtile.sample);
+
+ /* todo: it may be possible to avoid this copy, but we have to ensure that
+ * when other code copies data from the device it doesn't overwrite the
+ * denoiser buffers. */
+ rtile.buffers->buffer.copy_to_device();
+ }
+ else {
+ /* Per-tile denoising. */
+ rtile.sample = rtile.start_sample + rtile.num_samples;
+ const float scale = 1.0f / rtile.sample;
+ const float invscale = rtile.sample;
+ const size_t pass_stride = task.pass_stride;
+
+ /* Map neighboring tiles into one buffer for denoising. */
+ RenderTileNeighbors neighbors(rtile);
+ task.map_neighbor_tiles(neighbors, this);
+ RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
+ rtile = center_tile;
+
+ /* Calculate size of the tile to denoise (including overlap). The overlap
+ * size was chosen empirically. OpenImageDenoise specifies an overlap size
+ * of 128 but this is significantly bigger than typical tile size. */
+ const int4 rect = rect_clip(rect_expand(center_tile.bounds(), 64), neighbors.bounds());
+ const int2 rect_size = make_int2(rect.z - rect.x, rect.w - rect.y);
+
+ /* Adjacent tiles are in separate memory regions, copy into single buffer. */
+ array<float> merged(rect_size.x * rect_size.y * task.pass_stride);
+
+ for (int i = 0; i < RenderTileNeighbors::SIZE; i++) {
+ RenderTile &ntile = neighbors.tiles[i];
+ if (!ntile.buffer) {
+ continue;
+ }
+
+ const int xmin = max(ntile.x, rect.x);
+ const int ymin = max(ntile.y, rect.y);
+ const int xmax = min(ntile.x + ntile.w, rect.z);
+ const int ymax = min(ntile.y + ntile.h, rect.w);
+
+ const size_t tile_offset = ntile.offset + xmin + ymin * ntile.stride;
+ const float *tile_buffer = (float *)ntile.buffer + tile_offset * pass_stride;
+
+ const size_t merged_stride = rect_size.x;
+ const size_t merged_offset = (xmin - rect.x) + (ymin - rect.y) * merged_stride;
+ float *merged_buffer = merged.data() + merged_offset * pass_stride;
+
+ for (int y = ymin; y < ymax; y++) {
+ for (int x = 0; x < pass_stride * (xmax - xmin); x++) {
+ merged_buffer[x] = tile_buffer[x] * scale;
+ }
+ tile_buffer += ntile.stride * pass_stride;
+ merged_buffer += merged_stride * pass_stride;
+ }
+ }
+
+ /* Denoise */
+ denoise_openimagedenoise_buffer(
+ task, merged.data(), 0, rect_size.x, 0, 0, rect_size.x, rect_size.y, 1.0f);
+
+ /* Copy back result from merged buffer. */
+ RenderTile &ntile = neighbors.target;
+ if (ntile.buffer) {
+ const int xmin = max(ntile.x, rect.x);
+ const int ymin = max(ntile.y, rect.y);
+ const int xmax = min(ntile.x + ntile.w, rect.z);
+ const int ymax = min(ntile.y + ntile.h, rect.w);
+
+ const size_t tile_offset = ntile.offset + xmin + ymin * ntile.stride;
+ float *tile_buffer = (float *)ntile.buffer + tile_offset * pass_stride;
+
+ const size_t merged_stride = rect_size.x;
+ const size_t merged_offset = (xmin - rect.x) + (ymin - rect.y) * merged_stride;
+ const float *merged_buffer = merged.data() + merged_offset * pass_stride;
+
+ for (int y = ymin; y < ymax; y++) {
+ for (int x = 0; x < pass_stride * (xmax - xmin); x += pass_stride) {
+ tile_buffer[x + 0] = merged_buffer[x + 0] * invscale;
+ tile_buffer[x + 1] = merged_buffer[x + 1] * invscale;
+ tile_buffer[x + 2] = merged_buffer[x + 2] * invscale;
+ }
+ tile_buffer += ntile.stride * pass_stride;
+ merged_buffer += merged_stride * pass_stride;
+ }
+ }
+
+ task.unmap_neighbor_tiles(neighbors, this);
+ }
+ }
+
void denoise_nlm(DenoisingTask &denoising, RenderTile &tile)
{
ProfilingHelper profiling(denoising.profiler, PROFILING_DENOISING);
@@ -1040,7 +1192,7 @@ class CPUDevice : public Device {
denoising.render_buffer.samples = tile.sample;
denoising.buffer.gpu_temporary_mem = false;
- denoising.run_denoising(&tile);
+ denoising.run_denoising(tile);
}
void thread_render(DeviceTask &task)
@@ -1070,10 +1222,23 @@ class CPUDevice : public Device {
}
}
+ /* NLM denoiser. */
DenoisingTask *denoising = NULL;
+ /* OpenImageDenoise: we can only denoise with one thread at a time, so to
+ * avoid waiting with mutex locks in the denoiser, we let only a single
+ * thread acquire denoising tiles. */
+ uint tile_types = task.tile_types;
+ bool hold_denoise_lock = false;
+ if ((tile_types & RenderTile::DENOISE) && task.denoising.type == DENOISER_OPENIMAGEDENOISE) {
+ if (!oidn_task_lock.try_lock()) {
+ tile_types &= ~RenderTile::DENOISE;
+ hold_denoise_lock = true;
+ }
+ }
+
RenderTile tile;
- while (task.acquire_tile(this, tile, task.tile_types)) {
+ while (task.acquire_tile(this, tile, tile_types)) {
if (tile.task == RenderTile::PATH_TRACE) {
if (use_split_kernel) {
device_only_memory<uchar> void_buffer(this, "void_buffer");
@@ -1108,6 +1273,10 @@ class CPUDevice : public Device {
}
}
+ if (hold_denoise_lock) {
+ oidn_task_lock.unlock();
+ }
+
profiler.remove_state(&kg->profiler);
thread_kernel_globals_free((KernelGlobals *)kgbuffer.device_pointer);
diff --git a/intern/cycles/device/device_denoising.cpp b/intern/cycles/device/device_denoising.cpp
index 89de80a5bcd..38c42d15cab 100644
--- a/intern/cycles/device/device_denoising.cpp
+++ b/intern/cycles/device/device_denoising.cpp
@@ -71,29 +71,30 @@ DenoisingTask::~DenoisingTask()
tile_info_mem.free();
}
-void DenoisingTask::set_render_buffer(RenderTile *rtiles)
+void DenoisingTask::set_render_buffer(RenderTileNeighbors &neighbors)
{
- for (int i = 0; i < 9; i++) {
- tile_info->offsets[i] = rtiles[i].offset;
- tile_info->strides[i] = rtiles[i].stride;
- tile_info->buffers[i] = rtiles[i].buffer;
+ for (int i = 0; i < RenderTileNeighbors::SIZE; i++) {
+ RenderTile &rtile = neighbors.tiles[i];
+ tile_info->offsets[i] = rtile.offset;
+ tile_info->strides[i] = rtile.stride;
+ tile_info->buffers[i] = rtile.buffer;
}
- tile_info->x[0] = rtiles[3].x;
- tile_info->x[1] = rtiles[4].x;
- tile_info->x[2] = rtiles[5].x;
- tile_info->x[3] = rtiles[5].x + rtiles[5].w;
- tile_info->y[0] = rtiles[1].y;
- tile_info->y[1] = rtiles[4].y;
- tile_info->y[2] = rtiles[7].y;
- tile_info->y[3] = rtiles[7].y + rtiles[7].h;
-
- target_buffer.offset = rtiles[9].offset;
- target_buffer.stride = rtiles[9].stride;
- target_buffer.ptr = rtiles[9].buffer;
-
- if (do_prefilter && rtiles[9].buffers) {
+ tile_info->x[0] = neighbors.tiles[3].x;
+ tile_info->x[1] = neighbors.tiles[4].x;
+ tile_info->x[2] = neighbors.tiles[5].x;
+ tile_info->x[3] = neighbors.tiles[5].x + neighbors.tiles[5].w;
+ tile_info->y[0] = neighbors.tiles[1].y;
+ tile_info->y[1] = neighbors.tiles[4].y;
+ tile_info->y[2] = neighbors.tiles[7].y;
+ tile_info->y[3] = neighbors.tiles[7].y + neighbors.tiles[7].h;
+
+ target_buffer.offset = neighbors.target.offset;
+ target_buffer.stride = neighbors.target.stride;
+ target_buffer.ptr = neighbors.target.buffer;
+
+ if (do_prefilter && neighbors.target.buffers) {
target_buffer.denoising_output_offset =
- rtiles[9].buffers->params.get_denoising_prefiltered_offset();
+ neighbors.target.buffers->params.get_denoising_prefiltered_offset();
}
else {
target_buffer.denoising_output_offset = 0;
@@ -320,12 +321,11 @@ void DenoisingTask::reconstruct()
functions.solve(target_buffer.ptr);
}
-void DenoisingTask::run_denoising(RenderTile *tile)
+void DenoisingTask::run_denoising(RenderTile &tile)
{
- RenderTile rtiles[10];
- rtiles[4] = *tile;
- functions.map_neighbor_tiles(rtiles);
- set_render_buffer(rtiles);
+ RenderTileNeighbors neighbors(tile);
+ functions.map_neighbor_tiles(neighbors);
+ set_render_buffer(neighbors);
setup_denoising_buffer();
@@ -347,7 +347,7 @@ void DenoisingTask::run_denoising(RenderTile *tile)
write_buffer();
}
- functions.unmap_neighbor_tiles(rtiles);
+ functions.unmap_neighbor_tiles(neighbors);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_denoising.h b/intern/cycles/device/device_denoising.h
index 4c122e981eb..2c0dc23b44a 100644
--- a/intern/cycles/device/device_denoising.h
+++ b/intern/cycles/device/device_denoising.h
@@ -102,8 +102,8 @@ class DenoisingTask {
device_ptr output_ptr)>
detect_outliers;
function<bool(int out_offset, device_ptr frop_ptr, device_ptr buffer_ptr)> write_feature;
- function<void(RenderTile *rtiles)> map_neighbor_tiles;
- function<void(RenderTile *rtiles)> unmap_neighbor_tiles;
+ function<void(RenderTileNeighbors &neighbors)> map_neighbor_tiles;
+ function<void(RenderTileNeighbors &neighbors)> unmap_neighbor_tiles;
} functions;
/* Stores state of the current Reconstruction operation,
@@ -154,7 +154,7 @@ class DenoisingTask {
DenoisingTask(Device *device, const DeviceTask &task);
~DenoisingTask();
- void run_denoising(RenderTile *tile);
+ void run_denoising(RenderTile &tile);
struct DenoiseBuffers {
int pass_stride;
@@ -179,7 +179,7 @@ class DenoisingTask {
protected:
Device *device;
- void set_render_buffer(RenderTile *rtiles);
+ void set_render_buffer(RenderTileNeighbors &neighbors);
void setup_denoising_buffer();
void prefilter_shadowing();
void prefilter_features();
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index fd14bbdccc5..9ea8782d0f0 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -177,8 +177,11 @@ class MultiDevice : public Device {
return false;
if (requested_features.use_denoising) {
+ /* Only need denoising feature, everything else is unused. */
+ DeviceRequestedFeatures denoising_features;
+ denoising_features.use_denoising = true;
foreach (SubDevice &sub, denoising_devices)
- if (!sub.device->load_kernels(requested_features))
+ if (!sub.device->load_kernels(denoising_features))
return false;
}
@@ -581,20 +584,22 @@ class MultiDevice : public Device {
return -1;
}
- void map_neighbor_tiles(Device *sub_device, RenderTile *tiles)
+ void map_neighbor_tiles(Device *sub_device, RenderTileNeighbors &neighbors)
{
- for (int i = 0; i < 9; i++) {
- if (!tiles[i].buffers) {
+ for (int i = 0; i < RenderTileNeighbors::SIZE; i++) {
+ RenderTile &tile = neighbors.tiles[i];
+
+ if (!tile.buffers) {
continue;
}
- device_vector<float> &mem = tiles[i].buffers->buffer;
- tiles[i].buffer = mem.device_pointer;
+ device_vector<float> &mem = tile.buffers->buffer;
+ tile.buffer = mem.device_pointer;
if (mem.device == this && matching_rendering_and_denoising_devices) {
/* Skip unnecessary copies in viewport mode (buffer covers the
* whole image), but still need to fix up the tile device pointer. */
- map_tile(sub_device, tiles[i]);
+ map_tile(sub_device, tile);
continue;
}
@@ -607,15 +612,15 @@ class MultiDevice : public Device {
* also required for the case where a CPU thread is denoising
* a tile rendered on the GPU. In that case we have to avoid
* overwriting the buffer being de-noised by the CPU thread. */
- if (!tiles[i].buffers->map_neighbor_copied) {
- tiles[i].buffers->map_neighbor_copied = true;
+ if (!tile.buffers->map_neighbor_copied) {
+ tile.buffers->map_neighbor_copied = true;
mem.copy_from_device();
}
if (mem.device == this) {
/* Can re-use memory if tile is already allocated on the sub device. */
- map_tile(sub_device, tiles[i]);
- mem.swap_device(sub_device, mem.device_size, tiles[i].buffer);
+ map_tile(sub_device, tile);
+ mem.swap_device(sub_device, mem.device_size, tile.buffer);
}
else {
mem.swap_device(sub_device, 0, 0);
@@ -623,40 +628,42 @@ class MultiDevice : public Device {
mem.copy_to_device();
- tiles[i].buffer = mem.device_pointer;
- tiles[i].device_size = mem.device_size;
+ tile.buffer = mem.device_pointer;
+ tile.device_size = mem.device_size;
mem.restore_device();
}
}
}
- void unmap_neighbor_tiles(Device *sub_device, RenderTile *tiles)
+ void unmap_neighbor_tiles(Device *sub_device, RenderTileNeighbors &neighbors)
{
- device_vector<float> &mem = tiles[9].buffers->buffer;
+ RenderTile &target_tile = neighbors.target;
+ device_vector<float> &mem = target_tile.buffers->buffer;
if (mem.device == this && matching_rendering_and_denoising_devices) {
return;
}
/* Copy denoised result back to the host. */
- mem.swap_device(sub_device, tiles[9].device_size, tiles[9].buffer);
+ mem.swap_device(sub_device, target_tile.device_size, target_tile.buffer);
mem.copy_from_device();
mem.restore_device();
/* Copy denoised result to the original device. */
mem.copy_to_device();
- for (int i = 0; i < 9; i++) {
- if (!tiles[i].buffers) {
+ for (int i = 0; i < RenderTileNeighbors::SIZE; i++) {
+ RenderTile &tile = neighbors.tiles[i];
+ if (!tile.buffers) {
continue;
}
- device_vector<float> &mem = tiles[i].buffers->buffer;
+ device_vector<float> &mem = tile.buffers->buffer;
if (mem.device != sub_device && mem.device != this) {
/* Free up memory again if it was allocated for the copy above. */
- mem.swap_device(sub_device, tiles[i].device_size, tiles[i].buffer);
+ mem.swap_device(sub_device, tile.device_size, tile.buffer);
sub_device->mem_free(mem);
mem.restore_device();
}
diff --git a/intern/cycles/device/device_optix.cpp b/intern/cycles/device/device_optix.cpp
index ececca3df53..1cc45983565 100644
--- a/intern/cycles/device/device_optix.cpp
+++ b/intern/cycles/device/device_optix.cpp
@@ -131,8 +131,12 @@ class OptiXDevice : public CUDADevice {
PG_RGEN,
PG_MISS,
PG_HITD, // Default hit group
- PG_HITL, // __BVH_LOCAL__ hit group
PG_HITS, // __SHADOW_RECORD_ALL__ hit group
+ PG_HITL, // __BVH_LOCAL__ hit group (only used for triangles)
+# if OPTIX_ABI_VERSION >= 36
+ PG_HITD_MOTION,
+ PG_HITS_MOTION,
+# endif
# ifdef WITH_CYCLES_DEBUG
PG_EXCP,
# endif
@@ -177,6 +181,7 @@ class OptiXDevice : public CUDADevice {
OptixDeviceContext context = NULL;
OptixModule optix_module = NULL; // All necessary OptiX kernels are in one module
+ OptixModule builtin_modules[2] = {};
OptixPipeline pipelines[NUM_PIPELINES] = {};
bool motion_blur = false;
@@ -264,6 +269,9 @@ class OptiXDevice : public CUDADevice {
// Unload modules
if (optix_module != NULL)
optixModuleDestroy(optix_module);
+ for (unsigned int i = 0; i < 2; ++i)
+ if (builtin_modules[i] != NULL)
+ optixModuleDestroy(builtin_modules[i]);
for (unsigned int i = 0; i < NUM_PIPELINES; ++i)
if (pipelines[i] != NULL)
optixPipelineDestroy(pipelines[i]);
@@ -338,6 +346,12 @@ class OptiXDevice : public CUDADevice {
optixModuleDestroy(optix_module);
optix_module = NULL;
}
+ for (unsigned int i = 0; i < 2; ++i) {
+ if (builtin_modules[i] != NULL) {
+ optixModuleDestroy(builtin_modules[i]);
+ builtin_modules[i] = NULL;
+ }
+ }
for (unsigned int i = 0; i < NUM_PIPELINES; ++i) {
if (pipelines[i] != NULL) {
optixPipelineDestroy(pipelines[i]);
@@ -369,6 +383,18 @@ class OptiXDevice : public CUDADevice {
# endif
pipeline_options.pipelineLaunchParamsVariableName = "__params"; // See kernel_globals.h
+# if OPTIX_ABI_VERSION >= 36
+ pipeline_options.usesPrimitiveTypeFlags = OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE;
+ if (requested_features.use_hair) {
+ if (DebugFlags().optix.curves_api && requested_features.use_hair_thick) {
+ pipeline_options.usesPrimitiveTypeFlags |= OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CUBIC_BSPLINE;
+ }
+ else {
+ pipeline_options.usesPrimitiveTypeFlags |= OPTIX_PRIMITIVE_TYPE_FLAGS_CUSTOM;
+ }
+ }
+# endif
+
// Keep track of whether motion blur is enabled, so to enable/disable motion in BVH builds
// This is necessary since objects may be reported to have motion if the Vector pass is
// active, but may still need to be rendered without motion blur if that isn't active as well
@@ -442,6 +468,34 @@ class OptiXDevice : public CUDADevice {
group_descs[PG_HITD].hitgroup.entryFunctionNameIS = "__intersection__curve_ribbon";
group_descs[PG_HITS].hitgroup.entryFunctionNameIS = "__intersection__curve_ribbon";
}
+
+# if OPTIX_ABI_VERSION >= 36
+ if (DebugFlags().optix.curves_api && requested_features.use_hair_thick) {
+ OptixBuiltinISOptions builtin_options;
+ builtin_options.builtinISModuleType = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE;
+ builtin_options.usesMotionBlur = false;
+
+ check_result_optix_ret(optixBuiltinISModuleGet(
+ context, &module_options, &pipeline_options, &builtin_options, &builtin_modules[0]));
+
+ group_descs[PG_HITD].hitgroup.moduleIS = builtin_modules[0];
+ group_descs[PG_HITD].hitgroup.entryFunctionNameIS = nullptr;
+ group_descs[PG_HITS].hitgroup.moduleIS = builtin_modules[0];
+ group_descs[PG_HITS].hitgroup.entryFunctionNameIS = nullptr;
+
+ if (motion_blur) {
+ builtin_options.usesMotionBlur = true;
+
+ check_result_optix_ret(optixBuiltinISModuleGet(
+ context, &module_options, &pipeline_options, &builtin_options, &builtin_modules[1]));
+
+ group_descs[PG_HITD_MOTION] = group_descs[PG_HITD];
+ group_descs[PG_HITD_MOTION].hitgroup.moduleIS = builtin_modules[1];
+ group_descs[PG_HITS_MOTION] = group_descs[PG_HITS];
+ group_descs[PG_HITS_MOTION].hitgroup.moduleIS = builtin_modules[1];
+ }
+ }
+# endif
}
if (requested_features.use_subsurface || requested_features.use_shader_raytrace) {
@@ -493,8 +547,14 @@ class OptiXDevice : public CUDADevice {
unsigned int trace_css = stack_size[PG_HITD].cssCH;
// This is based on the maximum of closest-hit and any-hit/intersection programs
trace_css = std::max(trace_css, stack_size[PG_HITD].cssIS + stack_size[PG_HITD].cssAH);
- trace_css = std::max(trace_css, stack_size[PG_HITL].cssIS + stack_size[PG_HITL].cssAH);
trace_css = std::max(trace_css, stack_size[PG_HITS].cssIS + stack_size[PG_HITS].cssAH);
+ trace_css = std::max(trace_css, stack_size[PG_HITL].cssIS + stack_size[PG_HITL].cssAH);
+# if OPTIX_ABI_VERSION >= 36
+ trace_css = std::max(trace_css,
+ stack_size[PG_HITD_MOTION].cssIS + stack_size[PG_HITD_MOTION].cssAH);
+ trace_css = std::max(trace_css,
+ stack_size[PG_HITS_MOTION].cssIS + stack_size[PG_HITS_MOTION].cssAH);
+# endif
OptixPipelineLinkOptions link_options;
link_options.maxTraceDepth = 1;
@@ -503,17 +563,23 @@ class OptiXDevice : public CUDADevice {
# else
link_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_LINEINFO;
# endif
- link_options.overrideUsesMotionBlur = pipeline_options.usesMotionBlur;
+# if OPTIX_ABI_VERSION < 24
+ link_options.overrideUsesMotionBlur = motion_blur;
+# endif
{ // Create path tracing pipeline
OptixProgramGroup pipeline_groups[] = {
- groups[PG_RGEN],
- groups[PG_MISS],
- groups[PG_HITD],
- groups[PG_HITS],
- groups[PG_HITL],
+ groups[PG_RGEN],
+ groups[PG_MISS],
+ groups[PG_HITD],
+ groups[PG_HITS],
+ groups[PG_HITL],
+# if OPTIX_ABI_VERSION >= 36
+ groups[PG_HITD_MOTION],
+ groups[PG_HITS_MOTION],
+# endif
# ifdef WITH_CYCLES_DEBUG
- groups[PG_EXCP],
+ groups[PG_EXCP],
# endif
};
check_result_optix_ret(
@@ -530,8 +596,8 @@ class OptiXDevice : public CUDADevice {
const unsigned int css = stack_size[PG_RGEN].cssRG + link_options.maxTraceDepth * trace_css;
// Set stack size depending on pipeline options
- check_result_optix_ret(optixPipelineSetStackSize(
- pipelines[PIP_PATH_TRACE], 0, 0, css, (pipeline_options.usesMotionBlur ? 3 : 2)));
+ check_result_optix_ret(
+ optixPipelineSetStackSize(pipelines[PIP_PATH_TRACE], 0, 0, css, (motion_blur ? 3 : 2)));
}
// Only need to create shader evaluation pipeline if one of these features is used:
@@ -541,15 +607,19 @@ class OptiXDevice : public CUDADevice {
if (use_shader_eval_pipeline) { // Create shader evaluation pipeline
OptixProgramGroup pipeline_groups[] = {
- groups[PG_BAKE],
- groups[PG_DISP],
- groups[PG_BACK],
- groups[PG_MISS],
- groups[PG_HITD],
- groups[PG_HITS],
- groups[PG_HITL],
+ groups[PG_BAKE],
+ groups[PG_DISP],
+ groups[PG_BACK],
+ groups[PG_MISS],
+ groups[PG_HITD],
+ groups[PG_HITS],
+ groups[PG_HITL],
+# if OPTIX_ABI_VERSION >= 36
+ groups[PG_HITD_MOTION],
+ groups[PG_HITS_MOTION],
+# endif
# ifdef WITH_CYCLES_DEBUG
- groups[PG_EXCP],
+ groups[PG_EXCP],
# endif
};
check_result_optix_ret(
@@ -672,7 +742,11 @@ class OptiXDevice : public CUDADevice {
sbt_params.missRecordCount = 1;
sbt_params.hitgroupRecordBase = sbt_data.device_pointer + PG_HITD * sizeof(SbtRecord);
sbt_params.hitgroupRecordStrideInBytes = sizeof(SbtRecord);
- sbt_params.hitgroupRecordCount = 3; // PG_HITD, PG_HITL, PG_HITS
+# if OPTIX_ABI_VERSION >= 36
+ sbt_params.hitgroupRecordCount = 5; // PG_HITD(_MOTION), PG_HITS(_MOTION), PG_HITL
+# else
+ sbt_params.hitgroupRecordCount = 3; // PG_HITD, PG_HITS, PG_HITL
+# endif
// Launch the ray generation program
check_result_optix(optixLaunch(pipelines[PIP_PATH_TRACE],
@@ -727,19 +801,18 @@ class OptiXDevice : public CUDADevice {
// 0 1 2
// 3 4 5
// 6 7 8 9
- RenderTile rtiles[10];
- rtiles[4] = rtile;
- task.map_neighbor_tiles(rtiles, this);
- rtile = rtiles[4]; // Tile may have been modified by mapping code
+ RenderTileNeighbors neighbors(rtile);
+ task.map_neighbor_tiles(neighbors, this);
+ RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
+ RenderTile &target_tile = neighbors.target;
+ rtile = center_tile; // Tile may have been modified by mapping code
// Calculate size of the tile to denoise (including overlap)
- int4 rect = make_int4(
- rtiles[4].x, rtiles[4].y, rtiles[4].x + rtiles[4].w, rtiles[4].y + rtiles[4].h);
+ int4 rect = center_tile.bounds();
// Overlap between tiles has to be at least 64 pixels
// TODO(pmours): Query this value from OptiX
rect = rect_expand(rect, 64);
- int4 clip_rect = make_int4(
- rtiles[3].x, rtiles[1].y, rtiles[5].x + rtiles[5].w, rtiles[7].y + rtiles[7].h);
+ int4 clip_rect = neighbors.bounds();
rect = rect_clip(rect, clip_rect);
int2 rect_size = make_int2(rect.z - rect.x, rect.w - rect.y);
int2 overlap_offset = make_int2(rtile.x - rect.x, rtile.y - rect.y);
@@ -760,14 +833,14 @@ class OptiXDevice : public CUDADevice {
device_only_memory<float> input(this, "denoiser input");
device_vector<TileInfo> tile_info_mem(this, "denoiser tile info", MEM_READ_WRITE);
- if ((!rtiles[0].buffer || rtiles[0].buffer == rtile.buffer) &&
- (!rtiles[1].buffer || rtiles[1].buffer == rtile.buffer) &&
- (!rtiles[2].buffer || rtiles[2].buffer == rtile.buffer) &&
- (!rtiles[3].buffer || rtiles[3].buffer == rtile.buffer) &&
- (!rtiles[5].buffer || rtiles[5].buffer == rtile.buffer) &&
- (!rtiles[6].buffer || rtiles[6].buffer == rtile.buffer) &&
- (!rtiles[7].buffer || rtiles[7].buffer == rtile.buffer) &&
- (!rtiles[8].buffer || rtiles[8].buffer == rtile.buffer)) {
+ bool contiguous_memory = true;
+ for (int i = 0; i < RenderTileNeighbors::SIZE; i++) {
+ if (neighbors.tiles[i].buffer && neighbors.tiles[i].buffer != rtile.buffer) {
+ contiguous_memory = false;
+ }
+ }
+
+ if (contiguous_memory) {
// Tiles are in continous memory, so can just subtract overlap offset
input_ptr -= (overlap_offset.x + overlap_offset.y * rtile.stride) * pixel_stride;
// Stride covers the whole width of the image and not just a single tile
@@ -782,19 +855,19 @@ class OptiXDevice : public CUDADevice {
input_stride *= rect_size.x;
TileInfo *tile_info = tile_info_mem.alloc(1);
- for (int i = 0; i < 9; i++) {
- tile_info->offsets[i] = rtiles[i].offset;
- tile_info->strides[i] = rtiles[i].stride;
- tile_info->buffers[i] = rtiles[i].buffer;
+ for (int i = 0; i < RenderTileNeighbors::SIZE; i++) {
+ tile_info->offsets[i] = neighbors.tiles[i].offset;
+ tile_info->strides[i] = neighbors.tiles[i].stride;
+ tile_info->buffers[i] = neighbors.tiles[i].buffer;
}
- tile_info->x[0] = rtiles[3].x;
- tile_info->x[1] = rtiles[4].x;
- tile_info->x[2] = rtiles[5].x;
- tile_info->x[3] = rtiles[5].x + rtiles[5].w;
- tile_info->y[0] = rtiles[1].y;
- tile_info->y[1] = rtiles[4].y;
- tile_info->y[2] = rtiles[7].y;
- tile_info->y[3] = rtiles[7].y + rtiles[7].h;
+ tile_info->x[0] = neighbors.tiles[3].x;
+ tile_info->x[1] = neighbors.tiles[4].x;
+ tile_info->x[2] = neighbors.tiles[5].x;
+ tile_info->x[3] = neighbors.tiles[5].x + neighbors.tiles[5].w;
+ tile_info->y[0] = neighbors.tiles[1].y;
+ tile_info->y[1] = neighbors.tiles[4].y;
+ tile_info->y[2] = neighbors.tiles[7].y;
+ tile_info->y[3] = neighbors.tiles[7].y + neighbors.tiles[7].h;
tile_info_mem.copy_to_device();
void *args[] = {
@@ -804,7 +877,7 @@ class OptiXDevice : public CUDADevice {
# if OPTIX_DENOISER_NO_PIXEL_STRIDE
device_only_memory<float> input_rgb(this, "denoiser input rgb");
- input_rgb.alloc_to_device(rect_size.x * rect_size.y * 3 * task.denoising.optix_input_passes);
+ input_rgb.alloc_to_device(rect_size.x * rect_size.y * 3 * task.denoising.input_passes);
void *input_args[] = {&input_rgb.device_pointer,
&input_ptr,
@@ -813,7 +886,7 @@ class OptiXDevice : public CUDADevice {
&input_stride,
&task.pass_stride,
const_cast<int *>(pass_offset),
- &task.denoising.optix_input_passes,
+ &task.denoising.input_passes,
&rtile.sample};
launch_filter_kernel(
"kernel_cuda_filter_convert_to_rgb", rect_size.x, rect_size.y, input_args);
@@ -824,7 +897,7 @@ class OptiXDevice : public CUDADevice {
# endif
const bool recreate_denoiser = (denoiser == NULL) ||
- (task.denoising.optix_input_passes != denoiser_input_passes);
+ (task.denoising.input_passes != denoiser_input_passes);
if (recreate_denoiser) {
// Destroy existing handle before creating new one
if (denoiser != NULL) {
@@ -833,23 +906,29 @@ class OptiXDevice : public CUDADevice {
// Create OptiX denoiser handle on demand when it is first used
OptixDenoiserOptions denoiser_options;
- assert(task.denoising.optix_input_passes >= 1 && task.denoising.optix_input_passes <= 3);
+ assert(task.denoising.input_passes >= 1 && task.denoising.input_passes <= 3);
denoiser_options.inputKind = static_cast<OptixDenoiserInputKind>(
- OPTIX_DENOISER_INPUT_RGB + (task.denoising.optix_input_passes - 1));
+ OPTIX_DENOISER_INPUT_RGB + (task.denoising.input_passes - 1));
+# if OPTIX_ABI_VERSION < 28
denoiser_options.pixelFormat = OPTIX_PIXEL_FORMAT_FLOAT3;
+# endif
check_result_optix_ret(optixDenoiserCreate(context, &denoiser_options, &denoiser));
check_result_optix_ret(
optixDenoiserSetModel(denoiser, OPTIX_DENOISER_MODEL_KIND_HDR, NULL, 0));
// OptiX denoiser handle was created with the requested number of input passes
- denoiser_input_passes = task.denoising.optix_input_passes;
+ denoiser_input_passes = task.denoising.input_passes;
}
OptixDenoiserSizes sizes = {};
check_result_optix_ret(
optixDenoiserComputeMemoryResources(denoiser, rect_size.x, rect_size.y, &sizes));
+# if OPTIX_ABI_VERSION < 28
const size_t scratch_size = sizes.recommendedScratchSizeInBytes;
+# else
+ const size_t scratch_size = sizes.withOverlapScratchSizeInBytes;
+# endif
const size_t scratch_offset = sizes.stateSizeInBytes;
// Allocate denoiser state if tile size has changed since last setup
@@ -897,10 +976,10 @@ class OptiXDevice : public CUDADevice {
int2 output_offset = overlap_offset;
overlap_offset = make_int2(0, 0); // Not supported by denoiser API, so apply manually
# else
- output_layers[0].data = rtiles[9].buffer + pixel_offset;
- output_layers[0].width = rtiles[9].w;
- output_layers[0].height = rtiles[9].h;
- output_layers[0].rowStrideInBytes = rtiles[9].stride * pixel_stride;
+ output_layers[0].data = target_tile.buffer + pixel_offset;
+ output_layers[0].width = target_tile.w;
+ output_layers[0].height = target_tile.h;
+ output_layers[0].rowStrideInBytes = target_tile.stride * pixel_stride;
output_layers[0].pixelStrideInBytes = pixel_stride;
# endif
output_layers[0].format = OPTIX_PIXEL_FORMAT_FLOAT3;
@@ -913,7 +992,7 @@ class OptiXDevice : public CUDADevice {
denoiser_state.device_pointer,
scratch_offset,
input_layers,
- task.denoising.optix_input_passes,
+ task.denoising.input_passes,
overlap_offset.x,
overlap_offset.y,
output_layers,
@@ -922,26 +1001,26 @@ class OptiXDevice : public CUDADevice {
# if OPTIX_DENOISER_NO_PIXEL_STRIDE
void *output_args[] = {&input_ptr,
- &rtiles[9].buffer,
+ &target_tile.buffer,
&output_offset.x,
&output_offset.y,
&rect_size.x,
&rect_size.y,
- &rtiles[9].x,
- &rtiles[9].y,
- &rtiles[9].w,
- &rtiles[9].h,
- &rtiles[9].offset,
- &rtiles[9].stride,
+ &target_tile.x,
+ &target_tile.y,
+ &target_tile.w,
+ &target_tile.h,
+ &target_tile.offset,
+ &target_tile.stride,
&task.pass_stride,
&rtile.sample};
launch_filter_kernel(
- "kernel_cuda_filter_convert_from_rgb", rtiles[9].w, rtiles[9].h, output_args);
+ "kernel_cuda_filter_convert_from_rgb", target_tile.w, target_tile.h, output_args);
# endif
check_result_cuda_ret(cuStreamSynchronize(0));
- task.unmap_neighbor_tiles(rtiles, this);
+ task.unmap_neighbor_tiles(neighbors, this);
}
else {
// Run CUDA denoising kernels
@@ -993,7 +1072,11 @@ class OptiXDevice : public CUDADevice {
sbt_params.missRecordCount = 1;
sbt_params.hitgroupRecordBase = sbt_data.device_pointer + PG_HITD * sizeof(SbtRecord);
sbt_params.hitgroupRecordStrideInBytes = sizeof(SbtRecord);
- sbt_params.hitgroupRecordCount = 3; // PG_HITD, PG_HITL, PG_HITS
+# if OPTIX_ABI_VERSION >= 36
+ sbt_params.hitgroupRecordCount = 5; // PG_HITD(_MOTION), PG_HITS(_MOTION), PG_HITL
+# else
+ sbt_params.hitgroupRecordCount = 3; // PG_HITD, PG_HITS, PG_HITL
+# endif
check_result_optix(optixLaunch(pipelines[PIP_SHADER_EVAL],
cuda_stream[thread_index],
@@ -1070,7 +1153,7 @@ class OptiXDevice : public CUDADevice {
&build_input,
1,
temp_mem.device_pointer,
- temp_mem.device_size,
+ sizes.tempSizeInBytes,
out_data,
sizes.outputSizeInBytes,
&out_handle,
@@ -1142,7 +1225,6 @@ class OptiXDevice : public CUDADevice {
continue;
}
- const size_t num_curves = hair->num_curves();
const size_t num_segments = hair->num_segments();
size_t num_motion_steps = 1;
@@ -1152,7 +1234,18 @@ class OptiXDevice : public CUDADevice {
}
device_vector<OptixAabb> aabb_data(this, "temp_aabb_data", MEM_READ_ONLY);
- aabb_data.alloc(num_segments * num_motion_steps);
+# if OPTIX_ABI_VERSION >= 36
+ device_vector<int> index_data(this, "temp_index_data", MEM_READ_ONLY);
+ device_vector<float4> vertex_data(this, "temp_vertex_data", MEM_READ_ONLY);
+ // Four control points for each curve segment
+ const size_t num_vertices = num_segments * 4;
+ if (DebugFlags().optix.curves_api && hair->curve_shape == CURVE_THICK) {
+ index_data.alloc(num_segments);
+ vertex_data.alloc(num_vertices * num_motion_steps);
+ }
+ else
+# endif
+ aabb_data.alloc(num_segments * num_motion_steps);
// Get AABBs for each motion step
for (size_t step = 0; step < num_motion_steps; ++step) {
@@ -1165,44 +1258,127 @@ class OptiXDevice : public CUDADevice {
keys = motion_keys->data_float3() + attr_offset * hair->curve_keys.size();
}
- size_t i = step * num_segments;
- for (size_t j = 0; j < num_curves; ++j) {
- const Hair::Curve c = hair->get_curve(j);
-
- for (size_t k = 0; k < c.num_segments(); ++i, ++k) {
- BoundBox bounds = BoundBox::empty;
- c.bounds_grow(k, keys, hair->curve_radius.data(), bounds);
-
- aabb_data[i].minX = bounds.min.x;
- aabb_data[i].minY = bounds.min.y;
- aabb_data[i].minZ = bounds.min.z;
- aabb_data[i].maxX = bounds.max.x;
- aabb_data[i].maxY = bounds.max.y;
- aabb_data[i].maxZ = bounds.max.z;
+ for (size_t j = 0, i = 0; j < hair->num_curves(); ++j) {
+ const Hair::Curve curve = hair->get_curve(j);
+
+ for (int segment = 0; segment < curve.num_segments(); ++segment, ++i) {
+# if OPTIX_ABI_VERSION >= 36
+ if (DebugFlags().optix.curves_api && hair->curve_shape == CURVE_THICK) {
+ int k0 = curve.first_key + segment;
+ int k1 = k0 + 1;
+ int ka = max(k0 - 1, curve.first_key);
+ int kb = min(k1 + 1, curve.first_key + curve.num_keys - 1);
+
+ const float4 px = make_float4(keys[ka].x, keys[k0].x, keys[k1].x, keys[kb].x);
+ const float4 py = make_float4(keys[ka].y, keys[k0].y, keys[k1].y, keys[kb].y);
+ const float4 pz = make_float4(keys[ka].z, keys[k0].z, keys[k1].z, keys[kb].z);
+ const float4 pw = make_float4(hair->curve_radius[ka],
+ hair->curve_radius[k0],
+ hair->curve_radius[k1],
+ hair->curve_radius[kb]);
+
+ // Convert Catmull-Rom data to Bezier spline
+ static const float4 cr2bsp0 = make_float4(+7, -4, +5, -2) / 6.f;
+ static const float4 cr2bsp1 = make_float4(-2, 11, -4, +1) / 6.f;
+ static const float4 cr2bsp2 = make_float4(+1, -4, 11, -2) / 6.f;
+ static const float4 cr2bsp3 = make_float4(-2, +5, -4, +7) / 6.f;
+
+ index_data[i] = i * 4;
+ float4 *const v = vertex_data.data() + step * num_vertices + index_data[i];
+ v[0] = make_float4(
+ dot(cr2bsp0, px), dot(cr2bsp0, py), dot(cr2bsp0, pz), dot(cr2bsp0, pw));
+ v[1] = make_float4(
+ dot(cr2bsp1, px), dot(cr2bsp1, py), dot(cr2bsp1, pz), dot(cr2bsp1, pw));
+ v[2] = make_float4(
+ dot(cr2bsp2, px), dot(cr2bsp2, py), dot(cr2bsp2, pz), dot(cr2bsp2, pw));
+ v[3] = make_float4(
+ dot(cr2bsp3, px), dot(cr2bsp3, py), dot(cr2bsp3, pz), dot(cr2bsp3, pw));
+ }
+ else
+# endif
+ {
+ BoundBox bounds = BoundBox::empty;
+ curve.bounds_grow(segment, keys, hair->curve_radius.data(), bounds);
+
+ const size_t index = step * num_segments + i;
+ aabb_data[index].minX = bounds.min.x;
+ aabb_data[index].minY = bounds.min.y;
+ aabb_data[index].minZ = bounds.min.z;
+ aabb_data[index].maxX = bounds.max.x;
+ aabb_data[index].maxY = bounds.max.y;
+ aabb_data[index].maxZ = bounds.max.z;
+ }
}
}
}
// Upload AABB data to GPU
aabb_data.copy_to_device();
+# if OPTIX_ABI_VERSION >= 36
+ index_data.copy_to_device();
+ vertex_data.copy_to_device();
+# endif
vector<device_ptr> aabb_ptrs;
aabb_ptrs.reserve(num_motion_steps);
+# if OPTIX_ABI_VERSION >= 36
+ vector<device_ptr> width_ptrs;
+ vector<device_ptr> vertex_ptrs;
+ width_ptrs.reserve(num_motion_steps);
+ vertex_ptrs.reserve(num_motion_steps);
+# endif
for (size_t step = 0; step < num_motion_steps; ++step) {
aabb_ptrs.push_back(aabb_data.device_pointer + step * num_segments * sizeof(OptixAabb));
+# if OPTIX_ABI_VERSION >= 36
+ const device_ptr base_ptr = vertex_data.device_pointer +
+ step * num_vertices * sizeof(float4);
+ width_ptrs.push_back(base_ptr + 3 * sizeof(float)); // Offset by vertex size
+ vertex_ptrs.push_back(base_ptr);
+# endif
}
- // Disable visibility test anyhit program, since it is already checked during intersection
- // Those trace calls that require anyhit can force it with OPTIX_RAY_FLAG_ENFORCE_ANYHIT
- unsigned int build_flags = OPTIX_GEOMETRY_FLAG_DISABLE_ANYHIT;
+ // Force a single any-hit call, so shadow record-all behavior works correctly
+ unsigned int build_flags = OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL;
OptixBuildInput build_input = {};
- build_input.type = OPTIX_BUILD_INPUT_TYPE_CUSTOM_PRIMITIVES;
- build_input.aabbArray.aabbBuffers = (CUdeviceptr *)aabb_ptrs.data();
- build_input.aabbArray.numPrimitives = num_segments;
- build_input.aabbArray.strideInBytes = sizeof(OptixAabb);
- build_input.aabbArray.flags = &build_flags;
- build_input.aabbArray.numSbtRecords = 1;
- build_input.aabbArray.primitiveIndexOffset = hair->optix_prim_offset;
+# if OPTIX_ABI_VERSION >= 36
+ if (DebugFlags().optix.curves_api && hair->curve_shape == CURVE_THICK) {
+ build_input.type = OPTIX_BUILD_INPUT_TYPE_CURVES;
+ build_input.curveArray.curveType = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE;
+ build_input.curveArray.numPrimitives = num_segments;
+ build_input.curveArray.vertexBuffers = (CUdeviceptr *)vertex_ptrs.data();
+ build_input.curveArray.numVertices = num_vertices;
+ build_input.curveArray.vertexStrideInBytes = sizeof(float4);
+ build_input.curveArray.widthBuffers = (CUdeviceptr *)width_ptrs.data();
+ build_input.curveArray.widthStrideInBytes = sizeof(float4);
+ build_input.curveArray.indexBuffer = (CUdeviceptr)index_data.device_pointer;
+ build_input.curveArray.indexStrideInBytes = sizeof(int);
+ build_input.curveArray.flag = build_flags;
+ build_input.curveArray.primitiveIndexOffset = hair->optix_prim_offset;
+ }
+ else
+# endif
+ {
+ // Disable visibility test any-hit program, since it is already checked during
+ // intersection. Those trace calls that require anyhit can force it with a ray flag.
+ build_flags |= OPTIX_GEOMETRY_FLAG_DISABLE_ANYHIT;
+
+ build_input.type = OPTIX_BUILD_INPUT_TYPE_CUSTOM_PRIMITIVES;
+# if OPTIX_ABI_VERSION < 23
+ build_input.aabbArray.aabbBuffers = (CUdeviceptr *)aabb_ptrs.data();
+ build_input.aabbArray.numPrimitives = num_segments;
+ build_input.aabbArray.strideInBytes = sizeof(OptixAabb);
+ build_input.aabbArray.flags = &build_flags;
+ build_input.aabbArray.numSbtRecords = 1;
+ build_input.aabbArray.primitiveIndexOffset = hair->optix_prim_offset;
+# else
+ build_input.customPrimitiveArray.aabbBuffers = (CUdeviceptr *)aabb_ptrs.data();
+ build_input.customPrimitiveArray.numPrimitives = num_segments;
+ build_input.customPrimitiveArray.strideInBytes = sizeof(OptixAabb);
+ build_input.customPrimitiveArray.flags = &build_flags;
+ build_input.customPrimitiveArray.numSbtRecords = 1;
+ build_input.customPrimitiveArray.primitiveIndexOffset = hair->optix_prim_offset;
+# endif
+ }
// Allocate memory for new BLAS and build it
OptixTraversableHandle handle;
@@ -1257,8 +1433,8 @@ class OptiXDevice : public CUDADevice {
vertex_ptrs.push_back(vertex_data.device_pointer + num_verts * step * sizeof(float3));
}
- // No special build flags for triangle primitives
- unsigned int build_flags = OPTIX_GEOMETRY_FLAG_NONE;
+ // Force a single any-hit call, so shadow record-all behavior works correctly
+ unsigned int build_flags = OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL;
OptixBuildInput build_input = {};
build_input.type = OPTIX_BUILD_INPUT_TYPE_TRIANGLES;
build_input.triangleArray.vertexBuffers = (CUdeviceptr *)vertex_ptrs.data();
@@ -1324,9 +1500,26 @@ class OptiXDevice : public CUDADevice {
// Set user instance ID to object index
instance.instanceId = ob->get_device_index();
- // Volumes have a special bit set in the visibility mask so a trace can mask only volumes
- // See 'scene_intersect_volume' in bvh.h
- instance.visibilityMask = (ob->geometry->has_volume ? 3 : 1);
+ // Have to have at least one bit in the mask, or else instance would always be culled
+ instance.visibilityMask = 1;
+
+ if (ob->geometry->has_volume) {
+ // Volumes have a special bit set in the visibility mask so a trace can mask only volumes
+ instance.visibilityMask |= 2;
+ }
+
+ if (ob->geometry->type == Geometry::HAIR) {
+ // Same applies to curves (so they can be skipped in local trace calls)
+ instance.visibilityMask |= 4;
+
+# if OPTIX_ABI_VERSION >= 36
+ if (motion_blur && ob->geometry->has_motion_blur() && DebugFlags().optix.curves_api &&
+ static_cast<const Hair *>(ob->geometry)->curve_shape == CURVE_THICK) {
+ // Select between motion blur and non-motion blur built-in intersection module
+ instance.sbtOffset = PG_HITD_MOTION - PG_HITD;
+ }
+# endif
+ }
// Insert motion traversable if object has motion
if (motion_blur && ob->use_motion()) {
diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h
index 600973b8100..fd380788282 100644
--- a/intern/cycles/device/device_task.h
+++ b/intern/cycles/device/device_task.h
@@ -29,6 +29,7 @@ CCL_NAMESPACE_BEGIN
class Device;
class RenderBuffers;
class RenderTile;
+class RenderTileNeighbors;
class Tile;
enum DenoiserType {
@@ -41,6 +42,14 @@ enum DenoiserType {
DENOISER_ALL = ~0,
};
+enum DenoiserInput {
+ DENOISER_INPUT_RGB = 1,
+ DENOISER_INPUT_RGB_ALBEDO = 2,
+ DENOISER_INPUT_RGB_ALBEDO_NORMAL = 3,
+
+ DENOISER_INPUT_NUM,
+};
+
typedef int DenoiserTypeMask;
class DenoiseParams {
@@ -72,10 +81,10 @@ class DenoiseParams {
/* Clamp the input to the range of +-1e8. Should be enough for any legitimate data. */
bool clamp_input;
- /** Optix Denoiser **/
+ /** OIDN/Optix Denoiser **/
- /* Passes handed over to the OptiX denoiser (default to color + albedo). */
- int optix_input_passes;
+ /* Passes handed over to the OIDN/OptiX denoiser (default to color + albedo). */
+ DenoiserInput input_passes;
DenoiseParams()
{
@@ -91,7 +100,7 @@ class DenoiseParams {
neighbor_frames = 2;
clamp_input = true;
- optix_input_passes = 2;
+ input_passes = DENOISER_INPUT_RGB_ALBEDO_NORMAL;
start_sample = 0;
}
@@ -150,8 +159,8 @@ class DeviceTask {
function<void(RenderTile &)> update_tile_sample;
function<void(RenderTile &)> release_tile;
function<bool()> get_cancel;
- function<void(RenderTile *, Device *)> map_neighbor_tiles;
- function<void(RenderTile *, Device *)> unmap_neighbor_tiles;
+ function<void(RenderTileNeighbors &, Device *)> map_neighbor_tiles;
+ function<void(RenderTileNeighbors &, Device *)> unmap_neighbor_tiles;
uint tile_types;
DenoiseParams denoising;
diff --git a/intern/cycles/device/opencl/device_opencl_impl.cpp b/intern/cycles/device/opencl/device_opencl_impl.cpp
index 8c94815b193..e851749949d 100644
--- a/intern/cycles/device/opencl/device_opencl_impl.cpp
+++ b/intern/cycles/device/opencl/device_opencl_impl.cpp
@@ -1850,7 +1850,7 @@ void OpenCLDevice::denoise(RenderTile &rtile, DenoisingTask &denoising)
denoising.render_buffer.samples = rtile.sample;
denoising.buffer.gpu_temporary_mem = true;
- denoising.run_denoising(&rtile);
+ denoising.run_denoising(rtile);
}
void OpenCLDevice::shader(DeviceTask &task)
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 7cc0d32d521..db146226dc7 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -539,7 +539,7 @@ if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES)
${SRC_UTIL_HEADERS}
COMMAND ${CUBIN_CC_ENV}
"$<TARGET_FILE:cycles_cubin_cc>"
- -target 30
+ -target 50
-ptx
-i ${CMAKE_CURRENT_SOURCE_DIR}/${input}
${cuda_flags}
@@ -563,7 +563,7 @@ if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES)
COMMAND
${CUDA_NVCC_EXECUTABLE}
--ptx
- -arch=sm_30
+ -arch=sm_50
${cuda_flags}
${input}
WORKING_DIRECTORY
diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h
index 80b58f46329..3049f243ae9 100644
--- a/intern/cycles/kernel/bvh/bvh.h
+++ b/intern/cycles/kernel/bvh/bvh.h
@@ -172,11 +172,11 @@ ccl_device_intersect bool scene_intersect(KernelGlobals *kg,
0.0f,
ray->t,
ray->time,
- 0xFF,
+ 0xF,
OPTIX_RAY_FLAG_NONE,
+ 0, // SBT offset for PG_HITD
0,
0,
- 0, // SBT offset for PG_HITD
p0,
p1,
p2,
@@ -264,12 +264,13 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg,
0.0f,
ray->t,
ray->time,
+ // Skip curves
+ 0x3,
// Need to always call into __anyhit__kernel_optix_local_hit
- 0xFF,
OPTIX_RAY_FLAG_ENFORCE_ANYHIT,
- 1,
+ 2, // SBT offset for PG_HITL
+ 0,
0,
- 0, // SBT offset for PG_HITL
p0,
p1,
p2,
@@ -374,12 +375,12 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg,
0.0f,
ray->t,
ray->time,
+ 0xF,
// Need to always call into __anyhit__kernel_optix_shadow_all_hit
- 0xFF,
OPTIX_RAY_FLAG_ENFORCE_ANYHIT,
- 2,
+ 1, // SBT offset for PG_HITS
+ 0,
0,
- 0, // SBT offset for PG_HITS
p0,
p1,
*num_hits,
@@ -458,12 +459,12 @@ ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg,
0.0f,
ray->t,
ray->time,
- // Visibility mask set to only intersect objects with volumes
- 0x02,
+ // Skip everything but volumes
+ 0x2,
OPTIX_RAY_FLAG_NONE,
+ 0, // SBT offset for PG_HITD
0,
0,
- 0, // SBT offset for PG_HITD
p0,
p1,
p2,
diff --git a/intern/cycles/kernel/geom/geom_curve_intersect.h b/intern/cycles/kernel/geom/geom_curve_intersect.h
index c04dbee52cc..06d2c016f5b 100644
--- a/intern/cycles/kernel/geom/geom_curve_intersect.h
+++ b/intern/cycles/kernel/geom/geom_curve_intersect.h
@@ -734,7 +734,6 @@ ccl_device_inline void curve_shader_setup(KernelGlobals *kg,
}
sd->u = isect->u;
- sd->v = isect->v;
P = P + D * t;
@@ -750,6 +749,7 @@ ccl_device_inline void curve_shader_setup(KernelGlobals *kg,
sd->N = normalize(sine * bitangent - cosine * normalize(cross(tangent, bitangent)));
sd->Ng = -D;
+ sd->v = isect->v;
# if 0
/* This approximates the position and geometric normal of a thick curve too,
@@ -764,8 +764,11 @@ ccl_device_inline void curve_shader_setup(KernelGlobals *kg,
* This could be optimized by recording the normal in the intersection,
* however for Optix this would go beyond the size of the payload. */
const float3 P_inside = float4_to_float3(catmull_rom_basis_eval(P_curve, isect->u));
- sd->Ng = normalize(P - P_inside);
- sd->N = sd->Ng;
+ const float3 Ng = normalize(P - P_inside);
+
+ sd->N = Ng;
+ sd->Ng = Ng;
+ sd->v = 0.0f;
}
# ifdef __DPDU__
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index 445cf9eb44b..efe46d5b0dd 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -379,7 +379,7 @@ ccl_device_inline void camera_sample(KernelGlobals *kg,
const int shutter_table_offset = kernel_data.cam.shutter_table_offset;
ray->time = lookup_table_read(kg, time, shutter_table_offset, SHUTTER_TABLE_SIZE);
/* TODO(sergey): Currently single rolling shutter effect type only
- * where scan-lines are acquired from top to bottom and whole scanline
+ * where scan-lines are acquired from top to bottom and whole scan-line
* is acquired at once (no delay in acquisition happens between pixels
* of single scan-line).
*
diff --git a/intern/cycles/kernel/kernel_light_background.h b/intern/cycles/kernel/kernel_light_background.h
index 30e336f0f80..5fa25069fcd 100644
--- a/intern/cycles/kernel/kernel_light_background.h
+++ b/intern/cycles/kernel/kernel_light_background.h
@@ -445,4 +445,4 @@ ccl_device float background_light_pdf(KernelGlobals *kg, float3 P, float3 direct
#endif
-CCL_NAMESPACE_END \ No newline at end of file
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index ba46d84d158..c332d5ad3ec 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -284,19 +284,11 @@ ccl_device_forceinline bool kernel_path_shader_apply(KernelGlobals *kg,
#ifdef __HOLDOUT__
if (((sd->flag & SD_HOLDOUT) || (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) &&
(state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)) {
+ const float3 holdout_weight = shader_holdout_apply(kg, sd);
if (kernel_data.background.transparent) {
- float3 holdout_weight;
- if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
- holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
- }
- else {
- holdout_weight = shader_holdout_eval(kg, sd);
- }
- /* any throughput is ok, should all be identical here */
L->transparent += average(holdout_weight * throughput);
}
-
- if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
+ if (isequal_float3(holdout_weight, make_float3(1.0f, 1.0f, 1.0f))) {
return false;
}
}
@@ -673,11 +665,9 @@ ccl_device void kernel_path_trace(
kernel_path_trace_setup(kg, sample, x, y, &rng_hash, &ray);
-# ifndef __KERNEL_OPTIX__
if (ray.t == 0.0f) {
return;
}
-# endif
/* Initialize state. */
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 3d9f787f267..e461e1642b6 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -1017,15 +1017,36 @@ ccl_device float3 shader_emissive_eval(ShaderData *sd)
/* Holdout */
-ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
+ccl_device float3 shader_holdout_apply(KernelGlobals *kg, ShaderData *sd)
{
float3 weight = make_float3(0.0f, 0.0f, 0.0f);
- for (int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ /* For objects marked as holdout, preserve transparency and remove all other
+ * closures, replacing them with a holdout weight. */
+ if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
+ if ((sd->flag & SD_TRANSPARENT) && !(sd->flag & SD_HAS_ONLY_VOLUME)) {
+ weight = make_float3(1.0f, 1.0f, 1.0f) - sd->closure_transparent_extinction;
- if (CLOSURE_IS_HOLDOUT(sc->type))
- weight += sc->weight;
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+ if (!CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) {
+ sc->type = NBUILTIN_CLOSURES;
+ }
+ }
+
+ sd->flag &= ~(SD_CLOSURE_FLAGS - (SD_TRANSPARENT | SD_BSDF));
+ }
+ else {
+ weight = make_float3(1.0f, 1.0f, 1.0f);
+ }
+ }
+ else {
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+ if (CLOSURE_IS_HOLDOUT(sc->type)) {
+ weight += sc->weight;
+ }
+ }
}
return weight;
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
index 89fcb0ae60f..9ab374d1fba 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
+++ b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
@@ -77,7 +77,7 @@ ccl_device_inline float4 svm_image_texture_read(KernelGlobals *kg,
return make_float4(f, f, f, 1.0f);
}
/* Byte */
-#ifdef cl_khr_fp16
+#ifdef __KERNEL_CL_KHR_FP16__
/* half and half4 are optional in OpenCL */
else if (texture_type == IMAGE_DATA_TYPE_HALF) {
float f = tex_fetch(half, info, offset);
diff --git a/intern/cycles/kernel/kernels/optix/kernel_optix.cu b/intern/cycles/kernel/kernels/optix/kernel_optix.cu
index c730d952ed4..3b166e59dfd 100644
--- a/intern/cycles/kernel/kernels/optix/kernel_optix.cu
+++ b/intern/cycles/kernel/kernels/optix/kernel_optix.cu
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+// clang-format off
#include "kernel/kernel_compat_optix.h"
#include "util/util_atomic.h"
#include "kernel/kernel_types.h"
@@ -23,6 +24,7 @@
#include "kernel/kernel_path.h"
#include "kernel/kernel_bake.h"
+// clang-format on
template<typename T> ccl_device_forceinline T *get_payload_ptr_0()
{
@@ -139,8 +141,8 @@ extern "C" __global__ void __anyhit__kernel_optix_local_hit()
}
else {
if (local_isect->num_hits && optixGetRayTmax() > local_isect->hits[0].t) {
- // Record closest intersection only (do not terminate ray here, since there is no guarantee
- // about distance ordering in anyhit)
+ // Record closest intersection only
+ // Do not terminate ray here, since there is no guarantee about distance ordering in any-hit
return optixIgnoreIntersection();
}
@@ -153,15 +155,9 @@ extern "C" __global__ void __anyhit__kernel_optix_local_hit()
isect->object = get_object_id();
isect->type = kernel_tex_fetch(__prim_type, isect->prim);
- if (optixIsTriangleHit()) {
- const float2 barycentrics = optixGetTriangleBarycentrics();
- isect->u = 1.0f - barycentrics.y - barycentrics.x;
- isect->v = barycentrics.x;
- }
- else {
- isect->u = __uint_as_float(optixGetAttribute_0());
- isect->v = __uint_as_float(optixGetAttribute_1());
- }
+ const float2 barycentrics = optixGetTriangleBarycentrics();
+ isect->u = 1.0f - barycentrics.y - barycentrics.x;
+ isect->v = barycentrics.x;
// Record geometric normal
const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, isect->prim);
@@ -198,10 +194,18 @@ extern "C" __global__ void __anyhit__kernel_optix_shadow_all_hit()
isect->u = 1.0f - barycentrics.y - barycentrics.x;
isect->v = barycentrics.x;
}
+# ifdef __HAIR__
else {
- isect->u = __uint_as_float(optixGetAttribute_0());
+ const float u = __uint_as_float(optixGetAttribute_0());
+ isect->u = u;
isect->v = __uint_as_float(optixGetAttribute_1());
+
+ // Filter out curve endcaps
+ if (u == 0.0f || u == 1.0f) {
+ return optixIgnoreIntersection();
+ }
}
+# endif
# ifdef __TRANSPARENT_SHADOWS__
// Detect if this surface has a shader with transparent shadows
@@ -213,7 +217,6 @@ extern "C" __global__ void __anyhit__kernel_optix_shadow_all_hit()
# ifdef __TRANSPARENT_SHADOWS__
}
- // TODO(pmours): Do we need REQUIRE_UNIQUE_ANYHIT for this to work?
optixSetPayload_2(optixGetPayload_2() + 1); // num_hits++
// Continue tracing
@@ -227,13 +230,25 @@ extern "C" __global__ void __anyhit__kernel_optix_visibility_test()
uint visibility = optixGetPayload_4();
#ifdef __VISIBILITY_FLAG__
const uint prim = optixGetPrimitiveIndex();
- if ((kernel_tex_fetch(__prim_visibility, prim) & visibility) == 0)
+ if ((kernel_tex_fetch(__prim_visibility, prim) & visibility) == 0) {
return optixIgnoreIntersection();
+ }
+#endif
+
+#ifdef __HAIR__
+ if (!optixIsTriangleHit()) {
+ // Filter out curve endcaps
+ const float u = __uint_as_float(optixGetAttribute_0());
+ if (u == 0.0f || u == 1.0f) {
+ return optixIgnoreIntersection();
+ }
+ }
#endif
// Shadow ray early termination
- if (visibility & PATH_RAY_SHADOW_OPAQUE)
+ if (visibility & PATH_RAY_SHADOW_OPAQUE) {
return optixTerminateRay();
+ }
}
extern "C" __global__ void __closesthit__kernel_optix_hit()
@@ -250,7 +265,7 @@ extern "C" __global__ void __closesthit__kernel_optix_hit()
optixSetPayload_2(__float_as_uint(barycentrics.x));
}
else {
- optixSetPayload_1(optixGetAttribute_0());
+ optixSetPayload_1(optixGetAttribute_0()); // Same as 'optixGetCurveParameter()'
optixSetPayload_2(optixGetAttribute_1());
}
}
@@ -286,7 +301,6 @@ ccl_device_inline void optix_intersection_curve(const uint prim, const uint type
__float_as_int(isect.u), // Attribute_0
__float_as_int(isect.v)); // Attribute_1
}
-
}
extern "C" __global__ void __intersection__curve_ribbon()
diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl
index 08bc8f85120..a12e7a9dc17 100644
--- a/intern/cycles/kernel/shaders/node_sky_texture.osl
+++ b/intern/cycles/kernel/shaders/node_sky_texture.osl
@@ -122,12 +122,18 @@ vector geographical_to_direction(float lat, float lon)
return vector(cos(lat) * cos(lon), cos(lat) * sin(lon), sin(lat));
}
-color sky_radiance_nishita(vector dir, float nishita_data[9], string filename)
+float precise_angle(vector a, vector b)
+{
+ return 2.0 * atan2(length(a - b), length(a + b));
+}
+
+color sky_radiance_nishita(vector dir, float nishita_data[10], string filename)
{
/* definitions */
float sun_elevation = nishita_data[6];
float sun_rotation = nishita_data[7];
float angular_diameter = nishita_data[8];
+ float sun_intensity = nishita_data[9];
int sun_disc = angular_diameter > 0;
float alpha = 1.0;
color xyz;
@@ -138,13 +144,13 @@ color sky_radiance_nishita(vector dir, float nishita_data[9], string filename)
if (dir[2] >= 0.0) {
/* definitions */
vector sun_dir = geographical_to_direction(sun_elevation, sun_rotation + M_PI_2);
- float sun_dir_angle = acos(dot(dir, sun_dir));
+ float sun_dir_angle = precise_angle(dir, sun_dir);
float half_angular = angular_diameter / 2.0;
float dir_elevation = M_PI_2 - direction[0];
/* if ray inside sun disc render it, otherwise render sky */
if (sun_dir_angle < half_angular && sun_disc == 1) {
- /* get 3 pixels data */
+ /* get 2 pixels data */
color pixel_bottom = color(nishita_data[0], nishita_data[1], nishita_data[2]);
color pixel_top = color(nishita_data[3], nishita_data[4], nishita_data[5]);
float y;
@@ -153,13 +159,13 @@ color sky_radiance_nishita(vector dir, float nishita_data[9], string filename)
if (sun_elevation - half_angular > 0.0) {
if ((sun_elevation + half_angular) > 0.0) {
y = ((dir_elevation - sun_elevation) / angular_diameter) + 0.5;
- xyz = mix(pixel_bottom, pixel_top, y);
+ xyz = mix(pixel_bottom, pixel_top, y) * sun_intensity;
}
}
else {
if (sun_elevation + half_angular > 0.0) {
y = dir_elevation / (sun_elevation + half_angular);
- xyz = mix(pixel_bottom, pixel_top, y);
+ xyz = mix(pixel_bottom, pixel_top, y) * sun_intensity;
}
}
/* limb darkening, coefficient is 0.6f */
@@ -171,7 +177,8 @@ color sky_radiance_nishita(vector dir, float nishita_data[9], string filename)
else {
/* sky interpolation */
float x = (direction[1] + M_PI + sun_rotation) / M_2PI;
- float y = 1.0 - (dir_elevation / M_PI_2);
+ /* more pixels toward horizon compensation */
+ float y = 1.0 - sqrt(dir_elevation / M_PI_2);
if (x > 1.0) {
x = x - 1.0;
}
@@ -197,23 +204,24 @@ color sky_radiance_nishita(vector dir, float nishita_data[9], string filename)
mul;
}
}
- /* convert to RGB and adjust strength */
- return xyz_to_rgb(xyz[0], xyz[1], xyz[2]) * 120000.0;
+ /* convert to RGB */
+ return xyz_to_rgb(xyz[0], xyz[1], xyz[2]);
}
-shader node_sky_texture(int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- vector Vector = P,
- string type = "hosek_wilkie",
- float theta = 0.0,
- float phi = 0.0,
- string filename = "",
- color radiance = color(0.0, 0.0, 0.0),
- float config_x[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
- float config_y[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
- float config_z[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
- float nishita_data[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
- output color Color = color(0.0, 0.0, 0.0))
+shader node_sky_texture(
+ int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ vector Vector = P,
+ string type = "hosek_wilkie",
+ float theta = 0.0,
+ float phi = 0.0,
+ string filename = "",
+ color radiance = color(0.0, 0.0, 0.0),
+ float config_x[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+ float config_y[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+ float config_z[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+ float nishita_data[10] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+ output color Color = color(0.0, 0.0, 0.0))
{
vector p = Vector;
diff --git a/intern/cycles/kernel/svm/svm_sky.h b/intern/cycles/kernel/svm/svm_sky.h
index e877bd9a5c8..f824184c1d4 100644
--- a/intern/cycles/kernel/svm/svm_sky.h
+++ b/intern/cycles/kernel/svm/svm_sky.h
@@ -136,6 +136,7 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals *kg,
float sun_elevation = nishita_data[6];
float sun_rotation = nishita_data[7];
float angular_diameter = nishita_data[8];
+ float sun_intensity = nishita_data[9];
bool sun_disc = (angular_diameter > 0.0f);
float3 xyz;
/* convert dir to spherical coordinates */
@@ -145,13 +146,13 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals *kg,
if (dir.z >= 0.0f) {
/* definitions */
float3 sun_dir = geographical_to_direction(sun_elevation, sun_rotation + M_PI_2_F);
- float sun_dir_angle = acos(dot(dir, sun_dir));
+ float sun_dir_angle = precise_angle(dir, sun_dir);
float half_angular = angular_diameter / 2.0f;
float dir_elevation = M_PI_2_F - direction.x;
/* if ray inside sun disc render it, otherwise render sky */
if (sun_disc && sun_dir_angle < half_angular) {
- /* get 3 pixels data */
+ /* get 2 pixels data */
float3 pixel_bottom = make_float3(nishita_data[0], nishita_data[1], nishita_data[2]);
float3 pixel_top = make_float3(nishita_data[3], nishita_data[4], nishita_data[5]);
float y;
@@ -160,13 +161,13 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals *kg,
if (sun_elevation - half_angular > 0.0f) {
if (sun_elevation + half_angular > 0.0f) {
y = ((dir_elevation - sun_elevation) / angular_diameter) + 0.5f;
- xyz = interp(pixel_bottom, pixel_top, y);
+ xyz = interp(pixel_bottom, pixel_top, y) * sun_intensity;
}
}
else {
if (sun_elevation + half_angular > 0.0f) {
y = dir_elevation / (sun_elevation + half_angular);
- xyz = interp(pixel_bottom, pixel_top, y);
+ xyz = interp(pixel_bottom, pixel_top, y) * sun_intensity;
}
}
/* limb darkening, coefficient is 0.6f */
@@ -178,7 +179,8 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals *kg,
else {
/* sky interpolation */
float x = (direction.y + M_PI_F + sun_rotation) / M_2PI_F;
- float y = dir_elevation / M_PI_2_F;
+ /* more pixels toward horizon compensation */
+ float y = safe_sqrtf(dir_elevation / M_PI_2_F);
if (x > 1.0f) {
x -= 1.0f;
}
@@ -203,8 +205,8 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals *kg,
}
}
- /* convert to rgb and adjust strength */
- return xyz_to_rgb(kg, xyz) * 120000.0f;
+ /* convert to RGB */
+ return xyz_to_rgb(kg, xyz);
}
ccl_device void svm_node_tex_sky(
@@ -301,7 +303,7 @@ ccl_device void svm_node_tex_sky(
/* Nishita */
else {
/* Define variables */
- float nishita_data[9];
+ float nishita_data[10];
float4 data = read_node_float(kg, offset);
nishita_data[0] = data.x;
@@ -317,7 +319,8 @@ ccl_device void svm_node_tex_sky(
data = read_node_float(kg, offset);
nishita_data[8] = data.x;
- uint texture_id = __float_as_uint(data.y);
+ nishita_data[9] = data.y;
+ uint texture_id = __float_as_uint(data.z);
/* Compute Sky */
f = sky_radiance_nishita(kg, dir, nishita_data, texture_id);
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index e37a0407976..6a1335dc5dd 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -2,6 +2,7 @@
set(INC
..
../../glew-mx
+ ../../sky/include
)
set(INC_SYS
@@ -92,6 +93,7 @@ set(LIB
cycles_device
cycles_subd
cycles_util
+ bf_intern_sky
)
if(WITH_CYCLES_OSL)
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 975bae2239c..06b6094e6c9 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -52,7 +52,7 @@ class BufferParams {
/* passes */
vector<Pass> passes;
bool denoising_data_pass;
- /* If only some light path types should be denoised, an additional pass is needed. */
+ /* If only some light path types should be target, an additional pass is needed. */
bool denoising_clean_pass;
/* When we're prefiltering the passes during rendering, we need to keep both the
* original and the prefiltered data around because neighboring tiles might still
@@ -149,6 +149,50 @@ class RenderTile {
RenderBuffers *buffers;
RenderTile();
+
+ int4 bounds() const
+ {
+ return make_int4(x, /* xmin */
+ y, /* ymin */
+ x + w, /* xmax */
+ y + h); /* ymax */
+ }
+};
+
+/* Render Tile Neighbors
+ * Set of neighboring tiles used for denoising. Tile order:
+ * 0 1 2
+ * 3 4 5
+ * 6 7 8 */
+
+class RenderTileNeighbors {
+ public:
+ static const int SIZE = 9;
+ static const int CENTER = 4;
+
+ RenderTile tiles[SIZE];
+ RenderTile target;
+
+ RenderTileNeighbors(const RenderTile &center)
+ {
+ tiles[CENTER] = center;
+ }
+
+ int4 bounds() const
+ {
+ return make_int4(tiles[3].x, /* xmin */
+ tiles[1].y, /* ymin */
+ tiles[5].x + tiles[5].w, /* xmax */
+ tiles[7].y + tiles[7].h); /* ymax */
+ }
+
+ void set_bounds_from_center()
+ {
+ tiles[3].x = tiles[CENTER].x;
+ tiles[1].y = tiles[CENTER].y;
+ tiles[5].x = tiles[CENTER].x + tiles[CENTER].w;
+ tiles[7].y = tiles[CENTER].y + tiles[CENTER].h;
+ }
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 74953afae9d..bbc111cb798 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -26,6 +26,7 @@
#include "util/util_function.h"
#include "util/util_logging.h"
#include "util/util_math_cdf.h"
+#include "util/util_task.h"
#include "util/util_vector.h"
/* needed for calculating differentials */
@@ -496,20 +497,35 @@ void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scen
if (!need_device_update && !need_flags_update) {
return;
}
- KernelCamera *kcam = &dscene->data.cam;
- BoundBox viewplane_boundbox = viewplane_bounds_get();
- for (size_t i = 0; i < scene->objects.size(); ++i) {
- Object *object = scene->objects[i];
- if (object->geometry->has_volume && viewplane_boundbox.intersects(object->bounds)) {
- /* TODO(sergey): Consider adding more grained check. */
- VLOG(1) << "Detected camera inside volume.";
- kcam->is_inside_volume = 1;
- break;
+
+ KernelIntegrator *kintegrator = &dscene->data.integrator;
+ if (kintegrator->use_volumes) {
+ KernelCamera *kcam = &dscene->data.cam;
+ BoundBox viewplane_boundbox = viewplane_bounds_get();
+
+ /* Parallel object update, with grain size to avoid too much threading overhead
+ * for individual objects. */
+ static const int OBJECTS_PER_TASK = 32;
+ parallel_for(blocked_range<size_t>(0, scene->objects.size(), OBJECTS_PER_TASK),
+ [&](const blocked_range<size_t> &r) {
+ for (size_t i = r.begin(); i != r.end(); i++) {
+ Object *object = scene->objects[i];
+ if (object->geometry->has_volume &&
+ viewplane_boundbox.intersects(object->bounds)) {
+ /* TODO(sergey): Consider adding more grained check. */
+ VLOG(1) << "Detected camera inside volume.";
+ kcam->is_inside_volume = 1;
+ parallel_for_cancel();
+ break;
+ }
+ }
+ });
+
+ if (!kcam->is_inside_volume) {
+ VLOG(1) << "Camera is outside of the volume.";
}
}
- if (!kcam->is_inside_volume) {
- VLOG(1) << "Camera is outside of the volume.";
- }
+
need_device_update = false;
need_flags_update = false;
}
diff --git a/intern/cycles/render/denoising.cpp b/intern/cycles/render/denoising.cpp
index 4055bc4773b..76408ca4849 100644
--- a/intern/cycles/render/denoising.cpp
+++ b/intern/cycles/render/denoising.cpp
@@ -271,42 +271,45 @@ bool DenoiseTask::acquire_tile(Device *device, Device *tile_device, RenderTile &
*
* However, since there is only one large memory, the denoised result has to be written to
* a different buffer to avoid having to copy an entire horizontal slice of the image. */
-void DenoiseTask::map_neighboring_tiles(RenderTile *tiles, Device *tile_device)
+void DenoiseTask::map_neighboring_tiles(RenderTileNeighbors &neighbors, Device *tile_device)
{
+ RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
+ RenderTile &target_tile = neighbors.target;
+
/* Fill tile information. */
- for (int i = 0; i < 9; i++) {
- if (i == 4) {
+ for (int i = 0; i < RenderTileNeighbors::SIZE; i++) {
+ if (i == RenderTileNeighbors::CENTER) {
continue;
}
+ RenderTile &tile = neighbors.tiles[i];
int dx = (i % 3) - 1;
int dy = (i / 3) - 1;
- tiles[i].x = clamp(tiles[4].x + dx * denoiser->tile_size.x, 0, image.width);
- tiles[i].w = clamp(tiles[4].x + (dx + 1) * denoiser->tile_size.x, 0, image.width) - tiles[i].x;
- tiles[i].y = clamp(tiles[4].y + dy * denoiser->tile_size.y, 0, image.height);
- tiles[i].h = clamp(tiles[4].y + (dy + 1) * denoiser->tile_size.y, 0, image.height) -
- tiles[i].y;
+ tile.x = clamp(center_tile.x + dx * denoiser->tile_size.x, 0, image.width);
+ tile.w = clamp(center_tile.x + (dx + 1) * denoiser->tile_size.x, 0, image.width) - tile.x;
+ tile.y = clamp(center_tile.y + dy * denoiser->tile_size.y, 0, image.height);
+ tile.h = clamp(center_tile.y + (dy + 1) * denoiser->tile_size.y, 0, image.height) - tile.y;
- tiles[i].buffer = tiles[4].buffer;
- tiles[i].offset = tiles[4].offset;
- tiles[i].stride = image.width;
+ tile.buffer = center_tile.buffer;
+ tile.offset = center_tile.offset;
+ tile.stride = image.width;
}
/* Allocate output buffer. */
device_vector<float> *output_mem = new device_vector<float>(
tile_device, "denoising_output", MEM_READ_WRITE);
- output_mem->alloc(OUTPUT_NUM_CHANNELS * tiles[4].w * tiles[4].h);
+ output_mem->alloc(OUTPUT_NUM_CHANNELS * center_tile.w * center_tile.h);
/* Fill output buffer with noisy image, assumed by kernel_filter_finalize
* when skipping denoising of some pixels. */
float *result = output_mem->data();
- float *in = &image.pixels[image.num_channels * (tiles[4].y * image.width + tiles[4].x)];
+ float *in = &image.pixels[image.num_channels * (center_tile.y * image.width + center_tile.x)];
const DenoiseImageLayer &layer = image.layers[current_layer];
const int *input_to_image_channel = layer.input_to_image_channel.data();
- for (int y = 0; y < tiles[4].h; y++) {
- for (int x = 0; x < tiles[4].w; x++, result += OUTPUT_NUM_CHANNELS) {
+ for (int y = 0; y < center_tile.h; y++) {
+ for (int x = 0; x < center_tile.w; x++, result += OUTPUT_NUM_CHANNELS) {
for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
result[i] = in[image.num_channels * x + input_to_image_channel[INPUT_NOISY_IMAGE + i]];
}
@@ -317,35 +320,38 @@ void DenoiseTask::map_neighboring_tiles(RenderTile *tiles, Device *tile_device)
output_mem->copy_to_device();
/* Fill output tile info. */
- tiles[9] = tiles[4];
- tiles[9].buffer = output_mem->device_pointer;
- tiles[9].stride = tiles[9].w;
- tiles[9].offset -= tiles[9].x + tiles[9].y * tiles[9].stride;
+ target_tile = center_tile;
+ target_tile.buffer = output_mem->device_pointer;
+ target_tile.stride = target_tile.w;
+ target_tile.offset -= target_tile.x + target_tile.y * target_tile.stride;
thread_scoped_lock output_lock(output_mutex);
- assert(output_pixels.count(tiles[4].tile_index) == 0);
- output_pixels[tiles[9].tile_index] = output_mem;
+ assert(output_pixels.count(center_tile.tile_index) == 0);
+ output_pixels[target_tile.tile_index] = output_mem;
}
-void DenoiseTask::unmap_neighboring_tiles(RenderTile *tiles)
+void DenoiseTask::unmap_neighboring_tiles(RenderTileNeighbors &neighbors)
{
+ RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
+ RenderTile &target_tile = neighbors.target;
+
thread_scoped_lock output_lock(output_mutex);
- assert(output_pixels.count(tiles[4].tile_index) == 1);
- device_vector<float> *output_mem = output_pixels[tiles[9].tile_index];
- output_pixels.erase(tiles[4].tile_index);
+ assert(output_pixels.count(center_tile.tile_index) == 1);
+ device_vector<float> *output_mem = output_pixels[target_tile.tile_index];
+ output_pixels.erase(center_tile.tile_index);
output_lock.unlock();
/* Copy denoised pixels from device. */
- output_mem->copy_from_device(0, OUTPUT_NUM_CHANNELS * tiles[9].w, tiles[9].h);
+ output_mem->copy_from_device(0, OUTPUT_NUM_CHANNELS * target_tile.w, target_tile.h);
float *result = output_mem->data();
- float *out = &image.pixels[image.num_channels * (tiles[9].y * image.width + tiles[9].x)];
+ float *out = &image.pixels[image.num_channels * (target_tile.y * image.width + target_tile.x)];
const DenoiseImageLayer &layer = image.layers[current_layer];
const int *output_to_image_channel = layer.output_to_image_channel.data();
- for (int y = 0; y < tiles[9].h; y++) {
- for (int x = 0; x < tiles[9].w; x++, result += OUTPUT_NUM_CHANNELS) {
+ for (int y = 0; y < target_tile.h; y++) {
+ for (int x = 0; x < target_tile.w; x++, result += OUTPUT_NUM_CHANNELS) {
for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
out[image.num_channels * x + output_to_image_channel[i]] = result[i];
}
diff --git a/intern/cycles/render/denoising.h b/intern/cycles/render/denoising.h
index 5c6f913cb38..c1b4d0a5596 100644
--- a/intern/cycles/render/denoising.h
+++ b/intern/cycles/render/denoising.h
@@ -196,8 +196,8 @@ class DenoiseTask {
/* Device task callbacks */
bool acquire_tile(Device *device, Device *tile_device, RenderTile &tile);
- void map_neighboring_tiles(RenderTile *tiles, Device *tile_device);
- void unmap_neighboring_tiles(RenderTile *tiles);
+ void map_neighboring_tiles(RenderTileNeighbors &neighbors, Device *tile_device);
+ void unmap_neighboring_tiles(RenderTileNeighbors &neighbors);
void release_tile();
bool get_cancel();
};
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 436324b00ba..1b138455515 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -484,8 +484,8 @@ void ShaderGraph::remove_proxy_nodes()
vector<ShaderInput *> links(output->links);
foreach (ShaderInput *to, links) {
- /* remove any autoconvert nodes too if they lead to
- * sockets with an automatically set default value */
+ /* Remove any auto-convert nodes too if they lead to
+ * sockets with an automatically set default value. */
ShaderNode *tonode = to->parent;
if (tonode->special_type == SHADER_SPECIAL_TYPE_AUTOCONVERT) {
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 8d187814d64..691eb162dd0 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -362,9 +362,11 @@ ImageHandle ImageManager::add_image(const string &filename,
return handle;
}
-ImageHandle ImageManager::add_image(ImageLoader *loader, const ImageParams &params)
+ImageHandle ImageManager::add_image(ImageLoader *loader,
+ const ImageParams &params,
+ const bool builtin)
{
- const int slot = add_image_slot(loader, params, true);
+ const int slot = add_image_slot(loader, params, builtin);
ImageHandle handle;
handle.tile_slots.push_back(slot);
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index fffe7c5152a..47be0ee559a 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -169,7 +169,7 @@ class ImageManager {
ImageHandle add_image(const string &filename,
const ImageParams &params,
const vector<int> &tiles);
- ImageHandle add_image(ImageLoader *loader, const ImageParams &params);
+ ImageHandle add_image(ImageLoader *loader, const ImageParams &params, const bool builtin = true);
void device_update(Device *device, Scene *scene, Progress &progress);
void device_update_slot(Device *device, Scene *scene, int slot, Progress *progress);
diff --git a/intern/cycles/render/image_sky.cpp b/intern/cycles/render/image_sky.cpp
index 442e1d7941f..0560907c63e 100644
--- a/intern/cycles/render/image_sky.cpp
+++ b/intern/cycles/render/image_sky.cpp
@@ -16,16 +16,20 @@
#include "render/image_sky.h"
+#include "sky_model.h"
+
#include "util/util_image.h"
#include "util/util_logging.h"
#include "util/util_path.h"
-#include "util/util_sky_model.h"
#include "util/util_task.h"
CCL_NAMESPACE_BEGIN
-SkyLoader::SkyLoader(
- float sun_elevation, int altitude, float air_density, float dust_density, float ozone_density)
+SkyLoader::SkyLoader(float sun_elevation,
+ float altitude,
+ float air_density,
+ float dust_density,
+ float ozone_density)
: sun_elevation(sun_elevation),
altitude(altitude),
air_density(air_density),
@@ -56,23 +60,22 @@ bool SkyLoader::load_pixels(const ImageMetaData &metadata,
int width = metadata.width;
int height = metadata.height;
float *pixel_data = (float *)pixels;
- float altitude_f = (float)altitude;
/* precompute sky texture */
const int rows_per_task = divide_up(1024, width);
parallel_for(blocked_range<size_t>(0, height, rows_per_task),
[&](const blocked_range<size_t> &r) {
- nishita_skymodel_precompute_texture(pixel_data,
- metadata.channels,
- r.begin(),
- r.end(),
- width,
- height,
- sun_elevation,
- altitude_f,
- air_density,
- dust_density,
- ozone_density);
+ SKY_nishita_skymodel_precompute_texture(pixel_data,
+ metadata.channels,
+ r.begin(),
+ r.end(),
+ width,
+ height,
+ sun_elevation,
+ altitude,
+ air_density,
+ dust_density,
+ ozone_density);
});
return true;
diff --git a/intern/cycles/render/image_sky.h b/intern/cycles/render/image_sky.h
index cf4a3e8942c..686f4e5b885 100644
--- a/intern/cycles/render/image_sky.h
+++ b/intern/cycles/render/image_sky.h
@@ -21,14 +21,14 @@ CCL_NAMESPACE_BEGIN
class SkyLoader : public ImageLoader {
private:
float sun_elevation;
- int altitude;
+ float altitude;
float air_density;
float dust_density;
float ozone_density;
public:
SkyLoader(float sun_elevation,
- int altitude,
+ float altitude,
float air_density,
float dust_density,
float ozone_density);
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index c0615c6217b..183c02cb6b9 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -625,13 +625,19 @@ void LightManager::device_update_background(Device *device,
}
}
+ /* Determine sun direction from lat/long and texture mapping. */
float latitude = sky->sun_elevation;
float longitude = M_2PI_F - sky->sun_rotation + M_PI_2_F;
+ float3 sun_direction = make_float3(
+ cosf(latitude) * cosf(longitude), cosf(latitude) * sinf(longitude), sinf(latitude));
+ Transform sky_transform = transform_inverse(sky->tex_mapping.compute_transform());
+ sun_direction = transform_direction(&sky_transform, sun_direction);
+
+ /* Pack sun direction and size. */
float half_angle = sky->sun_size * 0.5f;
- kbackground->sun = make_float4(cosf(latitude) * cosf(longitude),
- cosf(latitude) * sinf(longitude),
- sinf(latitude),
- half_angle);
+ kbackground->sun = make_float4(
+ sun_direction.x, sun_direction.y, sun_direction.z, half_angle);
+
kbackground->sun_weight = 4.0f;
environment_res.x = max(environment_res.x, 512);
environment_res.y = max(environment_res.y, 256);
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index ab392839e52..d5f65fb54db 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -27,9 +27,10 @@
#include "render/scene.h"
#include "render/svm.h"
+#include "sky_model.h"
+
#include "util/util_foreach.h"
#include "util/util_logging.h"
-#include "util/util_sky_model.h"
#include "util/util_transform.h"
#include "kernel/svm/svm_color_util.h"
@@ -631,7 +632,7 @@ typedef struct SunSky {
/* Parameter */
float radiance_x, radiance_y, radiance_z;
- float config_x[9], config_y[9], config_z[9], nishita_data[9];
+ float config_x[9], config_y[9], config_z[9], nishita_data[10];
} SunSky;
/* Preetham model */
@@ -726,8 +727,8 @@ static void sky_texture_precompute_hosek(SunSky *sunsky,
float solarElevation = M_PI_2_F - theta;
/* Initialize Sky Model */
- ArHosekSkyModelState *sky_state;
- sky_state = arhosek_xyz_skymodelstate_alloc_init(
+ SKY_ArHosekSkyModelState *sky_state;
+ sky_state = SKY_arhosek_xyz_skymodelstate_alloc_init(
(double)turbidity, (double)ground_albedo, (double)solarElevation);
/* Copy values from sky_state to SunSky */
@@ -741,25 +742,31 @@ static void sky_texture_precompute_hosek(SunSky *sunsky,
sunsky->radiance_z = (float)sky_state->radiances[2];
/* Free sky_state */
- arhosekskymodelstate_free(sky_state);
+ SKY_arhosekskymodelstate_free(sky_state);
}
/* Nishita improved */
static void sky_texture_precompute_nishita(SunSky *sunsky,
bool sun_disc,
float sun_size,
+ float sun_intensity,
float sun_elevation,
float sun_rotation,
- int altitude,
+ float altitude,
float air_density,
float dust_density)
{
/* sample 2 sun pixels */
float pixel_bottom[3];
float pixel_top[3];
- float altitude_f = (float)altitude;
- nishita_skymodel_precompute_sun(
- sun_elevation, sun_size, altitude_f, air_density, dust_density, pixel_bottom, pixel_top);
+ SKY_nishita_skymodel_precompute_sun(
+ sun_elevation, sun_size, altitude, air_density, dust_density, pixel_bottom, pixel_top);
+ /* limit sun rotation between 0 and 360 degrees */
+ sun_rotation = fmodf(sun_rotation, M_2PI_F);
+ if (sun_rotation < 0.0f) {
+ sun_rotation += M_2PI_F;
+ }
+ sun_rotation = M_2PI_F - sun_rotation;
/* send data to svm_sky */
sunsky->nishita_data[0] = pixel_bottom[0];
sunsky->nishita_data[1] = pixel_bottom[1];
@@ -768,8 +775,9 @@ static void sky_texture_precompute_nishita(SunSky *sunsky,
sunsky->nishita_data[4] = pixel_top[1];
sunsky->nishita_data[5] = pixel_top[2];
sunsky->nishita_data[6] = sun_elevation;
- sunsky->nishita_data[7] = M_2PI_F - sun_rotation;
+ sunsky->nishita_data[7] = sun_rotation;
sunsky->nishita_data[8] = sun_disc ? sun_size : 0.0f;
+ sunsky->nishita_data[9] = sun_intensity;
}
NODE_DEFINE(SkyTextureNode)
@@ -789,9 +797,10 @@ NODE_DEFINE(SkyTextureNode)
SOCKET_FLOAT(ground_albedo, "Ground Albedo", 0.3f);
SOCKET_BOOLEAN(sun_disc, "Sun Disc", true);
SOCKET_FLOAT(sun_size, "Sun Size", 0.009512f);
- SOCKET_FLOAT(sun_elevation, "Sun Elevation", M_PI_2_F);
+ SOCKET_FLOAT(sun_intensity, "Sun Intensity", 1.0f);
+ SOCKET_FLOAT(sun_elevation, "Sun Elevation", 15.0f * M_PI_F / 180.0f);
SOCKET_FLOAT(sun_rotation, "Sun Rotation", 0.0f);
- SOCKET_INT(altitude, "Altitude", 0);
+ SOCKET_FLOAT(altitude, "Altitude", 1.0f);
SOCKET_FLOAT(air_density, "Air", 1.0f);
SOCKET_FLOAT(dust_density, "Dust", 1.0f);
SOCKET_FLOAT(ozone_density, "Ozone", 1.0f);
@@ -819,12 +828,17 @@ void SkyTextureNode::compile(SVMCompiler &compiler)
else if (type == NODE_SKY_HOSEK)
sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo);
else if (type == NODE_SKY_NISHITA) {
+ /* Clamp altitude to reasonable values.
+ * Below 1m causes numerical issues and above 60km is space. */
+ float clamped_altitude = clamp(altitude, 1.0f, 59999.0f);
+
sky_texture_precompute_nishita(&sunsky,
sun_disc,
sun_size,
+ sun_intensity,
sun_elevation,
sun_rotation,
- altitude,
+ clamped_altitude,
air_density,
dust_density);
/* precomputed texture image parameters */
@@ -836,7 +850,7 @@ void SkyTextureNode::compile(SVMCompiler &compiler)
/* precompute sky texture */
if (handle.empty()) {
SkyLoader *loader = new SkyLoader(
- sun_elevation, altitude, air_density, dust_density, ozone_density);
+ sun_elevation, clamped_altitude, air_density, dust_density, ozone_density);
handle = image_manager->add_image(loader, impar);
}
}
@@ -891,7 +905,10 @@ void SkyTextureNode::compile(SVMCompiler &compiler)
__float_as_uint(sunsky.nishita_data[5]),
__float_as_uint(sunsky.nishita_data[6]),
__float_as_uint(sunsky.nishita_data[7]));
- compiler.add_node(__float_as_uint(sunsky.nishita_data[8]), handle.svm_slot(), 0, 0);
+ compiler.add_node(__float_as_uint(sunsky.nishita_data[8]),
+ __float_as_uint(sunsky.nishita_data[9]),
+ handle.svm_slot(),
+ 0);
}
tex_mapping.compile_end(compiler, vector_in, vector_offset);
@@ -907,12 +924,17 @@ void SkyTextureNode::compile(OSLCompiler &compiler)
else if (type == NODE_SKY_HOSEK)
sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo);
else if (type == NODE_SKY_NISHITA) {
+ /* Clamp altitude to reasonable values.
+ * Below 1m causes numerical issues and above 60km is space. */
+ float clamped_altitude = clamp(altitude, 1.0f, 59999.0f);
+
sky_texture_precompute_nishita(&sunsky,
sun_disc,
sun_size,
+ sun_intensity,
sun_elevation,
sun_rotation,
- altitude,
+ clamped_altitude,
air_density,
dust_density);
/* precomputed texture image parameters */
@@ -924,7 +946,7 @@ void SkyTextureNode::compile(OSLCompiler &compiler)
/* precompute sky texture */
if (handle.empty()) {
SkyLoader *loader = new SkyLoader(
- sun_elevation, altitude, air_density, dust_density, ozone_density);
+ sun_elevation, clamped_altitude, air_density, dust_density, ozone_density);
handle = image_manager->add_image(loader, impar);
}
}
@@ -939,7 +961,7 @@ void SkyTextureNode::compile(OSLCompiler &compiler)
compiler.parameter_array("config_x", sunsky.config_x, 9);
compiler.parameter_array("config_y", sunsky.config_y, 9);
compiler.parameter_array("config_z", sunsky.config_z, 9);
- compiler.parameter_array("nishita_data", sunsky.nishita_data, 9);
+ compiler.parameter_array("nishita_data", sunsky.nishita_data, 10);
/* nishita texture */
if (type == NODE_SKY_NISHITA) {
compiler.parameter_texture("filename", handle.svm_slot());
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 846ba7423e5..326f1d14168 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -170,9 +170,10 @@ class SkyTextureNode : public TextureNode {
float ground_albedo;
bool sun_disc;
float sun_size;
+ float sun_intensity;
float sun_elevation;
float sun_rotation;
- int altitude;
+ float altitude;
float air_density;
float dust_density;
float ozone_density;
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index c45ae5553a8..f200e409b9e 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -823,6 +823,12 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P
Mesh *mesh = static_cast<Mesh *>(geom);
apply = apply && mesh->subdivision_type == Mesh::SUBDIVISION_NONE;
}
+ else if (geom->type == Geometry::HAIR) {
+ /* Can't apply non-uniform scale to curves, this can't be represented by
+ * control points and radius alone. */
+ float scale;
+ apply = apply && transform_uniform_scale(object->tfm, scale);
+ }
if (apply) {
if (!(motion_blur && object->use_motion())) {
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 1a94d3e9db7..08a8cb08254 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -536,7 +536,7 @@ void Session::release_tile(RenderTile &rtile, const bool need_denoise)
denoising_cond.notify_all();
}
-void Session::map_neighbor_tiles(RenderTile *tiles, Device *tile_device)
+void Session::map_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device)
{
thread_scoped_lock tile_lock(tile_mutex);
@@ -546,75 +546,77 @@ void Session::map_neighbor_tiles(RenderTile *tiles, Device *tile_device)
tile_manager.state.buffer.full_x + tile_manager.state.buffer.width,
tile_manager.state.buffer.full_y + tile_manager.state.buffer.height);
+ RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
+
if (!tile_manager.schedule_denoising) {
/* Fix up tile slices with overlap. */
if (tile_manager.slice_overlap != 0) {
- int y = max(tiles[4].y - tile_manager.slice_overlap, image_region.y);
- tiles[4].h = min(tiles[4].y + tiles[4].h + tile_manager.slice_overlap, image_region.w) - y;
- tiles[4].y = y;
+ int y = max(center_tile.y - tile_manager.slice_overlap, image_region.y);
+ center_tile.h = min(center_tile.y + center_tile.h + tile_manager.slice_overlap,
+ image_region.w) -
+ y;
+ center_tile.y = y;
}
/* Tiles are not being denoised individually, which means the entire image is processed. */
- tiles[3].x = tiles[4].x;
- tiles[1].y = tiles[4].y;
- tiles[5].x = tiles[4].x + tiles[4].w;
- tiles[7].y = tiles[4].y + tiles[4].h;
+ neighbors.set_bounds_from_center();
}
else {
- int center_idx = tiles[4].tile_index;
+ int center_idx = center_tile.tile_index;
assert(tile_manager.state.tiles[center_idx].state == Tile::DENOISE);
for (int dy = -1, i = 0; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++, i++) {
+ RenderTile &rtile = neighbors.tiles[i];
int nindex = tile_manager.get_neighbor_index(center_idx, i);
if (nindex >= 0) {
Tile *tile = &tile_manager.state.tiles[nindex];
- tiles[i].x = image_region.x + tile->x;
- tiles[i].y = image_region.y + tile->y;
- tiles[i].w = tile->w;
- tiles[i].h = tile->h;
+ rtile.x = image_region.x + tile->x;
+ rtile.y = image_region.y + tile->y;
+ rtile.w = tile->w;
+ rtile.h = tile->h;
if (buffers) {
- tile_manager.state.buffer.get_offset_stride(tiles[i].offset, tiles[i].stride);
+ tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
- tiles[i].buffer = buffers->buffer.device_pointer;
- tiles[i].buffers = buffers;
+ rtile.buffer = buffers->buffer.device_pointer;
+ rtile.buffers = buffers;
}
else {
assert(tile->buffers);
- tile->buffers->params.get_offset_stride(tiles[i].offset, tiles[i].stride);
+ tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride);
- tiles[i].buffer = tile->buffers->buffer.device_pointer;
- tiles[i].buffers = tile->buffers;
+ rtile.buffer = tile->buffers->buffer.device_pointer;
+ rtile.buffers = tile->buffers;
}
}
else {
- int px = tiles[4].x + dx * params.tile_size.x;
- int py = tiles[4].y + dy * params.tile_size.y;
+ int px = center_tile.x + dx * params.tile_size.x;
+ int py = center_tile.y + dy * params.tile_size.y;
- tiles[i].x = clamp(px, image_region.x, image_region.z);
- tiles[i].y = clamp(py, image_region.y, image_region.w);
- tiles[i].w = tiles[i].h = 0;
+ rtile.x = clamp(px, image_region.x, image_region.z);
+ rtile.y = clamp(py, image_region.y, image_region.w);
+ rtile.w = rtile.h = 0;
- tiles[i].buffer = (device_ptr)NULL;
- tiles[i].buffers = NULL;
+ rtile.buffer = (device_ptr)NULL;
+ rtile.buffers = NULL;
}
}
}
}
- assert(tiles[4].buffers);
- device->map_neighbor_tiles(tile_device, tiles);
+ assert(center_tile.buffers);
+ device->map_neighbor_tiles(tile_device, neighbors);
/* The denoised result is written back to the original tile. */
- tiles[9] = tiles[4];
+ neighbors.target = center_tile;
}
-void Session::unmap_neighbor_tiles(RenderTile *tiles, Device *tile_device)
+void Session::unmap_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device)
{
thread_scoped_lock tile_lock(tile_mutex);
- device->unmap_neighbor_tiles(tile_device, tiles);
+ device->unmap_neighbor_tiles(tile_device, neighbors);
}
void Session::run_cpu()
@@ -943,8 +945,14 @@ void Session::set_pause(bool pause_)
}
}
- if (notify)
- pause_cond.notify_all();
+ if (session_thread) {
+ if (notify) {
+ pause_cond.notify_all();
+ }
+ }
+ else if (pause_) {
+ update_status_time(pause_);
+ }
}
void Session::set_denoising(const DenoiseParams &denoising)
@@ -1003,7 +1011,7 @@ bool Session::update_scene()
int height = tile_manager.state.buffer.full_height;
int resolution = tile_manager.state.resolution_divider;
- if (width != cam->width || height != cam->height) {
+ if (width != cam->width || height != cam->height || resolution != cam->resolution) {
cam->width = width;
cam->height = height;
cam->resolution = resolution;
@@ -1126,6 +1134,11 @@ bool Session::render_need_denoise(bool &delayed)
{
delayed = false;
+ /* Not supported yet for baking. */
+ if (read_bake_tile_cb) {
+ return false;
+ }
+
/* Denoising enabled? */
if (!params.denoising.need_denoising_task()) {
return false;
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 0141629762c..e3ac054ead3 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -198,8 +198,8 @@ class Session {
void update_tile_sample(RenderTile &tile);
void release_tile(RenderTile &tile, const bool need_denoise);
- void map_neighbor_tiles(RenderTile *tiles, Device *tile_device);
- void unmap_neighbor_tiles(RenderTile *tiles, Device *tile_device);
+ void map_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device);
+ void unmap_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device);
bool device_use_gl;
diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt
index 6dcc7f7b3dd..07b345baff8 100644
--- a/intern/cycles/test/CMakeLists.txt
+++ b/intern/cycles/test/CMakeLists.txt
@@ -112,3 +112,4 @@ set_source_files_properties(util_avxf_avx_test.cpp PROPERTIES COMPILE_FLAGS "${C
CYCLES_TEST(util_avxf_avx "cycles_util;bf_intern_numaapi;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}")
set_source_files_properties(util_avxf_avx2_test.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
CYCLES_TEST(util_avxf_avx2 "cycles_util;bf_intern_numaapi;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}")
+CYCLES_TEST(util_transform "cycles_util;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}")
diff --git a/intern/cycles/test/util_transform_test.cpp b/intern/cycles/test/util_transform_test.cpp
new file mode 100644
index 00000000000..58ce0fdfee4
--- /dev/null
+++ b/intern/cycles/test/util_transform_test.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2011-2020 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "testing/testing.h"
+
+#include "util/util_transform.h"
+#include "util/util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+TEST(transform_motion_decompose, Degenerated)
+{
+ // Simple case: single degenerated matrix.
+ {
+ vector<Transform> motion = {transform_scale(0.0f, 0.0f, 0.0f)};
+ vector<DecomposedTransform> decomp(motion.size());
+ transform_motion_decompose(decomp.data(), motion.data(), motion.size());
+ EXPECT_TRUE(transform_decomposed_isfinite_safe(&decomp[0]));
+ }
+
+ // Copy from previous to current.
+ {
+ vector<Transform> motion = {transform_rotate(M_PI_4_F, make_float3(1.0f, 1.0f, 1.0f)),
+ transform_scale(0.0f, 0.0f, 0.0f)};
+ vector<DecomposedTransform> decomp(motion.size());
+ transform_motion_decompose(decomp.data(), motion.data(), motion.size());
+ EXPECT_NEAR(len(decomp[1].x - decomp[0].x), 0.0f, 1e-6f);
+ }
+
+ // Copy from next to current.
+ {
+ vector<Transform> motion = {transform_scale(0.0f, 0.0f, 0.0f),
+ transform_rotate(M_PI_4_F, make_float3(1.0f, 1.0f, 1.0f))};
+ vector<DecomposedTransform> decomp(motion.size());
+ transform_motion_decompose(decomp.data(), motion.data(), motion.size());
+ EXPECT_NEAR(len(decomp[0].x - decomp[1].x), 0.0f, 1e-6f);
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index ad4ea9c86e0..f5e488d1bd2 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -98,12 +98,9 @@ set(SRC_HEADERS
util_rect.h
util_set.h
util_simd.h
- util_sky_model.cpp
- util_sky_model.h
- util_sky_model_data.h
- util_sky_nishita.cpp
util_avxf.h
util_avxb.h
+ util_avxi.h
util_semaphore.h
util_sseb.h
util_ssef.h
diff --git a/intern/cycles/util/util_avxb.h b/intern/cycles/util/util_avxb.h
index 34fafd188de..5c03b1d88d7 100644
--- a/intern/cycles/util/util_avxb.h
+++ b/intern/cycles/util/util_avxb.h
@@ -57,7 +57,7 @@ struct avxb {
: m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a), b, 1))
{
}
- __forceinline operator const __m256 &(void)const
+ __forceinline operator const __m256 &(void) const
{
return m256;
}
diff --git a/intern/cycles/util/util_avxi.h b/intern/cycles/util/util_avxi.h
index e658a4f848f..1b3810764b7 100644
--- a/intern/cycles/util/util_avxi.h
+++ b/intern/cycles/util/util_avxi.h
@@ -54,7 +54,7 @@ struct avxi {
__forceinline avxi(const __m256i a) : m256(a)
{
}
- __forceinline operator const __m256i &(void)const
+ __forceinline operator const __m256i &(void) const
{
return m256;
}
diff --git a/intern/cycles/util/util_debug.cpp b/intern/cycles/util/util_debug.cpp
index 6ad4f709ab5..74ecefa1917 100644
--- a/intern/cycles/util/util_debug.cpp
+++ b/intern/cycles/util/util_debug.cpp
@@ -83,6 +83,7 @@ DebugFlags::OptiX::OptiX()
void DebugFlags::OptiX::reset()
{
cuda_streams = 1;
+ curves_api = false;
}
DebugFlags::OpenCL::OpenCL() : device_type(DebugFlags::OpenCL::DEVICE_ALL), debug(false)
diff --git a/intern/cycles/util/util_debug.h b/intern/cycles/util/util_debug.h
index da9f5408b59..6ac4beb55b8 100644
--- a/intern/cycles/util/util_debug.h
+++ b/intern/cycles/util/util_debug.h
@@ -108,6 +108,9 @@ class DebugFlags {
/* Number of CUDA streams to launch kernels concurrently from. */
int cuda_streams;
+
+ /* Use OptiX curves API for hair instead of custom implementation. */
+ bool curves_api;
};
/* Descriptor of OpenCL feature-set to be used. */
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 737c834e073..8caabf6eac3 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -787,6 +787,16 @@ ccl_device_inline float compare_floats(float a, float b, float abs_diff, int ulp
return (abs(__float_as_int(a) - __float_as_int(b)) < ulp_diff);
}
+/* Calculate the angle between the two vectors a and b.
+ * The usual approach acos(dot(a, b)) has severe precision issues for small angles,
+ * which are avoided by this method.
+ * Based on "Mangled Angles" from https://people.eecs.berkeley.edu/~wkahan/Mindless.pdf
+ */
+ccl_device_inline float precise_angle(float3 a, float3 b)
+{
+ return 2.0f * atan2f(len(a - b), len(a + b));
+}
+
CCL_NAMESPACE_END
#endif /* __UTIL_MATH_H__ */
diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h
index e979bd9e0c0..07b0878e3d5 100644
--- a/intern/cycles/util/util_math_fast.h
+++ b/intern/cycles/util/util_math_fast.h
@@ -87,7 +87,7 @@ ccl_device_inline int fast_rint(float x)
/* Single roundps instruction on SSE4.1+ (for gcc/clang at least). */
return float_to_int(rintf(x));
#else
- /* emulate rounding by adding/substracting 0.5. */
+ /* emulate rounding by adding/subtracting 0.5. */
return float_to_int(x + copysignf(0.5f, x));
#endif
}
@@ -445,12 +445,10 @@ ccl_device_inline float fast_expf(float x)
return fast_exp2f(x / M_LN2_F);
}
-#ifndef __KERNEL_GPU__
-/* MSVC seems to have a code-gen bug here in at least SSE41/AVX
- * see T78047 for details. */
-# ifdef _MSC_VER
-# pragma optimize("", off)
-# endif
+#if defined(__KERNEL_CPU__) && !defined(_MSC_VER)
+/* MSVC seems to have a code-gen bug here in at least SSE41/AVX, see
+ * T78047 and T78869 for details. Just disable for now, it only makes
+ * a small difference in denoising performance. */
ccl_device float4 fast_exp2f4(float4 x)
{
const float4 one = make_float4(1.0f);
@@ -466,14 +464,16 @@ ccl_device float4 fast_exp2f4(float4 x)
r = madd4(x, r, make_float4(1.0f));
return __int4_as_float4(__float4_as_int4(r) + (m << 23));
}
-# ifdef _MSC_VER
-# pragma optimize("", on)
-# endif
ccl_device_inline float4 fast_expf4(float4 x)
{
return fast_exp2f4(x / M_LN2_F);
}
+#else
+ccl_device_inline float4 fast_expf4(float4 x)
+{
+ return make_float4(fast_expf(x.x), fast_expf(x.y), fast_expf(x.z), fast_expf(x.w));
+}
#endif
ccl_device_inline float fast_exp10(float x)
diff --git a/intern/cycles/util/util_math_float4.h b/intern/cycles/util/util_math_float4.h
index cd4b3e3b74c..ec5328adb31 100644
--- a/intern/cycles/util/util_math_float4.h
+++ b/intern/cycles/util/util_math_float4.h
@@ -477,6 +477,24 @@ ccl_device_inline float4 safe_divide_float4_float(const float4 a, const float b)
return (b != 0.0f) ? a / b : make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
+ccl_device_inline bool isfinite4_safe(float4 v)
+{
+ return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z) && isfinite_safe(v.w);
+}
+
+ccl_device_inline float4 ensure_finite4(float4 v)
+{
+ if (!isfinite_safe(v.x))
+ v.x = 0.0f;
+ if (!isfinite_safe(v.y))
+ v.y = 0.0f;
+ if (!isfinite_safe(v.z))
+ v.z = 0.0f;
+ if (!isfinite_safe(v.w))
+ v.w = 0.0f;
+ return v;
+}
+
CCL_NAMESPACE_END
#endif /* __UTIL_MATH_FLOAT4_H__ */
diff --git a/intern/cycles/util/util_sseb.h b/intern/cycles/util/util_sseb.h
index 56f8f676ba1..d817e23c47e 100644
--- a/intern/cycles/util/util_sseb.h
+++ b/intern/cycles/util/util_sseb.h
@@ -57,7 +57,7 @@ struct sseb {
__forceinline sseb(const __m128 input) : m128(input)
{
}
- __forceinline operator const __m128 &(void)const
+ __forceinline operator const __m128 &(void) const
{
return m128;
}
diff --git a/intern/cycles/util/util_ssei.h b/intern/cycles/util/util_ssei.h
index e2bf81310cc..a4db9193206 100644
--- a/intern/cycles/util/util_ssei.h
+++ b/intern/cycles/util/util_ssei.h
@@ -57,7 +57,7 @@ struct ssei {
__forceinline ssei(const __m128i a) : m128(a)
{
}
- __forceinline operator const __m128i &(void)const
+ __forceinline operator const __m128i &(void) const
{
return m128;
}
diff --git a/intern/cycles/util/util_tbb.h b/intern/cycles/util/util_tbb.h
index 301cb80c5b0..206ba106ca6 100644
--- a/intern/cycles/util/util_tbb.h
+++ b/intern/cycles/util/util_tbb.h
@@ -34,6 +34,11 @@ using tbb::blocked_range;
using tbb::enumerable_thread_specific;
using tbb::parallel_for;
+static inline void parallel_for_cancel()
+{
+ tbb::task::self().cancel_group_execution();
+}
+
CCL_NAMESPACE_END
#endif /* __UTIL_TBB_H__ */
diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp
index 101122740d7..e8233b7fe6d 100644
--- a/intern/cycles/util/util_transform.cpp
+++ b/intern/cycles/util/util_transform.cpp
@@ -269,17 +269,17 @@ static void transform_decompose(DecomposedTransform *decomp, const Transform *tf
/* extract scale and shear first */
float3 scale, shear;
scale.x = len(colx);
- colx /= scale.x;
+ colx = safe_divide_float3_float(colx, scale.x);
shear.z = dot(colx, coly);
coly -= shear.z * colx;
scale.y = len(coly);
- coly /= scale.y;
+ coly = safe_divide_float3_float(coly, scale.y);
shear.y = dot(colx, colz);
colz -= shear.y * colx;
shear.x = dot(coly, colz);
colz -= shear.x * coly;
scale.z = len(colz);
- colz /= scale.z;
+ colz = safe_divide_float3_float(colz, scale.z);
transform_set_column(&M, 0, colx);
transform_set_column(&M, 1, coly);
@@ -300,6 +300,7 @@ static void transform_decompose(DecomposedTransform *decomp, const Transform *tf
void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size)
{
+ /* Decompose and correct rotation. */
for (size_t i = 0; i < size; i++) {
transform_decompose(decomp + i, motion + i);
@@ -310,6 +311,27 @@ void transform_motion_decompose(DecomposedTransform *decomp, const Transform *mo
decomp[i].x = -decomp[i].x;
}
}
+
+ /* Copy rotation to decomposed transform where scale is degenerate. This avoids weird object
+ * rotation interpolation when the scale goes to 0 for a time step.
+ *
+ * Note that this is very simple and naive implementation, which only deals with degenerated
+ * scale happening only on one frame. It is possible to improve it further by interpolating
+ * rotation into s degenerated range using rotation from time-steps from adjacent non-degenerated
+ * time steps. */
+ for (size_t i = 0; i < size; i++) {
+ const float3 scale = make_float3(decomp[i].y.w, decomp[i].z.w, decomp[i].w.w);
+ if (!is_zero(scale)) {
+ continue;
+ }
+
+ if (i > 0) {
+ decomp[i].x = decomp[i - 1].x;
+ }
+ else if (i < size - 1) {
+ decomp[i].x = decomp[i + 1].x;
+ }
+ }
}
Transform transform_from_viewplane(BoundBox2D &viewplane)
diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h
index d0a6264d5cf..d8bbd389aa6 100644
--- a/intern/cycles/util/util_transform.h
+++ b/intern/cycles/util/util_transform.h
@@ -466,6 +466,17 @@ ccl_device void transform_motion_array_interpolate(Transform *tfm,
transform_compose(tfm, &decomp);
}
+ccl_device_inline bool transform_isfinite_safe(Transform *tfm)
+{
+ return isfinite4_safe(tfm->x) && isfinite4_safe(tfm->y) && isfinite4_safe(tfm->z);
+}
+
+ccl_device_inline bool transform_decomposed_isfinite_safe(DecomposedTransform *decomp)
+{
+ return isfinite4_safe(decomp->x) && isfinite4_safe(decomp->y) && isfinite4_safe(decomp->z) &&
+ isfinite4_safe(decomp->w);
+}
+
#ifndef __KERNEL_GPU__
class BoundBox2D;
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 699ac4afe88..77e777db872 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -429,6 +429,7 @@ if(WITH_XR_OPENXR)
GHOST_IXrContext.h
intern/GHOST_IXrGraphicsBinding.h
intern/GHOST_XrContext.h
+ intern/GHOST_XrException.h
intern/GHOST_XrSession.h
intern/GHOST_XrSwapchain.h
intern/GHOST_Xr_intern.h
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index c7737392e7b..f23742a9166 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -21,8 +21,7 @@
* \brief GHOST C-API function and type declarations.
*/
-#ifndef __GHOST_C_API_H__
-#define __GHOST_C_API_H__
+#pragma once
#include "GHOST_Types.h"
@@ -362,8 +361,8 @@ extern GHOST_TSuccess GHOST_HasCursorShape(GHOST_WindowHandle windowhandle,
* \param mask The mask data for the cursor.
* \param sizex The width of the cursor
* \param sizey The height of the cursor
- * \param hotX The X coordinate of the cursor hotspot.
- * \param hotY The Y coordinate of the cursor hotspot.
+ * \param hotX The X coordinate of the cursor hot-spot.
+ * \param hotY The Y coordinate of the cursor hot-spot.
* \param canInvertColor Let macOS invert cursor color to match platform convention.
* \return Indication of success.
*/
@@ -1072,5 +1071,3 @@ GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_context);
#ifdef __cplusplus
}
#endif
-
-#endif
diff --git a/intern/ghost/GHOST_IContext.h b/intern/ghost/GHOST_IContext.h
index 8c24261644a..c6316e90ce4 100644
--- a/intern/ghost/GHOST_IContext.h
+++ b/intern/ghost/GHOST_IContext.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_IContext interface class.
*/
-#ifndef __GHOST_IContext_H__
-#define __GHOST_IContext_H__
+#pragma once
#include "GHOST_Types.h"
@@ -63,5 +62,3 @@ class GHOST_IContext {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IContext")
#endif
};
-
-#endif // __GHOST_IContext_H__
diff --git a/intern/ghost/GHOST_IEvent.h b/intern/ghost/GHOST_IEvent.h
index 0d9bfb2c4de..c63064c123a 100644
--- a/intern/ghost/GHOST_IEvent.h
+++ b/intern/ghost/GHOST_IEvent.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_IEvent interface class.
*/
-#ifndef __GHOST_IEVENT_H__
-#define __GHOST_IEVENT_H__
+#pragma once
#include "GHOST_Types.h"
#include <stddef.h>
@@ -78,5 +77,3 @@ class GHOST_IEvent {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IEvent")
#endif
};
-
-#endif // __GHOST_IEVENT_H__
diff --git a/intern/ghost/GHOST_IEventConsumer.h b/intern/ghost/GHOST_IEventConsumer.h
index d677a632a4b..b5975068da0 100644
--- a/intern/ghost/GHOST_IEventConsumer.h
+++ b/intern/ghost/GHOST_IEventConsumer.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_IEventConsumer interface class.
*/
-#ifndef __GHOST_IEVENTCONSUMER_H__
-#define __GHOST_IEVENTCONSUMER_H__
+#pragma once
#include "GHOST_IEvent.h"
@@ -56,5 +55,3 @@ class GHOST_IEventConsumer {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IEventConsumer")
#endif
};
-
-#endif /* __GHOST_IEVENTCONSUMER_H__ */
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 33600fd1219..04e9d5e4e14 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -24,8 +24,7 @@
* Contains the doxygen documentation main page.
*/
-#ifndef __GHOST_ISYSTEM_H__
-#define __GHOST_ISYSTEM_H__
+#pragma once
#include <stdlib.h>
@@ -494,5 +493,3 @@ class GHOST_ISystem {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_ISystem")
#endif
};
-
-#endif // __GHOST_ISYSTEM_H__
diff --git a/intern/ghost/GHOST_ISystemPaths.h b/intern/ghost/GHOST_ISystemPaths.h
index 297f6333a77..b47d14984d8 100644
--- a/intern/ghost/GHOST_ISystemPaths.h
+++ b/intern/ghost/GHOST_ISystemPaths.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_ISYSTEMPATHS_H__
-#define __GHOST_ISYSTEMPATHS_H__
+#pragma once
#include "GHOST_Types.h"
@@ -97,5 +96,3 @@ class GHOST_ISystemPaths {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_ISystemPaths")
#endif
};
-
-#endif
diff --git a/intern/ghost/GHOST_ITimerTask.h b/intern/ghost/GHOST_ITimerTask.h
index 46f4fdbc303..0f4ac74c466 100644
--- a/intern/ghost/GHOST_ITimerTask.h
+++ b/intern/ghost/GHOST_ITimerTask.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_ITimerTask interface class.
*/
-#ifndef __GHOST_ITIMERTASK_H__
-#define __GHOST_ITIMERTASK_H__
+#pragma once
#include "GHOST_Types.h"
@@ -76,5 +75,3 @@ class GHOST_ITimerTask {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_ITimerTask")
#endif
};
-
-#endif // __GHOST_ITIMERTASK_H__
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 62290d20f1c..6e8b61ae5a1 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_IWindow interface class.
*/
-#ifndef __GHOST_IWINDOW_H__
-#define __GHOST_IWINDOW_H__
+#pragma once
#include "GHOST_Rect.h"
#include "GHOST_Types.h"
@@ -287,8 +286,8 @@ class GHOST_IWindow {
* Set the shape of the cursor to a custom cursor.
* \param bitmap The bitmap data for the cursor.
* \param mask The mask data for the cursor.
- * \param hotX The X coordinate of the cursor hotspot.
- * \param hotY The Y coordinate of the cursor hotspot.
+ * \param hotX The X coordinate of the cursor hot-spot.
+ * \param hotY The Y coordinate of the cursor hot-spot.
* \return Indication of success.
*/
virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
@@ -363,5 +362,3 @@ class GHOST_IWindow {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IWindow")
#endif
};
-
-#endif // __GHOST_IWINDOW_H__
diff --git a/intern/ghost/GHOST_IXrContext.h b/intern/ghost/GHOST_IXrContext.h
index 3076de96690..dd266a3b6ae 100644
--- a/intern/ghost/GHOST_IXrContext.h
+++ b/intern/ghost/GHOST_IXrContext.h
@@ -18,8 +18,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_IXRCONTEXT_H__
-#define __GHOST_IXRCONTEXT_H__
+#pragma once
#include "GHOST_Types.h"
@@ -40,5 +39,3 @@ class GHOST_IXrContext {
virtual bool needsUpsideDownDrawing() const = 0;
};
-
-#endif // __GHOST_IXRCONTEXT_H__
diff --git a/intern/ghost/GHOST_Path-api.h b/intern/ghost/GHOST_Path-api.h
index 53abdf68bb4..4cc232be6b6 100644
--- a/intern/ghost/GHOST_Path-api.h
+++ b/intern/ghost/GHOST_Path-api.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_PATH_API_H__
-#define __GHOST_PATH_API_H__
+#pragma once
#include "GHOST_Types.h"
@@ -71,5 +70,3 @@ extern void GHOST_addToSystemRecentFiles(const char *filename);
#ifdef __cplusplus
}
#endif
-
-#endif
diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h
index 13632a1c03b..fcc9da20197 100644
--- a/intern/ghost/GHOST_Rect.h
+++ b/intern/ghost/GHOST_Rect.h
@@ -22,8 +22,7 @@
* Macro's used in GHOST debug target.
*/
-#ifndef __GHOST_RECT_H__
-#define __GHOST_RECT_H__
+#pragma once
#include "GHOST_Types.h"
@@ -263,5 +262,3 @@ inline bool GHOST_Rect::isInside(GHOST_TInt32 x, GHOST_TInt32 y) const
{
return (x >= m_l) && (x <= m_r) && (y >= m_t) && (y <= m_b);
}
-
-#endif // __GHOST_RECT_H__
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index b8de31df6c6..5f0516ae121 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_TYPES_H__
-#define __GHOST_TYPES_H__
+#pragma once
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
@@ -677,5 +676,3 @@ typedef struct GHOST_XrError {
} GHOST_XrError;
#endif
-
-#endif // __GHOST_TYPES_H__
diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h
index 0b824739950..e28fae8870c 100644
--- a/intern/ghost/intern/GHOST_Buttons.h
+++ b/intern/ghost/intern/GHOST_Buttons.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_Buttons struct.
*/
-#ifndef __GHOST_BUTTONS_H__
-#define __GHOST_BUTTONS_H__
+#pragma once
#include "GHOST_Types.h"
@@ -62,5 +61,3 @@ struct GHOST_Buttons {
GHOST_TUns8 m_ButtonMiddle : 1;
GHOST_TUns8 m_ButtonRight : 1;
};
-
-#endif // __GHOST_BUTTONS_H__
diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.h b/intern/ghost/intern/GHOST_CallbackEventConsumer.h
index 9c3fc642209..a1664e77717 100644
--- a/intern/ghost/intern/GHOST_CallbackEventConsumer.h
+++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_CallbackEventConsumer class.
*/
-#ifndef __GHOST_CALLBACKEVENTCONSUMER_H__
-#define __GHOST_CALLBACKEVENTCONSUMER_H__
+#pragma once
#include "GHOST_C-api.h"
#include "GHOST_IEventConsumer.h"
@@ -66,5 +65,3 @@ class GHOST_CallbackEventConsumer : public GHOST_IEventConsumer {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_CallbackEventConsumer")
#endif
};
-
-#endif // __GHOST_CALLBACKEVENTCONSUMER_H__
diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h
index 411a7de5c79..33eeacbb203 100644
--- a/intern/ghost/intern/GHOST_Context.h
+++ b/intern/ghost/intern/GHOST_Context.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_Context class.
*/
-#ifndef __GHOST_CONTEXT_H__
-#define __GHOST_CONTEXT_H__
+#pragma once
#include "GHOST_IContext.h"
#include "GHOST_Types.h"
@@ -160,5 +159,3 @@ bool win32_silent_chk(bool result);
# define WIN32_CHK_SILENT(x, silent) ((silent) ? win32_silent_chk(x) : WIN32_CHK(x))
#endif /* _WIN32 */
-
-#endif // __GHOST_CONTEXT_H__
diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h
index 37c1ac34299..7b1e186dede 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.h
+++ b/intern/ghost/intern/GHOST_ContextCGL.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_CONTEXTCGL_H__
-#define __GHOST_CONTEXTCGL_H__
+#pragma once
#include "GHOST_Context.h"
@@ -137,5 +136,3 @@ class GHOST_ContextCGL : public GHOST_Context {
void metalUpdateFramebuffer();
void metalSwapBuffers();
};
-
-#endif // __GHOST_CONTEXTCGL_H__
diff --git a/intern/ghost/intern/GHOST_ContextD3D.h b/intern/ghost/intern/GHOST_ContextD3D.h
index c482992a6e2..e85516838fc 100644
--- a/intern/ghost/intern/GHOST_ContextD3D.h
+++ b/intern/ghost/intern/GHOST_ContextD3D.h
@@ -18,8 +18,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_CONTEXTD3D_H__
-#define __GHOST_CONTEXTD3D_H__
+#pragma once
#ifndef WIN32
# error WIN32 only!
@@ -132,5 +131,3 @@ class GHOST_ContextD3D : public GHOST_Context {
ID3D11Device *m_device;
ID3D11DeviceContext *m_device_ctx;
};
-
-#endif /* __GHOST_CONTEXTD3D_H__ */
diff --git a/intern/ghost/intern/GHOST_ContextEGL.cpp b/intern/ghost/intern/GHOST_ContextEGL.cpp
index 02daad2111a..bac7057d953 100644
--- a/intern/ghost/intern/GHOST_ContextEGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextEGL.cpp
@@ -118,7 +118,7 @@ static const char *get_egl_error_message_string(EGLint error)
case EGL_CONTEXT_LOST:
return (
"A power management event has occurred. "
- "The application must destroy all contexts and reinitialise OpenGL ES state "
+ "The application must destroy all contexts and reinitialize OpenGL ES state "
"and objects to continue rendering.");
default:
diff --git a/intern/ghost/intern/GHOST_ContextEGL.h b/intern/ghost/intern/GHOST_ContextEGL.h
index da5ca7ef93f..e5dae0d22a8 100644
--- a/intern/ghost/intern/GHOST_ContextEGL.h
+++ b/intern/ghost/intern/GHOST_ContextEGL.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_CONTEXTEGL_H__
-#define __GHOST_CONTEXTEGL_H__
+#pragma once
#include "GHOST_Context.h"
@@ -137,5 +136,3 @@ class GHOST_ContextEGL : public GHOST_Context {
static HMODULE s_d3dcompiler;
#endif
};
-
-#endif // __GHOST_CONTEXTEGL_H__
diff --git a/intern/ghost/intern/GHOST_ContextGLX.h b/intern/ghost/intern/GHOST_ContextGLX.h
index 07d2601cd17..e5654b1aed7 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.h
+++ b/intern/ghost/intern/GHOST_ContextGLX.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_CONTEXTGLX_H__
-#define __GHOST_CONTEXTGLX_H__
+#pragma once
#include "GHOST_Context.h"
@@ -128,5 +127,3 @@ class GHOST_ContextGLX : public GHOST_Context {
/* used to get GLX info */
int GHOST_X11_GL_GetAttributes(
int *attribs, int attribs_max, bool is_stereo_visual, bool need_alpha, bool for_fb_config);
-
-#endif // __GHOST_CONTEXTGLX_H__
diff --git a/intern/ghost/intern/GHOST_ContextNone.h b/intern/ghost/intern/GHOST_ContextNone.h
index 2a3c08701b4..b1ac349e4a7 100644
--- a/intern/ghost/intern/GHOST_ContextNone.h
+++ b/intern/ghost/intern/GHOST_ContextNone.h
@@ -23,8 +23,7 @@
* Declaration of GHOST_Context class.
*/
-#ifndef __GHOST_CONTEXTNONE_H__
-#define __GHOST_CONTEXTNONE_H__
+#pragma once
#include "GHOST_Context.h"
@@ -86,5 +85,3 @@ class GHOST_ContextNone : public GHOST_Context {
private:
int m_swapInterval;
};
-
-#endif // __GHOST_CONTEXTNONE_H__
diff --git a/intern/ghost/intern/GHOST_ContextSDL.h b/intern/ghost/intern/GHOST_ContextSDL.h
index 670d930e1e7..ead2e91181c 100644
--- a/intern/ghost/intern/GHOST_ContextSDL.h
+++ b/intern/ghost/intern/GHOST_ContextSDL.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_CONTEXTSDL_H__
-#define __GHOST_CONTEXTSDL_H__
+#pragma once
#include "GHOST_Context.h"
@@ -121,5 +120,3 @@ class GHOST_ContextSDL : public GHOST_Context {
static SDL_GLContext s_sharedContext;
static int s_sharedCount;
};
-
-#endif // __GHOST_CONTEXTSDL_H__
diff --git a/intern/ghost/intern/GHOST_ContextWGL.h b/intern/ghost/intern/GHOST_ContextWGL.h
index a8d2c18b463..087fca100e4 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.h
+++ b/intern/ghost/intern/GHOST_ContextWGL.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_CONTEXTWGL_H__
-#define __GHOST_CONTEXTWGL_H__
+#pragma once
//#define WIN32_COMPOSITING
@@ -130,5 +129,3 @@ class GHOST_ContextWGL : public GHOST_Context {
static HGLRC s_sharedHGLRC;
static int s_sharedCount;
};
-
-#endif // __GHOST_CONTEXTWGL_H__
diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h
index 5b5c2688297..424f95aa573 100644
--- a/intern/ghost/intern/GHOST_Debug.h
+++ b/intern/ghost/intern/GHOST_Debug.h
@@ -22,8 +22,7 @@
* Macro's used in GHOST debug target.
*/
-#ifndef __GHOST_DEBUG_H__
-#define __GHOST_DEBUG_H__
+#pragma once
#ifdef _MSC_VER
# ifdef DEBUG
@@ -79,5 +78,3 @@
#else // WITH_GHOST_DEBUG
# define GHOST_ASSERT(x, info) ((void)0)
#endif // WITH_GHOST_DEBUG
-
-#endif // __GHOST_DEBUG_H__
diff --git a/intern/ghost/intern/GHOST_DisplayManager.h b/intern/ghost/intern/GHOST_DisplayManager.h
index 58b36c0035b..67b9aada55f 100644
--- a/intern/ghost/intern/GHOST_DisplayManager.h
+++ b/intern/ghost/intern/GHOST_DisplayManager.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_DisplayManager class.
*/
-#ifndef __GHOST_DISPLAYMANAGER_H__
-#define __GHOST_DISPLAYMANAGER_H__
+#pragma once
#include "GHOST_Types.h"
@@ -127,5 +126,3 @@ class GHOST_DisplayManager {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_DisplayManager")
#endif
};
-
-#endif // __GHOST_DISPLAYMANAGER_H__
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
index c99e93279f7..5edd555a78b 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_DisplayManagerCocoa class.
*/
-#ifndef __GHOST_DISPLAYMANAGERCOCOA_H__
-#define __GHOST_DISPLAYMANAGERCOCOA_H__
+#pragma once
#ifndef __APPLE__
# error Apple only!
@@ -93,5 +92,3 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager {
/** Cached display id's for each display. */
// CGDirectDisplayID* m_displayIDs;
};
-
-#endif // __GHOST_DISPLAYMANAGERCOCOA_H__
diff --git a/intern/ghost/intern/GHOST_DisplayManagerNULL.h b/intern/ghost/intern/GHOST_DisplayManagerNULL.h
index 266a3e9a699..4ca06faec12 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerNULL.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerNULL.h
@@ -19,8 +19,7 @@
* Declaration of GHOST_DisplayManagerNULL class.
*/
-#ifndef __GHOST_DISPLAYMANAGERNULL_H__
-#define __GHOST_DISPLAYMANAGERNULL_H__
+#pragma once
#include "GHOST_DisplayManager.h"
#include "GHOST_SystemNULL.h"
@@ -58,5 +57,3 @@ class GHOST_DisplayManagerNULL : public GHOST_DisplayManager {
private:
GHOST_SystemNULL *m_system;
};
-
-#endif /* __GHOST_DISPLAYMANAGERNULL_H__ */
diff --git a/intern/ghost/intern/GHOST_DisplayManagerSDL.h b/intern/ghost/intern/GHOST_DisplayManagerSDL.h
index f7704d57ab0..9a79a842057 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerSDL.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerSDL.h
@@ -19,8 +19,7 @@
* Declaration of GHOST_DisplayManagerSDL class.
*/
-#ifndef __GHOST_DISPLAYMANAGERSDL_H__
-#define __GHOST_DISPLAYMANAGERSDL_H__
+#pragma once
#include "GHOST_DisplayManager.h"
@@ -58,5 +57,3 @@ class GHOST_DisplayManagerSDL : public GHOST_DisplayManager {
GHOST_SystemSDL *m_system;
SDL_DisplayMode m_mode;
};
-
-#endif /* __GHOST_DISPLAYMANAGERSDL_H__ */
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
index c4ad90b1de7..3392d515c16 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerWin32.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_DisplayManagerWin32 class.
*/
-#ifndef __GHOST_DISPLAYMANAGERWIN32_H__
-#define __GHOST_DISPLAYMANAGERWIN32_H__
+#pragma once
#ifndef WIN32
# error WIN32 only!
@@ -87,5 +86,3 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager {
protected:
};
-
-#endif // __GHOST_DISPLAYMANAGERWIN32_H__
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h
index 941152aa034..a36ff8d49f1 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerX11.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_DisplayManagerX11 class.
*/
-#ifndef __GHOST_DISPLAYMANAGERX11_H__
-#define __GHOST_DISPLAYMANAGERX11_H__
+#pragma once
#include "GHOST_DisplayManager.h"
@@ -86,5 +85,3 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager {
private:
GHOST_SystemX11 *m_system;
};
-
-#endif //
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h
index ee75c017981..ecce3a68835 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.h
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_DROPTARGETWIN32_H__
-#define __GHOST_DROPTARGETWIN32_H__
+#pragma once
#include "GHOST_SystemWin32.h"
#include "GHOST_WindowWin32.h"
@@ -150,5 +149,3 @@ class GHOST_DropTargetWin32 : public IDropTarget {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_DropTargetWin32")
#endif
};
-
-#endif // __GHOST_DROPTARGETWIN32_H__
diff --git a/intern/ghost/intern/GHOST_DropTargetX11.h b/intern/ghost/intern/GHOST_DropTargetX11.h
index 9ca12442085..066f2f6bba2 100644
--- a/intern/ghost/intern/GHOST_DropTargetX11.h
+++ b/intern/ghost/intern/GHOST_DropTargetX11.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_DROPTARGETX11_H__
-#define __GHOST_DROPTARGETX11_H__
+#pragma once
#include "GHOST_SystemX11.h"
#include "GHOST_WindowX11.h"
@@ -126,5 +125,3 @@ class GHOST_DropTargetX11 {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_DropTargetX11")
#endif
};
-
-#endif // __GHOST_DROPTARGETX11_H__
diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h
index 2c14df7f243..845d62fa810 100644
--- a/intern/ghost/intern/GHOST_Event.h
+++ b/intern/ghost/intern/GHOST_Event.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_Event class.
*/
-#ifndef __GHOST_EVENT_H__
-#define __GHOST_EVENT_H__
+#pragma once
#include "GHOST_IEvent.h"
@@ -90,5 +89,3 @@ class GHOST_Event : public GHOST_IEvent {
/** Pointer to the event data. */
GHOST_TEventDataPtr m_data;
};
-
-#endif // __GHOST_EVENT_H__
diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h
index 4247ae150a4..7072e0c5409 100644
--- a/intern/ghost/intern/GHOST_EventButton.h
+++ b/intern/ghost/intern/GHOST_EventButton.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_EventButton class.
*/
-#ifndef __GHOST_EVENTBUTTON_H__
-#define __GHOST_EVENTBUTTON_H__
+#pragma once
#include "GHOST_Event.h"
#include "GHOST_Window.h"
@@ -57,5 +56,3 @@ class GHOST_EventButton : public GHOST_Event {
/** The button event data. */
GHOST_TEventButtonData m_buttonEventData;
};
-
-#endif // __GHOST_EVENTBUTTON_H__
diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h
index 8ba657fd9fa..ba85cd74723 100644
--- a/intern/ghost/intern/GHOST_EventCursor.h
+++ b/intern/ghost/intern/GHOST_EventCursor.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_EventCursor class.
*/
-#ifndef __GHOST_EVENTCURSOR_H__
-#define __GHOST_EVENTCURSOR_H__
+#pragma once
#include "GHOST_Event.h"
@@ -58,5 +57,3 @@ class GHOST_EventCursor : public GHOST_Event {
/** The x,y-coordinates of the cursor position. */
GHOST_TEventCursorData m_cursorEventData;
};
-
-#endif // __GHOST_EVENTCURSOR_H__
diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h
index 36291e8a254..10975792993 100644
--- a/intern/ghost/intern/GHOST_EventDragnDrop.h
+++ b/intern/ghost/intern/GHOST_EventDragnDrop.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_EVENTDRAGNDROP_H__
-#define __GHOST_EVENTDRAGNDROP_H__
+#pragma once
#include "GHOST_Event.h"
extern "C" {
@@ -122,5 +121,3 @@ class GHOST_EventDragnDrop : public GHOST_Event {
/** The x,y-coordinates of the cursor position. */
GHOST_TEventDragnDropData m_dragnDropEventData;
};
-
-#endif // __GHOST_EVENTDRAGNDROP_H__
diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h
index 8f59c555914..cb71b452d80 100644
--- a/intern/ghost/intern/GHOST_EventKey.h
+++ b/intern/ghost/intern/GHOST_EventKey.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_EventKey class.
*/
-#ifndef __GHOST_EVENTKEY_H__
-#define __GHOST_EVENTKEY_H__
+#pragma once
#include <string.h>
@@ -84,5 +83,3 @@ class GHOST_EventKey : public GHOST_Event {
/** The key event data. */
GHOST_TEventKeyData m_keyEventData;
};
-
-#endif // __GHOST_EVENTKEY_H__
diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h
index ada5abda89b..befbdc72a5c 100644
--- a/intern/ghost/intern/GHOST_EventManager.h
+++ b/intern/ghost/intern/GHOST_EventManager.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_EventManager class.
*/
-#ifndef __GHOST_EVENTMANAGER_H__
-#define __GHOST_EVENTMANAGER_H__
+#pragma once
#include <deque>
#include <vector>
@@ -140,5 +139,3 @@ class GHOST_EventManager {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_EventManager")
#endif
};
-
-#endif // __GHOST_EVENTMANAGER_H__
diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h
index 196d3868ccd..64e67434b74 100644
--- a/intern/ghost/intern/GHOST_EventNDOF.h
+++ b/intern/ghost/intern/GHOST_EventNDOF.h
@@ -18,8 +18,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_EVENTNDOF_H__
-#define __GHOST_EVENTNDOF_H__
+#pragma once
#ifndef WITH_INPUT_NDOF
# error NDOF code included in non-NDOF-enabled build
@@ -50,5 +49,3 @@ class GHOST_EventNDOFButton : public GHOST_Event {
m_data = &m_buttonData;
}
};
-
-#endif // __GHOST_EVENTNDOF_H__
diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h
index ead16525ec6..42de4da5ee5 100644
--- a/intern/ghost/intern/GHOST_EventPrinter.h
+++ b/intern/ghost/intern/GHOST_EventPrinter.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_EventPrinter class.
*/
-#ifndef __GHOST_EVENTPRINTER_H__
-#define __GHOST_EVENTPRINTER_H__
+#pragma once
#include "GHOST_IEventConsumer.h"
@@ -48,5 +47,3 @@ class GHOST_EventPrinter : public GHOST_IEventConsumer {
*/
void getKeyString(GHOST_TKey key, char str[32]) const;
};
-
-#endif // __GHOST_EVENTPRINTER_H__
diff --git a/intern/ghost/intern/GHOST_EventString.h b/intern/ghost/intern/GHOST_EventString.h
index f0d3ffb9e91..8cd24a8a78b 100644
--- a/intern/ghost/intern/GHOST_EventString.h
+++ b/intern/ghost/intern/GHOST_EventString.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_EventString class.
*/
-#ifndef __GHOST_EVENTSTRING_H__
-#define __GHOST_EVENTSTRING_H__
+#pragma once
#include "GHOST_Event.h"
@@ -54,5 +53,3 @@ class GHOST_EventString : public GHOST_Event {
free(m_data);
}
};
-
-#endif // __GHOST_EVENTSTRING_H__
diff --git a/intern/ghost/intern/GHOST_EventTrackpad.h b/intern/ghost/intern/GHOST_EventTrackpad.h
index 795e969b16d..a22f8a34fad 100644
--- a/intern/ghost/intern/GHOST_EventTrackpad.h
+++ b/intern/ghost/intern/GHOST_EventTrackpad.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_EventTrackpad class.
*/
-#ifndef __GHOST_EVENTTRACKPAD_H__
-#define __GHOST_EVENTTRACKPAD_H__
+#pragma once
#include "GHOST_Event.h"
@@ -61,5 +60,3 @@ class GHOST_EventTrackpad : public GHOST_Event {
/** The mouse pan data */
GHOST_TEventTrackpadData m_trackpadEventData;
};
-
-#endif // _GHOST_EVENT_PAN_H_
diff --git a/intern/ghost/intern/GHOST_EventWheel.h b/intern/ghost/intern/GHOST_EventWheel.h
index 4d3eeb9cd83..ea62e02d08d 100644
--- a/intern/ghost/intern/GHOST_EventWheel.h
+++ b/intern/ghost/intern/GHOST_EventWheel.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_EventWheel class.
*/
-#ifndef __GHOST_EVENTWHEEL_H__
-#define __GHOST_EVENTWHEEL_H__
+#pragma once
#include "GHOST_Event.h"
@@ -51,5 +50,3 @@ class GHOST_EventWheel : public GHOST_Event {
/** The z-displacement of the mouse wheel. */
GHOST_TEventWheelData m_wheelEventData;
};
-
-#endif // __GHOST_EVENTWHEEL_H__
diff --git a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
index b199c5f9b28..de8bf9f1a5a 100644
--- a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
+++ b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
@@ -18,8 +18,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_IXRGRAPHICSBINDING_H__
-#define __GHOST_IXRGRAPHICSBINDING_H__
+#pragma once
#include <memory>
#include <string>
@@ -71,5 +70,3 @@ class GHOST_IXrGraphicsBinding {
std::unique_ptr<GHOST_IXrGraphicsBinding> GHOST_XrGraphicsBindingCreateFromType(
GHOST_TXrGraphicsBinding type, GHOST_Context *ghost_ctx);
-
-#endif /* __GHOST_IXRGRAPHICSBINDING_H__ */
diff --git a/intern/ghost/intern/GHOST_IconX11.h b/intern/ghost/intern/GHOST_IconX11.h
index c5bcf4bedeb..615a7dae6b5 100644
--- a/intern/ghost/intern/GHOST_IconX11.h
+++ b/intern/ghost/intern/GHOST_IconX11.h
@@ -22,8 +22,7 @@
* Icon image data for X11.
*/
-#ifndef __GHOST_ICONX11_H__
-#define __GHOST_ICONX11_H__
+#pragma once
/*
* import bpy
@@ -1013,5 +1012,3 @@ static const unsigned long BLENDER_ICONS_WM_X11[] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
-
-#endif // __GHOST_ICONX11_H__
diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h
index 112217023a7..74698d50659 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.h
+++ b/intern/ghost/intern/GHOST_ImeWin32.h
@@ -23,8 +23,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_IME_H__
-#define __GHOST_IME_H__
+#pragma once
#ifdef WITH_INPUT_IME
@@ -388,4 +387,3 @@ class GHOST_ImeWin32 {
};
#endif // WITH_INPUT_IME
-#endif // __GHOST_IME_H__
diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h
index 27ad4034068..c41ce8b7f39 100644
--- a/intern/ghost/intern/GHOST_ModifierKeys.h
+++ b/intern/ghost/intern/GHOST_ModifierKeys.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_ModifierKeys struct.
*/
-#ifndef __GHOST_MODIFIERKEYS_H__
-#define __GHOST_MODIFIERKEYS_H__
+#pragma once
#include "GHOST_Types.h"
@@ -87,5 +86,3 @@ struct GHOST_ModifierKeys {
/** Bitfield that stores the appropriate key state. */
GHOST_TUns8 m_OS : 1;
};
-
-#endif // __GHOST_MODIFIERKEYS_H__
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index a190607ca66..d0b49bc13c2 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -14,8 +14,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __GHOST_NDOFMANAGER_H__
-#define __GHOST_NDOFMANAGER_H__
+#pragma once
#ifndef WITH_INPUT_NDOF
# error NDOF code included in non-NDOF-enabled build
@@ -167,5 +166,3 @@ class GHOST_NDOFManager {
bool m_motionEventPending;
float m_deadZone; // discard motion with each component < this
};
-
-#endif
diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h
index bd1e6903f94..f7c3599502e 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h
+++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h
@@ -14,8 +14,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __GHOST_NDOFMANAGERCOCOA_H__
-#define __GHOST_NDOFMANAGERCOCOA_H__
+#pragma once
#include "GHOST_NDOFManager.h"
@@ -29,5 +28,3 @@ class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager {
bool available();
};
-
-#endif // #include guard
diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.h b/intern/ghost/intern/GHOST_NDOFManagerUnix.h
index 75bd022631a..6dd4289ffac 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerUnix.h
+++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.h
@@ -14,8 +14,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __GHOST_NDOFMANAGERUNIX_H__
-#define __GHOST_NDOFMANAGERUNIX_H__
+#pragma once
#include "GHOST_NDOFManager.h"
@@ -32,5 +31,3 @@ class GHOST_NDOFManagerUnix : public GHOST_NDOFManager {
private:
bool m_available;
};
-
-#endif /* __GHOST_NDOFMANAGERUNIX_H__ */
diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.h b/intern/ghost/intern/GHOST_NDOFManagerWin32.h
index 9ed5e6ab978..62d9b9207dc 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerWin32.h
+++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.h
@@ -14,8 +14,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __GHOST_NDOFMANAGERWIN32_H__
-#define __GHOST_NDOFMANAGERWIN32_H__
+#pragma once
#include "GHOST_NDOFManager.h"
@@ -24,5 +23,3 @@ class GHOST_NDOFManagerWin32 : public GHOST_NDOFManager {
GHOST_NDOFManagerWin32(GHOST_System &);
bool available();
};
-
-#endif // #include guard
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index c2d712c11cd..e29a9ba0c29 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_System class.
*/
-#ifndef __GHOST_SYSTEM_H__
-#define __GHOST_SYSTEM_H__
+#pragma once
#include "GHOST_ISystem.h"
@@ -424,5 +423,3 @@ inline GHOST_NDOFManager *GHOST_System::getNDOFManager() const
return m_ndofManager;
}
#endif
-
-#endif // __GHOST_SYSTEM_H__
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index bbd6f1d8995..8e36cebb88a 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_SystemCocoa class.
*/
-#ifndef __GHOST_SYSTEMCOCOA_H__
-#define __GHOST_SYSTEMCOCOA_H__
+#pragma once
#ifndef __APPLE__
# error Apple OSX only!
@@ -313,5 +312,3 @@ class GHOST_SystemCocoa : public GHOST_System {
/** Is the scroll wheel event generated by a multitouch trackpad or mouse? */
bool m_multiTouchScroll;
};
-
-#endif // __GHOST_SYSTEMCOCOA_H__
diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h
index 186cb92d1aa..5becf110b15 100644
--- a/intern/ghost/intern/GHOST_SystemNULL.h
+++ b/intern/ghost/intern/GHOST_SystemNULL.h
@@ -19,8 +19,7 @@
* Declaration of GHOST_SystemNULL class.
*/
-#ifndef __GHOST_SYSTEMNULL_H__
-#define __GHOST_SYSTEMNULL_H__
+#pragma once
#include "../GHOST_Types.h"
#include "GHOST_DisplayManagerNULL.h"
@@ -130,5 +129,3 @@ class GHOST_SystemNULL : public GHOST_System {
((glSettings.flags & GHOST_glStereoVisual) != 0));
}
};
-
-#endif /* __GHOST_SYSTEMNULL_H__ */
diff --git a/intern/ghost/intern/GHOST_SystemPaths.h b/intern/ghost/intern/GHOST_SystemPaths.h
index 04180a143cb..ab53b2813cd 100644
--- a/intern/ghost/intern/GHOST_SystemPaths.h
+++ b/intern/ghost/intern/GHOST_SystemPaths.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_SYSTEMPATHS_H__
-#define __GHOST_SYSTEMPATHS_H__
+#pragma once
#include "GHOST_ISystemPaths.h"
@@ -70,5 +69,3 @@ class GHOST_SystemPaths : public GHOST_ISystemPaths {
*/
virtual void addToSystemRecentFiles(const char *filename) const = 0;
};
-
-#endif
diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.h b/intern/ghost/intern/GHOST_SystemPathsCocoa.h
index b66379649e7..188f6f02286 100644
--- a/intern/ghost/intern/GHOST_SystemPathsCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_SYSTEMPATHSCOCOA_H__
-#define __GHOST_SYSTEMPATHSCOCOA_H__
+#pragma once
#ifndef __APPLE__
# error Apple OSX only!
@@ -67,5 +66,3 @@ class GHOST_SystemPathsCocoa : public GHOST_SystemPaths {
*/
void addToSystemRecentFiles(const char *filename) const;
};
-
-#endif // __GHOST_SYSTEMPATHSCOCOA_H__
diff --git a/intern/ghost/intern/GHOST_SystemPathsUnix.h b/intern/ghost/intern/GHOST_SystemPathsUnix.h
index f9f89f6e79b..8d2f26a28aa 100644
--- a/intern/ghost/intern/GHOST_SystemPathsUnix.h
+++ b/intern/ghost/intern/GHOST_SystemPathsUnix.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_SYSTEMPATHSUNIX_H__
-#define __GHOST_SYSTEMPATHSUNIX_H__
+#pragma once
#include "../GHOST_Types.h"
#include "GHOST_SystemPaths.h"
@@ -65,5 +64,3 @@ class GHOST_SystemPathsUnix : public GHOST_SystemPaths {
*/
void addToSystemRecentFiles(const char *filename) const;
};
-
-#endif /* __GHOST_SYSTEMPATHSUNIX_H__ */
diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.h b/intern/ghost/intern/GHOST_SystemPathsWin32.h
index f1924ea51bc..1a1eab21bad 100644
--- a/intern/ghost/intern/GHOST_SystemPathsWin32.h
+++ b/intern/ghost/intern/GHOST_SystemPathsWin32.h
@@ -21,8 +21,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_SYSTEMPATHSWIN32_H__
-#define __GHOST_SYSTEMPATHSWIN32_H__
+#pragma once
#ifndef WIN32
# error WIN32 only!
@@ -74,5 +73,3 @@ class GHOST_SystemPathsWin32 : public GHOST_SystemPaths {
*/
void addToSystemRecentFiles(const char *filename) const;
};
-
-#endif // __GHOST_SYSTEMPATHSWIN32_H__
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index 8feec9de61d..4b2c52f8282 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -19,8 +19,7 @@
* Declaration of GHOST_SystemSDL class.
*/
-#ifndef __GHOST_SYSTEMSDL_H__
-#define __GHOST_SYSTEMSDL_H__
+#pragma once
#include "../GHOST_Types.h"
#include "GHOST_DisplayManagerSDL.h"
@@ -102,5 +101,3 @@ class GHOST_SystemSDL : public GHOST_System {
/// The vector of windows that need to be updated.
std::vector<GHOST_WindowSDL *> m_dirty_windows;
};
-
-#endif
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
index 89cd3406b69..30ee7679287 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.h
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -19,8 +19,7 @@
* Declaration of GHOST_SystemWayland class.
*/
-#ifndef __GHOST_SYSTEMWAYLAND_H__
-#define __GHOST_SYSTEMWAYLAND_H__
+#pragma once
#include "../GHOST_Types.h"
#include "GHOST_System.h"
@@ -107,5 +106,3 @@ class GHOST_SystemWayland : public GHOST_System {
struct display_t *d;
std::string selection;
};
-
-#endif /* __GHOST_SYSTEMWAYLAND_H__ */
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 849aa5a96f5..db26bd6a614 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -1144,9 +1144,13 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
int r;
GetKeyboardState((PBYTE)state);
+ /* No text with control key pressed. */
+ if (state[VK_CONTROL] & 0x80) {
+ utf8_char[0] = '\0';
+ }
// Don't call ToUnicodeEx on dead keys as it clears the buffer and so won't allow diacritical
// composition.
- if (MapVirtualKeyW(vk, 2) != 0) {
+ else if (MapVirtualKeyW(vk, 2) != 0) {
// todo: ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here).
// Could be up to 24 utf8 bytes.
if ((r = ToUnicodeEx(
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 6b7901c2ade..24925b9c403 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_SystemWin32 class.
*/
-#ifndef __GHOST_SYSTEMWIN32_H__
-#define __GHOST_SYSTEMWIN32_H__
+#pragma once
#ifndef WIN32
# error WIN32 only!
@@ -488,4 +487,3 @@ inline void GHOST_SystemWin32::handleKeyboardChange(void)
}
}
}
-#endif // __GHOST_SYSTEMWIN32_H__
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 5c1f34e3a63..74bdff3812e 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -1324,7 +1324,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
int revert_to;
/* as ICCCM say, we need reply this event
- * with a SetInputFocus, the data[1] have
+ * with a #SetInputFocus, the data[1] have
* the valid timestamp (send by the wm).
*
* Some WM send this event before the
@@ -1345,7 +1345,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
else {
#ifdef WITH_XDND
/* try to handle drag event
- * (if there's no such events, GHOST_HandleClientMessage will return zero) */
+ * (if there's no such events, #GHOST_HandleClientMessage will return zero) */
if (window->getDropTarget()->GHOST_HandleClientMessage(xe) == false) {
/* Unknown client message, ignore */
}
@@ -1366,12 +1366,12 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
case EnterNotify:
case LeaveNotify: {
- /* XCrossingEvents pointer leave enter window.
- * also do cursor move here, MotionNotify only
+ /* #XCrossingEvents pointer leave enter window.
+ * also do cursor move here, #MotionNotify only
* happens when motion starts & ends inside window.
* we only do moves when the crossing mode is 'normal'
- * (really crossing between windows) since some windowmanagers
- * also send grab/ungrab crossings for mousewheel events.
+ * (really crossing between windows) since some window-managers
+ * also send grab/un-grab crossings for mouse-wheel events.
*/
XCrossingEvent &xce = xe->xcrossing;
if (xce.mode == NotifyNormal) {
@@ -1396,11 +1396,11 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
case MapNotify:
/*
* From ICCCM:
- * [ Clients can select for StructureNotify on their
+ * [ Clients can select for #StructureNotify on their
* top-level windows to track transition between
- * Normal and Iconic states. Receipt of a MapNotify
+ * Normal and Iconic states. Receipt of a #MapNotify
* event will indicate a transition to the Normal
- * state, and receipt of an UnmapNotify event will
+ * state, and receipt of an #UnmapNotify event will
* indicate a transition to the Iconic state. ]
*/
if (window->m_post_init == True) {
@@ -1441,7 +1441,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
nxe.xselection.target = xse->target;
nxe.xselection.time = xse->time;
- /* Check to see if the requestor is asking for String */
+ /* Check to see if the requester is asking for String */
if (xse->target == utf8_string || xse->target == string || xse->target == compound_text ||
xse->target == c_string) {
if (xse->selection == XInternAtom(m_display, "PRIMARY", False)) {
@@ -1487,7 +1487,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
nxe.xselection.property = None;
}
- /* Send the event to the client 0 0 == False, SelectionNotify */
+ /* Send the event to the client 0 0 == False, #SelectionNotify */
XSendEvent(m_display, xse->requestor, 0, 0, &nxe);
XFlush(m_display);
break;
@@ -1513,7 +1513,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
/* Note: This event might be generated with incomplete data-set
* (don't exactly know why, looks like in some cases, if the value does not change,
- * it is not included in subsequent XDeviceMotionEvent events).
+ * it is not included in subsequent #XDeviceMotionEvent events).
* So we have to check which values this event actually contains!
*/
@@ -1569,14 +1569,13 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
GHOST_TSuccess GHOST_SystemX11::getModifierKeys(GHOST_ModifierKeys &keys) const
{
- /* Analyze the masks returned from XQueryPointer. */
+ /* Analyze the masks returned from #XQueryPointer. */
memset((void *)m_keyboard_vector, 0, sizeof(m_keyboard_vector));
XQueryKeymap(m_display, (char *)m_keyboard_vector);
- /* now translate key symbols into keycodes and
- * test with vector. */
+ /* Now translate key symbols into key-codes and test with vector. */
const static KeyCode shift_l = XKeysymToKeycode(m_display, XK_Shift_L);
const static KeyCode shift_r = XKeysymToKeycode(m_display, XK_Shift_R);
@@ -1671,7 +1670,7 @@ GHOST_TSuccess GHOST_SystemX11::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y
{
/* This is a brute force move in screen coordinates
- * XWarpPointer does relative moves so first determine the
+ * #XWarpPointer does relative moves so first determine the
* current pointer position. */
int cx, cy;
@@ -1952,7 +1951,7 @@ void GHOST_SystemX11::getClipboard_xcout(const XEvent *evt,
switch (*context) {
/* There is no context, do an XConvertSelection() */
case XCLIB_XCOUT_NONE:
- /* Initialise return length to 0 */
+ /* Initialize return length to 0. */
if (*len > 0) {
free(*txt);
*len = 0;
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 5888605ec95..ad58138d416 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_SystemX11 class.
*/
-#ifndef __GHOST_SYSTEMX11_H__
-#define __GHOST_SYSTEMX11_H__
+#pragma once
#include <X11/XKBlib.h> /* allow detectable autorepeate */
#include <X11/Xlib.h>
@@ -392,5 +391,3 @@ class GHOST_SystemX11 : public GHOST_System {
bool generateWindowExposeEvents();
};
-
-#endif
diff --git a/intern/ghost/intern/GHOST_TaskbarWin32.h b/intern/ghost/intern/GHOST_TaskbarWin32.h
index 58641123c24..e6464f5e626 100644
--- a/intern/ghost/intern/GHOST_TaskbarWin32.h
+++ b/intern/ghost/intern/GHOST_TaskbarWin32.h
@@ -17,8 +17,7 @@
/** \file
* \ingroup GHOST
*/
-#ifndef __GHOST_TASKBARWIN32_H__
-#define __GHOST_TASKBARWIN32_H__
+#pragma once
#ifndef WIN32
# error WIN32 only!
@@ -128,5 +127,3 @@ class ITaskbarList3 : public ITaskbarList2 {
virtual HRESULT STDMETHODCALLTYPE SetThumbnailClip(HWND hwnd, RECT *prcClip) = 0;
};
#endif /* ITaskbarList3 */
-
-#endif /*__GHOST_TASKBARWIN32_H__*/
diff --git a/intern/ghost/intern/GHOST_TaskbarX11.h b/intern/ghost/intern/GHOST_TaskbarX11.h
index cd00e25106c..25de5aa9511 100644
--- a/intern/ghost/intern/GHOST_TaskbarX11.h
+++ b/intern/ghost/intern/GHOST_TaskbarX11.h
@@ -17,8 +17,7 @@
/** \file
* \ingroup GHOST
*/
-#ifndef __GHOST_TASKBARX11_H__
-#define __GHOST_TASKBARX11_H__
+#pragma once
class GHOST_TaskBarX11 {
public:
@@ -34,5 +33,3 @@ class GHOST_TaskBarX11 {
private:
void *handle;
};
-
-#endif /*__GHOST_TASKBARX11_H__*/
diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h
index 039663a7a0e..2e0f5d42230 100644
--- a/intern/ghost/intern/GHOST_TimerManager.h
+++ b/intern/ghost/intern/GHOST_TimerManager.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_TimerManager class.
*/
-#ifndef __GHOST_TIMERMANAGER_H__
-#define __GHOST_TIMERMANAGER_H__
+#pragma once
#include <vector>
@@ -112,5 +111,3 @@ class GHOST_TimerManager {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_TimerManager")
#endif
};
-
-#endif // __GHOST_TIMERMANAGER_H__
diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h
index 561d9b3e705..6dc0728e19b 100644
--- a/intern/ghost/intern/GHOST_TimerTask.h
+++ b/intern/ghost/intern/GHOST_TimerTask.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_TimerTask class.
*/
-#ifndef __GHOST_TIMERTASK_H__
-#define __GHOST_TIMERTASK_H__
+#pragma once
#include "GHOST_ITimerTask.h"
@@ -179,5 +178,3 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
/** Auxiliary storage room. */
GHOST_TUns32 m_auxData;
};
-
-#endif // __GHOST_TIMERTASK_H__
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 6738aa850ce..c8c21b2b08f 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_Window class.
*/
-#ifndef __GHOST_WINDOW_H__
-#define __GHOST_WINDOW_H__
+#pragma once
#include "GHOST_IWindow.h"
@@ -124,8 +123,8 @@ class GHOST_Window : public GHOST_IWindow {
* Set the shape of the cursor to a custom cursor.
* \param bitmap The bitmap data for the cursor.
* \param mask The mask data for the cursor.
- * \param hotX The X coordinate of the cursor hotspot.
- * \param hotY The Y coordinate of the cursor hotspot.
+ * \param hotX The X coordinate of the cursor hot-spot.
+ * \param hotY The Y coordinate of the cursor hot-spot.
* \return Indication of success.
*/
GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
@@ -456,5 +455,3 @@ inline GHOST_TStandardCursor GHOST_Window::getCursorShape() const
{
return m_cursorShape;
}
-
-#endif // _GHOST_WINDOW_H
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index 15429eab5db..97486c9e77a 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_WindowCocoa class.
*/
-#ifndef __GHOST_WINDOWCOCOA_H__
-#define __GHOST_WINDOWCOCOA_H__
+#pragma once
#ifndef __APPLE__
# error Apple OSX only!
@@ -327,5 +326,3 @@ class GHOST_WindowCocoa : public GHOST_Window {
bool m_debug_context; // for debug messages during context setup
bool m_is_dialog;
};
-
-#endif // __GHOST_WINDOWCOCOA_H__
diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h
index 661439191c5..34fdfd30f27 100644
--- a/intern/ghost/intern/GHOST_WindowManager.h
+++ b/intern/ghost/intern/GHOST_WindowManager.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_WindowManager class.
*/
-#ifndef __GHOST_WINDOWMANAGER_H__
-#define __GHOST_WINDOWMANAGER_H__
+#pragma once
#include <vector>
@@ -149,5 +148,3 @@ class GHOST_WindowManager {
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_WindowManager")
#endif
};
-
-#endif // __GHOST_WINDOWMANAGER_H__
diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h
index e1aa0cb7f13..0b5a7ee3450 100644
--- a/intern/ghost/intern/GHOST_WindowNULL.h
+++ b/intern/ghost/intern/GHOST_WindowNULL.h
@@ -19,8 +19,7 @@
* Declaration of GHOST_WindowNULL class.
*/
-#ifndef __GHOST_WINDOWNULL_H__
-#define __GHOST_WINDOWNULL_H__
+#pragma once
#include "GHOST_Window.h"
@@ -177,5 +176,3 @@ class GHOST_WindowNULL : public GHOST_Window {
return NULL;
}
};
-
-#endif // __GHOST_WINDOWNULL_H__
diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h
index 5039c742c9d..643c54c282e 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.h
+++ b/intern/ghost/intern/GHOST_WindowSDL.h
@@ -19,8 +19,7 @@
* Declaration of GHOST_WindowSDL class.
*/
-#ifndef __GHOST_WINDOWSDL_H__
-#define __GHOST_WINDOWSDL_H__
+#pragma once
#include "GHOST_SystemSDL.h"
#include "GHOST_Window.h"
@@ -149,5 +148,3 @@ class GHOST_WindowSDL : public GHOST_Window {
GHOST_TUns16 getDPIHint();
};
-
-#endif // __GHOST_WINDOWSDL_H__
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index ef02db7abc3..fe65162d168 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -180,6 +180,10 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
wl_surface_commit(w->surface);
wl_display_roundtrip(m_system->display());
+#ifdef GHOST_OPENGL_ALPHA
+ setOpaque();
+#endif
+
setState(state);
setTitle(title);
@@ -214,6 +218,10 @@ GHOST_TSuccess GHOST_WindowWayland::deactivate()
GHOST_TSuccess GHOST_WindowWayland::notify_size()
{
+#ifdef GHOST_OPENGL_ALPHA
+ setOpaque();
+#endif
+
return m_system->pushEvent(
new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowSize, this));
}
@@ -385,6 +393,19 @@ bool GHOST_WindowWayland::isDialog() const
return w->is_dialog;
}
+#ifdef GHOST_OPENGL_ALPHA
+void GHOST_WindowWayland::setOpaque() const
+{
+ struct wl_region *region;
+
+ /* Make the window opaque. */
+ region = wl_compositor_create_region(m_system->compositor());
+ wl_region_add(region, 0, 0, w->width, w->height);
+ wl_surface_set_opaque_region(w->surface, region);
+ wl_region_destroy(region);
+}
+#endif
+
/**
* \param type The type of rendering context create.
* \return Indication of success.
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h
index 23e55fcd6e4..1ee41f4d0f6 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.h
+++ b/intern/ghost/intern/GHOST_WindowWayland.h
@@ -20,8 +20,7 @@
* Declaration of GHOST_WindowWayland class.
*/
-#ifndef __GHOST_WINDOWWAYLAND_H__
-#define __GHOST_WINDOWWAYLAND_H__
+#pragma once
#include "GHOST_Window.h"
@@ -109,6 +108,10 @@ class GHOST_WindowWayland : public GHOST_Window {
bool isDialog() const override;
+#ifdef GHOST_OPENGL_ALPHA
+ void setOpaque() const;
+#endif
+
private:
GHOST_SystemWayland *m_system;
struct window_t *w;
@@ -120,5 +123,3 @@ class GHOST_WindowWayland : public GHOST_Window {
*/
GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) override;
};
-
-#endif // __GHOST_WINDOWWAYLAND_H__
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index dbed7c5ee5f..224ff53bf7b 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_WindowWin32 class.
*/
-#ifndef __GHOST_WINDOWWIN32_H__
-#define __GHOST_WINDOWWIN32_H__
+#pragma once
#ifndef WIN32
# error WIN32 only!
@@ -586,5 +585,3 @@ class GHOST_WindowWin32 : public GHOST_Window {
#endif
bool m_debug_context;
};
-
-#endif // __GHOST_WINDOWWIN32_H__
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index 4232ff40b52..ef5d1755f1a 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -22,8 +22,7 @@
* Declaration of GHOST_WindowX11 class.
*/
-#ifndef __GHOST_WINDOWX11_H__
-#define __GHOST_WINDOWX11_H__
+#pragma once
#include "GHOST_Window.h"
#include <X11/Xlib.h>
@@ -288,5 +287,3 @@ class GHOST_WindowX11 : public GHOST_Window {
void motifFullScreen(bool set);
bool motifIsFullScreen() const;
};
-
-#endif // __GHOST_WINDOWX11_H__
diff --git a/intern/ghost/intern/GHOST_XrContext.h b/intern/ghost/intern/GHOST_XrContext.h
index 9be57cd90cc..d2edb40c080 100644
--- a/intern/ghost/intern/GHOST_XrContext.h
+++ b/intern/ghost/intern/GHOST_XrContext.h
@@ -18,8 +18,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_XRCONTEXT_H__
-#define __GHOST_XRCONTEXT_H__
+#pragma once
#include <memory>
#include <vector>
@@ -131,5 +130,3 @@ class GHOST_XrContext : public GHOST_IXrContext {
GHOST_TXrGraphicsBinding determineGraphicsBindingTypeToEnable(
const GHOST_XrContextCreateInfo *create_info);
};
-
-#endif // __GHOST_XRCONTEXT_H__
diff --git a/intern/ghost/intern/GHOST_XrException.h b/intern/ghost/intern/GHOST_XrException.h
index 9f779961e4f..30c33eaf98f 100644
--- a/intern/ghost/intern/GHOST_XrException.h
+++ b/intern/ghost/intern/GHOST_XrException.h
@@ -18,8 +18,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_XREXCEPTION_H__
-#define __GHOST_XREXCEPTION_H__
+#pragma once
#include <exception>
@@ -41,5 +40,3 @@ class GHOST_XrException : public std::exception {
const char *m_msg;
int m_result;
};
-
-#endif // __GHOST_XREXCEPTION_H__
diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h
index da0128b2851..74555c0c170 100644
--- a/intern/ghost/intern/GHOST_XrSession.h
+++ b/intern/ghost/intern/GHOST_XrSession.h
@@ -18,8 +18,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_XRSESSION_H__
-#define __GHOST_XRSESSION_H__
+#pragma once
#include <map>
#include <memory>
@@ -84,5 +83,3 @@ class GHOST_XrSession {
void beginFrameDrawing();
void endFrameDrawing(std::vector<XrCompositionLayerBaseHeader *> *layers);
};
-
-#endif /* GHOST_XRSESSION_H__ */
diff --git a/intern/ghost/intern/GHOST_XrSwapchain.h b/intern/ghost/intern/GHOST_XrSwapchain.h
index 7a3e7fcea68..33a1c17b993 100644
--- a/intern/ghost/intern/GHOST_XrSwapchain.h
+++ b/intern/ghost/intern/GHOST_XrSwapchain.h
@@ -18,8 +18,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_XRSWAPCHAIN_H__
-#define __GHOST_XRSWAPCHAIN_H__
+#pragma once
#include <memory>
@@ -45,5 +44,3 @@ class GHOST_XrSwapchain {
int32_t m_image_width, m_image_height;
bool m_is_srgb_buffer = false;
};
-
-#endif // GHOST_XRSWAPCHAIN_H
diff --git a/intern/ghost/intern/GHOST_Xr_intern.h b/intern/ghost/intern/GHOST_Xr_intern.h
index d59ffd31940..137541c4528 100644
--- a/intern/ghost/intern/GHOST_Xr_intern.h
+++ b/intern/ghost/intern/GHOST_Xr_intern.h
@@ -18,8 +18,7 @@
* \ingroup GHOST
*/
-#ifndef __GHOST_XR_INTERN_H__
-#define __GHOST_XR_INTERN_H__
+#pragma once
#include <memory>
#include <vector>
@@ -46,5 +45,3 @@
(void)_res; \
} \
(void)0
-
-#endif /* __GHOST_XR_INTERN_H__ */
diff --git a/intern/ghost/intern/GHOST_Xr_openxr_includes.h b/intern/ghost/intern/GHOST_Xr_openxr_includes.h
index 9cac43b1549..d1deaeb0d1a 100644
--- a/intern/ghost/intern/GHOST_Xr_openxr_includes.h
+++ b/intern/ghost/intern/GHOST_Xr_openxr_includes.h
@@ -22,8 +22,7 @@
* installed.
*/
-#ifndef __GHOST_XR_SYSTEM_INCLUDES_H__
-#define __GHOST_XR_SYSTEM_INCLUDES_H__
+#pragma once
/* Platform headers */
#ifdef XR_USE_PLATFORM_WIN32
@@ -48,5 +47,3 @@
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>
-
-#endif /* __GHOST_XR_SYSTEM_INCLUDES_H__ */
diff --git a/intern/guardedalloc/CMakeLists.txt b/intern/guardedalloc/CMakeLists.txt
index cb24df65ba0..1ab365a376a 100644
--- a/intern/guardedalloc/CMakeLists.txt
+++ b/intern/guardedalloc/CMakeLists.txt
@@ -28,6 +28,7 @@ set(INC_SYS
)
set(SRC
+ ./intern/leak_detector.cc
./intern/mallocn.c
./intern/mallocn_guarded_impl.c
./intern/mallocn_lockfree_impl.c
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
index 55ea1d0bb70..9c62b2396f6 100644
--- a/intern/guardedalloc/MEM_guardedalloc.h
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -211,6 +211,10 @@ extern size_t (*MEM_get_peak_memory)(void) ATTR_WARN_UNUSED_RESULT;
extern const char *(*MEM_name_ptr)(void *vmemh);
#endif
+/** This should be called as early as possible in the program. When it has been called, information
+ * about memory leaks will be printed on exit. */
+void MEM_init_memleak_detection(void);
+
/* Switch allocator to slower but fully guarded mode. */
void MEM_use_guarded_allocator(void);
@@ -243,6 +247,11 @@ void MEM_use_guarded_allocator(void);
void *operator new(size_t /*count*/, void *ptr) \
{ \
return ptr; \
+ } \
+ /* This is the matching delete operator to the placement-new operator above. Both parameters \
+ * will have the same value. Without this, we get the warning C4291 on windows. */ \
+ void operator delete(void * /*ptr_to_free*/, void * /*ptr*/) \
+ { \
}
/* Needed when type includes a namespace, then the namespace should not be
diff --git a/intern/guardedalloc/intern/leak_detector.cc b/intern/guardedalloc/intern/leak_detector.cc
new file mode 100644
index 00000000000..d7b6f749742
--- /dev/null
+++ b/intern/guardedalloc/intern/leak_detector.cc
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup MEM
+ */
+
+#include "MEM_guardedalloc.h"
+#include "mallocn_intern.h"
+
+bool leak_detector_has_run = false;
+char free_after_leak_detection_message[] =
+ "Freeing memory after the leak detector has run. This can happen when using "
+ "static variables in C++ that are defined outside of functions. To fix this "
+ "error, use the 'construct on first use' idiom.";
+
+namespace {
+class MemLeakPrinter {
+ public:
+ ~MemLeakPrinter()
+ {
+ leak_detector_has_run = true;
+ const uint leaked_blocks = MEM_get_memory_blocks_in_use();
+ if (leaked_blocks == 0) {
+ return;
+ }
+ const size_t mem_in_use = MEM_get_memory_in_use();
+ printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n",
+ leaked_blocks,
+ (double)mem_in_use / 1024 / 1024);
+ MEM_printmemlist();
+ }
+};
+} // namespace
+
+void MEM_init_memleak_detection(void)
+{
+ /**
+ * This variable is constructed when this function is first called. This should happen as soon as
+ * possible when the program starts.
+ *
+ * It is destructed when the program exits. During destruction, it will print information about
+ * leaked memory blocks. Static variables are destructed in reversed order of their
+ * construction. Therefore, all static variables that own memory have to be constructed after
+ * this function has been called.
+ */
+ static MemLeakPrinter printer;
+}
diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.c b/intern/guardedalloc/intern/mallocn_guarded_impl.c
index 20dcbed7235..2c207935e43 100644
--- a/intern/guardedalloc/intern/mallocn_guarded_impl.c
+++ b/intern/guardedalloc/intern/mallocn_guarded_impl.c
@@ -198,10 +198,12 @@ print_error(const char *str, ...)
va_end(ap);
buf[sizeof(buf) - 1] = '\0';
- if (error_callback)
+ if (error_callback) {
error_callback(buf);
- else
+ }
+ else {
fputs(buf, stderr);
+ }
}
static pthread_mutex_t thread_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -261,13 +263,16 @@ void *MEM_guarded_dupallocN(const void *vmemh)
memh--;
#ifndef DEBUG_MEMDUPLINAME
- if (LIKELY(memh->alignment == 0))
+ if (LIKELY(memh->alignment == 0)) {
newp = MEM_guarded_mallocN(memh->len, "dupli_alloc");
- else
+ }
+ else {
newp = MEM_guarded_mallocN_aligned(memh->len, (size_t)memh->alignment, "dupli_alloc");
+ }
- if (newp == NULL)
+ if (newp == NULL) {
return NULL;
+ }
#else
{
MemHead *nmemh;
@@ -450,8 +455,9 @@ void *MEM_guarded_mallocN(size_t len, const char *str)
if (LIKELY(memh)) {
make_memhead_header(memh, len, str);
- if (UNLIKELY(malloc_debug_memset && len))
+ if (UNLIKELY(malloc_debug_memset && len)) {
memset(memh + 1, 255, len);
+ }
#ifdef DEBUG_MEMCOUNTER
if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
@@ -522,8 +528,9 @@ void *MEM_guarded_mallocN_aligned(size_t len, size_t alignment, const char *str)
make_memhead_header(memh, len, str);
memh->alignment = (short)alignment;
- if (UNLIKELY(malloc_debug_memset && len))
+ if (UNLIKELY(malloc_debug_memset && len)) {
memset(memh + 1, 255, len);
+ }
#ifdef DEBUG_MEMCOUNTER
if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
@@ -601,12 +608,15 @@ static int compare_len(const void *p1, const void *p2)
const MemPrintBlock *pb1 = (const MemPrintBlock *)p1;
const MemPrintBlock *pb2 = (const MemPrintBlock *)p2;
- if (pb1->len < pb2->len)
+ if (pb1->len < pb2->len) {
return 1;
- else if (pb1->len == pb2->len)
+ }
+ else if (pb1->len == pb2->len) {
return 0;
- else
+ }
+ else {
return -1;
+ }
}
void MEM_guarded_printmemlist_stats(void)
@@ -636,8 +646,9 @@ void MEM_guarded_printmemlist_stats(void)
totpb = 0;
membl = membase->first;
- if (membl)
+ if (membl) {
membl = MEMNEXT(membl);
+ }
while (membl && pb) {
pb->name = membl->name;
@@ -654,10 +665,12 @@ void MEM_guarded_printmemlist_stats(void)
}
#endif
- if (membl->next)
+ if (membl->next) {
membl = MEMNEXT(membl->next);
- else
+ }
+ else {
break;
+ }
}
/* sort by name and add together blocks with the same name */
@@ -737,8 +750,9 @@ static void MEM_guarded_printmemlist_internal(int pydict)
mem_lock_thread();
membl = membase->first;
- if (membl)
+ if (membl) {
membl = MEMNEXT(membl);
+ }
if (pydict) {
print_error("# membase_debug.py\n");
@@ -771,10 +785,12 @@ static void MEM_guarded_printmemlist_internal(int pydict)
print_memhead_backtrace(membl);
#endif
}
- if (membl->next)
+ if (membl->next) {
membl = MEMNEXT(membl->next);
- else
+ }
+ else {
break;
+ }
}
if (pydict) {
print_error("]\n\n");
@@ -791,15 +807,18 @@ void MEM_guarded_callbackmemlist(void (*func)(void *))
mem_lock_thread();
membl = membase->first;
- if (membl)
+ if (membl) {
membl = MEMNEXT(membl);
+ }
while (membl) {
func(membl + 1);
- if (membl->next)
+ if (membl->next) {
membl = MEMNEXT(membl->next);
- else
+ }
+ else {
break;
+ }
}
mem_unlock_thread();
@@ -879,6 +898,10 @@ void MEM_guarded_freeN(void *vmemh)
memt = (MemTail *)(((char *)memh) + sizeof(MemHead) + memh->len);
if (memt->tag3 == MEMTAG3) {
+ if (leak_detector_has_run) {
+ MemorY_ErroR(memh->name, free_after_leak_detection_message);
+ }
+
memh->tag1 = MEMFREE;
memh->tag2 = MEMFREE;
memt->tag3 = MEMFREE;
@@ -890,24 +913,25 @@ void MEM_guarded_freeN(void *vmemh)
MemorY_ErroR(memh->name, "end corrupt");
name = check_memlist(memh);
if (name != NULL) {
- if (name != memh->name)
+ if (name != memh->name) {
MemorY_ErroR(name, "is also corrupt");
+ }
}
}
else {
mem_lock_thread();
name = check_memlist(memh);
mem_unlock_thread();
- if (name == NULL)
+ if (name == NULL) {
MemorY_ErroR("free", "pointer not in memlist");
- else
+ }
+ else {
MemorY_ErroR(name, "error in header");
+ }
}
totblock--;
/* here a DUMP should happen */
-
- return;
}
/* --------------------------------------------------------------------- */
@@ -930,10 +954,12 @@ static void addtail(volatile localListBase *listbase, void *vlink)
link->next = NULL;
link->prev = listbase->last;
- if (listbase->last)
+ if (listbase->last) {
((struct localLink *)listbase->last)->next = link;
- if (listbase->first == NULL)
+ }
+ if (listbase->first == NULL) {
listbase->first = link;
+ }
listbase->last = link;
}
@@ -950,15 +976,19 @@ static void remlink(volatile localListBase *listbase, void *vlink)
return;
#endif
- if (link->next)
+ if (link->next) {
link->next->prev = link->prev;
- if (link->prev)
+ }
+ if (link->prev) {
link->prev->next = link->next;
+ }
- if (listbase->last == link)
+ if (listbase->last == link) {
listbase->last = link->prev;
- if (listbase->first == link)
+ }
+ if (listbase->first == link) {
listbase->first = link->next;
+ }
}
static void rem_memblock(MemHead *memh)
@@ -966,10 +996,12 @@ static void rem_memblock(MemHead *memh)
mem_lock_thread();
remlink(membase, &memh->next);
if (memh->prev) {
- if (memh->next)
+ if (memh->next) {
MEMNEXT(memh->prev)->nextname = MEMNEXT(memh->next)->name;
- else
+ }
+ else {
MEMNEXT(memh->prev)->nextname = NULL;
+ }
}
mem_unlock_thread();
@@ -981,8 +1013,9 @@ static void rem_memblock(MemHead *memh)
free((char *)memh->name);
#endif
- if (UNLIKELY(malloc_debug_memset && memh->len))
+ if (UNLIKELY(malloc_debug_memset && memh->len)) {
memset(memh + 1, 255, memh->len);
+ }
if (LIKELY(memh->alignment == 0)) {
free(memh);
}
@@ -1006,78 +1039,100 @@ static const char *check_memlist(MemHead *memh)
const char *name;
forw = membase->first;
- if (forw)
+ if (forw) {
forw = MEMNEXT(forw);
+ }
forwok = NULL;
while (forw) {
- if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2)
+ if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) {
break;
+ }
forwok = forw;
- if (forw->next)
+ if (forw->next) {
forw = MEMNEXT(forw->next);
- else
+ }
+ else {
forw = NULL;
+ }
}
back = (MemHead *)membase->last;
- if (back)
+ if (back) {
back = MEMNEXT(back);
+ }
backok = NULL;
while (back) {
- if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2)
+ if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) {
break;
+ }
backok = back;
- if (back->prev)
+ if (back->prev) {
back = MEMNEXT(back->prev);
- else
+ }
+ else {
back = NULL;
+ }
}
- if (forw != back)
+ if (forw != back) {
return ("MORE THAN 1 MEMORYBLOCK CORRUPT");
+ }
if (forw == NULL && back == NULL) {
/* no wrong headers found then but in search of memblock */
forw = membase->first;
- if (forw)
+ if (forw) {
forw = MEMNEXT(forw);
+ }
forwok = NULL;
while (forw) {
- if (forw == memh)
+ if (forw == memh) {
break;
- if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2)
+ }
+ if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) {
break;
+ }
forwok = forw;
- if (forw->next)
+ if (forw->next) {
forw = MEMNEXT(forw->next);
- else
+ }
+ else {
forw = NULL;
+ }
}
- if (forw == NULL)
+ if (forw == NULL) {
return NULL;
+ }
back = (MemHead *)membase->last;
- if (back)
+ if (back) {
back = MEMNEXT(back);
+ }
backok = NULL;
while (back) {
- if (back == memh)
+ if (back == memh) {
break;
- if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2)
+ }
+ if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) {
break;
+ }
backok = back;
- if (back->prev)
+ if (back->prev) {
back = MEMNEXT(back->prev);
- else
+ }
+ else {
back = NULL;
+ }
}
}
- if (forwok)
+ if (forwok) {
name = forwok->nextname;
- else
+ }
+ else {
name = "No name found";
+ }
if (forw == memh) {
/* to be sure but this block is removed from the list */
diff --git a/intern/guardedalloc/intern/mallocn_inline.h b/intern/guardedalloc/intern/mallocn_inline.h
index f8bb7861fc9..4e73eb9bad6 100644
--- a/intern/guardedalloc/intern/mallocn_inline.h
+++ b/intern/guardedalloc/intern/mallocn_inline.h
@@ -33,6 +33,10 @@
#ifndef __MALLOCN_INLINE_H__
#define __MALLOCN_INLINE_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
MEM_INLINE bool MEM_size_safe_multiply(size_t a, size_t b, size_t *result)
{
/* A size_t with its high-half bits all set to 1. */
@@ -52,4 +56,8 @@ MEM_INLINE bool MEM_size_safe_multiply(size_t a, size_t b, size_t *result)
return ((high_bits & (a | b)) == 0 || (*result / b == a));
}
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __MALLOCN_INLINE_H__ */
diff --git a/intern/guardedalloc/intern/mallocn_intern.h b/intern/guardedalloc/intern/mallocn_intern.h
index ef8845a66b3..8fc3e432157 100644
--- a/intern/guardedalloc/intern/mallocn_intern.h
+++ b/intern/guardedalloc/intern/mallocn_intern.h
@@ -100,11 +100,18 @@ size_t malloc_usable_size(void *ptr);
#include "mallocn_inline.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define ALIGNED_MALLOC_MINIMUM_ALIGNMENT sizeof(void *)
void *aligned_malloc(size_t size, size_t alignment);
void aligned_free(void *ptr);
+extern bool leak_detector_has_run;
+extern char free_after_leak_detection_message[];
+
/* Prototypes for counted allocator functions */
size_t MEM_lockfree_allocN_len(const void *vmemh) ATTR_WARN_UNUSED_RESULT;
void MEM_lockfree_freeN(void *vmemh);
@@ -191,4 +198,8 @@ size_t MEM_guarded_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
const char *MEM_guarded_name_ptr(void *vmemh);
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __MALLOCN_INTERN_H__ */
diff --git a/intern/guardedalloc/intern/mallocn_lockfree_impl.c b/intern/guardedalloc/intern/mallocn_lockfree_impl.c
index 205cc688d72..b71e2c963eb 100644
--- a/intern/guardedalloc/intern/mallocn_lockfree_impl.c
+++ b/intern/guardedalloc/intern/mallocn_lockfree_impl.c
@@ -101,6 +101,10 @@ size_t MEM_lockfree_allocN_len(const void *vmemh)
void MEM_lockfree_freeN(void *vmemh)
{
+ if (leak_detector_has_run) {
+ print_error("%s\n", free_after_leak_detection_message);
+ }
+
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
size_t len = MEM_lockfree_allocN_len(vmemh);
diff --git a/intern/guardedalloc/test/simpletest/memtest.c b/intern/guardedalloc/test/simpletest/memtest.c
index 5c37ceb5b24..f7a9a785f5a 100644
--- a/intern/guardedalloc/test/simpletest/memtest.c
+++ b/intern/guardedalloc/test/simpletest/memtest.c
@@ -148,7 +148,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "|\n|--* Errors were detected\n");
}
else {
- fprintf(stderr, "|\n|--* Test exited succesfully\n");
+ fprintf(stderr, "|\n|--* Test exited successfully\n");
}
fprintf(stderr, "|\n*** Finished test\n\n");
diff --git a/intern/itasc/Scene.cpp b/intern/itasc/Scene.cpp
index 5438a005d7c..0d2486ceac7 100644
--- a/intern/itasc/Scene.cpp
+++ b/intern/itasc/Scene.cpp
@@ -16,532 +16,623 @@
namespace iTaSC {
class SceneLock : public ControlledObject::JointLockCallback {
-private:
- Scene* m_scene;
- Range m_qrange;
-
-public:
- SceneLock(Scene* scene) :
- m_scene(scene), m_qrange(0,0) {}
- virtual ~SceneLock() {}
-
- void setRange(Range& range)
- {
- m_qrange = range;
- }
- // lock a joint, no need to update output
- virtual void lockJoint(unsigned int q_nr, unsigned int ndof)
- {
- q_nr += m_qrange.start;
- project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero();
- }
- // lock a joint and update output in view of reiteration
- virtual void lockJoint(unsigned int q_nr, unsigned int ndof, double* qdot)
- {
- q_nr += m_qrange.start;
- project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero();
- // update the output vector so that the movement of this joint will be
- // taken into account and we can put the joint back in its initial position
- // which means that the jacobian doesn't need to be changed
- for (unsigned int i=0 ;i<ndof ; ++i, ++q_nr) {
- m_scene->m_ydot -= m_scene->m_A.col(q_nr)*qdot[i];
- }
- }
+ private:
+ Scene *m_scene;
+ Range m_qrange;
+
+ public:
+ SceneLock(Scene *scene) : m_scene(scene), m_qrange(0, 0)
+ {
+ }
+ virtual ~SceneLock()
+ {
+ }
+
+ void setRange(Range &range)
+ {
+ m_qrange = range;
+ }
+ // lock a joint, no need to update output
+ virtual void lockJoint(unsigned int q_nr, unsigned int ndof)
+ {
+ q_nr += m_qrange.start;
+ project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero();
+ }
+ // lock a joint and update output in view of reiteration
+ virtual void lockJoint(unsigned int q_nr, unsigned int ndof, double *qdot)
+ {
+ q_nr += m_qrange.start;
+ project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero();
+ // update the output vector so that the movement of this joint will be
+ // taken into account and we can put the joint back in its initial position
+ // which means that the jacobian doesn't need to be changed
+ for (unsigned int i = 0; i < ndof; ++i, ++q_nr) {
+ m_scene->m_ydot -= m_scene->m_A.col(q_nr) * qdot[i];
+ }
+ }
};
-Scene::Scene():
- m_A(), m_B(), m_Atemp(), m_Wq(), m_Jf(), m_Jq(), m_Ju(), m_Cf(), m_Cq(), m_Jf_inv(),
- m_Vf(),m_Uf(), m_Wy(), m_ydot(), m_qdot(), m_xdot(), m_Sf(),m_tempf(),
- m_ncTotal(0),m_nqTotal(0),m_nuTotal(0),m_nsets(0),
- m_solver(NULL),m_cache(NULL)
+Scene::Scene()
+ : m_A(),
+ m_B(),
+ m_Atemp(),
+ m_Wq(),
+ m_Jf(),
+ m_Jq(),
+ m_Ju(),
+ m_Cf(),
+ m_Cq(),
+ m_Jf_inv(),
+ m_Vf(),
+ m_Uf(),
+ m_Wy(),
+ m_ydot(),
+ m_qdot(),
+ m_xdot(),
+ m_Sf(),
+ m_tempf(),
+ m_ncTotal(0),
+ m_nqTotal(0),
+ m_nuTotal(0),
+ m_nsets(0),
+ m_solver(NULL),
+ m_cache(NULL)
{
- m_minstep = 0.01;
- m_maxstep = 0.06;
+ m_minstep = 0.01;
+ m_maxstep = 0.06;
}
-Scene::~Scene()
+Scene::~Scene()
{
- ConstraintMap::iterator constraint_it;
- while ((constraint_it = constraints.begin()) != constraints.end()) {
- delete constraint_it->second;
- constraints.erase(constraint_it);
- }
- ObjectMap::iterator object_it;
- while ((object_it = objects.begin()) != objects.end()) {
- delete object_it->second;
- objects.erase(object_it);
- }
+ ConstraintMap::iterator constraint_it;
+ while ((constraint_it = constraints.begin()) != constraints.end()) {
+ delete constraint_it->second;
+ constraints.erase(constraint_it);
+ }
+ ObjectMap::iterator object_it;
+ while ((object_it = objects.begin()) != objects.end()) {
+ delete object_it->second;
+ objects.erase(object_it);
+ }
}
bool Scene::setParam(SceneParam paramId, double value)
{
- switch (paramId) {
- case MIN_TIMESTEP:
- m_minstep = value;
- break;
- case MAX_TIMESTEP:
- m_maxstep = value;
- break;
- default:
- return false;
- }
- return true;
+ switch (paramId) {
+ case MIN_TIMESTEP:
+ m_minstep = value;
+ break;
+ case MAX_TIMESTEP:
+ m_maxstep = value;
+ break;
+ default:
+ return false;
+ }
+ return true;
}
-bool Scene::addObject(const std::string& name, Object* object, UncontrolledObject* base, const std::string& baseFrame)
+bool Scene::addObject(const std::string &name,
+ Object *object,
+ UncontrolledObject *base,
+ const std::string &baseFrame)
{
- // finalize the object before adding
- if (!object->finalize())
- return false;
- //Check if Object is controlled or uncontrolled.
- if(object->getType()==Object::Controlled){
- int baseFrameIndex = base->addEndEffector(baseFrame);
- if (baseFrameIndex < 0)
- return false;
- std::pair<ObjectMap::iterator, bool> result;
- if (base->getNrOfCoordinates() == 0) {
- // base is fixed object, no coordinate range
- result = objects.insert(ObjectMap::value_type(
- name, new Object_struct(object,base,baseFrameIndex,
- Range(m_nqTotal,object->getNrOfCoordinates()),
- Range(m_ncTotal,((ControlledObject*)object)->getNrOfConstraints()),
- Range(0,0))));
- } else {
- // base is a moving object, must be in list already
- ObjectMap::iterator base_it;
- for (base_it=objects.begin(); base_it != objects.end(); base_it++) {
- if (base_it->second->object == base)
- break;
- }
- if (base_it == objects.end())
- return false;
- result = objects.insert(ObjectMap::value_type(
- name, new Object_struct(object,base,baseFrameIndex,
- Range(m_nqTotal,object->getNrOfCoordinates()),
- Range(m_ncTotal,((ControlledObject*)object)->getNrOfConstraints()),
- base_it->second->coordinaterange)));
- }
- if (!result.second) {
- return false;
- }
- m_nqTotal+=object->getNrOfCoordinates();
- m_ncTotal+=((ControlledObject*)object)->getNrOfConstraints();
- return true;
+ // finalize the object before adding
+ if (!object->finalize())
+ return false;
+ // Check if Object is controlled or uncontrolled.
+ if (object->getType() == Object::Controlled) {
+ int baseFrameIndex = base->addEndEffector(baseFrame);
+ if (baseFrameIndex < 0)
+ return false;
+ std::pair<ObjectMap::iterator, bool> result;
+ if (base->getNrOfCoordinates() == 0) {
+ // base is fixed object, no coordinate range
+ result = objects.insert(ObjectMap::value_type(
+ name,
+ new Object_struct(object,
+ base,
+ baseFrameIndex,
+ Range(m_nqTotal, object->getNrOfCoordinates()),
+ Range(m_ncTotal, ((ControlledObject *)object)->getNrOfConstraints()),
+ Range(0, 0))));
+ }
+ else {
+ // base is a moving object, must be in list already
+ ObjectMap::iterator base_it;
+ for (base_it = objects.begin(); base_it != objects.end(); base_it++) {
+ if (base_it->second->object == base)
+ break;
+ }
+ if (base_it == objects.end())
+ return false;
+ result = objects.insert(ObjectMap::value_type(
+ name,
+ new Object_struct(object,
+ base,
+ baseFrameIndex,
+ Range(m_nqTotal, object->getNrOfCoordinates()),
+ Range(m_ncTotal, ((ControlledObject *)object)->getNrOfConstraints()),
+ base_it->second->coordinaterange)));
}
- if(object->getType()==Object::UnControlled){
- if ((WorldObject*)base != &Object::world)
- return false;
- std::pair<ObjectMap::iterator,bool> result = objects.insert(ObjectMap::value_type(
- name,new Object_struct(object,base,0,
- Range(0,0),
- Range(0,0),
- Range(m_nuTotal,object->getNrOfCoordinates()))));
- if(!result.second)
- return false;
- m_nuTotal+=object->getNrOfCoordinates();
- return true;
+ if (!result.second) {
+ return false;
}
- return false;
+ m_nqTotal += object->getNrOfCoordinates();
+ m_ncTotal += ((ControlledObject *)object)->getNrOfConstraints();
+ return true;
+ }
+ if (object->getType() == Object::UnControlled) {
+ if ((WorldObject *)base != &Object::world)
+ return false;
+ std::pair<ObjectMap::iterator, bool> result = objects.insert(
+ ObjectMap::value_type(name,
+ new Object_struct(object,
+ base,
+ 0,
+ Range(0, 0),
+ Range(0, 0),
+ Range(m_nuTotal, object->getNrOfCoordinates()))));
+ if (!result.second)
+ return false;
+ m_nuTotal += object->getNrOfCoordinates();
+ return true;
+ }
+ return false;
}
-bool Scene::addConstraintSet(const std::string& name,ConstraintSet* task,const std::string& object1,const std::string& object2, const std::string& ee1, const std::string& ee2)
+bool Scene::addConstraintSet(const std::string &name,
+ ConstraintSet *task,
+ const std::string &object1,
+ const std::string &object2,
+ const std::string &ee1,
+ const std::string &ee2)
{
- //Check if objects exist:
- ObjectMap::iterator object1_it = objects.find(object1);
- ObjectMap::iterator object2_it = objects.find(object2);
- if(object1_it==objects.end()||object2_it==objects.end())
- return false;
- int ee1_index = object1_it->second->object->addEndEffector(ee1);
- int ee2_index = object2_it->second->object->addEndEffector(ee2);
- if (ee1_index < 0 || ee2_index < 0)
- return false;
- std::pair<ConstraintMap::iterator,bool> result =
- constraints.insert(ConstraintMap::value_type(name,new ConstraintSet_struct(
- task,object1_it,ee1_index,object2_it,ee2_index,
- Range(m_ncTotal,task->getNrOfConstraints()),Range(6*m_nsets,6))));
- if(!result.second)
- return false;
- m_ncTotal+=task->getNrOfConstraints();
- m_nsets+=1;
- return true;
+ // Check if objects exist:
+ ObjectMap::iterator object1_it = objects.find(object1);
+ ObjectMap::iterator object2_it = objects.find(object2);
+ if (object1_it == objects.end() || object2_it == objects.end())
+ return false;
+ int ee1_index = object1_it->second->object->addEndEffector(ee1);
+ int ee2_index = object2_it->second->object->addEndEffector(ee2);
+ if (ee1_index < 0 || ee2_index < 0)
+ return false;
+ std::pair<ConstraintMap::iterator, bool> result = constraints.insert(ConstraintMap::value_type(
+ name,
+ new ConstraintSet_struct(task,
+ object1_it,
+ ee1_index,
+ object2_it,
+ ee2_index,
+ Range(m_ncTotal, task->getNrOfConstraints()),
+ Range(6 * m_nsets, 6))));
+ if (!result.second)
+ return false;
+ m_ncTotal += task->getNrOfConstraints();
+ m_nsets += 1;
+ return true;
}
-bool Scene::addSolver(Solver* _solver){
- if(m_solver==NULL){
- m_solver=_solver;
- return true;
- }
- else
- return false;
+bool Scene::addSolver(Solver *_solver)
+{
+ if (m_solver == NULL) {
+ m_solver = _solver;
+ return true;
+ }
+ else
+ return false;
}
-bool Scene::addCache(Cache* _cache){
- if(m_cache==NULL){
- m_cache=_cache;
- return true;
- }
- else
- return false;
+bool Scene::addCache(Cache *_cache)
+{
+ if (m_cache == NULL) {
+ m_cache = _cache;
+ return true;
+ }
+ else
+ return false;
}
-bool Scene::initialize(){
-
- //prepare all matrices:
- if (m_ncTotal == 0 || m_nqTotal == 0 || m_nsets == 0)
- return false;
-
- m_A = e_zero_matrix(m_ncTotal,m_nqTotal);
- if (m_nuTotal > 0) {
- m_B = e_zero_matrix(m_ncTotal,m_nuTotal);
- m_xdot = e_zero_vector(m_nuTotal);
- m_Ju = e_zero_matrix(6*m_nsets,m_nuTotal);
- }
- m_Atemp = e_zero_matrix(m_ncTotal,6*m_nsets);
- m_ydot = e_zero_vector(m_ncTotal);
- m_qdot = e_zero_vector(m_nqTotal);
- m_Wq = e_zero_matrix(m_nqTotal,m_nqTotal);
- m_Wy = e_zero_vector(m_ncTotal);
- m_Jq = e_zero_matrix(6*m_nsets,m_nqTotal);
- m_Jf = e_zero_matrix(6*m_nsets,6*m_nsets);
- m_Jf_inv = m_Jf;
- m_Cf = e_zero_matrix(m_ncTotal,m_Jf.rows());
- m_Cq = e_zero_matrix(m_ncTotal,m_nqTotal);
-
- bool result=true;
- // finalize all objects
- for (ObjectMap::iterator it=objects.begin(); it!=objects.end(); ++it) {
- Object_struct* os = it->second;
-
- os->object->initCache(m_cache);
- if (os->constraintrange.count > 0)
- project(m_Cq,os->constraintrange,os->jointrange) = (((ControlledObject*)(os->object))->getCq());
- }
-
- m_ytask.resize(m_ncTotal);
- bool toggle=true;
- int cnt = 0;
- //Initialize all ConstraintSets:
- for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){
- //Calculate the external pose:
- ConstraintSet_struct* cs = it->second;
- Frame external_pose;
- getConstraintPose(cs->task, cs, external_pose);
- result&=cs->task->initialise(external_pose);
- cs->task->initCache(m_cache);
- for (int i=0; i<cs->constraintrange.count; i++, cnt++) {
- m_ytask[cnt] = toggle;
- }
- toggle = !toggle;
- project(m_Cf,cs->constraintrange,cs->featurerange)=cs->task->getCf();
- }
+bool Scene::initialize()
+{
- if(m_solver!=NULL)
- m_solver->init(m_nqTotal,m_ncTotal,m_ytask);
- else
- return false;
+ // prepare all matrices:
+ if (m_ncTotal == 0 || m_nqTotal == 0 || m_nsets == 0)
+ return false;
+ m_A = e_zero_matrix(m_ncTotal, m_nqTotal);
+ if (m_nuTotal > 0) {
+ m_B = e_zero_matrix(m_ncTotal, m_nuTotal);
+ m_xdot = e_zero_vector(m_nuTotal);
+ m_Ju = e_zero_matrix(6 * m_nsets, m_nuTotal);
+ }
+ m_Atemp = e_zero_matrix(m_ncTotal, 6 * m_nsets);
+ m_ydot = e_zero_vector(m_ncTotal);
+ m_qdot = e_zero_vector(m_nqTotal);
+ m_Wq = e_zero_matrix(m_nqTotal, m_nqTotal);
+ m_Wy = e_zero_vector(m_ncTotal);
+ m_Jq = e_zero_matrix(6 * m_nsets, m_nqTotal);
+ m_Jf = e_zero_matrix(6 * m_nsets, 6 * m_nsets);
+ m_Jf_inv = m_Jf;
+ m_Cf = e_zero_matrix(m_ncTotal, m_Jf.rows());
+ m_Cq = e_zero_matrix(m_ncTotal, m_nqTotal);
+
+ bool result = true;
+ // finalize all objects
+ for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) {
+ Object_struct *os = it->second;
+
+ os->object->initCache(m_cache);
+ if (os->constraintrange.count > 0)
+ project(m_Cq,
+ os->constraintrange,
+ os->jointrange) = (((ControlledObject *)(os->object))->getCq());
+ }
+
+ m_ytask.resize(m_ncTotal);
+ bool toggle = true;
+ int cnt = 0;
+ // Initialize all ConstraintSets:
+ for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) {
+ // Calculate the external pose:
+ ConstraintSet_struct *cs = it->second;
+ Frame external_pose;
+ getConstraintPose(cs->task, cs, external_pose);
+ result &= cs->task->initialise(external_pose);
+ cs->task->initCache(m_cache);
+ for (int i = 0; i < cs->constraintrange.count; i++, cnt++) {
+ m_ytask[cnt] = toggle;
+ }
+ toggle = !toggle;
+ project(m_Cf, cs->constraintrange, cs->featurerange) = cs->task->getCf();
+ }
- return result;
+ if (m_solver != NULL)
+ m_solver->init(m_nqTotal, m_ncTotal, m_ytask);
+ else
+ return false;
+
+ return result;
}
-bool Scene::getConstraintPose(ConstraintSet* constraint, void *_param, KDL::Frame& _pose)
+bool Scene::getConstraintPose(ConstraintSet *constraint, void *_param, KDL::Frame &_pose)
{
- // function called from constraint when they need to get the external pose
- ConstraintSet_struct* cs = (ConstraintSet_struct*)_param;
- // verification, the pointer MUST match
- assert (constraint == cs->task);
- Object_struct* ob1 = cs->object1->second;
- Object_struct* ob2 = cs->object2->second;
- //Calculate the external pose:
- _pose=(ob1->base->getPose(ob1->baseFrameIndex)*ob1->object->getPose(cs->ee1index)).Inverse()*(ob2->base->getPose(ob2->baseFrameIndex)*ob2->object->getPose(cs->ee2index));
- return true;
+ // function called from constraint when they need to get the external pose
+ ConstraintSet_struct *cs = (ConstraintSet_struct *)_param;
+ // verification, the pointer MUST match
+ assert(constraint == cs->task);
+ Object_struct *ob1 = cs->object1->second;
+ Object_struct *ob2 = cs->object2->second;
+ // Calculate the external pose:
+ _pose =
+ (ob1->base->getPose(ob1->baseFrameIndex) * ob1->object->getPose(cs->ee1index)).Inverse() *
+ (ob2->base->getPose(ob2->baseFrameIndex) * ob2->object->getPose(cs->ee2index));
+ return true;
}
-bool Scene::update(double timestamp, double timestep, unsigned int numsubstep, bool reiterate, bool cache, bool interpolate)
+bool Scene::update(double timestamp,
+ double timestep,
+ unsigned int numsubstep,
+ bool reiterate,
+ bool cache,
+ bool interpolate)
{
- // we must have valid timestep and timestamp
- if (timestamp < KDL::epsilon || timestep < 0.0)
- return false;
- Timestamp ts;
- ts.realTimestamp = timestamp;
- // initially we start with the full timestep to allow velocity estimation over the full interval
- ts.realTimestep = timestep;
- setCacheTimestamp(ts);
- ts.substep = 0;
- // for reiteration don't load cache
- // reiteration=additional iteration with same timestamp if application finds the convergence not good enough
- ts.reiterate = (reiterate) ? 1 : 0;
- ts.interpolate = (interpolate) ? 1 : 0;
- ts.cache = (cache) ? 1 : 0;
- ts.update = 1;
- ts.numstep = (numsubstep & 0xFF);
- bool autosubstep = (numsubstep == 0) ? true : false;
- if (numsubstep < 1)
- numsubstep = 1;
- double timesubstep = timestep/numsubstep;
- double timeleft = timestep;
-
- if (timeleft == 0.0) {
- // this special case correspond to a request to cache data
- for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it){
- it->second->object->pushCache(ts);
- }
- //Update the Constraints
- for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){
- it->second->task->pushCache(ts);
- }
- return true;
- }
-
- // double maxqdot; // UNUSED
- e_scalar nlcoef;
- SceneLock lockCallback(this);
- Frame external_pose;
- bool locked;
-
- // initially we keep timestep unchanged so that update function compute the velocity over
- while (numsubstep > 0) {
- // get objects
- for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it) {
- Object_struct* os = it->second;
- if (os->object->getType()==Object::Controlled) {
- ((ControlledObject*)(os->object))->updateControlOutput(ts);
- if (os->constraintrange.count > 0) {
- project(m_ydot, os->constraintrange) = ((ControlledObject*)(os->object))->getControlOutput();
- project(m_Wy, os->constraintrange) = ((ControlledObject*)(os->object))->getWy();
- // project(m_Cq,os->constraintrange,os->jointrange) = (((ControlledObject*)(os->object))->getCq());
- }
- if (os->jointrange.count > 0) {
- project(m_Wq,os->jointrange,os->jointrange) = ((ControlledObject*)(os->object))->getWq();
- }
- }
- if (os->object->getType()==Object::UnControlled && ((UncontrolledObject*)os->object)->getNrOfCoordinates() != 0) {
- ((UncontrolledObject*)(os->object))->updateCoordinates(ts);
- if (!ts.substep) {
- // velocity of uncontrolled object remains constant during substepping
- project(m_xdot,os->coordinaterange) = ((UncontrolledObject*)(os->object))->getXudot();
- }
- }
- }
-
- //get new Constraints values
- for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it) {
- ConstraintSet_struct* cs = it->second;
- Object_struct* ob1 = cs->object1->second;
- Object_struct* ob2 = cs->object2->second;
-
- if (ob1->base->updated() || ob1->object->updated() || ob2->base->updated() || ob2->object->updated()) {
- // the object from which the constraint depends have changed position
- // recompute the constraint pose
- getConstraintPose(cs->task, cs, external_pose);
- cs->task->initialise(external_pose);
- }
- cs->task->updateControlOutput(ts);
- project(m_ydot,cs->constraintrange)=cs->task->getControlOutput();
- if (!ts.substep || cs->task->substep()) {
- project(m_Wy,cs->constraintrange)=(cs->task)->getWy();
- //project(m_Cf,cs->constraintrange,cs->featurerange)=cs->task->getCf();
- }
-
- project(m_Jf,cs->featurerange,cs->featurerange)=cs->task->getJf();
- //std::cout << "Jf = " << Jf << std::endl;
- //Transform the reference frame of this jacobian to the world reference frame
- Eigen::Block<e_matrix> Jf_part = project(m_Jf,cs->featurerange,cs->featurerange);
- changeBase(Jf_part,ob1->base->getPose(ob1->baseFrameIndex)*ob1->object->getPose(cs->ee1index));
- //std::cout << "Jf_w = " << Jf << std::endl;
-
- //calculate the inverse of Jf
- KDL::svd_eigen_HH(project(m_Jf,cs->featurerange,cs->featurerange),m_Uf,m_Sf,m_Vf,m_tempf);
- for(unsigned int i=0;i<6;++i)
- if(m_Sf(i)<KDL::epsilon)
- m_Uf.col(i).setConstant(0.0);
- else
- m_Uf.col(i)*=(1/m_Sf(i));
- project(m_Jf_inv,cs->featurerange,cs->featurerange).noalias()=m_Vf*m_Uf.transpose();
-
- //Get the robotjacobian associated with this constraintset
- //Each jacobian is expressed in robot base frame => convert to world reference
- //and negate second robot because it is taken reversed when closing the loop:
- if(ob1->object->getType()==Object::Controlled){
- project(m_Jq,cs->featurerange,ob1->jointrange) = (((ControlledObject*)(ob1->object))->getJq(cs->ee1index));
- //Transform the reference frame of this jacobian to the world reference frame:
- Eigen::Block<e_matrix> Jq_part = project(m_Jq,cs->featurerange,ob1->jointrange);
- changeBase(Jq_part,ob1->base->getPose(ob1->baseFrameIndex));
- // if the base of this object is moving, get the Ju part
- if (ob1->base->getNrOfCoordinates() != 0) {
- // Ju is already computed for world reference frame
- project(m_Ju,cs->featurerange,ob1->coordinaterange)=ob1->base->getJu(ob1->baseFrameIndex);
- }
- } else if (ob1->object->getType() == Object::UnControlled && ((UncontrolledObject*)ob1->object)->getNrOfCoordinates() != 0) {
- // object1 is uncontrolled moving object
- project(m_Ju,cs->featurerange,ob1->coordinaterange)=((UncontrolledObject*)ob1->object)->getJu(cs->ee1index);
- }
- if(ob2->object->getType()==Object::Controlled){
- //Get the robotjacobian associated with this constraintset
- // process a special case where object2 and object1 are equal but using different end effector
- if (ob1->object == ob2->object) {
- // we must create a temporary matrix
- e_matrix JqTemp(((ControlledObject*)(ob2->object))->getJq(cs->ee2index));
- //Transform the reference frame of this jacobian to the world reference frame:
- changeBase(JqTemp,ob2->base->getPose(ob2->baseFrameIndex));
- // substract in place
- project(m_Jq,cs->featurerange,ob2->jointrange) -= JqTemp;
- } else {
- project(m_Jq,cs->featurerange,ob2->jointrange) = -(((ControlledObject*)(ob2->object))->getJq(cs->ee2index));
- //Transform the reference frame of this jacobian to the world reference frame:
- Eigen::Block<e_matrix> Jq_part = project(m_Jq,cs->featurerange,ob2->jointrange);
- changeBase(Jq_part,ob2->base->getPose(ob2->baseFrameIndex));
- }
- if (ob2->base->getNrOfCoordinates() != 0) {
- // if base is the same as first object or first object base,
- // that portion of m_Ju has been set already => substract inplace
- if (ob2->base == ob1->base || ob2->base == ob1->object) {
- project(m_Ju,cs->featurerange,ob2->coordinaterange) -= ob2->base->getJu(ob2->baseFrameIndex);
- } else {
- project(m_Ju,cs->featurerange,ob2->coordinaterange) = -ob2->base->getJu(ob2->baseFrameIndex);
- }
- }
- } else if (ob2->object->getType() == Object::UnControlled && ((UncontrolledObject*)ob2->object)->getNrOfCoordinates() != 0) {
- if (ob2->object == ob1->base || ob2->object == ob1->object) {
- project(m_Ju,cs->featurerange,ob2->coordinaterange) -= ((UncontrolledObject*)ob2->object)->getJu(cs->ee2index);
- } else {
- project(m_Ju,cs->featurerange,ob2->coordinaterange) = -((UncontrolledObject*)ob2->object)->getJu(cs->ee2index);
- }
- }
- }
-
- //Calculate A
- m_Atemp.noalias()=m_Cf*m_Jf_inv;
- m_A.noalias() = m_Cq-(m_Atemp*m_Jq);
- if (m_nuTotal > 0) {
- m_B.noalias()=m_Atemp*m_Ju;
- m_ydot.noalias() += m_B*m_xdot;
- }
-
- //Call the solver with A, Wq, Wy, ydot to solver qdot:
- if(!m_solver->solve(m_A,m_Wy,m_ydot,m_Wq,m_qdot,nlcoef))
- // this should never happen
- return false;
- //send result to the objects
- for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it) {
- Object_struct* os = it->second;
- if(os->object->getType()==Object::Controlled)
- ((ControlledObject*)(os->object))->setJointVelocity(project(m_qdot,os->jointrange));
- }
- // compute the constraint velocity
- for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){
- ConstraintSet_struct* cs = it->second;
- Object_struct* ob1 = cs->object1->second;
- Object_struct* ob2 = cs->object2->second;
- //Calculate the twist of the world reference frame due to the robots (Jq*qdot+Ju*chiudot):
- e_vector6 external_vel = e_zero_vector(6);
- if (ob1->jointrange.count > 0)
- external_vel.noalias() += (project(m_Jq,cs->featurerange,ob1->jointrange)*project(m_qdot,ob1->jointrange));
- if (ob2->jointrange.count > 0)
- external_vel.noalias() += (project(m_Jq,cs->featurerange,ob2->jointrange)*project(m_qdot,ob2->jointrange));
- if (ob1->coordinaterange.count > 0)
- external_vel.noalias() += (project(m_Ju,cs->featurerange,ob1->coordinaterange)*project(m_xdot,ob1->coordinaterange));
- if (ob2->coordinaterange.count > 0)
- external_vel.noalias() += (project(m_Ju,cs->featurerange,ob2->coordinaterange)*project(m_xdot,ob2->coordinaterange));
- //the twist caused by the constraint must be opposite because of the closed loop
- //estimate the velocity of the joints using the inverse jacobian
- e_vector6 estimated_chidot = project(m_Jf_inv,cs->featurerange,cs->featurerange)*(-external_vel);
- cs->task->setJointVelocity(estimated_chidot);
- }
-
- if (autosubstep) {
- // automatic computing of substep based on maximum joint change
- // and joint limit gain variation
- // We will pass the joint velocity to each object and they will recommend a maximum timestep
- timesubstep = timeleft;
- // get armature max joint velocity to estimate the maximum duration of integration
- // maxqdot = m_qdot.cwise().abs().maxCoeff(); // UNUSED
- double maxsubstep = nlcoef*m_maxstep;
- if (maxsubstep < m_minstep)
- maxsubstep = m_minstep;
- if (timesubstep > maxsubstep)
- timesubstep = maxsubstep;
- for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it){
- Object_struct* os = it->second;
- if(os->object->getType()==Object::Controlled)
- ((ControlledObject*)(os->object))->getMaxTimestep(timesubstep);
- }
- for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){
- ConstraintSet_struct* cs = it->second;
- cs->task->getMaxTimestep(timesubstep);
- }
- // use substep that are even dividers of timestep for more regularity
- maxsubstep = 2.0*floor(timestep/2.0/timesubstep-0.66666);
- timesubstep = (maxsubstep < 0.0) ? timestep : timestep/(2.0+maxsubstep);
- if (timesubstep >= timeleft-(m_minstep/2.0)) {
- timesubstep = timeleft;
- numsubstep = 1;
- timeleft = 0.;
- } else {
- numsubstep = 2;
- timeleft -= timesubstep;
- }
- }
- if (numsubstep > 1) {
- ts.substep = 1;
- } else {
- // set substep to false for last iteration so that controlled output
- // can be updated in updateKinematics() and model_update)() before next call to Secne::update()
- ts.substep = 0;
- }
- // change timestep so that integration is done correctly
- ts.realTimestep = timesubstep;
-
- do {
- ObjectMap::iterator it;
- Object_struct* os;
- locked = false;
- for(it=objects.begin();it!=objects.end();++it){
- os = it->second;
- if (os->object->getType()==Object::Controlled) {
- lockCallback.setRange(os->jointrange);
- if (((ControlledObject*)os->object)->updateJoint(ts, lockCallback)) {
- // this means one of the joint was locked and we must rerun
- // the solver to update the remaining joints
- locked = true;
- break;
- }
- }
- }
- if (locked) {
- // Some rows of m_Wq have been cleared so that the corresponding joint will not move
- if(!m_solver->solve(m_A,m_Wy,m_ydot,m_Wq,m_qdot,nlcoef))
- // this should never happen
- return false;
-
- //send result to the objects
- for(it=objects.begin();it!=objects.end();++it) {
- os = it->second;
- if(os->object->getType()==Object::Controlled)
- ((ControlledObject*)(os->object))->setJointVelocity(project(m_qdot,os->jointrange));
- }
- }
- } while (locked);
-
- //Update the Objects
- for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it){
- it->second->object->updateKinematics(ts);
- // mark this object not updated since the constraint will be updated anyway
- // this flag is only useful to detect external updates
- it->second->object->updated(false);
- }
- //Update the Constraints
- for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){
- ConstraintSet_struct* cs = it->second;
- //Calculate the external pose:
- getConstraintPose(cs->task, cs, external_pose);
- cs->task->modelUpdate(external_pose,ts);
- // update the constraint output and cache
- cs->task->updateKinematics(ts);
- }
- numsubstep--;
- }
- return true;
-}
+ // we must have valid timestep and timestamp
+ if (timestamp < KDL::epsilon || timestep < 0.0)
+ return false;
+ Timestamp ts;
+ ts.realTimestamp = timestamp;
+ // initially we start with the full timestep to allow velocity estimation over the full interval
+ ts.realTimestep = timestep;
+ setCacheTimestamp(ts);
+ ts.substep = 0;
+ // for reiteration don't load cache
+ // reiteration=additional iteration with same timestamp if application finds the convergence not
+ // good enough
+ ts.reiterate = (reiterate) ? 1 : 0;
+ ts.interpolate = (interpolate) ? 1 : 0;
+ ts.cache = (cache) ? 1 : 0;
+ ts.update = 1;
+ ts.numstep = (numsubstep & 0xFF);
+ bool autosubstep = (numsubstep == 0) ? true : false;
+ if (numsubstep < 1)
+ numsubstep = 1;
+ double timesubstep = timestep / numsubstep;
+ double timeleft = timestep;
+
+ if (timeleft == 0.0) {
+ // this special case correspond to a request to cache data
+ for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) {
+ it->second->object->pushCache(ts);
+ }
+ // Update the Constraints
+ for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) {
+ it->second->task->pushCache(ts);
+ }
+ return true;
+ }
+
+ // double maxqdot; // UNUSED
+ e_scalar nlcoef;
+ SceneLock lockCallback(this);
+ Frame external_pose;
+ bool locked;
+
+ // initially we keep timestep unchanged so that update function compute the velocity over
+ while (numsubstep > 0) {
+ // get objects
+ for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) {
+ Object_struct *os = it->second;
+ if (os->object->getType() == Object::Controlled) {
+ ((ControlledObject *)(os->object))->updateControlOutput(ts);
+ if (os->constraintrange.count > 0) {
+ project(m_ydot,
+ os->constraintrange) = ((ControlledObject *)(os->object))->getControlOutput();
+ project(m_Wy, os->constraintrange) = ((ControlledObject *)(os->object))->getWy();
+ // project(m_Cq,os->constraintrange,os->jointrange) =
+ // (((ControlledObject*)(os->object))->getCq());
+ }
+ if (os->jointrange.count > 0) {
+ project(
+ m_Wq, os->jointrange, os->jointrange) = ((ControlledObject *)(os->object))->getWq();
+ }
+ }
+ if (os->object->getType() == Object::UnControlled &&
+ ((UncontrolledObject *)os->object)->getNrOfCoordinates() != 0) {
+ ((UncontrolledObject *)(os->object))->updateCoordinates(ts);
+ if (!ts.substep) {
+ // velocity of uncontrolled object remains constant during substepping
+ project(m_xdot, os->coordinaterange) = ((UncontrolledObject *)(os->object))->getXudot();
+ }
+ }
+ }
+
+ // get new Constraints values
+ for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) {
+ ConstraintSet_struct *cs = it->second;
+ Object_struct *ob1 = cs->object1->second;
+ Object_struct *ob2 = cs->object2->second;
+
+ if (ob1->base->updated() || ob1->object->updated() || ob2->base->updated() ||
+ ob2->object->updated()) {
+ // the object from which the constraint depends have changed position
+ // recompute the constraint pose
+ getConstraintPose(cs->task, cs, external_pose);
+ cs->task->initialise(external_pose);
+ }
+ cs->task->updateControlOutput(ts);
+ project(m_ydot, cs->constraintrange) = cs->task->getControlOutput();
+ if (!ts.substep || cs->task->substep()) {
+ project(m_Wy, cs->constraintrange) = (cs->task)->getWy();
+ // project(m_Cf,cs->constraintrange,cs->featurerange)=cs->task->getCf();
+ }
+
+ project(m_Jf, cs->featurerange, cs->featurerange) = cs->task->getJf();
+ // std::cout << "Jf = " << Jf << std::endl;
+ // Transform the reference frame of this jacobian to the world reference frame
+ Eigen::Block<e_matrix> Jf_part = project(m_Jf, cs->featurerange, cs->featurerange);
+ changeBase(Jf_part,
+ ob1->base->getPose(ob1->baseFrameIndex) * ob1->object->getPose(cs->ee1index));
+ // std::cout << "Jf_w = " << Jf << std::endl;
+
+ // calculate the inverse of Jf
+ KDL::svd_eigen_HH(
+ project(m_Jf, cs->featurerange, cs->featurerange), m_Uf, m_Sf, m_Vf, m_tempf);
+ for (unsigned int i = 0; i < 6; ++i)
+ if (m_Sf(i) < KDL::epsilon)
+ m_Uf.col(i).setConstant(0.0);
+ else
+ m_Uf.col(i) *= (1 / m_Sf(i));
+ project(m_Jf_inv, cs->featurerange, cs->featurerange).noalias() = m_Vf * m_Uf.transpose();
+
+ // Get the robotjacobian associated with this constraintset
+ // Each jacobian is expressed in robot base frame => convert to world reference
+ // and negate second robot because it is taken reversed when closing the loop:
+ if (ob1->object->getType() == Object::Controlled) {
+ project(m_Jq,
+ cs->featurerange,
+ ob1->jointrange) = (((ControlledObject *)(ob1->object))->getJq(cs->ee1index));
+ // Transform the reference frame of this jacobian to the world reference frame:
+ Eigen::Block<e_matrix> Jq_part = project(m_Jq, cs->featurerange, ob1->jointrange);
+ changeBase(Jq_part, ob1->base->getPose(ob1->baseFrameIndex));
+ // if the base of this object is moving, get the Ju part
+ if (ob1->base->getNrOfCoordinates() != 0) {
+ // Ju is already computed for world reference frame
+ project(m_Ju, cs->featurerange, ob1->coordinaterange) = ob1->base->getJu(
+ ob1->baseFrameIndex);
+ }
+ }
+ else if (ob1->object->getType() == Object::UnControlled &&
+ ((UncontrolledObject *)ob1->object)->getNrOfCoordinates() != 0) {
+ // object1 is uncontrolled moving object
+ project(m_Ju,
+ cs->featurerange,
+ ob1->coordinaterange) = ((UncontrolledObject *)ob1->object)->getJu(cs->ee1index);
+ }
+ if (ob2->object->getType() == Object::Controlled) {
+ // Get the robotjacobian associated with this constraintset
+ // process a special case where object2 and object1 are equal but using different end
+ // effector
+ if (ob1->object == ob2->object) {
+ // we must create a temporary matrix
+ e_matrix JqTemp(((ControlledObject *)(ob2->object))->getJq(cs->ee2index));
+ // Transform the reference frame of this jacobian to the world reference frame:
+ changeBase(JqTemp, ob2->base->getPose(ob2->baseFrameIndex));
+ // subtract in place
+ project(m_Jq, cs->featurerange, ob2->jointrange) -= JqTemp;
+ }
+ else {
+ project(m_Jq, cs->featurerange, ob2->jointrange) = -(
+ ((ControlledObject *)(ob2->object))->getJq(cs->ee2index));
+ // Transform the reference frame of this jacobian to the world reference frame:
+ Eigen::Block<e_matrix> Jq_part = project(m_Jq, cs->featurerange, ob2->jointrange);
+ changeBase(Jq_part, ob2->base->getPose(ob2->baseFrameIndex));
+ }
+ if (ob2->base->getNrOfCoordinates() != 0) {
+ // if base is the same as first object or first object base,
+ // that portion of m_Ju has been set already => subtract inplace
+ if (ob2->base == ob1->base || ob2->base == ob1->object) {
+ project(m_Ju, cs->featurerange, ob2->coordinaterange) -= ob2->base->getJu(
+ ob2->baseFrameIndex);
+ }
+ else {
+ project(m_Ju, cs->featurerange, ob2->coordinaterange) = -ob2->base->getJu(
+ ob2->baseFrameIndex);
+ }
+ }
+ }
+ else if (ob2->object->getType() == Object::UnControlled &&
+ ((UncontrolledObject *)ob2->object)->getNrOfCoordinates() != 0) {
+ if (ob2->object == ob1->base || ob2->object == ob1->object) {
+ project(m_Ju, cs->featurerange, ob2->coordinaterange) -=
+ ((UncontrolledObject *)ob2->object)->getJu(cs->ee2index);
+ }
+ else {
+ project(m_Ju, cs->featurerange, ob2->coordinaterange) =
+ -((UncontrolledObject *)ob2->object)->getJu(cs->ee2index);
+ }
+ }
+ }
+
+ // Calculate A
+ m_Atemp.noalias() = m_Cf * m_Jf_inv;
+ m_A.noalias() = m_Cq - (m_Atemp * m_Jq);
+ if (m_nuTotal > 0) {
+ m_B.noalias() = m_Atemp * m_Ju;
+ m_ydot.noalias() += m_B * m_xdot;
+ }
+ // Call the solver with A, Wq, Wy, ydot to solver qdot:
+ if (!m_solver->solve(m_A, m_Wy, m_ydot, m_Wq, m_qdot, nlcoef))
+ // this should never happen
+ return false;
+ // send result to the objects
+ for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) {
+ Object_struct *os = it->second;
+ if (os->object->getType() == Object::Controlled)
+ ((ControlledObject *)(os->object))->setJointVelocity(project(m_qdot, os->jointrange));
+ }
+ // compute the constraint velocity
+ for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) {
+ ConstraintSet_struct *cs = it->second;
+ Object_struct *ob1 = cs->object1->second;
+ Object_struct *ob2 = cs->object2->second;
+ // Calculate the twist of the world reference frame due to the robots (Jq*qdot+Ju*chiudot):
+ e_vector6 external_vel = e_zero_vector(6);
+ if (ob1->jointrange.count > 0)
+ external_vel.noalias() += (project(m_Jq, cs->featurerange, ob1->jointrange) *
+ project(m_qdot, ob1->jointrange));
+ if (ob2->jointrange.count > 0)
+ external_vel.noalias() += (project(m_Jq, cs->featurerange, ob2->jointrange) *
+ project(m_qdot, ob2->jointrange));
+ if (ob1->coordinaterange.count > 0)
+ external_vel.noalias() += (project(m_Ju, cs->featurerange, ob1->coordinaterange) *
+ project(m_xdot, ob1->coordinaterange));
+ if (ob2->coordinaterange.count > 0)
+ external_vel.noalias() += (project(m_Ju, cs->featurerange, ob2->coordinaterange) *
+ project(m_xdot, ob2->coordinaterange));
+ // the twist caused by the constraint must be opposite because of the closed loop
+ // estimate the velocity of the joints using the inverse jacobian
+ e_vector6 estimated_chidot = project(m_Jf_inv, cs->featurerange, cs->featurerange) *
+ (-external_vel);
+ cs->task->setJointVelocity(estimated_chidot);
+ }
+
+ if (autosubstep) {
+ // automatic computing of substep based on maximum joint change
+ // and joint limit gain variation
+ // We will pass the joint velocity to each object and they will recommend a maximum timestep
+ timesubstep = timeleft;
+ // get armature max joint velocity to estimate the maximum duration of integration
+ // maxqdot = m_qdot.cwise().abs().maxCoeff(); // UNUSED
+ double maxsubstep = nlcoef * m_maxstep;
+ if (maxsubstep < m_minstep)
+ maxsubstep = m_minstep;
+ if (timesubstep > maxsubstep)
+ timesubstep = maxsubstep;
+ for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) {
+ Object_struct *os = it->second;
+ if (os->object->getType() == Object::Controlled)
+ ((ControlledObject *)(os->object))->getMaxTimestep(timesubstep);
+ }
+ for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) {
+ ConstraintSet_struct *cs = it->second;
+ cs->task->getMaxTimestep(timesubstep);
+ }
+ // use substep that are even dividers of timestep for more regularity
+ maxsubstep = 2.0 * floor(timestep / 2.0 / timesubstep - 0.66666);
+ timesubstep = (maxsubstep < 0.0) ? timestep : timestep / (2.0 + maxsubstep);
+ if (timesubstep >= timeleft - (m_minstep / 2.0)) {
+ timesubstep = timeleft;
+ numsubstep = 1;
+ timeleft = 0.;
+ }
+ else {
+ numsubstep = 2;
+ timeleft -= timesubstep;
+ }
+ }
+ if (numsubstep > 1) {
+ ts.substep = 1;
+ }
+ else {
+ // set substep to false for last iteration so that controlled output
+ // can be updated in updateKinematics() and model_update)() before next call to
+ // Secne::update()
+ ts.substep = 0;
+ }
+ // change timestep so that integration is done correctly
+ ts.realTimestep = timesubstep;
+
+ do {
+ ObjectMap::iterator it;
+ Object_struct *os;
+ locked = false;
+ for (it = objects.begin(); it != objects.end(); ++it) {
+ os = it->second;
+ if (os->object->getType() == Object::Controlled) {
+ lockCallback.setRange(os->jointrange);
+ if (((ControlledObject *)os->object)->updateJoint(ts, lockCallback)) {
+ // this means one of the joint was locked and we must rerun
+ // the solver to update the remaining joints
+ locked = true;
+ break;
+ }
+ }
+ }
+ if (locked) {
+ // Some rows of m_Wq have been cleared so that the corresponding joint will not move
+ if (!m_solver->solve(m_A, m_Wy, m_ydot, m_Wq, m_qdot, nlcoef))
+ // this should never happen
+ return false;
+
+ // send result to the objects
+ for (it = objects.begin(); it != objects.end(); ++it) {
+ os = it->second;
+ if (os->object->getType() == Object::Controlled)
+ ((ControlledObject *)(os->object))->setJointVelocity(project(m_qdot, os->jointrange));
+ }
+ }
+ } while (locked);
+
+ // Update the Objects
+ for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) {
+ it->second->object->updateKinematics(ts);
+ // mark this object not updated since the constraint will be updated anyway
+ // this flag is only useful to detect external updates
+ it->second->object->updated(false);
+ }
+ // Update the Constraints
+ for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) {
+ ConstraintSet_struct *cs = it->second;
+ // Calculate the external pose:
+ getConstraintPose(cs->task, cs, external_pose);
+ cs->task->modelUpdate(external_pose, ts);
+ // update the constraint output and cache
+ cs->task->updateKinematics(ts);
+ }
+ numsubstep--;
+ }
+ return true;
}
+
+} // namespace iTaSC
diff --git a/intern/libc_compat/libc_compat.c b/intern/libc_compat/libc_compat.c
index 8da3ca218af..78e387e3117 100644
--- a/intern/libc_compat/libc_compat.c
+++ b/intern/libc_compat/libc_compat.c
@@ -28,6 +28,7 @@
# if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 31)
double __exp_finite(double x);
+double __exp2_finite(double x);
double __acos_finite(double x);
double __asin_finite(double x);
double __log2_finite(double x);
@@ -35,6 +36,7 @@ double __log10_finite(double x);
double __log_finite(double x);
double __pow_finite(double x, double y);
float __expf_finite(float x);
+float __exp2f_finite(float x);
float __acosf_finite(float x);
float __asinf_finite(float x);
float __log2f_finite(float x);
@@ -47,6 +49,11 @@ double __exp_finite(double x)
return exp(x);
}
+double __exp2_finite(double x)
+{
+ return exp2(x);
+}
+
double __acos_finite(double x)
{
return acos(x);
@@ -82,6 +89,11 @@ float __expf_finite(float x)
return expf(x);
}
+float __exp2f_finite(float x)
+{
+ return exp2f(x);
+}
+
float __acosf_finite(float x)
{
return acosf(x);
diff --git a/intern/libmv/CMakeLists.txt b/intern/libmv/CMakeLists.txt
index c6078268512..5bb66649529 100644
--- a/intern/libmv/CMakeLists.txt
+++ b/intern/libmv/CMakeLists.txt
@@ -212,6 +212,8 @@ if(WITH_LIBMV)
if(WITH_GTESTS)
+ include(GTestTesting)
+
blender_add_lib(libmv_test_dataset "./libmv/multiview/test_data_sets.cc" "" "" "")
BLENDER_SRC_GTEST("libmv_predict_tracks" "./libmv/autotrack/predict_tracks_test.cc" "libmv_test_dataset;bf_intern_libmv;extern_ceres")
diff --git a/intern/libmv/libmv/simple_pipeline/pipeline.cc b/intern/libmv/libmv/simple_pipeline/pipeline.cc
index 6c8592baa00..728601f3732 100644
--- a/intern/libmv/libmv/simple_pipeline/pipeline.cc
+++ b/intern/libmv/libmv/simple_pipeline/pipeline.cc
@@ -316,8 +316,8 @@ double InternalReprojectionError(
}
LG << "Skipped " << num_skipped << " markers.";
LG << "Reprojected " << num_reprojected << " markers.";
- LG << "Total error: " << total_error;
- LG << "Average error: " << (total_error / num_reprojected) << " [pixels].";
+ LG << "Total error: " << total_error << " px";
+ LG << "Average error: " << (total_error / num_reprojected) << " px";
return total_error / num_reprojected;
}
diff --git a/intern/mantaflow/extern/manta_fluid_API.h b/intern/mantaflow/extern/manta_fluid_API.h
index 1dbfc6bdd9c..124671467f7 100644
--- a/intern/mantaflow/extern/manta_fluid_API.h
+++ b/intern/mantaflow/extern/manta_fluid_API.h
@@ -33,10 +33,10 @@ struct MANTA;
/* Fluid functions */
struct MANTA *manta_init(int *res, struct FluidModifierData *fmd);
void manta_free(struct MANTA *fluid);
-void manta_ensure_obstacle(struct MANTA *fluid, struct FluidModifierData *fmd);
-void manta_ensure_guiding(struct MANTA *fluid, struct FluidModifierData *fmd);
-void manta_ensure_invelocity(struct MANTA *fluid, struct FluidModifierData *fmd);
-void manta_ensure_outflow(struct MANTA *fluid, struct FluidModifierData *fmd);
+int manta_ensure_obstacle(struct MANTA *fluid, struct FluidModifierData *fmd);
+int manta_ensure_guiding(struct MANTA *fluid, struct FluidModifierData *fmd);
+int manta_ensure_invelocity(struct MANTA *fluid, struct FluidModifierData *fmd);
+int manta_ensure_outflow(struct MANTA *fluid, struct FluidModifierData *fmd);
int manta_write_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
int manta_write_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
int manta_write_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
@@ -77,6 +77,7 @@ int manta_get_frame(struct MANTA *fluid);
float manta_get_timestep(struct MANTA *fluid);
void manta_adapt_timestep(struct MANTA *fluid);
bool manta_needs_realloc(struct MANTA *fluid, struct FluidModifierData *fmd);
+void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd, bool flush);
/* Fluid accessors */
size_t manta_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */);
@@ -111,49 +112,19 @@ float *manta_get_phioutstatic_in(struct MANTA *fluid);
/* Smoke functions */
void manta_smoke_export_script(struct MANTA *smoke, struct FluidModifierData *fmd);
-void manta_smoke_export(struct MANTA *smoke,
- float *dt,
- float *dx,
- float **dens,
- float **react,
- float **flame,
- float **fuel,
- float **heat,
- float **vx,
- float **vy,
- float **vz,
- float **r,
- float **g,
- float **b,
- int **flags,
- float **shadow);
-void manta_smoke_turbulence_export(struct MANTA *smoke,
- float **dens,
- float **react,
- float **flame,
- float **fuel,
- float **r,
- float **g,
- float **b,
- float **tcu,
- float **tcv,
- float **tcw,
- float **tcu2,
- float **tcv2,
- float **tcw2);
void manta_smoke_get_rgba(struct MANTA *smoke, float *data, int sequential);
-void manta_smoke_turbulence_get_rgba(struct MANTA *smoke, float *data, int sequential);
+void manta_noise_get_rgba(struct MANTA *smoke, float *data, int sequential);
void manta_smoke_get_rgba_fixed_color(struct MANTA *smoke,
float color[3],
float *data,
int sequential);
-void manta_smoke_turbulence_get_rgba_fixed_color(struct MANTA *smoke,
- float color[3],
- float *data,
- int sequential);
-void manta_smoke_ensure_heat(struct MANTA *smoke, struct FluidModifierData *fmd);
-void manta_smoke_ensure_fire(struct MANTA *smoke, struct FluidModifierData *fmd);
-void manta_smoke_ensure_colors(struct MANTA *smoke, struct FluidModifierData *fmd);
+void manta_noise_get_rgba_fixed_color(struct MANTA *smoke,
+ float color[3],
+ float *data,
+ int sequential);
+int manta_smoke_ensure_heat(struct MANTA *smoke, struct FluidModifierData *fmd);
+int manta_smoke_ensure_fire(struct MANTA *smoke, struct FluidModifierData *fmd);
+int manta_smoke_ensure_colors(struct MANTA *smoke, struct FluidModifierData *fmd);
/* Smoke accessors */
float *manta_smoke_get_density(struct MANTA *smoke);
@@ -177,21 +148,27 @@ float *manta_smoke_get_emission_in(struct MANTA *smoke);
int manta_smoke_has_heat(struct MANTA *smoke);
int manta_smoke_has_fuel(struct MANTA *smoke);
int manta_smoke_has_colors(struct MANTA *smoke);
-float *manta_smoke_turbulence_get_density(struct MANTA *smoke);
-float *manta_smoke_turbulence_get_fuel(struct MANTA *smoke);
-float *manta_smoke_turbulence_get_react(struct MANTA *smoke);
-float *manta_smoke_turbulence_get_color_r(struct MANTA *smoke);
-float *manta_smoke_turbulence_get_color_g(struct MANTA *smoke);
-float *manta_smoke_turbulence_get_color_b(struct MANTA *smoke);
-float *manta_smoke_turbulence_get_flame(struct MANTA *smoke);
-int manta_smoke_turbulence_has_fuel(struct MANTA *smoke);
-int manta_smoke_turbulence_has_colors(struct MANTA *smoke);
-void manta_smoke_turbulence_get_res(struct MANTA *smoke, int *res);
-int manta_smoke_turbulence_get_cells(struct MANTA *smoke);
+float *manta_noise_get_density(struct MANTA *smoke);
+float *manta_noise_get_fuel(struct MANTA *smoke);
+float *manta_noise_get_react(struct MANTA *smoke);
+float *manta_noise_get_color_r(struct MANTA *smoke);
+float *manta_noise_get_color_g(struct MANTA *smoke);
+float *manta_noise_get_color_b(struct MANTA *smoke);
+float *manta_noise_get_texture_u(struct MANTA *smoke);
+float *manta_noise_get_texture_v(struct MANTA *smoke);
+float *manta_noise_get_texture_w(struct MANTA *smoke);
+float *manta_noise_get_texture_u2(struct MANTA *smoke);
+float *manta_noise_get_texture_v2(struct MANTA *smoke);
+float *manta_noise_get_texture_w2(struct MANTA *smoke);
+float *manta_noise_get_flame(struct MANTA *smoke);
+int manta_noise_has_fuel(struct MANTA *smoke);
+int manta_noise_has_colors(struct MANTA *smoke);
+void manta_noise_get_res(struct MANTA *smoke, int *res);
+int manta_noise_get_cells(struct MANTA *smoke);
/* Liquid functions */
void manta_liquid_export_script(struct MANTA *smoke, struct FluidModifierData *fmd);
-void manta_liquid_ensure_sndparts(struct MANTA *fluid, struct FluidModifierData *fmd);
+int manta_liquid_ensure_sndparts(struct MANTA *fluid, struct FluidModifierData *fmd);
/* Liquid accessors */
int manta_liquid_get_particle_res_x(struct MANTA *liquid);
diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp
index 43121f08f2d..586c413b044 100644
--- a/intern/mantaflow/intern/MANTA_main.cpp
+++ b/intern/mantaflow/intern/MANTA_main.cpp
@@ -27,10 +27,6 @@
#include <sstream>
#include <zlib.h>
-#if OPENVDB == 1
-# include "openvdb/openvdb.h"
-#endif
-
#include "MANTA_main.h"
#include "Python.h"
#include "fluid_script.h"
@@ -60,13 +56,6 @@ using std::to_string;
atomic<int> MANTA::solverID(0);
int MANTA::with_debug(0);
-/* Number of particles that the cache reads at once (with zlib). */
-#define PARTICLE_CHUNK 20000
-/* Number of mesh nodes that the cache reads at once (with zlib). */
-#define NODE_CHUNK 20000
-/* Number of mesh triangles that the cache reads at once (with zlib). */
-#define TRIANGLE_CHUNK 20000
-
MANTA::MANTA(int *res, FluidModifierData *fmd) : mCurrentID(++solverID)
{
if (with_debug)
@@ -96,8 +85,7 @@ MANTA::MANTA(int *res, FluidModifierData *fmd) : mCurrentID(++solverID)
mUsingInvel = (fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL);
mUsingOutflow = (fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW);
- // Simulation constants
- mTempAmb = 0; // TODO: Maybe use this later for buoyancy calculation
+ /* Simulation constants. */
mResX = res[0];
mResY = res[1];
mResZ = res[2];
@@ -105,7 +93,7 @@ MANTA::MANTA(int *res, FluidModifierData *fmd) : mCurrentID(++solverID)
mTotalCells = mResX * mResY * mResZ;
mResGuiding = fds->res;
- // Smoke low res grids
+ /* Smoke low res grids. */
mDensity = nullptr;
mShadow = nullptr;
mHeat = nullptr;
@@ -131,7 +119,7 @@ MANTA::MANTA(int *res, FluidModifierData *fmd) : mCurrentID(++solverID)
mReactIn = nullptr;
mEmissionIn = nullptr;
- // Smoke high res grids
+ /* Smoke high res grids. */
mDensityHigh = nullptr;
mFlameHigh = nullptr;
mFuelHigh = nullptr;
@@ -146,19 +134,19 @@ MANTA::MANTA(int *res, FluidModifierData *fmd) : mCurrentID(++solverID)
mTextureV2 = nullptr;
mTextureW2 = nullptr;
- // Fluid low res grids
+ /* Fluid low res grids. */
mPhiIn = nullptr;
mPhiStaticIn = nullptr;
mPhiOutIn = nullptr;
mPhiOutStaticIn = nullptr;
mPhi = nullptr;
- // Mesh
+ /* Mesh. */
mMeshNodes = nullptr;
mMeshTriangles = nullptr;
mMeshVelocities = nullptr;
- // Fluid obstacle
+ /* Fluid obstacle. */
mPhiObsIn = nullptr;
mPhiObsStaticIn = nullptr;
mNumObstacle = nullptr;
@@ -166,47 +154,48 @@ MANTA::MANTA(int *res, FluidModifierData *fmd) : mCurrentID(++solverID)
mObVelocityY = nullptr;
mObVelocityZ = nullptr;
- // Fluid guiding
+ /* Fluid guiding. */
mPhiGuideIn = nullptr;
mNumGuide = nullptr;
mGuideVelocityX = nullptr;
mGuideVelocityY = nullptr;
mGuideVelocityZ = nullptr;
- // Fluid initial velocity
+ /* Fluid initial velocity. */
mInVelocityX = nullptr;
mInVelocityY = nullptr;
mInVelocityZ = nullptr;
- // Secondary particles
+ /* Secondary particles. */
mFlipParticleData = nullptr;
mFlipParticleVelocity = nullptr;
- mSndParticleData = nullptr;
- mSndParticleVelocity = nullptr;
- mSndParticleLife = nullptr;
+ mParticleData = nullptr;
+ mParticleVelocity = nullptr;
+ mParticleLife = nullptr;
- // Cache read success indicators
+ /* Cache read success indicators. */
mFlipFromFile = false;
mMeshFromFile = false;
mParticlesFromFile = false;
- // Setup Mantaflow in Python
+ /* Setup Mantaflow in Python. */
initializeMantaflow();
- // Initializa RNA map with values that Python will need
+ /* Initializa RNA map with values that Python will need. */
initializeRNAMap(fmd);
- // Initialize Mantaflow variables in Python
- // Liquid
+ bool initSuccess = true;
+ /* Initialize Mantaflow variables in Python. */
+ /* Liquid. */
if (mUsingLiquid) {
- initDomain();
- initLiquid();
+ initSuccess &= initDomain();
+ initSuccess &= initLiquid();
if (mUsingObstacle)
- initObstacle();
+ initSuccess &= initObstacle();
if (mUsingInvel)
- initInVelocity();
+ initSuccess &= initInVelocity();
if (mUsingOutflow)
- initOutflow();
+ initSuccess &= initOutflow();
if (mUsingDrops || mUsingBubbles || mUsingFloats || mUsingTracers) {
mUpresParticle = fds->particle_scale;
@@ -215,8 +204,8 @@ MANTA::MANTA(int *res, FluidModifierData *fmd) : mCurrentID(++solverID)
mResZParticle = mUpresParticle * mResZ;
mTotalCellsParticles = mResXParticle * mResYParticle * mResZParticle;
- initSndParts();
- initLiquidSndParts();
+ initSuccess &= initSndParts();
+ initSuccess &= initLiquidSndParts();
}
if (mUsingMesh) {
@@ -226,44 +215,44 @@ MANTA::MANTA(int *res, FluidModifierData *fmd) : mCurrentID(++solverID)
mResZMesh = mUpresMesh * mResZ;
mTotalCellsMesh = mResXMesh * mResYMesh * mResZMesh;
- // Initialize Mantaflow variables in Python
- initMesh();
- initLiquidMesh();
+ /* Initialize Mantaflow variables in Python. */
+ initSuccess &= initMesh();
+ initSuccess &= initLiquidMesh();
}
if (mUsingDiffusion) {
- initCurvature();
+ initSuccess &= initCurvature();
}
if (mUsingGuiding) {
mResGuiding = (fds->guide_parent) ? fds->guide_res : fds->res;
- initGuiding();
+ initSuccess &= initGuiding();
}
if (mUsingFractions) {
- initFractions();
+ initSuccess &= initFractions();
}
}
- // Smoke
+ /* Smoke. */
if (mUsingSmoke) {
- initDomain();
- initSmoke();
+ initSuccess &= initDomain();
+ initSuccess &= initSmoke();
if (mUsingHeat)
- initHeat();
+ initSuccess &= initHeat();
if (mUsingFire)
- initFire();
+ initSuccess &= initFire();
if (mUsingColors)
- initColors();
+ initSuccess &= initColors();
if (mUsingObstacle)
- initObstacle();
+ initSuccess &= initObstacle();
if (mUsingInvel)
- initInVelocity();
+ initSuccess &= initInVelocity();
if (mUsingOutflow)
- initOutflow();
+ initSuccess &= initOutflow();
if (mUsingGuiding) {
mResGuiding = (fds->guide_parent) ? fds->guide_res : fds->res;
- initGuiding();
+ initSuccess &= initGuiding();
}
if (mUsingNoise) {
@@ -273,31 +262,33 @@ MANTA::MANTA(int *res, FluidModifierData *fmd) : mCurrentID(++solverID)
mResZNoise = amplify * mResZ;
mTotalCellsHigh = mResXNoise * mResYNoise * mResZNoise;
- // Initialize Mantaflow variables in Python
- initNoise();
- initSmokeNoise();
+ /* Initialize Mantaflow variables in Python. */
+ initSuccess &= initNoise();
+ initSuccess &= initSmokeNoise();
if (mUsingFire)
- initFireHigh();
+ initSuccess &= initFireHigh();
if (mUsingColors)
- initColorsHigh();
+ initSuccess &= initColorsHigh();
}
}
- updatePointers();
+ /* All requested initializations must not fail in constructor. */
+ BLI_assert(initSuccess);
+ updatePointers(fmd);
}
-void MANTA::initDomain(FluidModifierData *fmd)
+bool MANTA::initDomain(FluidModifierData *fmd)
{
- // Vector will hold all python commands that are to be executed
+ /* Vector will hold all python commands that are to be executed. */
vector<string> pythonCommands;
- // Set manta debug level first
+ /* Set manta debug level first. */
pythonCommands.push_back(manta_import + manta_debuglevel);
ostringstream ss;
ss << "set_manta_debuglevel(" << with_debug << ")";
pythonCommands.push_back(ss.str());
- // Now init basic fluid domain
+ /* Now init basic fluid domain. */
string tmpString = fluid_variables + fluid_solver + fluid_alloc + fluid_cache_helper +
fluid_bake_multiprocessing + fluid_bake_data + fluid_bake_noise +
fluid_bake_mesh + fluid_bake_particles + fluid_bake_guiding +
@@ -305,20 +296,20 @@ void MANTA::initDomain(FluidModifierData *fmd)
fluid_adapt_time_step + fluid_time_stepping;
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
+ return runPythonString(pythonCommands);
}
-void MANTA::initNoise(FluidModifierData *fmd)
+bool MANTA::initNoise(FluidModifierData *fmd)
{
vector<string> pythonCommands;
string tmpString = fluid_variables_noise + fluid_solver_noise;
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
+ return runPythonString(pythonCommands);
}
-void MANTA::initSmoke(FluidModifierData *fmd)
+bool MANTA::initSmoke(FluidModifierData *fmd)
{
vector<string> pythonCommands;
string tmpString = smoke_variables + smoke_alloc + smoke_adaptive_step + smoke_save_data +
@@ -326,10 +317,10 @@ void MANTA::initSmoke(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
+ return runPythonString(pythonCommands);
}
-void MANTA::initSmokeNoise(FluidModifierData *fmd)
+bool MANTA::initSmokeNoise(FluidModifierData *fmd)
{
vector<string> pythonCommands;
string tmpString = smoke_variables_noise + smoke_alloc_noise + smoke_wavelet_noise +
@@ -337,11 +328,11 @@ void MANTA::initSmokeNoise(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingNoise = true;
+ return runPythonString(pythonCommands);
}
-void MANTA::initHeat(FluidModifierData *fmd)
+bool MANTA::initHeat(FluidModifierData *fmd)
{
if (!mHeat) {
vector<string> pythonCommands;
@@ -349,12 +340,13 @@ void MANTA::initHeat(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingHeat = true;
+ return runPythonString(pythonCommands);
}
+ return false;
}
-void MANTA::initFire(FluidModifierData *fmd)
+bool MANTA::initFire(FluidModifierData *fmd)
{
if (!mFuel) {
vector<string> pythonCommands;
@@ -362,12 +354,13 @@ void MANTA::initFire(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingFire = true;
+ return runPythonString(pythonCommands);
}
+ return false;
}
-void MANTA::initFireHigh(FluidModifierData *fmd)
+bool MANTA::initFireHigh(FluidModifierData *fmd)
{
if (!mFuelHigh) {
vector<string> pythonCommands;
@@ -375,12 +368,13 @@ void MANTA::initFireHigh(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingFire = true;
+ return runPythonString(pythonCommands);
}
+ return false;
}
-void MANTA::initColors(FluidModifierData *fmd)
+bool MANTA::initColors(FluidModifierData *fmd)
{
if (!mColorR) {
vector<string> pythonCommands;
@@ -388,12 +382,13 @@ void MANTA::initColors(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingColors = true;
+ return runPythonString(pythonCommands);
}
+ return false;
}
-void MANTA::initColorsHigh(FluidModifierData *fmd)
+bool MANTA::initColorsHigh(FluidModifierData *fmd)
{
if (!mColorRHigh) {
vector<string> pythonCommands;
@@ -401,12 +396,13 @@ void MANTA::initColorsHigh(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingColors = true;
+ return runPythonString(pythonCommands);
}
+ return false;
}
-void MANTA::initLiquid(FluidModifierData *fmd)
+bool MANTA::initLiquid(FluidModifierData *fmd)
{
if (!mPhiIn) {
vector<string> pythonCommands;
@@ -415,44 +411,45 @@ void MANTA::initLiquid(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingLiquid = true;
+ return runPythonString(pythonCommands);
}
+ return false;
}
-void MANTA::initMesh(FluidModifierData *fmd)
+bool MANTA::initMesh(FluidModifierData *fmd)
{
vector<string> pythonCommands;
string tmpString = fluid_variables_mesh + fluid_solver_mesh + liquid_load_mesh;
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingMesh = true;
+ return runPythonString(pythonCommands);
}
-void MANTA::initLiquidMesh(FluidModifierData *fmd)
+bool MANTA::initLiquidMesh(FluidModifierData *fmd)
{
vector<string> pythonCommands;
string tmpString = liquid_alloc_mesh + liquid_step_mesh + liquid_save_mesh;
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingMesh = true;
+ return runPythonString(pythonCommands);
}
-void MANTA::initCurvature(FluidModifierData *fmd)
+bool MANTA::initCurvature(FluidModifierData *fmd)
{
std::vector<std::string> pythonCommands;
std::string finalString = parseScript(liquid_alloc_curvature, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingDiffusion = true;
+ return runPythonString(pythonCommands);
}
-void MANTA::initObstacle(FluidModifierData *fmd)
+bool MANTA::initObstacle(FluidModifierData *fmd)
{
if (!mPhiObsIn) {
vector<string> pythonCommands;
@@ -460,12 +457,13 @@ void MANTA::initObstacle(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingObstacle = true;
+ return runPythonString(pythonCommands);
}
+ return false;
}
-void MANTA::initGuiding(FluidModifierData *fmd)
+bool MANTA::initGuiding(FluidModifierData *fmd)
{
if (!mPhiGuideIn) {
vector<string> pythonCommands;
@@ -474,23 +472,24 @@ void MANTA::initGuiding(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingGuiding = true;
+ return runPythonString(pythonCommands);
}
+ return false;
}
-void MANTA::initFractions(FluidModifierData *fmd)
+bool MANTA::initFractions(FluidModifierData *fmd)
{
vector<string> pythonCommands;
string tmpString = fluid_alloc_fractions + fluid_with_fractions;
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingFractions = true;
+ return runPythonString(pythonCommands);
}
-void MANTA::initInVelocity(FluidModifierData *fmd)
+bool MANTA::initInVelocity(FluidModifierData *fmd)
{
if (!mInVelocityX) {
vector<string> pythonCommands;
@@ -498,12 +497,13 @@ void MANTA::initInVelocity(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingInvel = true;
+ return runPythonString(pythonCommands);
}
+ return false;
}
-void MANTA::initOutflow(FluidModifierData *fmd)
+bool MANTA::initOutflow(FluidModifierData *fmd)
{
if (!mPhiOutIn) {
vector<string> pythonCommands;
@@ -511,24 +511,25 @@ void MANTA::initOutflow(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
mUsingOutflow = true;
+ return runPythonString(pythonCommands);
}
+ return false;
}
-void MANTA::initSndParts(FluidModifierData *fmd)
+bool MANTA::initSndParts(FluidModifierData *fmd)
{
vector<string> pythonCommands;
string tmpString = fluid_variables_particles + fluid_solver_particles;
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
+ return runPythonString(pythonCommands);
}
-void MANTA::initLiquidSndParts(FluidModifierData *fmd)
+bool MANTA::initLiquidSndParts(FluidModifierData *fmd)
{
- if (!mSndParticleData) {
+ if (!mParticleData) {
vector<string> pythonCommands;
string tmpString = liquid_alloc_particles + liquid_variables_particles +
liquid_step_particles + fluid_with_sndparts + liquid_load_particles +
@@ -536,8 +537,9 @@ void MANTA::initLiquidSndParts(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- runPythonString(pythonCommands);
+ return runPythonString(pythonCommands);
}
+ return false;
}
MANTA::~MANTA()
@@ -546,7 +548,7 @@ MANTA::~MANTA()
cout << "~FLUID: " << mCurrentID << " with res(" << mResX << ", " << mResY << ", " << mResZ
<< ")" << endl;
- // Destruction string for Python
+ /* Destruction string for Python. */
string tmpString = "";
vector<string> pythonCommands;
bool result = false;
@@ -554,10 +556,10 @@ MANTA::~MANTA()
tmpString += manta_import;
tmpString += fluid_delete_all;
- // Initializa RNA map with values that Python will need
+ /* Initializa RNA map with values that Python will need. */
initializeRNAMap();
- // Leave out fmd argument in parseScript since only looking up IDs
+ /* Leave out fmd argument in parseScript since only looking up IDs. */
string finalString = parseScript(tmpString);
pythonCommands.push_back(finalString);
result = runPythonString(pythonCommands);
@@ -619,10 +621,10 @@ void MANTA::initializeMantaflow()
string filename = "manta_scene_" + to_string(mCurrentID) + ".py";
vector<string> fill = vector<string>();
- // Initialize extension classes and wrappers
+ /* Initialize extension classes and wrappers. */
srand(0);
PyGILState_STATE gilstate = PyGILState_Ensure();
- Pb::setup(filename, fill); // Namespace from Mantaflow (registry)
+ Pb::setup(filename, fill); /* Namespace from Mantaflow (registry). */
PyGILState_Release(gilstate);
}
@@ -632,7 +634,7 @@ void MANTA::terminateMantaflow()
cout << "Fluid: Releasing Mantaflow framework" << endl;
PyGILState_STATE gilstate = PyGILState_Ensure();
- Pb::finalize(); // Namespace from Mantaflow (registry)
+ Pb::finalize(); /* Namespace from Mantaflow (registry). */
PyGILState_Release(gilstate);
}
@@ -870,12 +872,13 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd)
mRNAMap["GUIDING_ALPHA"] = to_string(fds->guide_alpha);
mRNAMap["GUIDING_BETA"] = to_string(fds->guide_beta);
mRNAMap["GUIDING_FACTOR"] = to_string(fds->guide_vel_factor);
- mRNAMap["GRAVITY_X"] = to_string(fds->gravity[0]);
- mRNAMap["GRAVITY_Y"] = to_string(fds->gravity[1]);
- mRNAMap["GRAVITY_Z"] = to_string(fds->gravity[2]);
+ mRNAMap["GRAVITY_X"] = to_string(fds->gravity_final[0]);
+ mRNAMap["GRAVITY_Y"] = to_string(fds->gravity_final[1]);
+ mRNAMap["GRAVITY_Z"] = to_string(fds->gravity_final[2]);
mRNAMap["CACHE_DIR"] = cacheDirectory;
mRNAMap["COMPRESSION_OPENVDB"] = vdbCompressionMethod;
mRNAMap["PRECISION_OPENVDB"] = vdbPrecisionHalf;
+ mRNAMap["PP_PARTICLE_MAXIMUM"] = to_string(fds->sys_particle_maximum);
/* Fluid object names. */
mRNAMap["NAME_FLAGS"] = FLUID_NAME_FLAGS;
@@ -1072,7 +1075,7 @@ string MANTA::parseScript(const string &setup_string, FluidModifierData *fmd)
ostringstream res;
string line = "";
- // Update RNA map if modifier data is handed over
+ /* Update RNA map if modifier data is handed over. */
if (fmd) {
initializeRNAMap(fmd);
}
@@ -1110,7 +1113,8 @@ bool MANTA::writeConfiguration(FluidModifierData *fmd, int framenr)
/* Create 'config' subdir if it does not exist already. */
BLI_dir_create_recursive(directory.c_str());
- gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "wb1"); // do some compression
+ /* Open new file with some compression. */
+ gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "wb1");
if (!gzf) {
cerr << "Fluid Error -- Cannot open file " << file << endl;
return false;
@@ -1256,6 +1260,7 @@ bool MANTA::readData(FluidModifierData *fmd, int framenr, bool resumable)
<< ", '" << volume_format << "', " << resumable_cache << ")";
pythonCommands.push_back(ss.str());
result &= runPythonString(pythonCommands);
+ return (mSmokeFromFile = result);
}
if (mUsingLiquid) {
ss.str("");
@@ -1263,6 +1268,7 @@ bool MANTA::readData(FluidModifierData *fmd, int framenr, bool resumable)
<< ", '" << volume_format << "', " << resumable_cache << ")";
pythonCommands.push_back(ss.str());
result &= runPythonString(pythonCommands);
+ return (mFlipFromFile = result);
}
return result;
}
@@ -1296,7 +1302,7 @@ bool MANTA::readNoise(FluidModifierData *fmd, int framenr, bool resumable)
<< ", '" << volume_format << "', " << resumable_cache << ")";
pythonCommands.push_back(ss.str());
- return runPythonString(pythonCommands);
+ return (mNoiseFromFile = runPythonString(pythonCommands));
}
bool MANTA::readMesh(FluidModifierData *fmd, int framenr)
@@ -1331,7 +1337,7 @@ bool MANTA::readMesh(FluidModifierData *fmd, int framenr)
pythonCommands.push_back(ss.str());
}
- return runPythonString(pythonCommands);
+ return (mMeshFromFile = runPythonString(pythonCommands));
}
bool MANTA::readParticles(FluidModifierData *fmd, int framenr, bool resumable)
@@ -1365,7 +1371,7 @@ bool MANTA::readParticles(FluidModifierData *fmd, int framenr, bool resumable)
<< framenr << ", '" << volume_format << "', " << resumable_cache << ")";
pythonCommands.push_back(ss.str());
- return runPythonString(pythonCommands);
+ return (mParticlesFromFile = runPythonString(pythonCommands));
}
bool MANTA::readGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain)
@@ -1612,10 +1618,10 @@ void MANTA::exportSmokeScript(FluidModifierData *fmd)
string manta_script;
- // Libraries
+ /* Libraries. */
manta_script += header_libraries + manta_import;
- // Variables
+ /* Variables. */
manta_script += header_variables + fluid_variables + smoke_variables;
if (noise) {
manta_script += fluid_variables_noise + smoke_variables_noise;
@@ -1623,14 +1629,14 @@ void MANTA::exportSmokeScript(FluidModifierData *fmd)
if (guiding)
manta_script += fluid_variables_guiding;
- // Solvers
+ /* Solvers. */
manta_script += header_solvers + fluid_solver;
if (noise)
manta_script += fluid_solver_noise;
if (guiding)
manta_script += fluid_solver_guiding;
- // Grids
+ /* Grids. */
manta_script += header_grids + fluid_alloc + smoke_alloc;
if (noise) {
manta_script += smoke_alloc_noise;
@@ -1654,36 +1660,36 @@ void MANTA::exportSmokeScript(FluidModifierData *fmd)
if (outflow)
manta_script += fluid_alloc_outflow;
- // Noise field
+ /* Noise field. */
if (noise)
manta_script += smoke_wavelet_noise;
- // Time
+ /* Time. */
manta_script += header_time + fluid_time_stepping + fluid_adapt_time_step;
- // Import
+ /* Import. */
manta_script += header_import + fluid_file_import + fluid_cache_helper + smoke_load_data;
if (noise)
manta_script += smoke_load_noise;
if (guiding)
manta_script += fluid_load_guiding;
- // Pre/Post Steps
+ /* Pre/Post Steps. */
manta_script += header_prepost + fluid_pre_step + fluid_post_step;
- // Steps
+ /* Steps. */
manta_script += header_steps + smoke_adaptive_step + smoke_step;
if (noise) {
manta_script += smoke_step_noise;
}
- // Main
+ /* Main. */
manta_script += header_main + smoke_standalone + fluid_standalone;
- // Fill in missing variables in script
+ /* Fill in missing variables in script. */
string final_script = MANTA::parseScript(manta_script, fmd);
- // Write script
+ /* Write script. */
ofstream myfile;
myfile.open(cacheDirScript);
myfile << final_script;
@@ -1722,10 +1728,10 @@ void MANTA::exportLiquidScript(FluidModifierData *fmd)
string manta_script;
- // Libraries
+ /* Libraries. */
manta_script += header_libraries + manta_import;
- // Variables
+ /* Variables. */
manta_script += header_variables + fluid_variables + liquid_variables;
if (mesh)
manta_script += fluid_variables_mesh;
@@ -1734,7 +1740,7 @@ void MANTA::exportLiquidScript(FluidModifierData *fmd)
if (guiding)
manta_script += fluid_variables_guiding;
- // Solvers
+ /* Solvers. */
manta_script += header_solvers + fluid_solver;
if (mesh)
manta_script += fluid_solver_mesh;
@@ -1743,7 +1749,7 @@ void MANTA::exportLiquidScript(FluidModifierData *fmd)
if (guiding)
manta_script += fluid_solver_guiding;
- // Grids
+ /* Grids. */
manta_script += header_grids + fluid_alloc + liquid_alloc;
if (mesh)
manta_script += liquid_alloc_mesh;
@@ -1760,13 +1766,13 @@ void MANTA::exportLiquidScript(FluidModifierData *fmd)
if (outflow)
manta_script += fluid_alloc_outflow;
- // Domain init
+ /* Domain init. */
manta_script += header_gridinit + liquid_init_phi;
- // Time
+ /* Time. */
manta_script += header_time + fluid_time_stepping + fluid_adapt_time_step;
- // Import
+ /* Import. */
manta_script += header_import + fluid_file_import + fluid_cache_helper + liquid_load_data;
if (mesh)
manta_script += liquid_load_mesh;
@@ -1775,23 +1781,23 @@ void MANTA::exportLiquidScript(FluidModifierData *fmd)
if (guiding)
manta_script += fluid_load_guiding;
- // Pre/Post Steps
+ /* Pre/Post Steps. */
manta_script += header_prepost + fluid_pre_step + fluid_post_step;
- // Steps
+ /* Steps. */
manta_script += header_steps + liquid_adaptive_step + liquid_step;
if (mesh)
manta_script += liquid_step_mesh;
if (drops || bubble || floater || tracer)
manta_script += liquid_step_particles;
- // Main
+ /* Main. */
manta_script += header_main + liquid_standalone + fluid_standalone;
- // Fill in missing variables in script
+ /* Fill in missing variables in script. */
string final_script = MANTA::parseScript(manta_script, fmd);
- // Write script
+ /* Write script. */
ofstream myfile;
myfile.open(cacheDirScript);
myfile << final_script;
@@ -1820,12 +1826,18 @@ static PyObject *callPythonFunction(string varName, string functionName, bool is
/* Be sure to initialize Python before using it. */
Py_Initialize();
- // Get pyobject that holds result value
+ /* Get pyobject that holds result value. */
if (!manta_main_module) {
PyGILState_Release(gilstate);
return nullptr;
}
+ /* Ensure that requested variable is present in module - avoid attribute errors later on. */
+ if (!PyObject_HasAttrString(manta_main_module, varName.c_str())) {
+ PyGILState_Release(gilstate);
+ return nullptr;
+ }
+
var = PyObject_GetAttrString(manta_main_module, varName.c_str());
if (!var) {
PyGILState_Release(gilstate);
@@ -1908,6 +1920,11 @@ static long pyObjectToLong(PyObject *inputObject)
return result;
}
+template<class T> static T *getPointer(string pyObjectName, string pyFunctionName)
+{
+ return static_cast<T *>(pyObjectToPointer(callPythonFunction(pyObjectName, pyFunctionName)));
+}
+
int MANTA::getFrame()
{
if (with_debug)
@@ -1952,137 +1969,137 @@ void MANTA::adaptTimestep()
runPythonString(pythonCommands);
}
-void MANTA::updatePointers()
+void MANTA::updatePointers(FluidModifierData *fmd, bool flush)
{
if (with_debug)
cout << "MANTA::updatePointers()" << endl;
+ FluidDomainSettings *fds = fmd->domain;
+
+ bool liquid = !flush && (fds->type == FLUID_DOMAIN_TYPE_LIQUID);
+ bool smoke = !flush && (fds->type == FLUID_DOMAIN_TYPE_GAS);
+ bool noise = !flush && smoke && fds->flags & FLUID_DOMAIN_USE_NOISE;
+ bool heat = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT;
+ bool colors = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS;
+ bool fire = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE;
+ bool obstacle = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
+ bool guiding = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
+ bool invel = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
+ bool outflow = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
+ bool drops = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY;
+ bool bubble = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE;
+ bool floater = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM;
+ bool tracer = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER;
+ bool parts = !flush && liquid && (drops | bubble | floater | tracer);
+ bool mesh = !flush && liquid && fds->flags & FLUID_DOMAIN_USE_MESH;
+ bool meshvel = !flush && liquid && mesh && fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS;
+
string func = "getDataPointer";
string funcNodes = "getNodesDataPointer";
string funcTris = "getTrisDataPointer";
string id = to_string(mCurrentID);
- string solver = "s" + id;
- string parts = "pp" + id;
- string snd = "sp" + id;
- string mesh = "sm" + id;
- string mesh2 = "mesh" + id;
- string noise = "sn" + id;
- string solver_ext = "_" + solver;
- string parts_ext = "_" + parts;
- string snd_ext = "_" + snd;
- string mesh_ext = "_" + mesh;
- string mesh_ext2 = "_" + mesh2;
- string noise_ext = "_" + noise;
-
- mFlags = (int *)pyObjectToPointer(callPythonFunction("flags" + solver_ext, func));
- mPhiIn = (float *)pyObjectToPointer(callPythonFunction("phiIn" + solver_ext, func));
- mPhiStaticIn = (float *)pyObjectToPointer(callPythonFunction("phiSIn" + solver_ext, func));
- mVelocityX = (float *)pyObjectToPointer(callPythonFunction("x_vel" + solver_ext, func));
- mVelocityY = (float *)pyObjectToPointer(callPythonFunction("y_vel" + solver_ext, func));
- mVelocityZ = (float *)pyObjectToPointer(callPythonFunction("z_vel" + solver_ext, func));
- mForceX = (float *)pyObjectToPointer(callPythonFunction("x_force" + solver_ext, func));
- mForceY = (float *)pyObjectToPointer(callPythonFunction("y_force" + solver_ext, func));
- mForceZ = (float *)pyObjectToPointer(callPythonFunction("z_force" + solver_ext, func));
-
- if (mUsingOutflow) {
- mPhiOutIn = (float *)pyObjectToPointer(callPythonFunction("phiOutIn" + solver_ext, func));
- mPhiOutStaticIn = (float *)pyObjectToPointer(
- callPythonFunction("phiOutSIn" + solver_ext, func));
- }
- if (mUsingObstacle) {
- mPhiObsIn = (float *)pyObjectToPointer(callPythonFunction("phiObsIn" + solver_ext, func));
- mPhiObsStaticIn = (float *)pyObjectToPointer(
- callPythonFunction("phiObsSIn" + solver_ext, func));
- mObVelocityX = (float *)pyObjectToPointer(callPythonFunction("x_obvel" + solver_ext, func));
- mObVelocityY = (float *)pyObjectToPointer(callPythonFunction("y_obvel" + solver_ext, func));
- mObVelocityZ = (float *)pyObjectToPointer(callPythonFunction("z_obvel" + solver_ext, func));
- mNumObstacle = (float *)pyObjectToPointer(callPythonFunction("numObs" + solver_ext, func));
- }
- if (mUsingGuiding) {
- mPhiGuideIn = (float *)pyObjectToPointer(callPythonFunction("phiGuideIn" + solver_ext, func));
- mGuideVelocityX = (float *)pyObjectToPointer(
- callPythonFunction("x_guidevel" + solver_ext, func));
- mGuideVelocityY = (float *)pyObjectToPointer(
- callPythonFunction("y_guidevel" + solver_ext, func));
- mGuideVelocityZ = (float *)pyObjectToPointer(
- callPythonFunction("z_guidevel" + solver_ext, func));
- mNumGuide = (float *)pyObjectToPointer(callPythonFunction("numGuides" + solver_ext, func));
- }
- if (mUsingInvel) {
- mInVelocityX = (float *)pyObjectToPointer(callPythonFunction("x_invel" + solver_ext, func));
- mInVelocityY = (float *)pyObjectToPointer(callPythonFunction("y_invel" + solver_ext, func));
- mInVelocityZ = (float *)pyObjectToPointer(callPythonFunction("z_invel" + solver_ext, func));
- }
- if (mUsingSmoke) {
- mDensity = (float *)pyObjectToPointer(callPythonFunction("density" + solver_ext, func));
- mDensityIn = (float *)pyObjectToPointer(callPythonFunction("densityIn" + solver_ext, func));
- mShadow = (float *)pyObjectToPointer(callPythonFunction("shadow" + solver_ext, func));
- mEmissionIn = (float *)pyObjectToPointer(callPythonFunction("emissionIn" + solver_ext, func));
- }
- if (mUsingSmoke && mUsingHeat) {
- mHeat = (float *)pyObjectToPointer(callPythonFunction("heat" + solver_ext, func));
- mHeatIn = (float *)pyObjectToPointer(callPythonFunction("heatIn" + solver_ext, func));
- }
- if (mUsingSmoke && mUsingFire) {
- mFlame = (float *)pyObjectToPointer(callPythonFunction("flame" + solver_ext, func));
- mFuel = (float *)pyObjectToPointer(callPythonFunction("fuel" + solver_ext, func));
- mReact = (float *)pyObjectToPointer(callPythonFunction("react" + solver_ext, func));
- mFuelIn = (float *)pyObjectToPointer(callPythonFunction("fuelIn" + solver_ext, func));
- mReactIn = (float *)pyObjectToPointer(callPythonFunction("reactIn" + solver_ext, func));
- }
- if (mUsingSmoke && mUsingColors) {
- mColorR = (float *)pyObjectToPointer(callPythonFunction("color_r" + solver_ext, func));
- mColorG = (float *)pyObjectToPointer(callPythonFunction("color_g" + solver_ext, func));
- mColorB = (float *)pyObjectToPointer(callPythonFunction("color_b" + solver_ext, func));
- mColorRIn = (float *)pyObjectToPointer(callPythonFunction("color_r_in" + solver_ext, func));
- mColorGIn = (float *)pyObjectToPointer(callPythonFunction("color_g_in" + solver_ext, func));
- mColorBIn = (float *)pyObjectToPointer(callPythonFunction("color_b_in" + solver_ext, func));
- }
- if (mUsingSmoke && mUsingNoise) {
- mDensityHigh = (float *)pyObjectToPointer(callPythonFunction("density" + noise_ext, func));
- mTextureU = (float *)pyObjectToPointer(callPythonFunction("texture_u" + solver_ext, func));
- mTextureV = (float *)pyObjectToPointer(callPythonFunction("texture_v" + solver_ext, func));
- mTextureW = (float *)pyObjectToPointer(callPythonFunction("texture_w" + solver_ext, func));
- mTextureU2 = (float *)pyObjectToPointer(callPythonFunction("texture_u2" + solver_ext, func));
- mTextureV2 = (float *)pyObjectToPointer(callPythonFunction("texture_v2" + solver_ext, func));
- mTextureW2 = (float *)pyObjectToPointer(callPythonFunction("texture_w2" + solver_ext, func));
- }
- if (mUsingSmoke && mUsingNoise && mUsingFire) {
- mFlameHigh = (float *)pyObjectToPointer(callPythonFunction("flame" + noise_ext, func));
- mFuelHigh = (float *)pyObjectToPointer(callPythonFunction("fuel" + noise_ext, func));
- mReactHigh = (float *)pyObjectToPointer(callPythonFunction("react" + noise_ext, func));
- }
- if (mUsingSmoke && mUsingNoise && mUsingColors) {
- mColorRHigh = (float *)pyObjectToPointer(callPythonFunction("color_r" + noise_ext, func));
- mColorGHigh = (float *)pyObjectToPointer(callPythonFunction("color_g" + noise_ext, func));
- mColorBHigh = (float *)pyObjectToPointer(callPythonFunction("color_b" + noise_ext, func));
- }
- if (mUsingLiquid) {
- mPhi = (float *)pyObjectToPointer(callPythonFunction("phi" + solver_ext, func));
- mFlipParticleData = (vector<pData> *)pyObjectToPointer(
- callPythonFunction("pp" + solver_ext, func));
- mFlipParticleVelocity = (vector<pVel> *)pyObjectToPointer(
- callPythonFunction("pVel" + parts_ext, func));
- }
- if (mUsingLiquid && mUsingMesh) {
- mMeshNodes = (vector<Node> *)pyObjectToPointer(
- callPythonFunction("mesh" + mesh_ext, funcNodes));
- mMeshTriangles = (vector<Triangle> *)pyObjectToPointer(
- callPythonFunction("mesh" + mesh_ext, funcTris));
- }
- if (mUsingLiquid && mUsingMVel) {
- mMeshVelocities = (vector<pVel> *)pyObjectToPointer(
- callPythonFunction("mVel" + mesh_ext2, func));
- }
- if (mUsingLiquid && (mUsingDrops | mUsingBubbles | mUsingFloats | mUsingTracers)) {
- mSndParticleData = (vector<pData> *)pyObjectToPointer(
- callPythonFunction("ppSnd" + snd_ext, func));
- mSndParticleVelocity = (vector<pVel> *)pyObjectToPointer(
- callPythonFunction("pVelSnd" + parts_ext, func));
- mSndParticleLife = (vector<float> *)pyObjectToPointer(
- callPythonFunction("pLifeSnd" + parts_ext, func));
- }
+ string s_ext = "_s" + id;
+ string pp_ext = "_pp" + id;
+ string snd_ext = "_sp" + id;
+ string sm_ext = "_sm" + id;
+ string mesh_ext = "_mesh" + id;
+ string sn_ext = "_sn" + id;
+
+ mFlags = (smoke || liquid) ? getPointer<int>("flags" + s_ext, func) : nullptr;
+ mPhiIn = (smoke || liquid) ? getPointer<float>("phiIn" + s_ext, func) : nullptr;
+ mPhiStaticIn = (smoke || liquid) ? getPointer<float>("phiSIn" + s_ext, func) : nullptr;
+ mVelocityX = (smoke || liquid) ? getPointer<float>("x_vel" + s_ext, func) : nullptr;
+ mVelocityY = (smoke || liquid) ? getPointer<float>("y_vel" + s_ext, func) : nullptr;
+ mVelocityZ = (smoke || liquid) ? getPointer<float>("z_vel" + s_ext, func) : nullptr;
+ mForceX = (smoke || liquid) ? getPointer<float>("x_force" + s_ext, func) : nullptr;
+ mForceY = (smoke || liquid) ? getPointer<float>("y_force" + s_ext, func) : nullptr;
+ mForceZ = (smoke || liquid) ? getPointer<float>("z_force" + s_ext, func) : nullptr;
+
+ /* Outflow. */
+ mPhiOutIn = (outflow) ? getPointer<float>("phiOutIn" + s_ext, func) : nullptr;
+ mPhiOutStaticIn = (outflow) ? getPointer<float>("phiOutSIn" + s_ext, func) : nullptr;
+
+ /* Obstacles. */
+ mPhiObsIn = (obstacle) ? getPointer<float>("phiObsIn" + s_ext, func) : nullptr;
+ mPhiObsStaticIn = (obstacle) ? getPointer<float>("phiObsSIn" + s_ext, func) : nullptr;
+ mObVelocityX = (obstacle) ? getPointer<float>("x_obvel" + s_ext, func) : nullptr;
+ mObVelocityY = (obstacle) ? getPointer<float>("y_obvel" + s_ext, func) : nullptr;
+ mObVelocityZ = (obstacle) ? getPointer<float>("z_obvel" + s_ext, func) : nullptr;
+ mNumObstacle = (obstacle) ? getPointer<float>("numObs" + s_ext, func) : nullptr;
+
+ /* Guiding. */
+ mPhiGuideIn = (guiding) ? getPointer<float>("phiGuideIn" + s_ext, func) : nullptr;
+ mGuideVelocityX = (guiding) ? getPointer<float>("x_guidevel" + s_ext, func) : nullptr;
+ mGuideVelocityY = (guiding) ? getPointer<float>("y_guidevel" + s_ext, func) : nullptr;
+ mGuideVelocityZ = (guiding) ? getPointer<float>("z_guidevel" + s_ext, func) : nullptr;
+ mNumGuide = (guiding) ? getPointer<float>("numGuides" + s_ext, func) : nullptr;
+
+ /* Initial velocities. */
+ mInVelocityX = (invel) ? getPointer<float>("x_invel" + s_ext, func) : nullptr;
+ mInVelocityY = (invel) ? getPointer<float>("y_invel" + s_ext, func) : nullptr;
+ mInVelocityZ = (invel) ? getPointer<float>("z_invel" + s_ext, func) : nullptr;
+
+ /* Smoke. */
+ mDensity = (smoke) ? getPointer<float>("density" + s_ext, func) : nullptr;
+ mDensityIn = (smoke) ? getPointer<float>("densityIn" + s_ext, func) : nullptr;
+ mShadow = (smoke) ? getPointer<float>("shadow" + s_ext, func) : nullptr;
+ mEmissionIn = (smoke) ? getPointer<float>("emissionIn" + s_ext, func) : nullptr;
+
+ /* Heat. */
+ mHeat = (heat) ? getPointer<float>("heat" + s_ext, func) : nullptr;
+ mHeatIn = (heat) ? getPointer<float>("heatIn" + s_ext, func) : nullptr;
+
+ /* Fire. */
+ mFlame = (fire) ? getPointer<float>("flame" + s_ext, func) : nullptr;
+ mFuel = (fire) ? getPointer<float>("fuel" + s_ext, func) : nullptr;
+ mReact = (fire) ? getPointer<float>("react" + s_ext, func) : nullptr;
+ mFuelIn = (fire) ? getPointer<float>("fuelIn" + s_ext, func) : nullptr;
+ mReactIn = (fire) ? getPointer<float>("reactIn" + s_ext, func) : nullptr;
+
+ /* Colors. */
+ mColorR = (colors) ? getPointer<float>("color_r" + s_ext, func) : nullptr;
+ mColorG = (colors) ? getPointer<float>("color_g" + s_ext, func) : nullptr;
+ mColorB = (colors) ? getPointer<float>("color_b" + s_ext, func) : nullptr;
+ mColorRIn = (colors) ? getPointer<float>("color_r_in" + s_ext, func) : nullptr;
+ mColorGIn = (colors) ? getPointer<float>("color_g_in" + s_ext, func) : nullptr;
+ mColorBIn = (colors) ? getPointer<float>("color_b_in" + s_ext, func) : nullptr;
+
+ /* Noise. */
+ mDensityHigh = (noise) ? getPointer<float>("density" + sn_ext, func) : nullptr;
+ mTextureU = (noise) ? getPointer<float>("texture_u" + s_ext, func) : nullptr;
+ mTextureV = (noise) ? getPointer<float>("texture_v" + s_ext, func) : nullptr;
+ mTextureW = (noise) ? getPointer<float>("texture_w" + s_ext, func) : nullptr;
+ mTextureU2 = (noise) ? getPointer<float>("texture_u2" + s_ext, func) : nullptr;
+ mTextureV2 = (noise) ? getPointer<float>("texture_v2" + s_ext, func) : nullptr;
+ mTextureW2 = (noise) ? getPointer<float>("texture_w2" + s_ext, func) : nullptr;
+
+ /* Fire with noise. */
+ mFlameHigh = (noise && fire) ? getPointer<float>("flame" + sn_ext, func) : nullptr;
+ mFuelHigh = (noise && fire) ? getPointer<float>("fuel" + sn_ext, func) : nullptr;
+ mReactHigh = (noise && fire) ? getPointer<float>("react" + sn_ext, func) : nullptr;
+
+ /* Colors with noise. */
+ mColorRHigh = (noise && colors) ? getPointer<float>("color_r" + sn_ext, func) : nullptr;
+ mColorGHigh = (noise && colors) ? getPointer<float>("color_g" + sn_ext, func) : nullptr;
+ mColorBHigh = (noise && colors) ? getPointer<float>("color_b" + sn_ext, func) : nullptr;
+
+ /* Liquid. */
+ mPhi = (liquid) ? getPointer<float>("phi" + s_ext, func) : nullptr;
+ mFlipParticleData = (liquid) ? getPointer<vector<pData>>("pp" + s_ext, func) : nullptr;
+ mFlipParticleVelocity = (liquid) ? getPointer<vector<pVel>>("pVel" + pp_ext, func) : nullptr;
+
+ /* Mesh. */
+ mMeshNodes = (mesh) ? getPointer<vector<Node>>("mesh" + sm_ext, funcNodes) : nullptr;
+ mMeshTriangles = (mesh) ? getPointer<vector<Triangle>>("mesh" + sm_ext, funcTris) : nullptr;
+
+ /* Mesh velocities. */
+ mMeshVelocities = (meshvel) ? getPointer<vector<pVel>>("mVel" + mesh_ext, func) : nullptr;
+
+ /* Secondary particles. */
+ mParticleData = (parts) ? getPointer<vector<pData>>("ppSnd" + snd_ext, func) : nullptr;
+ mParticleVelocity = (parts) ? getPointer<vector<pVel>>("pVelSnd" + pp_ext, func) : nullptr;
+ mParticleLife = (parts) ? getPointer<vector<float>>("pLifeSnd" + pp_ext, func) : nullptr;
mFlipFromFile = false;
mMeshFromFile = false;
diff --git a/intern/mantaflow/intern/MANTA_main.h b/intern/mantaflow/intern/MANTA_main.h
index dae2aea4e08..5fd94ca01bc 100644
--- a/intern/mantaflow/intern/MANTA_main.h
+++ b/intern/mantaflow/intern/MANTA_main.h
@@ -41,7 +41,7 @@ struct MANTA {
MANTA(){};
virtual ~MANTA();
- // Mirroring Mantaflow structures for particle data (pVel also used for mesh vert vels)
+ /* Mirroring Mantaflow structures for particle data (pVel also used for mesh vert vels). */
typedef struct PData {
float pos[3];
int flag;
@@ -50,7 +50,7 @@ struct MANTA {
float pos[3];
} pVel;
- // Mirroring Mantaflow structures for meshes
+ /* Mirroring Mantaflow structures for meshes. */
typedef struct Node {
int flags;
float pos[3], normal[3];
@@ -60,36 +60,33 @@ struct MANTA {
int flags;
} Triangle;
- // Manta step, handling everything
- void step(struct FluidModifierData *fmd, int startFrame);
-
- // Grid initialization functions
- void initHeat(struct FluidModifierData *fmd = NULL);
- void initFire(struct FluidModifierData *fmd = NULL);
- void initColors(struct FluidModifierData *fmd = NULL);
- void initFireHigh(struct FluidModifierData *fmd = NULL);
- void initColorsHigh(struct FluidModifierData *fmd = NULL);
- void initLiquid(FluidModifierData *fmd = NULL);
- void initLiquidMesh(FluidModifierData *fmd = NULL);
- void initObstacle(FluidModifierData *fmd = NULL);
- void initCurvature(FluidModifierData *fmd = NULL);
- void initGuiding(FluidModifierData *fmd = NULL);
- void initFractions(FluidModifierData *fmd = NULL);
- void initInVelocity(FluidModifierData *fmd = NULL);
- void initOutflow(FluidModifierData *fmd = NULL);
- void initSndParts(FluidModifierData *fmd = NULL);
- void initLiquidSndParts(FluidModifierData *fmd = NULL);
-
- // Pointer transfer: Mantaflow -> Blender
- void updatePointers();
-
- // Write cache
+ /* Grid initialization functions. */
+ bool initHeat(struct FluidModifierData *fmd = nullptr);
+ bool initFire(struct FluidModifierData *fmd = nullptr);
+ bool initColors(struct FluidModifierData *fmd = nullptr);
+ bool initFireHigh(struct FluidModifierData *fmd = nullptr);
+ bool initColorsHigh(struct FluidModifierData *fmd = nullptr);
+ bool initLiquid(FluidModifierData *fmd = nullptr);
+ bool initLiquidMesh(FluidModifierData *fmd = nullptr);
+ bool initObstacle(FluidModifierData *fmd = nullptr);
+ bool initCurvature(FluidModifierData *fmd = nullptr);
+ bool initGuiding(FluidModifierData *fmd = nullptr);
+ bool initFractions(FluidModifierData *fmd = nullptr);
+ bool initInVelocity(FluidModifierData *fmd = nullptr);
+ bool initOutflow(FluidModifierData *fmd = nullptr);
+ bool initSndParts(FluidModifierData *fmd = nullptr);
+ bool initLiquidSndParts(FluidModifierData *fmd = nullptr);
+
+ /* Pointer transfer: Mantaflow -> Blender. Use flush to reset all pointers to nullptr. */
+ void updatePointers(FluidModifierData *fmd, bool flush = false);
+
+ /* Write cache. */
bool writeConfiguration(FluidModifierData *fmd, int framenr);
bool writeData(FluidModifierData *fmd, int framenr);
bool writeNoise(FluidModifierData *fmd, int framenr);
- // write calls for mesh and particles were left in bake calls for now
+ /* Write calls for mesh and particles were left in bake calls for now. */
- // Read cache (via Manta save/load)
+ /* Read cache (via Python). */
bool readConfiguration(FluidModifierData *fmd, int framenr);
bool readData(FluidModifierData *fmd, int framenr, bool resumable);
bool readNoise(FluidModifierData *fmd, int framenr, bool resumable);
@@ -97,26 +94,21 @@ struct MANTA {
bool readParticles(FluidModifierData *fmd, int framenr, bool resumable);
bool readGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain);
- // Read cache (via file read functions in MANTA - e.g. read .bobj.gz meshes, .uni particles)
- bool updateMeshStructures(FluidModifierData *fmd, int framenr);
- bool updateFlipStructures(FluidModifierData *fmd, int framenr);
- bool updateParticleStructures(FluidModifierData *fmd, int framenr);
- bool updateSmokeStructures(FluidModifierData *fmd, int framenr);
- bool updateNoiseStructures(FluidModifierData *fmd, int framenr);
+ /* Propagate variable changes from RNA to Python. */
bool updateVariables(FluidModifierData *fmd);
- // Bake cache
+ /* Bake cache. */
bool bakeData(FluidModifierData *fmd, int framenr);
bool bakeNoise(FluidModifierData *fmd, int framenr);
bool bakeMesh(FluidModifierData *fmd, int framenr);
bool bakeParticles(FluidModifierData *fmd, int framenr);
bool bakeGuiding(FluidModifierData *fmd, int framenr);
- // IO for Mantaflow scene script
+ /* IO for Mantaflow scene script. */
void exportSmokeScript(struct FluidModifierData *fmd);
void exportLiquidScript(struct FluidModifierData *fmd);
- // Check cache status by frame
+ /* Check cache status by frame. */
bool hasConfig(FluidModifierData *fmd, int framenr);
bool hasData(FluidModifierData *fmd, int framenr);
bool hasNoise(FluidModifierData *fmd, int framenr);
@@ -193,7 +185,7 @@ struct MANTA {
return mUpresParticle;
}
- // Smoke getters
+ /* Smoke getters. */
inline float *getDensity()
{
return mDensity;
@@ -422,9 +414,9 @@ struct MANTA {
}
static atomic<int> solverID;
- static int with_debug; // on or off (1 or 0), also sets manta debug level
+ static int with_debug; /* On or off (1 or 0), also sets manta debug level. */
- // Mesh getters
+ /* Mesh getters. */
inline int getNumVertices()
{
return (mMeshNodes && !mMeshNodes->empty()) ? mMeshNodes->size() : 0;
@@ -563,9 +555,9 @@ struct MANTA {
inline int getSndParticleFlagAt(int i)
{
assert(i >= 0);
- if (mSndParticleData && !mSndParticleData->empty()) {
- assert(i < mSndParticleData->size());
- return (*mSndParticleData)[i].flag;
+ if (mParticleData && !mParticleData->empty()) {
+ assert(i < mParticleData->size());
+ return (*mParticleData)[i].flag;
}
return 0;
}
@@ -601,27 +593,27 @@ struct MANTA {
inline float getSndParticlePositionXAt(int i)
{
assert(i >= 0);
- if (mSndParticleData && !mSndParticleData->empty()) {
- assert(i < mSndParticleData->size());
- return (*mSndParticleData)[i].pos[0];
+ if (mParticleData && !mParticleData->empty()) {
+ assert(i < mParticleData->size());
+ return (*mParticleData)[i].pos[0];
}
return 0.0f;
}
inline float getSndParticlePositionYAt(int i)
{
assert(i >= 0);
- if (mSndParticleData && !mSndParticleData->empty()) {
- assert(i < mSndParticleData->size());
- return (*mSndParticleData)[i].pos[1];
+ if (mParticleData && !mParticleData->empty()) {
+ assert(i < mParticleData->size());
+ return (*mParticleData)[i].pos[1];
}
return 0.0f;
}
inline float getSndParticlePositionZAt(int i)
{
assert(i >= 0);
- if (mSndParticleData && !mSndParticleData->empty()) {
- assert(i < mSndParticleData->size());
- return (*mSndParticleData)[i].pos[2];
+ if (mParticleData && !mParticleData->empty()) {
+ assert(i < mParticleData->size());
+ return (*mParticleData)[i].pos[2];
}
return 0.0f;
}
@@ -657,27 +649,27 @@ struct MANTA {
inline float getSndParticleVelocityXAt(int i)
{
assert(i >= 0);
- if (mSndParticleVelocity && !mSndParticleVelocity->empty()) {
- assert(i < mSndParticleVelocity->size());
- return (*mSndParticleVelocity)[i].pos[0];
+ if (mParticleVelocity && !mParticleVelocity->empty()) {
+ assert(i < mParticleVelocity->size());
+ return (*mParticleVelocity)[i].pos[0];
}
return 0.0f;
}
inline float getSndParticleVelocityYAt(int i)
{
assert(i >= 0);
- if (mSndParticleVelocity && !mSndParticleVelocity->empty()) {
- assert(i < mSndParticleVelocity->size());
- return (*mSndParticleVelocity)[i].pos[1];
+ if (mParticleVelocity && !mParticleVelocity->empty()) {
+ assert(i < mParticleVelocity->size());
+ return (*mParticleVelocity)[i].pos[1];
}
return 0.0f;
}
inline float getSndParticleVelocityZAt(int i)
{
assert(i >= 0);
- if (mSndParticleVelocity && !mSndParticleVelocity->empty()) {
- assert(i < mSndParticleVelocity->size());
- return (*mSndParticleVelocity)[i].pos[2];
+ if (mParticleVelocity && !mParticleVelocity->empty()) {
+ assert(i < mParticleVelocity->size());
+ return (*mParticleVelocity)[i].pos[2];
}
return 0.0f;
}
@@ -686,30 +678,28 @@ struct MANTA {
{
return (mFlipParticleData && !mFlipParticleData->empty()) ?
(float *)&mFlipParticleData->front() :
- NULL;
+ nullptr;
}
inline float *getSndParticleData()
{
- return (mSndParticleData && !mSndParticleData->empty()) ? (float *)&mSndParticleData->front() :
- NULL;
+ return (mParticleData && !mParticleData->empty()) ? (float *)&mParticleData->front() : nullptr;
}
inline float *getFlipParticleVelocity()
{
return (mFlipParticleVelocity && !mFlipParticleVelocity->empty()) ?
(float *)&mFlipParticleVelocity->front() :
- NULL;
+ nullptr;
}
inline float *getSndParticleVelocity()
{
- return (mSndParticleVelocity && !mSndParticleVelocity->empty()) ?
- (float *)&mSndParticleVelocity->front() :
- NULL;
+ return (mParticleVelocity && !mParticleVelocity->empty()) ?
+ (float *)&mParticleVelocity->front() :
+ nullptr;
}
inline float *getSndParticleLife()
{
- return (mSndParticleLife && !mSndParticleLife->empty()) ? (float *)&mSndParticleLife->front() :
- NULL;
+ return (mParticleLife && !mParticleLife->empty()) ? (float *)&mParticleLife->front() : nullptr;
}
inline int getNumFlipParticles()
@@ -718,7 +708,7 @@ struct MANTA {
}
inline int getNumSndParticles()
{
- return (mSndParticleData && !mSndParticleData->empty()) ? mSndParticleData->size() : 0;
+ return (mParticleData && !mParticleData->empty()) ? mParticleData->size() : 0;
}
inline bool usingFlipFromFile()
@@ -734,7 +724,7 @@ struct MANTA {
return mParticlesFromFile;
}
- // Direct access to solver time attributes
+ /* Direct access to solver time attributes. */
int getFrame();
float getTimestep();
void adaptTimestep();
@@ -742,7 +732,7 @@ struct MANTA {
bool needsRealloc(FluidModifierData *fmd);
private:
- // simulation constants
+ /* Simulation constants. */
size_t mTotalCells;
size_t mTotalCellsHigh;
size_t mTotalCellsMesh;
@@ -750,6 +740,7 @@ struct MANTA {
unordered_map<string, string> mRNAMap;
+ /* The ID of the solver objects will be incremented for every new object. */
int mCurrentID;
bool mUsingHeat;
@@ -796,10 +787,7 @@ struct MANTA {
int mUpresMesh;
int mUpresParticle;
- float mTempAmb; /* ambient temperature */
- float mConstantScaling;
-
- // Fluid grids
+ /* Fluid grids. */
float *mVelocityX;
float *mVelocityY;
float *mVelocityZ;
@@ -819,7 +807,7 @@ struct MANTA {
float *mNumObstacle;
float *mNumGuide;
- // Smoke grids
+ /* Smoke grids. */
float *mDensity;
float *mHeat;
float *mFlame;
@@ -851,7 +839,7 @@ struct MANTA {
float *mTextureV2;
float *mTextureW2;
- // Liquid grids
+ /* Liquid grids. */
float *mPhiIn;
float *mPhiStaticIn;
float *mPhiObsIn;
@@ -861,31 +849,31 @@ struct MANTA {
float *mPhiOutStaticIn;
float *mPhi;
- // Mesh fields
+ /* Mesh fields. */
vector<Node> *mMeshNodes;
vector<Triangle> *mMeshTriangles;
vector<pVel> *mMeshVelocities;
- // Particle fields
+ /* Particle fields. */
vector<pData> *mFlipParticleData;
vector<pVel> *mFlipParticleVelocity;
- vector<pData> *mSndParticleData;
- vector<pVel> *mSndParticleVelocity;
- vector<float> *mSndParticleLife;
+ vector<pData> *mParticleData;
+ vector<pVel> *mParticleVelocity;
+ vector<float> *mParticleLife;
- void initializeRNAMap(struct FluidModifierData *fmd = NULL);
- void initDomain(struct FluidModifierData *fmd = NULL);
- void initNoise(struct FluidModifierData *fmd = NULL);
- void initMesh(struct FluidModifierData *fmd = NULL);
- void initSmoke(struct FluidModifierData *fmd = NULL);
- void initSmokeNoise(struct FluidModifierData *fmd = NULL);
+ void initializeRNAMap(struct FluidModifierData *doRnaRefresh = nullptr);
+ bool initDomain(struct FluidModifierData *doRnaRefresh = nullptr);
+ bool initNoise(struct FluidModifierData *doRnaRefresh = nullptr);
+ bool initMesh(struct FluidModifierData *doRnaRefresh = nullptr);
+ bool initSmoke(struct FluidModifierData *doRnaRefresh = nullptr);
+ bool initSmokeNoise(struct FluidModifierData *doRnaRefresh = nullptr);
void initializeMantaflow();
void terminateMantaflow();
bool runPythonString(vector<string> commands);
string getRealValue(const string &varName);
string parseLine(const string &line);
- string parseScript(const string &setup_string, FluidModifierData *fmd = NULL);
+ string parseScript(const string &setup_string, FluidModifierData *fmd = nullptr);
string getDirectory(struct FluidModifierData *fmd, string subdirectory);
string getFile(struct FluidModifierData *fmd,
string subdirectory,
diff --git a/intern/mantaflow/intern/manta_fluid_API.cpp b/intern/mantaflow/intern/manta_fluid_API.cpp
index 1db3da63ecc..530dbd49b7c 100644
--- a/intern/mantaflow/intern/manta_fluid_API.cpp
+++ b/intern/mantaflow/intern/manta_fluid_API.cpp
@@ -37,33 +37,29 @@ void manta_free(MANTA *fluid)
fluid = nullptr;
}
-void manta_ensure_obstacle(MANTA *fluid, struct FluidModifierData *fmd)
+int manta_ensure_obstacle(MANTA *fluid, struct FluidModifierData *fmd)
{
- if (!fluid)
- return;
- fluid->initObstacle(fmd);
- fluid->updatePointers();
+ if (!fluid || !fmd)
+ return 0;
+ return fluid->initObstacle(fmd);
}
-void manta_ensure_guiding(MANTA *fluid, struct FluidModifierData *fmd)
+int manta_ensure_guiding(MANTA *fluid, struct FluidModifierData *fmd)
{
- if (!fluid)
- return;
- fluid->initGuiding(fmd);
- fluid->updatePointers();
+ if (!fluid || !fmd)
+ return 0;
+ return fluid->initGuiding(fmd);
}
-void manta_ensure_invelocity(MANTA *fluid, struct FluidModifierData *fmd)
+int manta_ensure_invelocity(MANTA *fluid, struct FluidModifierData *fmd)
{
- if (!fluid)
- return;
- fluid->initInVelocity(fmd);
- fluid->updatePointers();
+ if (!fluid || !fmd)
+ return 0;
+ return fluid->initInVelocity(fmd);
}
-void manta_ensure_outflow(MANTA *fluid, struct FluidModifierData *fmd)
+int manta_ensure_outflow(MANTA *fluid, struct FluidModifierData *fmd)
{
- if (!fluid)
- return;
- fluid->initOutflow(fmd);
- fluid->updatePointers();
+ if (!fluid || !fmd)
+ return 0;
+ return fluid->initOutflow(fmd);
}
int manta_write_config(MANTA *fluid, FluidModifierData *fmd, int framenr)
@@ -229,11 +225,18 @@ void manta_adapt_timestep(MANTA *fluid)
bool manta_needs_realloc(MANTA *fluid, FluidModifierData *fmd)
{
- if (!fluid)
+ if (!fluid || !fmd)
return false;
return fluid->needsRealloc(fmd);
}
+void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd, bool flush)
+{
+ if (!fluid || !fmd)
+ return;
+ fluid->updatePointers(fmd, flush);
+}
+
/* Fluid accessors */
size_t manta_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */)
{
@@ -368,89 +371,6 @@ void manta_smoke_export_script(MANTA *smoke, FluidModifierData *fmd)
smoke->exportSmokeScript(fmd);
}
-void manta_smoke_export(MANTA *smoke,
- float *dt,
- float *dx,
- float **dens,
- float **react,
- float **flame,
- float **fuel,
- float **heat,
- float **vx,
- float **vy,
- float **vz,
- float **r,
- float **g,
- float **b,
- int **flags,
- float **shadow)
-{
- if (dens)
- *dens = smoke->getDensity();
- if (fuel)
- *fuel = smoke->getFuel();
- if (react)
- *react = smoke->getReact();
- if (flame)
- *flame = smoke->getFlame();
- if (heat)
- *heat = smoke->getHeat();
- *vx = smoke->getVelocityX();
- *vy = smoke->getVelocityY();
- *vz = smoke->getVelocityZ();
- if (r)
- *r = smoke->getColorR();
- if (g)
- *g = smoke->getColorG();
- if (b)
- *b = smoke->getColorB();
- *flags = smoke->getFlags();
- if (shadow)
- *shadow = smoke->getShadow();
- *dt = 1; // dummy value, not needed for smoke
- *dx = 1; // dummy value, not needed for smoke
-}
-
-void manta_smoke_turbulence_export(MANTA *smoke,
- float **dens,
- float **react,
- float **flame,
- float **fuel,
- float **r,
- float **g,
- float **b,
- float **tcu,
- float **tcv,
- float **tcw,
- float **tcu2,
- float **tcv2,
- float **tcw2)
-{
- if (!smoke && !(smoke->usingNoise()))
- return;
-
- *dens = smoke->getDensityHigh();
- if (fuel)
- *fuel = smoke->getFuelHigh();
- if (react)
- *react = smoke->getReactHigh();
- if (flame)
- *flame = smoke->getFlameHigh();
- if (r)
- *r = smoke->getColorRHigh();
- if (g)
- *g = smoke->getColorGHigh();
- if (b)
- *b = smoke->getColorBHigh();
- *tcu = smoke->getTextureU();
- *tcv = smoke->getTextureV();
- *tcw = smoke->getTextureW();
-
- *tcu2 = smoke->getTextureU2();
- *tcv2 = smoke->getTextureV2();
- *tcw2 = smoke->getTextureW2();
-}
-
static void get_rgba(
float *r, float *g, float *b, float *a, int total_cells, float *data, int sequential)
{
@@ -484,7 +404,7 @@ void manta_smoke_get_rgba(MANTA *smoke, float *data, int sequential)
sequential);
}
-void manta_smoke_turbulence_get_rgba(MANTA *smoke, float *data, int sequential)
+void manta_noise_get_rgba(MANTA *smoke, float *data, int sequential)
{
get_rgba(smoke->getColorRHigh(),
smoke->getColorGHigh(),
@@ -519,42 +439,40 @@ void manta_smoke_get_rgba_fixed_color(MANTA *smoke, float color[3], float *data,
get_rgba_fixed_color(color, smoke->getTotalCells(), data, sequential);
}
-void manta_smoke_turbulence_get_rgba_fixed_color(MANTA *smoke,
- float color[3],
- float *data,
- int sequential)
+void manta_noise_get_rgba_fixed_color(MANTA *smoke, float color[3], float *data, int sequential)
{
get_rgba_fixed_color(color, smoke->getTotalCellsHigh(), data, sequential);
}
-void manta_smoke_ensure_heat(MANTA *smoke, struct FluidModifierData *fmd)
+int manta_smoke_ensure_heat(MANTA *smoke, struct FluidModifierData *fmd)
{
- if (smoke) {
- smoke->initHeat(fmd);
- smoke->updatePointers();
- }
+ if (!smoke || !fmd)
+ return 0;
+ return smoke->initHeat(fmd);
}
-void manta_smoke_ensure_fire(MANTA *smoke, struct FluidModifierData *fmd)
+int manta_smoke_ensure_fire(MANTA *smoke, struct FluidModifierData *fmd)
{
- if (smoke) {
- smoke->initFire(fmd);
- if (smoke->usingNoise()) {
- smoke->initFireHigh(fmd);
- }
- smoke->updatePointers();
+ if (!smoke || !fmd)
+ return 0;
+
+ int result = smoke->initFire(fmd);
+ if (smoke->usingNoise()) {
+ result &= smoke->initFireHigh(fmd);
}
+ return result;
}
-void manta_smoke_ensure_colors(MANTA *smoke, struct FluidModifierData *fmd)
+int manta_smoke_ensure_colors(MANTA *smoke, struct FluidModifierData *fmd)
{
- if (smoke) {
- smoke->initColors(fmd);
- if (smoke->usingNoise()) {
- smoke->initColorsHigh(fmd);
- }
- smoke->updatePointers();
+ if (!smoke || !fmd)
+ return 0;
+
+ int result = smoke->initColors(fmd);
+ if (smoke->usingNoise()) {
+ result &= smoke->initColorsHigh(fmd);
}
+ return result;
}
/* Smoke accessors */
@@ -647,45 +565,69 @@ int manta_smoke_has_colors(MANTA *smoke)
return (smoke->getColorR() && smoke->getColorG() && smoke->getColorB()) ? 1 : 0;
}
-float *manta_smoke_turbulence_get_density(MANTA *smoke)
+float *manta_noise_get_density(MANTA *smoke)
{
return (smoke && smoke->usingNoise()) ? smoke->getDensityHigh() : nullptr;
}
-float *manta_smoke_turbulence_get_fuel(MANTA *smoke)
+float *manta_noise_get_fuel(MANTA *smoke)
{
return (smoke && smoke->usingNoise()) ? smoke->getFuelHigh() : nullptr;
}
-float *manta_smoke_turbulence_get_react(MANTA *smoke)
+float *manta_noise_get_react(MANTA *smoke)
{
return (smoke && smoke->usingNoise()) ? smoke->getReactHigh() : nullptr;
}
-float *manta_smoke_turbulence_get_color_r(MANTA *smoke)
+float *manta_noise_get_color_r(MANTA *smoke)
{
return (smoke && smoke->usingNoise()) ? smoke->getColorRHigh() : nullptr;
}
-float *manta_smoke_turbulence_get_color_g(MANTA *smoke)
+float *manta_noise_get_color_g(MANTA *smoke)
{
return (smoke && smoke->usingNoise()) ? smoke->getColorGHigh() : nullptr;
}
-float *manta_smoke_turbulence_get_color_b(MANTA *smoke)
+float *manta_noise_get_color_b(MANTA *smoke)
{
return (smoke && smoke->usingNoise()) ? smoke->getColorBHigh() : nullptr;
}
-float *manta_smoke_turbulence_get_flame(MANTA *smoke)
+float *manta_noise_get_flame(MANTA *smoke)
{
return (smoke && smoke->usingNoise()) ? smoke->getFlameHigh() : nullptr;
}
+float *manta_noise_get_texture_u(MANTA *smoke)
+{
+ return (smoke && smoke->usingNoise()) ? smoke->getTextureU() : nullptr;
+}
+float *manta_noise_get_texture_v(MANTA *smoke)
+{
+ return (smoke && smoke->usingNoise()) ? smoke->getTextureV() : nullptr;
+}
+float *manta_noise_get_texture_w(MANTA *smoke)
+{
+ return (smoke && smoke->usingNoise()) ? smoke->getTextureW() : nullptr;
+}
+float *manta_noise_get_texture_u2(MANTA *smoke)
+{
+ return (smoke && smoke->usingNoise()) ? smoke->getTextureU2() : nullptr;
+}
+float *manta_noise_get_texture_v2(MANTA *smoke)
+{
+ return (smoke && smoke->usingNoise()) ? smoke->getTextureV2() : nullptr;
+}
+float *manta_noise_get_texture_w2(MANTA *smoke)
+{
+ return (smoke && smoke->usingNoise()) ? smoke->getTextureW2() : nullptr;
+}
-int manta_smoke_turbulence_has_fuel(MANTA *smoke)
+int manta_noise_has_fuel(MANTA *smoke)
{
return (smoke->getFuelHigh()) ? 1 : 0;
}
-int manta_smoke_turbulence_has_colors(MANTA *smoke)
+int manta_noise_has_colors(MANTA *smoke)
{
return (smoke->getColorRHigh() && smoke->getColorGHigh() && smoke->getColorBHigh()) ? 1 : 0;
}
-void manta_smoke_turbulence_get_res(MANTA *smoke, int *res)
+void manta_noise_get_res(MANTA *smoke, int *res)
{
if (smoke && smoke->usingNoise()) {
res[0] = smoke->getResXHigh();
@@ -693,7 +635,7 @@ void manta_smoke_turbulence_get_res(MANTA *smoke, int *res)
res[2] = smoke->getResZHigh();
}
}
-int manta_smoke_turbulence_get_cells(MANTA *smoke)
+int manta_noise_get_cells(MANTA *smoke)
{
int total_cells_high = smoke->getResXHigh() * smoke->getResYHigh() * smoke->getResZHigh();
return (smoke && smoke->usingNoise()) ? total_cells_high : 0;
@@ -707,12 +649,11 @@ void manta_liquid_export_script(MANTA *liquid, FluidModifierData *fmd)
liquid->exportLiquidScript(fmd);
}
-void manta_liquid_ensure_sndparts(MANTA *liquid, struct FluidModifierData *fmd)
+int manta_liquid_ensure_sndparts(MANTA *liquid, struct FluidModifierData *fmd)
{
- if (liquid) {
- liquid->initLiquidSndParts(fmd);
- liquid->updatePointers();
- }
+ if (!liquid || !fmd)
+ return 0;
+ return liquid->initLiquidSndParts(fmd);
}
/* Liquid accessors */
diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h
index 977b99e7759..a01e333ab5e 100644
--- a/intern/mantaflow/intern/strings/fluid_script.h
+++ b/intern/mantaflow/intern/strings/fluid_script.h
@@ -146,19 +146,19 @@ mantaMsg('1 Mantaflow cell is ' + str(ratioMetersToRes_s$ID$) + ' Blender length
ratioResToBLength_s$ID$ = float(res_s$ID$) / float(domainSize_s$ID$) # [cells / blength] (blength: cm, m, or km, ... )\n\
mantaMsg('1 Blender length unit is ' + str(ratioResToBLength_s$ID$) + ' Mantaflow cells long.')\n\
\n\
-ratioBTimeToTimstep_s$ID$ = float(1) / float(frameLengthRaw_s$ID$) # the time within 1 blender time unit, see also fluid.c\n\
-mantaMsg('1 Blender time unit is ' + str(ratioBTimeToTimstep_s$ID$) + ' Mantaflow time units long.')\n\
+ratioBTimeToTimestep_s$ID$ = float(1) / float(frameLengthRaw_s$ID$) # the time within 1 blender time unit, see also fluid.c\n\
+mantaMsg('1 Blender time unit is ' + str(ratioBTimeToTimestep_s$ID$) + ' Mantaflow time units long.')\n\
\n\
ratioFrameToFramelength_s$ID$ = float(1) / float(frameLengthUnscaled_s$ID$ ) # the time within 1 frame\n\
mantaMsg('frame / frameLength is ' + str(ratioFrameToFramelength_s$ID$) + ' Mantaflow time units long.')\n\
\n\
-scaleAcceleration_s$ID$ = ratioResToBLength_s$ID$ * (ratioBTimeToTimstep_s$ID$**2)# [meters/btime^2] to [cells/timestep^2] (btime: sec, min, or h, ...)\n\
+scaleAcceleration_s$ID$ = ratioResToBLength_s$ID$ * (ratioBTimeToTimestep_s$ID$**2)# [meters/btime^2] to [cells/timestep^2] (btime: sec, min, or h, ...)\n\
mantaMsg('scaleAcceleration is ' + str(scaleAcceleration_s$ID$))\n\
\n\
scaleSpeedFrames_s$ID$ = ratioResToBLength_s$ID$ * ratioFrameToFramelength_s$ID$ # [blength/frame] to [cells/frameLength]\n\
mantaMsg('scaleSpeed is ' + str(scaleSpeedFrames_s$ID$))\n\
\n\
-scaleSpeedTime_s$ID$ = ratioResToBLength_s$ID$ * ratioBTimeToTimstep_s$ID$ # [blength/btime] to [cells/frameLength]\n\
+scaleSpeedTime_s$ID$ = ratioResToBLength_s$ID$ * ratioBTimeToTimestep_s$ID$ # [blength/btime] to [cells/frameLength]\n\
mantaMsg('scaleSpeedTime is ' + str(scaleSpeedTime_s$ID$))\n\
\n\
gravity_s$ID$ *= scaleAcceleration_s$ID$ # scale from world acceleration to cell based acceleration\n\
@@ -418,19 +418,6 @@ const std::string fluid_post_step =
"\n\
def fluid_post_step_$ID$():\n\
mantaMsg('Fluid post step')\n\
- forces_s$ID$.clear()\n\
- x_force_s$ID$.clear()\n\
- y_force_s$ID$.clear()\n\
- z_force_s$ID$.clear()\n\
- \n\
- if using_guiding_s$ID$:\n\
- weightGuide_s$ID$.clear()\n\
- if using_invel_s$ID$:\n\
- x_invel_s$ID$.clear()\n\
- y_invel_s$ID$.clear()\n\
- z_invel_s$ID$.clear()\n\
- invel_s$ID$.clear()\n\
- invelC_s$ID$.clear()\n\
\n\
# Copy vel grid to reals grids (which Blender internal will in turn use for vel access)\n\
copyVec3ToReal(source=vel_s$ID$, targetX=x_vel_s$ID$, targetY=y_vel_s$ID$, targetZ=z_vel_s$ID$)\n";
@@ -770,8 +757,6 @@ if (GUI):\n\
cache_resumable = $CACHE_RESUMABLE$\n\
cache_dir = '$CACHE_DIR$'\n\
file_format_data = '$CACHE_DATA_FORMAT$'\n\
-file_format_noise = '$CACHE_NOISE_FORMAT$'\n\
-file_format_particles = '$CACHE_PARTICLE_FORMAT$'\n\
file_format_mesh = '$CACHE_MESH_FORMAT$'\n\
\n\
# How many frame to load from cache\n\
diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h
index 04505206601..08d8dcd7de3 100644
--- a/intern/mantaflow/intern/strings/liquid_script.h
+++ b/intern/mantaflow/intern/strings/liquid_script.h
@@ -48,7 +48,8 @@ meshRadiusFactor_s$ID$ = $MESH_PARTICLE_RADIUS$\n\
smoothenPos_s$ID$ = $MESH_SMOOTHEN_POS$\n\
smoothenNeg_s$ID$ = $MESH_SMOOTHEN_NEG$\n\
randomness_s$ID$ = $PARTICLE_RANDOMNESS$\n\
-surfaceTension_s$ID$ = $LIQUID_SURFACE_TENSION$\n";
+surfaceTension_s$ID$ = $LIQUID_SURFACE_TENSION$\n\
+maxSysParticles_s$ID$ = $PP_PARTICLE_MAXIMUM$\n";
const std::string liquid_variables_particles =
"\n\
@@ -216,6 +217,7 @@ def liquid_adaptive_step_$ID$(framenr):\n\
else:\n\
pVel_pp$ID$.setSource(grid=None, isMAC=False)\n\
\n\
+ pp_s$ID$.maxParticles = maxSysParticles_s$ID$ # remember, 0 means no particle cap\n\
sampleLevelsetWithParticles(phi=phiIn_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, discretization=particleNumber_s$ID$, randomness=randomness_s$ID$)\n\
flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\
\n\
@@ -477,7 +479,7 @@ const std::string liquid_standalone =
def load(frame, cache_resumable):\n\
liquid_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\
if using_sndparts_s$ID$:\n\
- liquid_load_particles_$ID$(os.path.join(cache_dir, 'particles'), frame, file_format_particles, cache_resumable)\n\
+ liquid_load_particles_$ID$(os.path.join(cache_dir, 'particles'), frame, file_format_data, cache_resumable)\n\
if using_mesh_s$ID$:\n\
liquid_load_mesh_$ID$(os.path.join(cache_dir, 'mesh'), frame, file_format_mesh)\n\
if using_guiding_s$ID$:\n\
diff --git a/intern/mantaflow/intern/strings/smoke_script.h b/intern/mantaflow/intern/strings/smoke_script.h
index 612d01b85ef..f81259115c5 100644
--- a/intern/mantaflow/intern/strings/smoke_script.h
+++ b/intern/mantaflow/intern/strings/smoke_script.h
@@ -100,6 +100,9 @@ color_r_in_s$ID$ = None\n\
color_g_in_s$ID$ = None\n\
color_b_in_s$ID$ = None\n\
\n\
+# Set some initial values\n\
+shadow_s$ID$.setConst(-1)\n\
+\n\
# Keep track of important objects in dict to load them later on\n\
smoke_data_dict_final_s$ID$ = { 'density' : density_s$ID$, 'shadow' : shadow_s$ID$ }\n\
smoke_data_dict_resume_s$ID$ = { 'densityIn' : densityIn_s$ID$, 'emission' : emission_s$ID$ }\n";
@@ -490,6 +493,9 @@ def step_noise_$ID$():\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=uvGrid1_s$ID$, order=2)\n\
updateUvWeight(resetTime=sn$ID$.timestep*10.0 , index=1, numUvs=uvs_s$ID$, uv=uvGrid1_s$ID$, offset=uvs_offset_s$ID$)\n\
\n\
+ if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\
+ resetOutflow(flags=flags_sn$ID$, real=density_sn$ID$)\n\
+ \n\
mantaMsg('Energy')\n\
computeEnergy(flags=flags_s$ID$, vel=vel_s$ID$, energy=energy_s$ID$)\n\
\n\
@@ -595,7 +601,7 @@ const std::string smoke_standalone =
def load(frame, cache_resumable):\n\
smoke_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\
if using_noise_s$ID$:\n\
- smoke_load_noise_$ID$(os.path.join(cache_dir, 'noise'), frame, file_format_noise, cache_resumable)\n\
+ smoke_load_noise_$ID$(os.path.join(cache_dir, 'noise'), frame, file_format_data, cache_resumable)\n\
if using_guiding_s$ID$:\n\
fluid_load_guiding_$ID$(os.path.join(cache_dir, 'guiding'), frame, file_format_data)\n\
\n\
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index 43416f734c5..f766f57732a 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -45,9 +45,8 @@
# pragma warning(pop)
#endif
-extern "C" {
#include "GPU_immediate.h"
-}
+#include "GPU_shader.h"
using namespace OCIO_NAMESPACE;
@@ -94,18 +93,15 @@ struct OCIO_GLSLCurveMappingParameters {
struct OCIO_GLSLShader {
/** Cache IDs */
std::string cacheId;
- /** TODO(fclem): Remove. IMM shader interface. */
- struct GPUShaderInterface *interface;
- /** OpenGL Shader objects handles. */
- GLuint frag;
- GLuint vert;
- GLuint program;
+
+ struct GPUShader *shader;
/** Uniform locations. */
GLint dither_loc;
GLint overlay_loc;
GLint overlay_tex_loc;
GLint predivide_loc;
GLint curve_mapping_loc;
+ GLint ubo_bind;
/** Error checking. */
bool valid;
};
@@ -152,56 +148,6 @@ static OCIO_GLSLDrawState *allocateOpenGLState(void)
/** \name Shader
* \{ */
-static GLuint compileShaderText(GLenum shader_type, const char *text)
-{
- GLuint shader;
- GLint stat;
-
- shader = glCreateShader(shader_type);
- glShaderSource(shader, 1, (const GLchar **)&text, NULL);
- glCompileShader(shader);
- glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
-
- if (!stat) {
- GLchar log[1000];
- GLsizei len;
- glGetShaderInfoLog(shader, 1000, &len, log);
- fprintf(stderr, "Shader compile error:\n%s\n", log);
- return 0;
- }
-
- return shader;
-}
-
-static GLuint linkShaders(GLuint frag, GLuint vert)
-{
- if (!frag || !vert) {
- return 0;
- }
-
- GLuint program = glCreateProgram();
-
- glAttachShader(program, frag);
- glAttachShader(program, vert);
-
- glLinkProgram(program);
-
- /* check link */
- {
- GLint stat;
- glGetProgramiv(program, GL_LINK_STATUS, &stat);
- if (!stat) {
- GLchar log[1000];
- GLsizei len;
- glGetProgramInfoLog(program, 1000, &len, log);
- fprintf(stderr, "Shader link error:\n%s\n", log);
- return 0;
- }
- }
-
- return program;
-}
-
static void updateGLSLShader(OCIO_GLSLShader *shader,
ConstProcessorRcPtr *processor_scene_to_ui,
ConstProcessorRcPtr *processpr_ui_to_display,
@@ -213,28 +159,14 @@ static void updateGLSLShader(OCIO_GLSLShader *shader,
}
/* Delete any previous shader. */
- glDeleteProgram(shader->program);
- glDeleteShader(shader->frag);
- glDeleteShader(shader->vert);
-
- if (shader->interface) {
- GPU_shaderinterface_discard(shader->interface);
+ if (shader->shader) {
+ GPU_shader_free(shader->shader);
}
- {
- /* Vertex shader */
- std::ostringstream osv;
-
- osv << "#version 330\n";
- osv << datatoc_gpu_shader_display_transform_vertex_glsl;
-
- shader->vert = compileShaderText(GL_VERTEX_SHADER, osv.str().c_str());
- }
+ std::ostringstream os;
{
/* Fragment shader */
- std::ostringstream os;
- os << "#version 330\n";
/* Work around OpenColorIO not supporting latest GLSL yet. */
os << "#define texture2D texture\n";
os << "#define texture3D texture\n";
@@ -246,41 +178,36 @@ static void updateGLSLShader(OCIO_GLSLShader *shader,
os << (*processpr_ui_to_display)->getGpuShaderText(*shader_desc) << "\n";
os << datatoc_gpu_shader_display_transform_glsl;
-
- shader->frag = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
}
- /* shader_Program */
- if (shader->frag && shader->vert) {
- shader->program = linkShaders(shader->frag, shader->vert);
- }
+ shader->shader = GPU_shader_create(datatoc_gpu_shader_display_transform_vertex_glsl,
+ os.str().c_str(),
+ NULL,
+ NULL,
+ NULL,
+ __func__);
- if (shader->program) {
- shader->dither_loc = glGetUniformLocation(shader->program, "dither");
- shader->overlay_tex_loc = glGetUniformLocation(shader->program, "overlay_texture");
- shader->overlay_loc = glGetUniformLocation(shader->program, "overlay");
- shader->predivide_loc = glGetUniformLocation(shader->program, "predivide");
- shader->curve_mapping_loc = glGetUniformLocation(shader->program, "curve_mapping");
+ if (shader->shader) {
+ shader->dither_loc = GPU_shader_get_uniform(shader->shader, "dither");
+ shader->overlay_tex_loc = GPU_shader_get_uniform(shader->shader, "overlay_texture");
+ shader->overlay_loc = GPU_shader_get_uniform(shader->shader, "overlay");
+ shader->predivide_loc = GPU_shader_get_uniform(shader->shader, "predivide");
+ shader->curve_mapping_loc = GPU_shader_get_uniform(shader->shader, "curve_mapping");
+ shader->ubo_bind = GPU_shader_get_uniform_block_binding(shader->shader,
+ "OCIO_GLSLCurveMappingParameters");
- glUseProgram(shader->program);
-
- /* TODO(fclem) Remove this. Make caller always assume viewport space and
- * specify texco via vertex attribs. */
- shader->interface = GPU_shaderinterface_create(shader->program);
-
- /* Set UBO binding location. */
- GLuint index = glGetUniformBlockIndex(shader->program, "OCIO_GLSLCurveMappingParameters");
- glUniformBlockBinding(shader->program, index, UBO_BIND_LOC);
+ GPU_shader_bind(shader->shader);
/* Set texture bind point uniform once. This is saved by the shader. */
- glUniform1i(glGetUniformLocation(shader->program, "image_texture"), 0);
- glUniform1i(glGetUniformLocation(shader->program, "lut3d_texture"), 2);
- glUniform1i(glGetUniformLocation(shader->program, "lut3d_display_texture"), 3);
- glUniform1i(glGetUniformLocation(shader->program, "curve_mapping_texture"), 4);
+ GPUShader *sh = shader->shader;
+ GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "image_texture"), 0);
+ GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_texture"), 2);
+ GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_display_texture"), 3);
+ GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "curve_mapping_texture"), 4);
}
shader->cacheId = cache_id;
- shader->valid = (shader->program != 0);
+ shader->valid = (shader->shader != NULL);
}
static void ensureGLSLShader(OCIO_GLSLShader **shader_ptr,
@@ -302,12 +229,8 @@ static void ensureGLSLShader(OCIO_GLSLShader **shader_ptr,
static void freeGLSLShader(OCIO_GLSLShader *shader)
{
- glDeleteProgram(shader->program);
- glDeleteShader(shader->frag);
- glDeleteShader(shader->vert);
-
- if (shader->interface) {
- GPU_shaderinterface_discard(shader->interface);
+ if (shader->shader) {
+ GPU_shader_free(shader->shader);
}
OBJECT_GUARDED_DELETE(shader, OCIO_GLSLShader);
@@ -674,10 +597,10 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r,
glActiveTexture(GL_TEXTURE0);
/* Bind UBO. */
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, shader_curvemap->buffer);
+ glBindBufferBase(GL_UNIFORM_BUFFER, shader->ubo_bind, shader_curvemap->buffer);
/* TODO(fclem) remove remains of IMM. */
- immBindProgram(shader->program, shader->interface);
+ immBindShader(shader->shader);
/* Bind Shader and set uniforms. */
// glUseProgram(shader->program);
diff --git a/intern/rigidbody/RBI_api.h b/intern/rigidbody/RBI_api.h
index d46cb5a7eed..07cda49e04b 100644
--- a/intern/rigidbody/RBI_api.h
+++ b/intern/rigidbody/RBI_api.h
@@ -238,6 +238,14 @@ rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh);
/* 2b - GImpact Meshes */
rbCollisionShape *RB_shape_new_gimpact_mesh(rbMeshData *mesh);
+/* Compound Shape ---------------- */
+
+rbCollisionShape *RB_shape_new_compound(void);
+void RB_compound_add_child_shape(rbCollisionShape *collisionShape,
+ rbCollisionShape *shape,
+ const float loc[3],
+ const float rot[4]);
+
/* Cleanup --------------------------- */
void RB_shape_delete(rbCollisionShape *shape);
diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp
index a8bf1420523..db8c062990c 100644
--- a/intern/rigidbody/rb_bullet_api.cpp
+++ b/intern/rigidbody/rb_bullet_api.cpp
@@ -98,6 +98,8 @@ struct rbMeshData {
struct rbCollisionShape {
btCollisionShape *cshape;
rbMeshData *mesh;
+ rbCollisionShape **compoundChildShapes;
+ int compoundChilds;
};
struct rbFilterCallback : public btOverlapFilterCallback {
@@ -331,6 +333,7 @@ rbRigidBody *RB_body_new(rbCollisionShape *shape, const float loc[3], const floa
rbRigidBody *object = new rbRigidBody;
/* current transform */
btTransform trans;
+ trans.setIdentity();
trans.setOrigin(btVector3(loc[0], loc[1], loc[2]));
trans.setRotation(btQuaternion(rot[1], rot[2], rot[3], rot[0]));
@@ -413,6 +416,10 @@ void RB_body_set_mass(rbRigidBody *object, float value)
shape->calculateLocalInertia(value, localInertia);
}
+ btVector3 minAabb, maxAabb;
+ btTransform ident;
+ ident.setIdentity();
+ body->getCollisionShape()->getAabb(ident, minAabb, maxAabb);
body->setMassProps(value, localInertia);
body->updateInertiaTensor();
}
@@ -597,6 +604,7 @@ void RB_body_set_loc_rot(rbRigidBody *object, const float loc[3], const float ro
/* set transform matrix */
btTransform trans;
+ trans.setIdentity();
trans.setOrigin(btVector3(loc[0], loc[1], loc[2]));
trans.setRotation(btQuaternion(rot[1], rot[2], rot[3], rot[0]));
@@ -655,6 +663,8 @@ rbCollisionShape *RB_shape_new_box(float x, float y, float z)
rbCollisionShape *shape = new rbCollisionShape;
shape->cshape = new btBoxShape(btVector3(x, y, z));
shape->mesh = NULL;
+ shape->compoundChilds = 0;
+ shape->compoundChildShapes = NULL;
return shape;
}
@@ -663,6 +673,8 @@ rbCollisionShape *RB_shape_new_sphere(float radius)
rbCollisionShape *shape = new rbCollisionShape;
shape->cshape = new btSphereShape(radius);
shape->mesh = NULL;
+ shape->compoundChilds = 0;
+ shape->compoundChildShapes = NULL;
return shape;
}
@@ -671,6 +683,8 @@ rbCollisionShape *RB_shape_new_capsule(float radius, float height)
rbCollisionShape *shape = new rbCollisionShape;
shape->cshape = new btCapsuleShapeZ(radius, height);
shape->mesh = NULL;
+ shape->compoundChilds = 0;
+ shape->compoundChildShapes = NULL;
return shape;
}
@@ -679,6 +693,8 @@ rbCollisionShape *RB_shape_new_cone(float radius, float height)
rbCollisionShape *shape = new rbCollisionShape;
shape->cshape = new btConeShapeZ(radius, height);
shape->mesh = NULL;
+ shape->compoundChilds = 0;
+ shape->compoundChildShapes = NULL;
return shape;
}
@@ -687,6 +703,8 @@ rbCollisionShape *RB_shape_new_cylinder(float radius, float height)
rbCollisionShape *shape = new rbCollisionShape;
shape->cshape = new btCylinderShapeZ(btVector3(radius, radius, height));
shape->mesh = NULL;
+ shape->compoundChilds = 0;
+ shape->compoundChildShapes = NULL;
return shape;
}
@@ -709,6 +727,8 @@ rbCollisionShape *RB_shape_new_convex_hull(
shape->cshape = hull_shape;
shape->mesh = NULL;
+ shape->compoundChilds = 0;
+ shape->compoundChildShapes = NULL;
return shape;
}
@@ -773,6 +793,8 @@ rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh)
shape->cshape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f));
shape->mesh = mesh;
+ shape->compoundChilds = 0;
+ shape->compoundChildShapes = NULL;
return shape;
}
@@ -813,9 +835,46 @@ rbCollisionShape *RB_shape_new_gimpact_mesh(rbMeshData *mesh)
shape->cshape = gimpactShape;
shape->mesh = mesh;
+ shape->compoundChilds = 0;
+ shape->compoundChildShapes = NULL;
return shape;
}
+/* Compound Shape ---------------- */
+
+rbCollisionShape *RB_shape_new_compound()
+{
+ rbCollisionShape *shape = new rbCollisionShape;
+ btCompoundShape *compoundShape = new btCompoundShape();
+
+ shape->cshape = compoundShape;
+ shape->mesh = NULL;
+ shape->compoundChilds = 0;
+ shape->compoundChildShapes = NULL;
+ return shape;
+}
+
+void RB_compound_add_child_shape(rbCollisionShape *parentShape,
+ rbCollisionShape *shape,
+ const float loc[3],
+ const float rot[4])
+{
+ /* set transform matrix */
+ btTransform trans;
+ trans.setIdentity();
+ trans.setOrigin(btVector3(loc[0], loc[1], loc[2]));
+ trans.setRotation(btQuaternion(rot[1], rot[2], rot[3], rot[0]));
+
+ btCompoundShape *compoundShape = (btCompoundShape *)(parentShape->cshape);
+ compoundShape->addChildShape(trans, shape->cshape);
+
+ /* Store shapes for deletion later */
+ parentShape->compoundChildShapes = (rbCollisionShape **)(realloc(
+ parentShape->compoundChildShapes,
+ sizeof(rbCollisionShape *) * (++parentShape->compoundChilds)));
+ parentShape->compoundChildShapes[parentShape->compoundChilds - 1] = shape;
+}
+
/* Cleanup --------------------------- */
void RB_shape_delete(rbCollisionShape *shape)
@@ -829,6 +888,15 @@ void RB_shape_delete(rbCollisionShape *shape)
if (shape->mesh)
RB_trimesh_data_delete(shape->mesh);
delete shape->cshape;
+
+ /* Delete compound child shapes if there are any */
+ for (int i = 0; i < shape->compoundChilds; i++) {
+ RB_shape_delete(shape->compoundChildShapes[i]);
+ }
+ if (shape->compoundChildShapes != NULL) {
+ free(shape->compoundChildShapes);
+ }
+
delete shape;
}
@@ -873,6 +941,7 @@ static void make_constraint_transforms(btTransform &transform1,
float orn[4])
{
btTransform pivot_transform = btTransform();
+ pivot_transform.setIdentity();
pivot_transform.setOrigin(btVector3(pivot[0], pivot[1], pivot[2]));
pivot_transform.setRotation(btQuaternion(orn[1], orn[2], orn[3], orn[0]));
diff --git a/intern/sky/CMakeLists.txt b/intern/sky/CMakeLists.txt
new file mode 100644
index 00000000000..f67941605aa
--- /dev/null
+++ b/intern/sky/CMakeLists.txt
@@ -0,0 +1,39 @@
+# ***** 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.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ include
+)
+
+set(INC_SYS
+
+)
+
+set(SRC
+ source/sky_model.cpp
+ source/sky_nishita.cpp
+
+ include/sky_model.h
+ source/sky_float3.h
+ source/sky_model_data.h
+)
+
+set(LIB
+)
+
+blender_add_lib(bf_intern_sky "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/intern/cycles/util/util_sky_model.h b/intern/sky/include/sky_model.h
index 36f1079a16d..983b90fed35 100644
--- a/intern/cycles/util/util_sky_model.h
+++ b/intern/sky/include/sky_model.h
@@ -112,7 +112,7 @@ bands, you would need something like
ArHosekSkyModelState * skymodel_state[num_channels];
-You then have to allocate and initialise these states. In the following code
+You then have to allocate and initialize these states. In the following code
snippet, we assume that 'albedo' is defined as
double albedo[num_channels];
@@ -228,7 +228,7 @@ actually not altered at all in this release. All we did was to add some support
functionality for doing this more easily with the existing data and functions,
and to add some explanations.
-Just use 'arhosekskymodelstate_alienworld_alloc_init()' to initialise the sky
+Just use 'arhosekskymodelstate_alienworld_alloc_init()' to initialize the sky
model states (you will have to provide values for star temperature and solar
intensity compared to the terrestrial sun), and do everything else as you
did before.
@@ -298,14 +298,14 @@ HINT #1: if you want to model the sky of an earth-like planet that orbits
previous paragraph.
*/
-#include "util/util_types.h"
+#ifndef __SKY_MODEL_H__
+#define __SKY_MODEL_H__
-CCL_NAMESPACE_BEGIN
+#ifdef __cplusplus
+extern "C" {
+#endif
-#ifndef _SKY_MODEL_H_
-# define _SKY_MODEL_H_
-
-typedef double ArHosekSkyModelConfiguration[9];
+typedef double SKY_ArHosekSkyModelConfiguration[9];
// Spectral version of the model
@@ -335,8 +335,8 @@ typedef double ArHosekSkyModelConfiguration[9];
---------------------------------------------------------------------------- */
-typedef struct ArHosekSkyModelState {
- ArHosekSkyModelConfiguration configs[11];
+typedef struct SKY_ArHosekSkyModelState {
+ SKY_ArHosekSkyModelConfiguration configs[11];
double radiances[11];
double turbidity;
double solar_radius;
@@ -344,27 +344,27 @@ typedef struct ArHosekSkyModelState {
double emission_correction_factor_sun[11];
double albedo;
double elevation;
-} ArHosekSkyModelState;
+} SKY_ArHosekSkyModelState;
/* ----------------------------------------------------------------------------
arhosekskymodelstate_alloc_init() function
------------------------------------------
- Initialises an ArHosekSkyModelState struct for a terrestrial setting.
+ Initializes an #ArHosekSkyModelState struct for a terrestrial setting.
---------------------------------------------------------------------------- */
-ArHosekSkyModelState *arhosekskymodelstate_alloc_init(const double solar_elevation,
- const double atmospheric_turbidity,
- const double ground_albedo);
+SKY_ArHosekSkyModelState *SKY_arhosekskymodelstate_alloc_init(const double solar_elevation,
+ const double atmospheric_turbidity,
+ const double ground_albedo);
/* ----------------------------------------------------------------------------
arhosekskymodelstate_alienworld_alloc_init() function
-----------------------------------------------------
- Initialises an ArHosekSkyModelState struct for an "alien world" setting
+ Initializes an ArHosekSkyModelState struct for an "alien world" setting
with a sun of a surface temperature given in 'kelvin'. The parameter
'solar_intensity' controls the overall brightness of the sky, relative
to the solar irradiance on Earth. A value of 1.0 yields a sky dome that
@@ -388,66 +388,68 @@ ArHosekSkyModelState *arhosekskymodelstate_alloc_init(const double solar_elevati
---------------------------------------------------------------------------- */
-ArHosekSkyModelState *arhosekskymodelstate_alienworld_alloc_init(
+SKY_ArHosekSkyModelState *SKY_arhosekskymodelstate_alienworld_alloc_init(
const double solar_elevation,
const double solar_intensity,
const double solar_surface_temperature_kelvin,
const double atmospheric_turbidity,
const double ground_albedo);
-void arhosekskymodelstate_free(ArHosekSkyModelState *state);
+void SKY_arhosekskymodelstate_free(SKY_ArHosekSkyModelState *state);
-double arhosekskymodel_radiance(ArHosekSkyModelState *state,
- double theta,
- double gamma,
- double wavelength);
+double SKY_arhosekskymodel_radiance(SKY_ArHosekSkyModelState *state,
+ double theta,
+ double gamma,
+ double wavelength);
// CIE XYZ and RGB versions
-ArHosekSkyModelState *arhosek_xyz_skymodelstate_alloc_init(const double turbidity,
- const double albedo,
- const double elevation);
+SKY_ArHosekSkyModelState *SKY_arhosek_xyz_skymodelstate_alloc_init(const double turbidity,
+ const double albedo,
+ const double elevation);
-ArHosekSkyModelState *arhosek_rgb_skymodelstate_alloc_init(const double turbidity,
- const double albedo,
- const double elevation);
+SKY_ArHosekSkyModelState *SKY_arhosek_rgb_skymodelstate_alloc_init(const double turbidity,
+ const double albedo,
+ const double elevation);
-double arhosek_tristim_skymodel_radiance(ArHosekSkyModelState *state,
- double theta,
- double gamma,
- int channel);
+double SKY_arhosek_tristim_skymodel_radiance(SKY_ArHosekSkyModelState *state,
+ double theta,
+ double gamma,
+ int channel);
// Delivers the complete function: sky + sun, including limb darkening.
// Please read the above description before using this - there are several
// caveats!
-double arhosekskymodel_solar_radiance(ArHosekSkyModelState *state,
- double theta,
- double gamma,
- double wavelength);
-
-#endif // _SKY_MODEL_H_
+double SKY_arhosekskymodel_solar_radiance(SKY_ArHosekSkyModelState *state,
+ double theta,
+ double gamma,
+ double wavelength);
/* Nishita improved sky model */
-void nishita_skymodel_precompute_texture(float *pixels,
- int stride,
- int start_y,
- int end_y,
- int width,
- int height,
- float sun_elevation,
+void SKY_nishita_skymodel_precompute_texture(float *pixels,
+ int stride,
+ int start_y,
+ int end_y,
+ int width,
+ int height,
+ float sun_elevation,
+ float altitude,
+ float air_density,
+ float dust_density,
+ float ozone_density);
+
+void SKY_nishita_skymodel_precompute_sun(float sun_elevation,
+ float angular_diameter,
float altitude,
float air_density,
float dust_density,
- float ozone_density);
+ float *r_pixel_bottom,
+ float *r_pixel_top);
-void nishita_skymodel_precompute_sun(float sun_elevation,
- float angular_diameter,
- float altitude,
- float air_density,
- float dust_density,
- float *pixel_bottom,
- float *pixel_top);
+#ifdef __cplusplus
+}
+#endif
-CCL_NAMESPACE_END
+#endif // __SKY_MODEL_H__
diff --git a/intern/sky/source/sky_float3.h b/intern/sky/source/sky_float3.h
new file mode 100644
index 00000000000..2a9b9c89623
--- /dev/null
+++ b/intern/sky/source/sky_float3.h
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+#ifndef __SKY_FLOAT3_H__
+#define __SKY_FLOAT3_H__
+
+// minimal float3 + util_math.h implementation for nishita sky model
+
+#include <math.h>
+
+#ifndef M_PI_F
+# define M_PI_F (3.1415926535897932f) /* pi */
+#endif
+#ifndef M_PI_2_F
+# define M_PI_2_F (1.5707963267948966f) /* pi/2 */
+#endif
+#ifndef M_2PI_F
+# define M_2PI_F (6.2831853071795864f) /* 2*pi */
+#endif
+
+struct float3 {
+ float x, y, z;
+
+ float3() = default;
+
+ float3(const float *ptr) : x{ptr[0]}, y{ptr[1]}, z{ptr[2]}
+ {
+ }
+
+ float3(const float (*ptr)[3]) : float3((const float *)ptr)
+ {
+ }
+
+ explicit float3(float value) : x(value), y(value), z(value)
+ {
+ }
+
+ explicit float3(int value) : x(value), y(value), z(value)
+ {
+ }
+
+ float3(float x, float y, float z) : x{x}, y{y}, z{z}
+ {
+ }
+
+ operator const float *() const
+ {
+ return &x;
+ }
+
+ operator float *()
+ {
+ return &x;
+ }
+
+ friend float3 operator*(const float3 &a, float b)
+ {
+ return {a.x * b, a.y * b, a.z * b};
+ }
+
+ friend float3 operator*(float b, const float3 &a)
+ {
+ return {a.x * b, a.y * b, a.z * b};
+ }
+
+ friend float3 operator-(const float3 &a, const float3 &b)
+ {
+ return {a.x - b.x, a.y - b.y, a.z - b.z};
+ }
+
+ friend float3 operator-(const float3 &a)
+ {
+ return {-a.x, -a.y, -a.z};
+ }
+
+ float length_squared() const
+ {
+ return x * x + y * y + z * z;
+ }
+
+ float length() const
+ {
+ return sqrt(length_squared());
+ }
+
+ static float distance(const float3 &a, const float3 &b)
+ {
+ return (a - b).length();
+ }
+
+ friend float3 operator+(const float3 &a, const float3 &b)
+ {
+ return {a.x + b.x, a.y + b.y, a.z + b.z};
+ }
+
+ void operator+=(const float3 &b)
+ {
+ this->x += b.x;
+ this->y += b.y;
+ this->z += b.z;
+ }
+
+ friend float3 operator*(const float3 &a, const float3 &b)
+ {
+ return {a.x * b.x, a.y * b.y, a.z * b.z};
+ }
+};
+
+inline float sqr(float a)
+{
+ return a * a;
+}
+
+inline float3 make_float3(float x, float y, float z)
+{
+ return float3(x, y, z);
+}
+
+inline float dot(const float3 &a, const float3 &b)
+{
+ return a.x * b.x + a.y * b.y + a.z * b.z;
+}
+
+inline float distance(const float3 &a, const float3 &b)
+{
+ return float3::distance(a, b);
+}
+
+inline float len_squared(float3 f)
+{
+ return f.length_squared();
+}
+
+inline float len(float3 f)
+{
+ return f.length();
+}
+
+inline float reduce_add(float3 f)
+{
+ return f.x + f.y + f.z;
+}
+
+#endif /* __SKY_FLOAT3_H__ */
diff --git a/intern/cycles/util/util_sky_model.cpp b/intern/sky/source/sky_model.cpp
index 8cdad8a90a4..64cf14ec030 100644
--- a/intern/cycles/util/util_sky_model.cpp
+++ b/intern/sky/source/sky_model.cpp
@@ -97,16 +97,14 @@ All instructions on how to use this code are in the accompanying header file.
*/
-#include "util/util_sky_model.h"
-#include "util/util_sky_model_data.h"
+#include "sky_model.h"
+#include "sky_model_data.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
-CCL_NAMESPACE_BEGIN
-
// Some macro definitions that occur elsewhere in ART, and that have to be
// replicated to make this a stand-alone module.
@@ -138,7 +136,7 @@ typedef const double *ArHosekSkyModel_Radiance_Dataset;
// internal functions
static void ArHosekSkyModel_CookConfiguration(ArHosekSkyModel_Dataset dataset,
- ArHosekSkyModelConfiguration config,
+ SKY_ArHosekSkyModelConfiguration config,
double turbidity,
double albedo,
double solar_elevation)
@@ -272,7 +270,7 @@ static double ArHosekSkyModel_CookRadianceConfiguration(ArHosekSkyModel_Radiance
return res;
}
-static double ArHosekSkyModel_GetRadianceInternal(ArHosekSkyModelConfiguration configuration,
+static double ArHosekSkyModel_GetRadianceInternal(SKY_ArHosekSkyModelConfiguration configuration,
double theta,
double gamma)
{
@@ -288,15 +286,15 @@ static double ArHosekSkyModel_GetRadianceInternal(ArHosekSkyModelConfiguration c
configuration[6] * mieM + configuration[7] * zenith);
}
-void arhosekskymodelstate_free(ArHosekSkyModelState *state)
+void SKY_arhosekskymodelstate_free(SKY_ArHosekSkyModelState *state)
{
free(state);
}
-double arhosekskymodel_radiance(ArHosekSkyModelState *state,
- double theta,
- double gamma,
- double wavelength)
+double SKY_arhosekskymodel_radiance(SKY_ArHosekSkyModelState *state,
+ double theta,
+ double gamma,
+ double wavelength)
{
int low_wl = (int)((wavelength - 320.0) / 40.0);
@@ -324,11 +322,11 @@ double arhosekskymodel_radiance(ArHosekSkyModelState *state,
// xyz and rgb versions
-ArHosekSkyModelState *arhosek_xyz_skymodelstate_alloc_init(const double turbidity,
- const double albedo,
- const double elevation)
+SKY_ArHosekSkyModelState *SKY_arhosek_xyz_skymodelstate_alloc_init(const double turbidity,
+ const double albedo,
+ const double elevation)
{
- ArHosekSkyModelState *state = ALLOC(ArHosekSkyModelState);
+ SKY_ArHosekSkyModelState *state = ALLOC(SKY_ArHosekSkyModelState);
state->solar_radius = TERRESTRIAL_SOLAR_RADIUS;
state->turbidity = turbidity;
@@ -345,5 +343,3 @@ ArHosekSkyModelState *arhosek_xyz_skymodelstate_alloc_init(const double turbidit
return state;
}
-
-CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_sky_model_data.h b/intern/sky/source/sky_model_data.h
index a2a3935eb84..8d98f84cdae 100644
--- a/intern/cycles/util/util_sky_model_data.h
+++ b/intern/sky/source/sky_model_data.h
@@ -91,8 +91,6 @@ an updated version of this code has been published!
============================================================================ */
-CCL_NAMESPACE_BEGIN
-
/*
This file contains the coefficient data for the XYZ colour space version of
@@ -3843,5 +3841,3 @@ static const double datasetXYZRad3[] = {
static const double *datasetsXYZ[] = {datasetXYZ1, datasetXYZ2, datasetXYZ3};
static const double *datasetsXYZRad[] = {datasetXYZRad1, datasetXYZRad2, datasetXYZRad3};
-
-CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_sky_nishita.cpp b/intern/sky/source/sky_nishita.cpp
index 92397804d43..f36bfcc3d7b 100644
--- a/intern/cycles/util/util_sky_nishita.cpp
+++ b/intern/sky/source/sky_nishita.cpp
@@ -14,22 +14,25 @@
* limitations under the License.
*/
-#include "util/util_math.h"
-#include "util/util_sky_model.h"
-
-CCL_NAMESPACE_BEGIN
+#include "sky_float3.h"
+#include "sky_model.h"
/* Constants */
-static const float rayleigh_scale = 8000.0f; // Rayleigh scale height (m)
-static const float mie_scale = 1200.0f; // Mie scale height (m)
-static const float mie_coeff = 2e-5f; // Mie scattering coefficient
-static const float mie_G = 0.76f; // aerosols anisotropy
-static const float earth_radius = 6360000.0f; // radius of Earth (m)
-static const float atmosphere_radius = 6420000.0f; // radius of atmosphere (m)
-static const int steps = 32; // segments per primary ray
-static const int steps_light = 16; // segments per sun connection ray
-static const int num_wavelengths = 21; // number of wavelengths
-/* irradiance at top of atmosphere */
+static const float rayleigh_scale = 8e3f; // Rayleigh scale height (m)
+static const float mie_scale = 1.2e3f; // Mie scale height (m)
+static const float mie_coeff = 2e-5f; // Mie scattering coefficient (m^-1)
+static const float mie_G = 0.76f; // aerosols anisotropy
+static const float sqr_G = mie_G * mie_G; // squared aerosols anisotropy
+static const float earth_radius = 6360e3f; // radius of Earth (m)
+static const float atmosphere_radius = 6420e3f; // radius of atmosphere (m)
+static const int steps = 32; // segments of primary ray
+static const int steps_light = 16; // segments of sun connection ray
+static const int num_wavelengths = 21; // number of wavelengths
+static const int min_wavelength = 380; // lowest sampled wavelength (nm)
+static const int max_wavelength = 780; // highest sampled wavelength (nm)
+// step between each sampled wavelength (nm)
+static const float step_lambda = (max_wavelength - min_wavelength) / (num_wavelengths - 1);
+/* Sun irradiance on top of the atmosphere (W*m^-2*nm^-1) */
static const float irradiance[] = {
1.45756829855592995315f, 1.56596305559738380175f, 1.65148449067670455293f,
1.71496242737209314555f, 1.75797983805020541226f, 1.78256407885924539336f,
@@ -38,7 +41,7 @@ static const float irradiance[] = {
1.61993437242451854274f, 1.57083597368892080581f, 1.51932335059305478886f,
1.46628494965214395407f, 1.41245852740172450623f, 1.35844961970384092709f,
1.30474913844739281998f, 1.25174963272610817455f, 1.19975998755420620867f};
-/* Rayleigh scattering coefficient */
+/* Rayleigh scattering coefficient (m^-1) */
static const float rayleigh_coeff[] = {
0.00005424820087636473f, 0.00004418549866505454f, 0.00003635151910165377f,
0.00003017929012024763f, 0.00002526320226989157f, 0.00002130859310621843f,
@@ -47,7 +50,7 @@ static const float rayleigh_coeff[] = {
0.00000765513700977967f, 0.00000674217203751443f, 0.00000596134125832052f,
0.00000529034598065810f, 0.00000471115687557433f, 0.00000420910481110487f,
0.00000377218381260133f, 0.00000339051255477280f, 0.00000305591531679811f};
-/* Ozone absorption coefficient */
+/* Ozone absorption coefficient (m^-1) */
static const float ozone_coeff[] = {
0.00000000325126849861f, 0.00000000585395365047f, 0.00000001977191155085f,
0.00000007309568762914f, 0.00000020084561514287f, 0.00000040383958096161f,
@@ -92,11 +95,10 @@ static float3 spec_to_xyz(float *spectrum)
xyz.y += cmf_xyz[i][1] * spectrum[i];
xyz.z += cmf_xyz[i][2] * spectrum[i];
}
- return xyz * (20 * 683 * 1e-9f);
+ return xyz * step_lambda;
}
/* Atmosphere volume models */
-
static float density_rayleigh(float height)
{
return expf(-height / rayleigh_scale);
@@ -124,8 +126,6 @@ static float phase_rayleigh(float mu)
static float phase_mie(float mu)
{
- static const float sqr_G = mie_G * mie_G;
-
return (3.0f * (1.0f - sqr_G) * (1.0f + sqr(mu))) /
(8.0f * M_PI_F * (2.0f + sqr_G) * powf((1.0f + sqr_G - 2.0f * mie_G * mu), 1.5));
}
@@ -135,11 +135,13 @@ static bool surface_intersection(float3 pos, float3 dir)
{
if (dir.z >= 0)
return false;
- float t = dot(dir, -pos) / len_squared(dir);
- float D = pos.x * pos.x - 2.0f * (-pos.x) * dir.x * t + dir.x * t * dir.x * t + pos.y * pos.y -
- 2.0f * (-pos.y) * dir.y * t + (dir.y * t) * (dir.y * t) + pos.z * pos.z -
- 2.0f * (-pos.z) * dir.z * t + dir.z * t * dir.z * t;
- return (D <= sqr(earth_radius));
+ float b = -2.0f * dot(dir, -pos);
+ float c = len_squared(pos) - sqr(earth_radius);
+ float t = b * b - 4.0f * c;
+ if (t >= 0.0f)
+ return true;
+ else
+ return false;
}
static float3 atmosphere_intersection(float3 pos, float3 dir)
@@ -152,40 +154,40 @@ static float3 atmosphere_intersection(float3 pos, float3 dir)
static float3 ray_optical_depth(float3 ray_origin, float3 ray_dir)
{
- /* This code computes the optical depth along a ray through the atmosphere. */
+ /* this code computes the optical depth along a ray through the atmosphere */
float3 ray_end = atmosphere_intersection(ray_origin, ray_dir);
float ray_length = distance(ray_origin, ray_end);
- /* To compute the optical depth, we step along the ray in segments and
- * accumulate the optical depth along each segment. */
+ /* to compute the optical depth, we step along the ray in segments and
+ * accumulate the optical depth along each segment */
float segment_length = ray_length / steps_light;
float3 segment = segment_length * ray_dir;
- /* Instead of tracking the transmission spectrum across all wavelengths directly,
+ /* instead of tracking the transmission spectrum across all wavelengths directly,
* we use the fact that the density always has the same spectrum for each type of
* scattering, so we split the density into a constant spectrum and a factor and
- * only track the factors. */
+ * only track the factors */
float3 optical_depth = make_float3(0.0f, 0.0f, 0.0f);
- /* The density of each segment is evaluated at its middle. */
+ /* the density of each segment is evaluated at its middle */
float3 P = ray_origin + 0.5f * segment;
+
for (int i = 0; i < steps_light; i++) {
- /* Compute height above sea level. */
+ /* height above sea level */
float height = len(P) - earth_radius;
- /* Accumulate optical depth of this segment (density is assumed to be constant along it). */
+ /* accumulate optical depth of this segment (density is assumed to be constant along it) */
float3 density = make_float3(
density_rayleigh(height), density_mie(height), density_ozone(height));
- optical_depth += segment_length * density;
+ optical_depth += density;
- /* Advance along ray. */
+ /* advance along ray */
P += segment;
}
- return optical_depth;
+ return optical_depth * segment_length;
}
-/* Single Scattering implementation */
static void single_scattering(float3 ray_dir,
float3 sun_dir,
float3 ray_origin,
@@ -194,44 +196,45 @@ static void single_scattering(float3 ray_dir,
float ozone_density,
float *r_spectrum)
{
- /* This code computes single-inscattering along a ray through the atmosphere. */
+ /* this code computes single-inscattering along a ray through the atmosphere */
float3 ray_end = atmosphere_intersection(ray_origin, ray_dir);
float ray_length = distance(ray_origin, ray_end);
- /* To compute the inscattering, we step along the ray in segments and accumulate
- * the inscattering as well as the optical depth along each segment. */
+ /* to compute the inscattering, we step along the ray in segments and accumulate
+ * the inscattering as well as the optical depth along each segment */
float segment_length = ray_length / steps;
float3 segment = segment_length * ray_dir;
- /* Instead of tracking the transmission spectrum across all wavelengths directly,
+ /* instead of tracking the transmission spectrum across all wavelengths directly,
* we use the fact that the density always has the same spectrum for each type of
* scattering, so we split the density into a constant spectrum and a factor and
- * only track the factors. */
+ * only track the factors */
float3 optical_depth = make_float3(0.0f, 0.0f, 0.0f);
- /* Zero out light accumulation. */
+ /* zero out light accumulation */
for (int wl = 0; wl < num_wavelengths; wl++) {
r_spectrum[wl] = 0.0f;
}
- /* Compute phase function for scattering and the density scale factor. */
+ /* phase function for scattering and the density scale factor */
float mu = dot(ray_dir, sun_dir);
float3 phase_function = make_float3(phase_rayleigh(mu), phase_mie(mu), 0.0f);
float3 density_scale = make_float3(air_density, dust_density, ozone_density);
- /* The density and in-scattering of each segment is evaluated at its middle. */
+ /* the density and in-scattering of each segment is evaluated at its middle */
float3 P = ray_origin + 0.5f * segment;
+
for (int i = 0; i < steps; i++) {
- /* Compute height above sea level. */
+ /* height above sea level */
float height = len(P) - earth_radius;
- /* Evaluate and accumulate optical depth along the ray. */
+ /* evaluate and accumulate optical depth along the ray */
float3 density = density_scale * make_float3(density_rayleigh(height),
density_mie(height),
density_ozone(height));
optical_depth += segment_length * density;
- /* If the earth isn't in the way, evaluate inscattering from the sun. */
+ /* if the Earth isn't in the way, evaluate inscattering from the sun */
if (!surface_intersection(P, sun_dir)) {
float3 light_optical_depth = density_scale * ray_optical_depth(P, sun_dir);
float3 total_optical_depth = optical_depth + light_optical_depth;
@@ -245,7 +248,7 @@ static void single_scattering(float3 ray_dir,
float3 scattering_density = density * make_float3(rayleigh_coeff[wl], mie_coeff, 0.0f);
- /* The total inscattered radiance from one segment is:
+ /* the total inscattered radiance from one segment is:
* Tr(A<->B) * Tr(B<->C) * sigma_s * phase * L * segment_length
*
* These terms are:
@@ -256,30 +259,29 @@ static void single_scattering(float3 ray_dir,
* length of the segment
*
* The code here is just that, with a bit of additional optimization to not store full
- * spectra for the optical depth.
+ * spectra for the optical depth
*/
r_spectrum[wl] += attenuation * reduce_add(phase_function * scattering_density) *
irradiance[wl] * segment_length;
}
}
- /* Advance along ray. */
+ /* advance along ray */
P += segment;
}
}
-/* calculate texture array */
-void nishita_skymodel_precompute_texture(float *pixels,
- int stride,
- int start_y,
- int end_y,
- int width,
- int height,
- float sun_elevation,
- float altitude,
- float air_density,
- float dust_density,
- float ozone_density)
+void SKY_nishita_skymodel_precompute_texture(float *pixels,
+ int stride,
+ int start_y,
+ int end_y,
+ int width,
+ int height,
+ float sun_elevation,
+ float altitude,
+ float air_density,
+ float dust_density,
+ float ozone_density)
{
/* calculate texture pixels */
float spectrum[num_wavelengths];
@@ -289,11 +291,13 @@ void nishita_skymodel_precompute_texture(float *pixels,
float latitude_step = M_PI_2_F / height;
float longitude_step = M_2PI_F / width;
+ float half_lat_step = latitude_step / 2.0f;
for (int y = start_y; y < end_y; y++) {
- float latitude = latitude_step * y;
+ /* sample more pixels toward the horizon */
+ float latitude = (M_PI_2_F + half_lat_step) * sqr((float)y / height);
- float *pixel_row = pixels + (y * width) * stride;
+ float *pixel_row = pixels + (y * width * stride);
for (int x = 0; x < half_width; x++) {
float longitude = longitude_step * x - M_PI_F;
@@ -301,18 +305,21 @@ void nishita_skymodel_precompute_texture(float *pixels,
single_scattering(dir, sun_dir, cam_pos, air_density, dust_density, ozone_density, spectrum);
float3 xyz = spec_to_xyz(spectrum);
- pixel_row[x * stride + 0] = xyz.x;
- pixel_row[x * stride + 1] = xyz.y;
- pixel_row[x * stride + 2] = xyz.z;
- int mirror_x = width - x - 1;
- pixel_row[mirror_x * stride + 0] = xyz.x;
- pixel_row[mirror_x * stride + 1] = xyz.y;
- pixel_row[mirror_x * stride + 2] = xyz.z;
+ /* store pixels */
+ int pos_x = x * stride;
+ pixel_row[pos_x] = xyz.x;
+ pixel_row[pos_x + 1] = xyz.y;
+ pixel_row[pos_x + 2] = xyz.z;
+ /* mirror sky */
+ int mirror_x = (width - x - 1) * stride;
+ pixel_row[mirror_x] = xyz.x;
+ pixel_row[mirror_x + 1] = xyz.y;
+ pixel_row[mirror_x + 2] = xyz.z;
}
}
}
-/* Sun disc */
+/*********** Sun ***********/
static void sun_radiation(float3 cam_dir,
float altitude,
float air_density,
@@ -323,22 +330,22 @@ static void sun_radiation(float3 cam_dir,
float3 cam_pos = make_float3(0, 0, earth_radius + altitude);
float3 optical_depth = ray_optical_depth(cam_pos, cam_dir);
- /* Compute final spectrum. */
+ /* compute final spectrum */
for (int i = 0; i < num_wavelengths; i++) {
- /* Combine spectra and the optical depth into transmittance. */
+ /* combine spectra and the optical depth into transmittance */
float transmittance = rayleigh_coeff[i] * optical_depth.x * air_density +
1.11f * mie_coeff * optical_depth.y * dust_density;
- r_spectrum[i] = (irradiance[i] / solid_angle) * expf(-transmittance);
+ r_spectrum[i] = irradiance[i] * expf(-transmittance) / solid_angle;
}
}
-void nishita_skymodel_precompute_sun(float sun_elevation,
- float angular_diameter,
- float altitude,
- float air_density,
- float dust_density,
- float *pixel_bottom,
- float *pixel_top)
+void SKY_nishita_skymodel_precompute_sun(float sun_elevation,
+ float angular_diameter,
+ float altitude,
+ float air_density,
+ float dust_density,
+ float *r_pixel_bottom,
+ float *r_pixel_top)
{
/* definitions */
float half_angular = angular_diameter / 2.0f;
@@ -360,12 +367,10 @@ void nishita_skymodel_precompute_sun(float sun_elevation,
pix_top = spec_to_xyz(spectrum);
/* store pixels */
- pixel_bottom[0] = pix_bottom.x;
- pixel_bottom[1] = pix_bottom.y;
- pixel_bottom[2] = pix_bottom.z;
- pixel_top[0] = pix_top.x;
- pixel_top[1] = pix_top.y;
- pixel_top[2] = pix_top.z;
+ r_pixel_bottom[0] = pix_bottom.x;
+ r_pixel_bottom[1] = pix_bottom.y;
+ r_pixel_bottom[2] = pix_bottom.z;
+ r_pixel_top[0] = pix_top.x;
+ r_pixel_top[1] = pix_top.y;
+ r_pixel_top[2] = pix_top.z;
}
-
-CCL_NAMESPACE_END