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/cycles/CMakeLists.txt22
-rw-r--r--intern/cycles/blender/CMakeLists.txt2
-rw-r--r--intern/cycles/blender/addon/ui.py2
-rw-r--r--intern/cycles/blender/blender_camera.cpp141
-rw-r--r--intern/cycles/blender/blender_curves.cpp83
-rw-r--r--intern/cycles/blender/blender_device.cpp3
-rw-r--r--intern/cycles/blender/blender_geometry.cpp99
-rw-r--r--intern/cycles/blender/blender_light.cpp106
-rw-r--r--intern/cycles/blender/blender_mesh.cpp165
-rw-r--r--intern/cycles/blender/blender_object.cpp272
-rw-r--r--intern/cycles/blender/blender_object_cull.cpp6
-rw-r--r--intern/cycles/blender/blender_particles.cpp14
-rw-r--r--intern/cycles/blender/blender_session.cpp38
-rw-r--r--intern/cycles/blender/blender_shader.cpp472
-rw-r--r--intern/cycles/blender/blender_sync.cpp194
-rw-r--r--intern/cycles/blender/blender_sync.h27
-rw-r--r--intern/cycles/blender/blender_util.h3
-rw-r--r--intern/cycles/blender/blender_volume.cpp15
-rw-r--r--intern/cycles/bvh/bvh.cpp20
-rw-r--r--intern/cycles/bvh/bvh_build.cpp36
-rw-r--r--intern/cycles/bvh/bvh_embree.cpp57
-rw-r--r--intern/cycles/bvh/bvh_optix.cpp22
-rw-r--r--intern/cycles/bvh/bvh_optix.h4
-rw-r--r--intern/cycles/bvh/bvh_split.cpp19
-rw-r--r--intern/cycles/bvh/bvh_unaligned.cpp8
-rw-r--r--intern/cycles/device/CMakeLists.txt1
-rw-r--r--intern/cycles/device/device.cpp22
-rw-r--r--intern/cycles/device/device.h3
-rw-r--r--intern/cycles/device/device_cpu.cpp5
-rw-r--r--intern/cycles/device/device_dummy.cpp83
-rw-r--r--intern/cycles/device/device_intern.h1
-rw-r--r--intern/cycles/device/device_memory.h8
-rw-r--r--intern/cycles/device/device_optix.cpp187
-rw-r--r--intern/cycles/device/device_task.h1
-rw-r--r--intern/cycles/graph/node.cpp86
-rw-r--r--intern/cycles/graph/node.h66
-rw-r--r--intern/cycles/kernel/CMakeLists.txt8
-rw-r--r--intern/cycles/kernel/geom/geom_attribute.h12
-rw-r--r--intern/cycles/kernel/geom/geom_curve.h144
-rw-r--r--intern/cycles/kernel/geom/geom_patch.h37
-rw-r--r--intern/cycles/kernel/geom/geom_primitive.h172
-rw-r--r--intern/cycles/kernel/geom/geom_subd_triangle.h75
-rw-r--r--intern/cycles/kernel/geom/geom_triangle.h227
-rw-r--r--intern/cycles/kernel/geom/geom_volume.h45
-rw-r--r--intern/cycles/kernel/kernel_compat_cuda.h4
-rw-r--r--intern/cycles/kernel/kernel_compat_opencl.h2
-rw-r--r--intern/cycles/kernel/kernel_compat_optix.h4
-rw-r--r--intern/cycles/kernel/kernel_types.h24
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h112
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h92
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h246
-rw-r--r--intern/cycles/kernel/kernels/optix/kernel_optix.cu7
-rw-r--r--intern/cycles/kernel/osl/CMakeLists.txt4
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp181
-rw-r--r--intern/cycles/kernel/shaders/node_attribute.osl10
-rw-r--r--intern/cycles/kernel/svm/svm_attribute.h176
-rw-r--r--intern/cycles/kernel/svm/svm_types.h7
-rw-r--r--intern/cycles/kernel/svm/svm_vertex_color.h6
-rw-r--r--intern/cycles/render/attribute.cpp38
-rw-r--r--intern/cycles/render/attribute.h1
-rw-r--r--intern/cycles/render/background.cpp14
-rw-r--r--intern/cycles/render/background.h23
-rw-r--r--intern/cycles/render/bake.cpp15
-rw-r--r--intern/cycles/render/buffers.cpp1
-rw-r--r--intern/cycles/render/buffers.h3
-rw-r--r--intern/cycles/render/camera.cpp76
-rw-r--r--intern/cycles/render/camera.h103
-rw-r--r--intern/cycles/render/film.cpp65
-rw-r--r--intern/cycles/render/film.h52
-rw-r--r--intern/cycles/render/geometry.cpp388
-rw-r--r--intern/cycles/render/geometry.h44
-rw-r--r--intern/cycles/render/graph.cpp22
-rw-r--r--intern/cycles/render/hair.cpp15
-rw-r--r--intern/cycles/render/hair.h10
-rw-r--r--intern/cycles/render/image.cpp2
-rw-r--r--intern/cycles/render/image.h2
-rw-r--r--intern/cycles/render/image_vdb.cpp12
-rw-r--r--intern/cycles/render/integrator.cpp16
-rw-r--r--intern/cycles/render/integrator.h71
-rw-r--r--intern/cycles/render/light.cpp98
-rw-r--r--intern/cycles/render/light.h60
-rw-r--r--intern/cycles/render/mesh.cpp173
-rw-r--r--intern/cycles/render/mesh.h85
-rw-r--r--intern/cycles/render/mesh_displace.cpp19
-rw-r--r--intern/cycles/render/mesh_subdivision.cpp69
-rw-r--r--intern/cycles/render/nodes.cpp184
-rw-r--r--intern/cycles/render/nodes.h661
-rw-r--r--intern/cycles/render/object.cpp96
-rw-r--r--intern/cycles/render/object.h42
-rw-r--r--intern/cycles/render/osl.cpp10
-rw-r--r--intern/cycles/render/scene.cpp40
-rw-r--r--intern/cycles/render/session.cpp162
-rw-r--r--intern/cycles/render/session.h13
-rw-r--r--intern/cycles/render/shader.cpp51
-rw-r--r--intern/cycles/render/shader.h24
-rw-r--r--intern/cycles/render/svm.cpp10
-rw-r--r--intern/cycles/render/volume.cpp30
-rw-r--r--intern/cycles/render/volume.h8
-rw-r--r--intern/cycles/subd/subd_dice.cpp6
-rw-r--r--intern/cycles/subd/subd_split.cpp12
-rw-r--r--intern/cycles/test/render_graph_finalize_test.cpp174
-rw-r--r--intern/cycles/util/util_array.h20
-rw-r--r--intern/cycles/util/util_types.h2
-rw-r--r--intern/ghost/CMakeLists.txt2
-rw-r--r--intern/ghost/GHOST_C-api.h398
-rw-r--r--intern/ghost/GHOST_IContext.h4
-rw-r--r--intern/ghost/GHOST_IEventConsumer.h4
-rw-r--r--intern/ghost/GHOST_ISystem.h86
-rw-r--r--intern/ghost/GHOST_ITimerTask.h2
-rw-r--r--intern/ghost/GHOST_IWindow.h98
-rw-r--r--intern/ghost/GHOST_Rect.h42
-rw-r--r--intern/ghost/GHOST_Types.h7
-rw-r--r--intern/ghost/intern/GHOST_Buttons.h6
-rw-r--r--intern/ghost/intern/GHOST_CallbackEventConsumer.h6
-rw-r--r--intern/ghost/intern/GHOST_Context.h16
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.h14
-rw-r--r--intern/ghost/intern/GHOST_ContextD3D.h14
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.h14
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.h14
-rw-r--r--intern/ghost/intern/GHOST_ContextNone.h18
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.h14
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.h14
-rw-r--r--intern/ghost/intern/GHOST_DisplayManager.h26
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCocoa.h18
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.h18
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerX11.h18
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.h18
-rw-r--r--intern/ghost/intern/GHOST_DropTargetX11.h32
-rw-r--r--intern/ghost/intern/GHOST_Event.h6
-rw-r--r--intern/ghost/intern/GHOST_EventButton.h14
-rw-r--r--intern/ghost/intern/GHOST_EventCursor.h15
-rw-r--r--intern/ghost/intern/GHOST_EventDragnDrop.h14
-rw-r--r--intern/ghost/intern/GHOST_EventKey.h14
-rw-r--r--intern/ghost/intern/GHOST_EventManager.h18
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.h6
-rw-r--r--intern/ghost/intern/GHOST_EventString.h8
-rw-r--r--intern/ghost/intern/GHOST_EventTrackpad.h8
-rw-r--r--intern/ghost/intern/GHOST_IXrGraphicsBinding.h4
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.h6
-rw-r--r--intern/ghost/intern/GHOST_ModifierKeys.h2
-rw-r--r--intern/ghost/intern/GHOST_System.h92
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h78
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm6
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp223
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h164
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp29
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h71
-rw-r--r--intern/ghost/intern/GHOST_TimerManager.h10
-rw-r--r--intern/ghost/intern/GHOST_TimerTask.h14
-rw-r--r--intern/ghost/intern/GHOST_Window.h63
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h78
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm28
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.h38
-rw-r--r--intern/ghost/intern/GHOST_WindowNULL.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp496
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h214
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h22
-rw-r--r--intern/ghost/intern/GHOST_XrContext.cpp2
-rw-r--r--intern/ghost/intern/GHOST_XrSession.cpp2
-rw-r--r--intern/ghost/test/CMakeLists.txt4
-rw-r--r--intern/libmv/CMakeLists.txt4
-rwxr-xr-xintern/libmv/bundle.sh4
-rw-r--r--intern/libmv/intern/reconstruction.cc23
-rw-r--r--intern/libmv/intern/reconstruction.h20
-rw-r--r--intern/libmv/libmv/image/array_nd_test.cc8
-rw-r--r--intern/libmv/libmv/multiview/homography.h34
-rw-r--r--intern/libmv/libmv/simple_pipeline/bundle.cc24
-rw-r--r--intern/libmv/libmv/simple_pipeline/bundle.h24
-rw-r--r--intern/libmv/libmv/simple_pipeline/camera_intrinsics.h24
-rw-r--r--intern/libmv/libmv/simple_pipeline/keyframe_selection.h10
-rw-r--r--intern/libmv/libmv/simple_pipeline/packed_intrinsics.cc6
-rw-r--r--intern/libmv/libmv/simple_pipeline/packed_intrinsics.h2
-rw-r--r--intern/mantaflow/extern/manta_fluid_API.h91
-rw-r--r--intern/mantaflow/intern/MANTA_main.cpp41
-rw-r--r--intern/mantaflow/intern/MANTA_main.h4
-rw-r--r--intern/mantaflow/intern/manta_fluid_API.cpp208
-rw-r--r--intern/mantaflow/intern/strings/fluid_script.h6
-rw-r--r--intern/mantaflow/intern/strings/liquid_script.h25
-rw-r--r--intern/sky/source/sky_model.cpp5
-rw-r--r--intern/sky/source/sky_nishita.cpp17
182 files changed, 6021 insertions, 4127 deletions
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 9d5b5a2d1a6..b1bb1d3654d 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -45,7 +45,7 @@ if(WITH_CYCLES_NATIVE_ONLY)
)
if(NOT MSVC)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
+ string(APPEND CMAKE_CXX_FLAGS " -march=native")
set(CYCLES_KERNEL_FLAGS "-march=native")
else()
if(NOT MSVC_NATIVE_ARCH_FLAGS)
@@ -101,10 +101,10 @@ elseif(WIN32 AND MSVC AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_AVX2_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
endif()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CYCLES_KERNEL_FLAGS}")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox")
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox")
- set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /Ox")
+ string(APPEND CMAKE_CXX_FLAGS " ${CYCLES_KERNEL_FLAGS}")
+ string(APPEND CMAKE_CXX_FLAGS_RELEASE " /Ox")
+ string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /Ox")
+ string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " /Ox")
elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
check_cxx_compiler_flag(-msse CXX_HAS_SSE)
check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
@@ -113,20 +113,20 @@ elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
# Assume no signal trapping for better code generation.
set(CYCLES_KERNEL_FLAGS "-fno-trapping-math")
# Avoid overhead of setting errno for NaNs.
- set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-math-errno")
+ string(APPEND CYCLES_KERNEL_FLAGS " -fno-math-errno")
# Let compiler optimize 0.0 - x without worrying about signed zeros.
- set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-signed-zeros")
+ string(APPEND CYCLES_KERNEL_FLAGS " -fno-signed-zeros")
if(CMAKE_COMPILER_IS_GNUCC)
# Assume no signal trapping for better code generation.
- set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-signaling-nans")
+ string(APPEND CYCLES_KERNEL_FLAGS " -fno-signaling-nans")
# Assume a fixed rounding mode for better constant folding.
- set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-rounding-math")
+ string(APPEND CYCLES_KERNEL_FLAGS " -fno-rounding-math")
endif()
if(CXX_HAS_SSE)
if(CMAKE_COMPILER_IS_GNUCC)
- set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -mfpmath=sse")
+ string(APPEND CYCLES_KERNEL_FLAGS " -mfpmath=sse")
endif()
set(CYCLES_SSE2_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -msse -msse2")
@@ -140,7 +140,7 @@ elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
endif()
endif()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CYCLES_KERNEL_FLAGS}")
+ string(APPEND CMAKE_CXX_FLAGS " ${CYCLES_KERNEL_FLAGS}")
elseif(WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "Intel")
check_cxx_compiler_flag(/QxSSE2 CXX_HAS_SSE)
check_cxx_compiler_flag(/arch:AVX CXX_HAS_AVX)
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index 0d805dc8683..2d48563d8a6 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -130,7 +130,7 @@ blender_add_lib(bf_intern_cycles "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# avoid link failure with clang 3.4 debug
if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT ${CMAKE_C_COMPILER_VERSION} VERSION_LESS '3.4')
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -gline-tables-only")
+ string(APPEND CMAKE_CXX_FLAGS_DEBUG " -gline-tables-only")
endif()
add_dependencies(bf_intern_cycles bf_rna)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 72d98e78c4d..6b88be3e7aa 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1271,7 +1271,7 @@ class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel):
layout.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False)
- col = layout.column(heading="Show in")
+ col = layout.column(heading="Show In")
col.prop(ob, "hide_viewport", text="Viewports", invert_checkbox=True, toggle=False)
col.prop(ob, "hide_render", text="Renders", invert_checkbox=True, toggle=False)
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index e1ab3b3fbc1..c1da9f1983f 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -388,18 +388,19 @@ static void blender_camera_sync(Camera *cam,
const char *viewname,
PointerRNA *cscene)
{
- /* copy camera to compare later */
- Camera prevcam = *cam;
float aspectratio, sensor_size;
/* viewplane */
- blender_camera_viewplane(bcam, width, height, &cam->viewplane, &aspectratio, &sensor_size);
+ BoundBox2D viewplane;
+ blender_camera_viewplane(bcam, width, height, &viewplane, &aspectratio, &sensor_size);
- cam->width = bcam->full_width;
- cam->height = bcam->full_height;
+ cam->set_viewplane_left(viewplane.left);
+ cam->set_viewplane_right(viewplane.right);
+ cam->set_viewplane_top(viewplane.top);
+ cam->set_viewplane_bottom(viewplane.bottom);
- cam->full_width = width;
- cam->full_height = height;
+ cam->set_full_width(width);
+ cam->set_full_height(height);
/* panorama sensor */
if (bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) {
@@ -422,85 +423,91 @@ static void blender_camera_sync(Camera *cam,
}
if (horizontal_fit) {
- cam->sensorwidth = sensor_size;
- cam->sensorheight = sensor_size * fit_yratio / fit_xratio;
+ cam->set_sensorwidth(sensor_size);
+ cam->set_sensorheight(sensor_size * fit_yratio / fit_xratio);
}
else {
- cam->sensorwidth = sensor_size * fit_xratio / fit_yratio;
- cam->sensorheight = sensor_size;
+ cam->set_sensorwidth(sensor_size * fit_xratio / fit_yratio);
+ cam->set_sensorheight(sensor_size);
}
}
/* clipping distances */
- cam->nearclip = bcam->nearclip;
- cam->farclip = bcam->farclip;
+ cam->set_nearclip(bcam->nearclip);
+ cam->set_farclip(bcam->farclip);
/* type */
- cam->type = bcam->type;
+ cam->set_camera_type(bcam->type);
/* panorama */
- cam->panorama_type = bcam->panorama_type;
- cam->fisheye_fov = bcam->fisheye_fov;
- cam->fisheye_lens = bcam->fisheye_lens;
- cam->latitude_min = bcam->latitude_min;
- cam->latitude_max = bcam->latitude_max;
+ cam->set_panorama_type(bcam->panorama_type);
+ cam->set_fisheye_fov(bcam->fisheye_fov);
+ cam->set_fisheye_lens(bcam->fisheye_lens);
+ cam->set_latitude_min(bcam->latitude_min);
+ cam->set_latitude_max(bcam->latitude_max);
- cam->longitude_min = bcam->longitude_min;
- cam->longitude_max = bcam->longitude_max;
+ cam->set_longitude_min(bcam->longitude_min);
+ cam->set_longitude_max(bcam->longitude_max);
/* panorama stereo */
- cam->interocular_distance = bcam->interocular_distance;
- cam->convergence_distance = bcam->convergence_distance;
- cam->use_spherical_stereo = bcam->use_spherical_stereo;
+ cam->set_interocular_distance(bcam->interocular_distance);
+ cam->set_convergence_distance(bcam->convergence_distance);
+ cam->set_use_spherical_stereo(bcam->use_spherical_stereo);
- if (cam->use_spherical_stereo) {
+ if (cam->get_use_spherical_stereo()) {
if (strcmp(viewname, "left") == 0)
- cam->stereo_eye = Camera::STEREO_LEFT;
+ cam->set_stereo_eye(Camera::STEREO_LEFT);
else if (strcmp(viewname, "right") == 0)
- cam->stereo_eye = Camera::STEREO_RIGHT;
+ cam->set_stereo_eye(Camera::STEREO_RIGHT);
else
- cam->stereo_eye = Camera::STEREO_NONE;
+ cam->set_stereo_eye(Camera::STEREO_NONE);
}
- cam->use_pole_merge = bcam->use_pole_merge;
- cam->pole_merge_angle_from = bcam->pole_merge_angle_from;
- cam->pole_merge_angle_to = bcam->pole_merge_angle_to;
+ cam->set_use_pole_merge(bcam->use_pole_merge);
+ cam->set_pole_merge_angle_from(bcam->pole_merge_angle_from);
+ cam->set_pole_merge_angle_to(bcam->pole_merge_angle_to);
/* anamorphic lens bokeh */
- cam->aperture_ratio = bcam->aperture_ratio;
+ cam->set_aperture_ratio(bcam->aperture_ratio);
/* perspective */
- cam->fov = 2.0f * atanf((0.5f * sensor_size) / bcam->lens / aspectratio);
- cam->focaldistance = bcam->focaldistance;
- cam->aperturesize = bcam->aperturesize;
- cam->blades = bcam->apertureblades;
- cam->bladesrotation = bcam->aperturerotation;
+ cam->set_fov(2.0f * atanf((0.5f * sensor_size) / bcam->lens / aspectratio));
+ cam->set_focaldistance(bcam->focaldistance);
+ cam->set_aperturesize(bcam->aperturesize);
+ cam->set_blades(bcam->apertureblades);
+ cam->set_bladesrotation(bcam->aperturerotation);
/* transform */
- cam->matrix = blender_camera_matrix(bcam->matrix, bcam->type, bcam->panorama_type);
- cam->motion.clear();
- cam->motion.resize(bcam->motion_steps, cam->matrix);
- cam->use_perspective_motion = false;
- cam->shuttertime = bcam->shuttertime;
- cam->fov_pre = cam->fov;
- cam->fov_post = cam->fov;
- cam->motion_position = bcam->motion_position;
+ cam->set_matrix(blender_camera_matrix(bcam->matrix, bcam->type, bcam->panorama_type));
- cam->rolling_shutter_type = bcam->rolling_shutter_type;
- cam->rolling_shutter_duration = bcam->rolling_shutter_duration;
+ array<Transform> motion;
+ motion.resize(bcam->motion_steps, cam->get_matrix());
+ cam->set_motion(motion);
+ cam->set_use_perspective_motion(false);
- cam->shutter_curve = bcam->shutter_curve;
+ cam->set_shuttertime(bcam->shuttertime);
+ cam->set_fov_pre(cam->get_fov());
+ cam->set_fov_post(cam->get_fov());
+ cam->set_motion_position(bcam->motion_position);
+
+ cam->set_rolling_shutter_type(bcam->rolling_shutter_type);
+ cam->set_rolling_shutter_duration(bcam->rolling_shutter_duration);
+
+ cam->set_shutter_curve(bcam->shutter_curve);
/* border */
- cam->border = bcam->border;
- cam->viewport_camera_border = bcam->viewport_camera_border;
+ cam->set_border_left(bcam->border.left);
+ cam->set_border_right(bcam->border.right);
+ cam->set_border_top(bcam->border.top);
+ cam->set_border_bottom(bcam->border.bottom);
- bcam->offscreen_dicing_scale = RNA_float_get(cscene, "offscreen_dicing_scale");
- cam->offscreen_dicing_scale = bcam->offscreen_dicing_scale;
+ cam->set_viewport_camera_border_left(bcam->viewport_camera_border.left);
+ cam->set_viewport_camera_border_right(bcam->viewport_camera_border.right);
+ cam->set_viewport_camera_border_top(bcam->viewport_camera_border.top);
+ cam->set_viewport_camera_border_bottom(bcam->viewport_camera_border.bottom);
- /* set update flag */
- if (cam->modified(prevcam))
- cam->tag_update();
+ bcam->offscreen_dicing_scale = RNA_float_get(cscene, "offscreen_dicing_scale");
+ cam->set_offscreen_dicing_scale(bcam->offscreen_dicing_scale);
}
/* Sync Render Camera */
@@ -582,22 +589,24 @@ void BlenderSync::sync_camera_motion(
Camera *cam = scene->camera;
BL::Array<float, 16> b_ob_matrix;
- b_engine.camera_model_matrix(b_ob, cam->use_spherical_stereo, b_ob_matrix);
+ b_engine.camera_model_matrix(b_ob, cam->get_use_spherical_stereo(), b_ob_matrix);
Transform tfm = get_transform(b_ob_matrix);
- tfm = blender_camera_matrix(tfm, cam->type, cam->panorama_type);
+ tfm = blender_camera_matrix(tfm, cam->get_camera_type(), cam->get_panorama_type());
if (motion_time == 0.0f) {
/* When motion blur is not centered in frame, cam->matrix gets reset. */
- cam->matrix = tfm;
+ cam->set_matrix(tfm);
}
/* Set transform in motion array. */
int motion_step = cam->motion_step(motion_time);
if (motion_step >= 0) {
- cam->motion[motion_step] = tfm;
+ array<Transform> motion = cam->get_motion();
+ motion[motion_step] = tfm;
+ cam->set_motion(motion);
}
- if (cam->type == CAMERA_PERSPECTIVE) {
+ if (cam->get_camera_type() == CAMERA_PERSPECTIVE) {
BlenderCamera bcam;
float aspectratio, sensor_size;
blender_camera_init(&bcam, b_render);
@@ -610,18 +619,18 @@ void BlenderSync::sync_camera_motion(
blender_camera_viewplane(&bcam, width, height, NULL, &aspectratio, &sensor_size);
/* TODO(sergey): De-duplicate calculation with camera sync. */
float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio);
- if (fov != cam->fov) {
+ if (fov != cam->get_fov()) {
VLOG(1) << "Camera " << b_ob.name() << " FOV change detected.";
if (motion_time == 0.0f) {
- cam->fov = fov;
+ cam->set_fov(fov);
}
else if (motion_time == -1.0f) {
- cam->fov_pre = fov;
- cam->use_perspective_motion = true;
+ cam->set_fov_pre(fov);
+ cam->set_use_perspective_motion(true);
}
else if (motion_time == 1.0f) {
- cam->fov_post = fov;
- cam->use_perspective_motion = true;
+ cam->set_fov_post(fov);
+ cam->set_use_perspective_motion(true);
}
}
}
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 6288c370567..8344684ac64 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -77,7 +77,7 @@ static bool ObtainCacheParticleData(
if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) &&
(b_part.type() == BL::ParticleSettings::type_HAIR)) {
- int shader = clamp(b_part.material() - 1, 0, hair->used_shaders.size() - 1);
+ int shader = clamp(b_part.material() - 1, 0, hair->get_used_shaders().size() - 1);
int display_step = background ? b_part.render_step() : b_part.display_step();
int totparts = b_psys.particles.length();
int totchild = background ? b_psys.child_particles.length() :
@@ -307,7 +307,7 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa
VLOG(1) << "Exporting curve segments for mesh " << hair->name;
}
- hair->reserve_curves(hair->num_curves() + num_curves, hair->curve_keys.size() + num_keys);
+ hair->reserve_curves(hair->num_curves() + num_curves, hair->get_curve_keys().size() + num_keys);
num_keys = 0;
num_curves = 0;
@@ -350,9 +350,9 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa
}
/* check allocation */
- if ((hair->curve_keys.size() != num_keys) || (hair->num_curves() != num_curves)) {
+ if ((hair->get_curve_keys().size() != num_keys) || (hair->num_curves() != num_curves)) {
VLOG(1) << "Allocation failed, clearing data";
- hair->clear();
+ hair->clear(true);
}
}
@@ -402,7 +402,7 @@ static void export_hair_motion_validate_attribute(Hair *hair,
bool have_motion)
{
Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- const int num_keys = hair->curve_keys.size();
+ const int num_keys = hair->get_curve_keys().size();
if (num_motion_keys != num_keys || !have_motion) {
/* No motion or hair "topology" changed, remove attributes again. */
@@ -423,8 +423,8 @@ static void export_hair_motion_validate_attribute(Hair *hair,
float4 *mP = attr_mP->data_float4() + step * num_keys;
for (int key = 0; key < num_keys; key++) {
- mP[key] = float3_to_float4(hair->curve_keys[key]);
- mP[key].w = hair->curve_radius[key];
+ mP[key] = float3_to_float4(hair->get_curve_keys()[key]);
+ mP[key].w = hair->get_curve_radius()[key];
}
}
}
@@ -447,7 +447,7 @@ static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int
}
/* export motion vectors for curve keys */
- size_t numkeys = hair->curve_keys.size();
+ size_t numkeys = hair->get_curve_keys().size();
float4 *mP = attr_mP->data_float4() + motion_step * numkeys;
bool have_motion = false;
int i = 0;
@@ -458,24 +458,24 @@ static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int
curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
curve++) {
/* Curve lengths may not match! Curves can be clipped. */
- int curve_key_end = (num_curves + 1 < (int)hair->curve_first_key.size() ?
- hair->curve_first_key[num_curves + 1] :
- (int)hair->curve_keys.size());
- const int num_center_curve_keys = curve_key_end - hair->curve_first_key[num_curves];
+ int curve_key_end = (num_curves + 1 < (int)hair->get_curve_first_key().size() ?
+ hair->get_curve_first_key()[num_curves + 1] :
+ (int)hair->get_curve_keys().size());
+ const int num_center_curve_keys = curve_key_end - hair->get_curve_first_key()[num_curves];
const int is_num_keys_different = CData->curve_keynum[curve] - num_center_curve_keys;
if (!is_num_keys_different) {
for (int curvekey = CData->curve_firstkey[curve];
curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve];
curvekey++) {
- if (i < hair->curve_keys.size()) {
+ if (i < hair->get_curve_keys().size()) {
mP[i] = CurveSegmentMotionCV(CData, sys, curve, curvekey);
if (!have_motion) {
/* unlike mesh coordinates, these tend to be slightly different
* between frames due to particle transforms into/out of object
* space, so we use an epsilon to detect actual changes */
- float4 curve_key = float3_to_float4(hair->curve_keys[i]);
- curve_key.w = hair->curve_radius[i];
+ float4 curve_key = float3_to_float4(hair->get_curve_keys()[i]);
+ curve_key.w = hair->get_curve_radius()[i];
if (len_squared(mP[i] - curve_key) > 1e-5f * 1e-5f)
have_motion = true;
}
@@ -560,7 +560,7 @@ void BlenderSync::sync_particle_hair(
float3 *generated = attr_generated->data_float3();
for (size_t i = 0; i < hair->num_curves(); i++) {
- float3 co = hair->curve_keys[hair->get_curve(i).first_key];
+ float3 co = hair->get_curve_keys()[hair->get_curve(i).first_key];
generated[i] = co * size - loc;
}
}
@@ -742,7 +742,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
}
/* Export motion keys. */
- const int num_keys = hair->curve_keys.size();
+ const int num_keys = hair->get_curve_keys().size();
float4 *mP = attr_mP->data_float4() + motion_step * num_keys;
bool have_motion = false;
int num_motion_keys = 0;
@@ -769,8 +769,8 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
if (!have_motion) {
/* TODO: use epsilon for comparison? Was needed for particles due to
* transform, but ideally should not happen anymore. */
- float4 curve_key = float3_to_float4(hair->curve_keys[i]);
- curve_key.w = hair->curve_radius[i];
+ float4 curve_key = float3_to_float4(hair->get_curve_keys()[i]);
+ curve_key.w = hair->get_curve_radius()[i];
have_motion = !(mP[i] == curve_key);
}
}
@@ -817,42 +817,53 @@ void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motio
}
#endif
-void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph,
- BL::Object b_ob,
- Hair *hair,
- const vector<Shader *> &used_shaders)
+void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair)
{
- /* Compares curve_keys rather than strands in order to handle quick hair
- * adjustments in dynamic BVH - other methods could probably do this better. */
- array<float3> oldcurve_keys;
- array<float> oldcurve_radius;
- oldcurve_keys.steal_data(hair->curve_keys);
- oldcurve_radius.steal_data(hair->curve_radius);
+ /* make a copy of the shaders as the caller in the main thread still need them for syncing the
+ * attributes */
+ array<Node *> used_shaders = hair->get_used_shaders();
- hair->clear();
- hair->used_shaders = used_shaders;
+ Hair new_hair;
+ new_hair.set_used_shaders(used_shaders);
if (view_layer.use_hair) {
if (b_ob.type() == BL::Object::type_HAIR) {
/* Hair object. */
- sync_hair(hair, b_ob, false);
+ sync_hair(&new_hair, b_ob, false);
}
else {
/* Particle hair. */
- bool need_undeformed = hair->need_attribute(scene, ATTR_STD_GENERATED);
+ bool need_undeformed = new_hair.need_attribute(scene, ATTR_STD_GENERATED);
BL::Mesh b_mesh = object_to_mesh(
b_data, b_ob, b_depsgraph, need_undeformed, Mesh::SUBDIVISION_NONE);
if (b_mesh) {
- sync_particle_hair(hair, b_mesh, b_ob, false);
+ sync_particle_hair(&new_hair, b_mesh, b_ob, false);
free_object_to_mesh(b_data, b_ob, b_mesh);
}
}
}
+ /* update original sockets */
+
+ for (const SocketType &socket : new_hair.type->inputs) {
+ /* Those sockets are updated in sync_object, so do not modify them. */
+ if (socket.name == "use_motion_blur" || socket.name == "motion_steps" ||
+ socket.name == "used_shaders") {
+ continue;
+ }
+ hair->set_value(socket, new_hair, socket);
+ }
+
+ foreach (Attribute &attr, new_hair.attributes.attributes) {
+ hair->attributes.attributes.push_back(std::move(attr));
+ }
+
/* tag update */
- const bool rebuild = ((oldcurve_keys != hair->curve_keys) ||
- (oldcurve_radius != hair->curve_radius));
+
+ /* Compares curve_keys rather than strands in order to handle quick hair
+ * adjustments in dynamic BVH - other methods could probably do this better. */
+ const bool rebuild = (hair->curve_keys_is_modified() || hair->curve_radius_is_modified());
hair->tag_update(scene, rebuild);
}
diff --git a/intern/cycles/blender/blender_device.cpp b/intern/cycles/blender/blender_device.cpp
index 0293223864d..ffcaef0b2a9 100644
--- a/intern/cycles/blender/blender_device.cpp
+++ b/intern/cycles/blender/blender_device.cpp
@@ -47,8 +47,7 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen
vector<DeviceInfo> devices = Device::available_devices(BlenderSession::device_override);
if (devices.empty()) {
- printf("Found no Cycles device of the specified type, falling back to CPU...\n");
- return Device::available_devices(DEVICE_MASK_CPU).front();
+ return Device::dummy_device("Found no Cycles device of the specified type");
}
int threads = blender_device_threads(b_scene);
diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp
index a665bd97a8d..bd2f0731030 100644
--- a/intern/cycles/blender/blender_geometry.cpp
+++ b/intern/cycles/blender/blender_geometry.cpp
@@ -25,6 +25,7 @@
#include "blender/blender_util.h"
#include "util/util_foreach.h"
+#include "util/util_task.h"
CCL_NAMESPACE_BEGIN
@@ -45,7 +46,8 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
BL::Object &b_ob,
BL::Object &b_ob_instance,
bool object_updated,
- bool use_particle_hair)
+ bool use_particle_hair,
+ TaskPool *task_pool)
{
/* Test if we can instance or if the object is modified. */
BL::ID b_ob_data = b_ob.data();
@@ -57,7 +59,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
GeometryKey key(b_key_id.ptr.data, geom_type);
/* Find shader indices. */
- vector<Shader *> used_shaders;
+ array<Node *> used_shaders;
BL::Object::material_slots_iterator slot;
for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
@@ -74,11 +76,18 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
if (material_override)
find_shader(material_override, used_shaders, default_shader);
else
- used_shaders.push_back(default_shader);
+ used_shaders.push_back_slow(default_shader);
}
- /* Test if we need to sync. */
+ /* Ensure we only sync instanced geometry once. */
Geometry *geom = geometry_map.find(key);
+ if (geom) {
+ if (geometry_synced.find(geom) != geometry_synced.end()) {
+ return geom;
+ }
+ }
+
+ /* Test if we need to sync. */
bool sync = true;
if (geom == NULL) {
/* Add new geometry if it did not exist yet. */
@@ -105,7 +114,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
}
/* Test if shaders changed, these can be object level so geometry
* does not get tagged for recalc. */
- else if (geom->used_shaders != used_shaders) {
+ else if (geom->get_used_shaders() != used_shaders) {
;
}
else {
@@ -113,7 +122,8 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
* because the shader needs different geometry attributes. */
bool attribute_recalc = false;
- foreach (Shader *shader, geom->used_shaders) {
+ foreach (Node *node, geom->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
if (shader->need_update_geometry) {
attribute_recalc = true;
}
@@ -125,28 +135,39 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
}
}
- /* Ensure we only sync instanced geometry once. */
- if (geometry_synced.find(geom) != geometry_synced.end()) {
- return geom;
- }
-
- progress.set_sync_status("Synchronizing object", b_ob.name());
-
geometry_synced.insert(geom);
geom->name = ustring(b_ob_data.name().c_str());
- if (geom_type == Geometry::HAIR) {
- Hair *hair = static_cast<Hair *>(geom);
- sync_hair(b_depsgraph, b_ob, hair, used_shaders);
- }
- else if (geom_type == Geometry::VOLUME) {
- Volume *volume = static_cast<Volume *>(geom);
- sync_volume(b_ob, volume, used_shaders);
+ /* Store the shaders immediately for the object attribute code. */
+ geom->set_used_shaders(used_shaders);
+
+ auto sync_func = [=]() mutable {
+ if (progress.get_cancel())
+ return;
+
+ progress.set_sync_status("Synchronizing object", b_ob.name());
+
+ if (geom_type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ sync_hair(b_depsgraph, b_ob, hair);
+ }
+ else if (geom_type == Geometry::VOLUME) {
+ Volume *volume = static_cast<Volume *>(geom);
+ sync_volume(b_ob, volume);
+ }
+ else {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ sync_mesh(b_depsgraph, b_ob, mesh);
+ }
+ };
+
+ /* Defer the actual geometry sync to the task_pool for multithreading */
+ if (task_pool) {
+ task_pool->push(sync_func);
}
else {
- Mesh *mesh = static_cast<Mesh *>(geom);
- sync_mesh(b_depsgraph, b_ob, mesh, used_shaders);
+ sync_func();
}
return geom;
@@ -156,10 +177,11 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
BL::Object &b_ob,
Object *object,
float motion_time,
- bool use_particle_hair)
+ bool use_particle_hair,
+ TaskPool *task_pool)
{
/* Ensure we only sync instanced geometry once. */
- Geometry *geom = object->geometry;
+ Geometry *geom = object->get_geometry();
if (geometry_motion_synced.find(geom) != geometry_motion_synced.end())
return;
@@ -177,16 +199,29 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
return;
}
- if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
- Hair *hair = static_cast<Hair *>(geom);
- sync_hair_motion(b_depsgraph, b_ob, hair, motion_step);
- }
- else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
- /* No volume motion blur support yet. */
+ auto sync_func = [=]() mutable {
+ if (progress.get_cancel())
+ return;
+
+ if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
+ Hair *hair = static_cast<Hair *>(geom);
+ sync_hair_motion(b_depsgraph, b_ob, hair, motion_step);
+ }
+ else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
+ /* No volume motion blur support yet. */
+ }
+ else {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step);
+ }
+ };
+
+ /* Defer the actual geometry sync to the task_pool for multithreading */
+ if (task_pool) {
+ task_pool->push(sync_func);
}
else {
- Mesh *mesh = static_cast<Mesh *>(geom);
- sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step);
+ sync_func();
}
}
diff --git a/intern/cycles/blender/blender_light.cpp b/intern/cycles/blender/blender_light.cpp
index 6f95821e31e..ff4ecc5a3f9 100644
--- a/intern/cycles/blender/blender_light.cpp
+++ b/intern/cycles/blender/blender_light.cpp
@@ -42,7 +42,7 @@ void BlenderSync::sync_light(BL::Object &b_parent,
if (!light_map.add_or_update(&light, b_ob, b_parent, key)) {
Shader *shader;
if (!shader_map.add_or_update(&shader, b_light)) {
- if (light->is_portal)
+ if (light->get_is_portal())
*use_portal = true;
return;
}
@@ -52,16 +52,16 @@ void BlenderSync::sync_light(BL::Object &b_parent,
switch (b_light.type()) {
case BL::Light::type_POINT: {
BL::PointLight b_point_light(b_light);
- light->size = b_point_light.shadow_soft_size();
- light->type = LIGHT_POINT;
+ light->set_size(b_point_light.shadow_soft_size());
+ light->set_light_type(LIGHT_POINT);
break;
}
case BL::Light::type_SPOT: {
BL::SpotLight b_spot_light(b_light);
- light->size = b_spot_light.shadow_soft_size();
- light->type = LIGHT_SPOT;
- light->spot_angle = b_spot_light.spot_size();
- light->spot_smooth = b_spot_light.spot_blend();
+ light->set_size(b_spot_light.shadow_soft_size());
+ light->set_light_type(LIGHT_SPOT);
+ light->set_spot_angle(b_spot_light.spot_size());
+ light->set_spot_smooth(b_spot_light.spot_blend());
break;
}
/* Hemi were removed from 2.8 */
@@ -72,88 +72,88 @@ void BlenderSync::sync_light(BL::Object &b_parent,
// }
case BL::Light::type_SUN: {
BL::SunLight b_sun_light(b_light);
- light->angle = b_sun_light.angle();
- light->type = LIGHT_DISTANT;
+ light->set_angle(b_sun_light.angle());
+ light->set_light_type(LIGHT_DISTANT);
break;
}
case BL::Light::type_AREA: {
BL::AreaLight b_area_light(b_light);
- light->size = 1.0f;
- light->axisu = transform_get_column(&tfm, 0);
- light->axisv = transform_get_column(&tfm, 1);
- light->sizeu = b_area_light.size();
+ light->set_size(1.0f);
+ light->set_axisu(transform_get_column(&tfm, 0));
+ light->set_axisv(transform_get_column(&tfm, 1));
+ light->set_sizeu(b_area_light.size());
switch (b_area_light.shape()) {
case BL::AreaLight::shape_SQUARE:
- light->sizev = light->sizeu;
- light->round = false;
+ light->set_sizev(light->get_sizeu());
+ light->set_round(false);
break;
case BL::AreaLight::shape_RECTANGLE:
- light->sizev = b_area_light.size_y();
- light->round = false;
+ light->set_sizev(b_area_light.size_y());
+ light->set_round(false);
break;
case BL::AreaLight::shape_DISK:
- light->sizev = light->sizeu;
- light->round = true;
+ light->set_sizev(light->get_sizeu());
+ light->set_round(true);
break;
case BL::AreaLight::shape_ELLIPSE:
- light->sizev = b_area_light.size_y();
- light->round = true;
+ light->set_sizev(b_area_light.size_y());
+ light->set_round(true);
break;
}
- light->type = LIGHT_AREA;
+ light->set_light_type(LIGHT_AREA);
break;
}
}
/* strength */
- light->strength = get_float3(b_light.color());
- light->strength *= BL::PointLight(b_light).energy();
+ float3 strength = get_float3(b_light.color()) * BL::PointLight(b_light).energy();
+ light->set_strength(strength);
/* location and (inverted!) direction */
- light->co = transform_get_column(&tfm, 3);
- light->dir = -transform_get_column(&tfm, 2);
- light->tfm = tfm;
+ light->set_co(transform_get_column(&tfm, 3));
+ light->set_dir(-transform_get_column(&tfm, 2));
+ light->set_tfm(tfm);
/* shader */
- vector<Shader *> used_shaders;
+ array<Node *> used_shaders;
find_shader(b_light, used_shaders, scene->default_light);
- light->shader = used_shaders[0];
+ light->set_shader(static_cast<Shader *>(used_shaders[0]));
/* shadow */
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles");
- light->cast_shadow = get_boolean(clight, "cast_shadow");
- light->use_mis = get_boolean(clight, "use_multiple_importance_sampling");
+ light->set_cast_shadow(get_boolean(clight, "cast_shadow"));
+ light->set_use_mis(get_boolean(clight, "use_multiple_importance_sampling"));
int samples = get_int(clight, "samples");
if (get_boolean(cscene, "use_square_samples"))
- light->samples = samples * samples;
+ light->set_samples(samples * samples);
else
- light->samples = samples;
+ light->set_samples(samples);
- light->max_bounces = get_int(clight, "max_bounces");
+ light->set_max_bounces(get_int(clight, "max_bounces"));
if (b_ob != b_ob_instance) {
- light->random_id = random_id;
+ light->set_random_id(random_id);
}
else {
- light->random_id = hash_uint2(hash_string(b_ob.name().c_str()), 0);
+ light->set_random_id(hash_uint2(hash_string(b_ob.name().c_str()), 0));
}
- if (light->type == LIGHT_AREA)
- light->is_portal = get_boolean(clight, "is_portal");
+ if (light->get_light_type() == LIGHT_AREA)
+ light->set_is_portal(get_boolean(clight, "is_portal"));
else
- light->is_portal = false;
+ light->set_is_portal(false);
- if (light->is_portal)
+ if (light->get_is_portal())
*use_portal = true;
/* visibility */
uint visibility = object_ray_visibility(b_ob);
- light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
- light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0;
- light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0;
- light->use_scatter = (visibility & PATH_RAY_VOLUME_SCATTER) != 0;
+ light->set_use_diffuse((visibility & PATH_RAY_DIFFUSE) != 0);
+ light->set_use_glossy((visibility & PATH_RAY_GLOSSY) != 0);
+ light->set_use_transmission((visibility & PATH_RAY_TRANSMIT) != 0);
+ light->set_use_scatter((visibility & PATH_RAY_VOLUME_SCATTER) != 0);
/* tag */
light->tag_update(scene);
@@ -178,25 +178,25 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
if (light_map.add_or_update(&light, b_world, b_world, key) || world_recalc ||
b_world.ptr.data != world_map) {
- light->type = LIGHT_BACKGROUND;
+ light->set_light_type(LIGHT_BACKGROUND);
if (sampling_method == SAMPLING_MANUAL) {
- light->map_resolution = get_int(cworld, "sample_map_resolution");
+ light->set_map_resolution(get_int(cworld, "sample_map_resolution"));
}
else {
- light->map_resolution = 0;
+ light->set_map_resolution(0);
}
- light->shader = scene->default_background;
- light->use_mis = sample_as_light;
- light->max_bounces = get_int(cworld, "max_bounces");
+ light->set_shader(scene->default_background);
+ light->set_use_mis(sample_as_light);
+ light->set_max_bounces(get_int(cworld, "max_bounces"));
/* force enable light again when world is resynced */
- light->is_enabled = true;
+ light->set_is_enabled(true);
int samples = get_int(cworld, "samples");
if (get_boolean(cscene, "use_square_samples"))
- light->samples = samples * samples;
+ light->set_samples(samples * samples);
else
- light->samples = samples;
+ light->set_samples(samples);
light->tag_update(scene);
light_map.set_recalc(b_world);
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index e40e1f5f001..20637af96df 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -48,8 +48,8 @@ struct MikkUserData {
float *tangent_sign)
: mesh(mesh), texface(NULL), orco(NULL), tangent(tangent), tangent_sign(tangent_sign)
{
- const AttributeSet &attributes = (mesh->subd_faces.size()) ? mesh->subd_attributes :
- mesh->attributes;
+ const AttributeSet &attributes = (mesh->get_num_subd_faces()) ? mesh->subd_attributes :
+ mesh->attributes;
Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
vertex_normal = attr_vN->data_float3();
@@ -85,8 +85,8 @@ struct MikkUserData {
static int mikk_get_num_faces(const SMikkTSpaceContext *context)
{
const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
- if (userdata->mesh->subd_faces.size()) {
- return userdata->mesh->subd_faces.size();
+ if (userdata->mesh->get_num_subd_faces()) {
+ return userdata->mesh->get_num_subd_faces();
}
else {
return userdata->mesh->num_triangles();
@@ -96,9 +96,9 @@ static int mikk_get_num_faces(const SMikkTSpaceContext *context)
static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num)
{
const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
- if (userdata->mesh->subd_faces.size()) {
+ if (userdata->mesh->get_num_subd_faces()) {
const Mesh *mesh = userdata->mesh;
- return mesh->subd_faces[face_num].num_corners;
+ return mesh->get_subd_num_corners()[face_num];
}
else {
return 3;
@@ -107,19 +107,19 @@ static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const i
static int mikk_vertex_index(const Mesh *mesh, const int face_num, const int vert_num)
{
- if (mesh->subd_faces.size()) {
- const Mesh::SubdFace &face = mesh->subd_faces[face_num];
- return mesh->subd_face_corners[face.start_corner + vert_num];
+ if (mesh->get_num_subd_faces()) {
+ const Mesh::SubdFace &face = mesh->get_subd_face(face_num);
+ return mesh->get_subd_face_corners()[face.start_corner + vert_num];
}
else {
- return mesh->triangles[face_num * 3 + vert_num];
+ return mesh->get_triangles()[face_num * 3 + vert_num];
}
}
static int mikk_corner_index(const Mesh *mesh, const int face_num, const int vert_num)
{
- if (mesh->subd_faces.size()) {
- const Mesh::SubdFace &face = mesh->subd_faces[face_num];
+ if (mesh->get_num_subd_faces()) {
+ const Mesh::SubdFace &face = mesh->get_subd_face(face_num);
return face.start_corner + vert_num;
}
else {
@@ -135,7 +135,7 @@ static void mikk_get_position(const SMikkTSpaceContext *context,
const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
const Mesh *mesh = userdata->mesh;
const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
- const float3 vP = mesh->verts[vertex_index];
+ const float3 vP = mesh->get_verts()[vertex_index];
P[0] = vP.x;
P[1] = vP.y;
P[2] = vP.z;
@@ -178,8 +178,8 @@ static void mikk_get_normal(const SMikkTSpaceContext *context,
const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
const Mesh *mesh = userdata->mesh;
float3 vN;
- if (mesh->subd_faces.size()) {
- const Mesh::SubdFace &face = mesh->subd_faces[face_num];
+ if (mesh->get_num_subd_faces()) {
+ const Mesh::SubdFace &face = mesh->get_subd_face(face_num);
if (face.smooth) {
const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
vN = userdata->vertex_normal[vertex_index];
@@ -189,13 +189,13 @@ static void mikk_get_normal(const SMikkTSpaceContext *context,
}
}
else {
- if (mesh->smooth[face_num]) {
+ if (mesh->get_smooth()[face_num]) {
const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
vN = userdata->vertex_normal[vertex_index];
}
else {
const Mesh::Triangle tri = mesh->get_triangle(face_num);
- vN = tri.compute_normal(&mesh->verts[0]);
+ vN = tri.compute_normal(&mesh->get_verts()[0]);
}
}
N[0] = vN.x;
@@ -222,7 +222,8 @@ static void mikk_compute_tangents(
const BL::Mesh &b_mesh, const char *layer_name, Mesh *mesh, bool need_sign, bool active_render)
{
/* Create tangent attributes. */
- AttributeSet &attributes = (mesh->subd_faces.size()) ? mesh->subd_attributes : mesh->attributes;
+ AttributeSet &attributes = (mesh->get_num_subd_faces()) ? mesh->subd_attributes :
+ mesh->attributes;
Attribute *attr;
ustring name;
if (layer_name != NULL) {
@@ -554,7 +555,7 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b
for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
sorted_vert_indeices[vert_index] = vert_index;
}
- VertexAverageComparator compare(mesh->verts);
+ VertexAverageComparator compare(mesh->get_verts());
sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare);
/* This array stores index of the original vertex for the given vertex
* index.
@@ -562,12 +563,12 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b
vector<int> vert_orig_index(num_verts);
for (int sorted_vert_index = 0; sorted_vert_index < num_verts; ++sorted_vert_index) {
const int vert_index = sorted_vert_indeices[sorted_vert_index];
- const float3 &vert_co = mesh->verts[vert_index];
+ const float3 &vert_co = mesh->get_verts()[vert_index];
bool found = false;
for (int other_sorted_vert_index = sorted_vert_index + 1; other_sorted_vert_index < num_verts;
++other_sorted_vert_index) {
const int other_vert_index = sorted_vert_indeices[other_sorted_vert_index];
- const float3 &other_vert_co = mesh->verts[other_vert_index];
+ const float3 &other_vert_co = mesh->get_verts()[other_vert_index];
/* We are too far away now, we wouldn't have duplicate. */
if ((other_vert_co.x + other_vert_co.y + other_vert_co.z) -
(vert_co.x + vert_co.y + vert_co.z) >
@@ -732,7 +733,7 @@ static void attr_create_random_per_island(Scene *scene,
static void create_mesh(Scene *scene,
Mesh *mesh,
BL::Mesh &b_mesh,
- const vector<Shader *> &used_shaders,
+ const array<Node *> &used_shaders,
bool subdivision = false,
bool subdivide_uvs = true)
{
@@ -743,7 +744,7 @@ static void create_mesh(Scene *scene,
int numcorners = 0;
int numngons = 0;
bool use_loop_normals = b_mesh.use_auto_smooth() &&
- (mesh->subdivision_type != Mesh::SUBDIVISION_CATMULL_CLARK);
+ (mesh->get_subdivision_type() != Mesh::SUBDIVISION_CATMULL_CLARK);
/* If no faces, create empty mesh. */
if (numfaces == 0) {
@@ -762,8 +763,11 @@ static void create_mesh(Scene *scene,
}
/* allocate memory */
+ if (subdivision) {
+ mesh->reserve_subd_faces(numfaces, numngons, numcorners);
+ }
+
mesh->reserve_mesh(numverts, numtris);
- mesh->reserve_subd_faces(numfaces, numngons, numcorners);
/* create vertex coordinates and normals */
BL::Mesh::vertices_iterator v;
@@ -875,7 +879,7 @@ static void create_subd_mesh(Scene *scene,
Mesh *mesh,
BL::Object &b_ob,
BL::Mesh &b_mesh,
- const vector<Shader *> &used_shaders,
+ const array<Node *> &used_shaders,
float dicing_rate,
int max_subdivisions)
{
@@ -894,31 +898,21 @@ static void create_subd_mesh(Scene *scene,
}
}
- mesh->subd_creases.resize(num_creases);
+ mesh->reserve_subd_creases(num_creases);
- Mesh::SubdEdgeCrease *crease = mesh->subd_creases.data();
for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) {
if (e->crease() != 0.0f) {
- crease->v[0] = e->vertices()[0];
- crease->v[1] = e->vertices()[1];
- crease->crease = e->crease();
-
- crease++;
+ mesh->add_crease(e->vertices()[0], e->vertices()[1], e->crease());
}
}
/* set subd params */
- if (!mesh->subd_params) {
- mesh->subd_params = new SubdParams(mesh);
- }
- SubdParams &sdparams = *mesh->subd_params;
-
PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
+ float subd_dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate);
- sdparams.dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate);
- sdparams.max_level = max_subdivisions;
-
- sdparams.objecttoworld = get_transform(b_ob.matrix_world());
+ mesh->set_subd_dicing_rate(subd_dicing_rate);
+ mesh->set_subd_max_level(max_subdivisions);
+ mesh->set_subd_objecttoworld(get_transform(b_ob.matrix_world()));
}
/* Sync */
@@ -955,14 +949,14 @@ static void sync_mesh_cached_velocities(BL::Object &b_ob, Scene *scene, Mesh *me
return;
}
- const size_t numverts = mesh->verts.size();
+ const size_t numverts = mesh->get_verts().size();
if (b_mesh_cache.vertex_velocities.length() != numverts) {
return;
}
/* Find or add attribute */
- float3 *P = &mesh->verts[0];
+ float3 *P = &mesh->get_verts()[0];
Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (!attr_mP) {
@@ -996,11 +990,11 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
return;
/* If the mesh has modifiers following the fluid domain we can't export motion. */
- if (b_fluid_domain.mesh_vertices.length() != mesh->verts.size())
+ if (b_fluid_domain.mesh_vertices.length() != mesh->get_verts().size())
return;
/* Find or add attribute */
- float3 *P = &mesh->verts[0];
+ float3 *P = &mesh->get_verts()[0];
Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (!attr_mP) {
@@ -1011,7 +1005,7 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
float motion_times[2] = {-1.0f, 1.0f};
for (int step = 0; step < 2; step++) {
float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f;
- float3 *mP = attr_mP->data_float3() + step * mesh->verts.size();
+ float3 *mP = attr_mP->data_float3() + step * mesh->get_verts().size();
BL::FluidDomainSettings::mesh_vertices_iterator svi;
int i = 0;
@@ -1023,56 +1017,77 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
}
}
-void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph,
- BL::Object b_ob,
- Mesh *mesh,
- const vector<Shader *> &used_shaders)
+void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh)
{
- array<int> oldtriangles;
- array<Mesh::SubdFace> oldsubd_faces;
- array<int> oldsubd_face_corners;
- oldtriangles.steal_data(mesh->triangles);
- oldsubd_faces.steal_data(mesh->subd_faces);
- oldsubd_face_corners.steal_data(mesh->subd_face_corners);
+ /* make a copy of the shaders as the caller in the main thread still need them for syncing the
+ * attributes */
+ array<Node *> used_shaders = mesh->get_used_shaders();
- mesh->clear();
- mesh->used_shaders = used_shaders;
-
- mesh->subdivision_type = Mesh::SUBDIVISION_NONE;
+ Mesh new_mesh;
+ new_mesh.set_used_shaders(used_shaders);
if (view_layer.use_surfaces) {
/* Adaptive subdivision setup. Not for baking since that requires
* exact mapping to the Blender mesh. */
if (!scene->bake_manager->get_baking()) {
- mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental);
+ new_mesh.set_subdivision_type(object_subdivision_type(b_ob, preview, experimental));
}
/* For some reason, meshes do not need this... */
- bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
+ bool need_undeformed = new_mesh.need_attribute(scene, ATTR_STD_GENERATED);
BL::Mesh b_mesh = object_to_mesh(
- b_data, b_ob, b_depsgraph, need_undeformed, mesh->subdivision_type);
+ b_data, b_ob, b_depsgraph, need_undeformed, new_mesh.get_subdivision_type());
if (b_mesh) {
/* Sync mesh itself. */
- if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE)
- create_subd_mesh(
- scene, mesh, b_ob, b_mesh, mesh->used_shaders, dicing_rate, max_subdivisions);
+ if (new_mesh.get_subdivision_type() != Mesh::SUBDIVISION_NONE)
+ create_subd_mesh(scene,
+ &new_mesh,
+ b_ob,
+ b_mesh,
+ new_mesh.get_used_shaders(),
+ dicing_rate,
+ max_subdivisions);
else
- create_mesh(scene, mesh, b_mesh, mesh->used_shaders, false);
+ create_mesh(scene, &new_mesh, b_mesh, new_mesh.get_used_shaders(), false);
free_object_to_mesh(b_data, b_ob, b_mesh);
}
}
/* cached velocities (e.g. from alembic archive) */
- sync_mesh_cached_velocities(b_ob, scene, mesh);
+ sync_mesh_cached_velocities(b_ob, scene, &new_mesh);
/* mesh fluid motion mantaflow */
- sync_mesh_fluid_motion(b_ob, scene, mesh);
+ sync_mesh_fluid_motion(b_ob, scene, &new_mesh);
+
+ /* update original sockets */
+
+ for (const SocketType &socket : new_mesh.type->inputs) {
+ /* Those sockets are updated in sync_object, so do not modify them. */
+ if (socket.name == "use_motion_blur" || socket.name == "motion_steps" ||
+ socket.name == "used_shaders") {
+ continue;
+ }
+ mesh->set_value(socket, new_mesh, socket);
+ }
+
+ foreach (Attribute &attr, new_mesh.attributes.attributes) {
+ mesh->attributes.attributes.push_back(std::move(attr));
+ }
+
+ foreach (Attribute &attr, new_mesh.subd_attributes.attributes) {
+ mesh->subd_attributes.attributes.push_back(std::move(attr));
+ }
+
+ mesh->set_num_subd_faces(new_mesh.get_num_subd_faces());
/* tag update */
- bool rebuild = (oldtriangles != mesh->triangles) || (oldsubd_faces != mesh->subd_faces) ||
- (oldsubd_face_corners != mesh->subd_face_corners);
+ bool rebuild = (mesh->triangles_is_modified()) || (mesh->subd_num_corners_is_modified()) ||
+ (mesh->subd_shader_is_modified()) || (mesh->subd_smooth_is_modified()) ||
+ (mesh->subd_ptex_offset_is_modified()) ||
+ (mesh->subd_start_corner_is_modified()) ||
+ (mesh->subd_face_corners_is_modified());
mesh->tag_update(scene, rebuild);
}
@@ -1095,7 +1110,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
}
/* Skip if no vertices were exported. */
- size_t numverts = mesh->verts.size();
+ size_t numverts = mesh->get_verts().size();
if (numverts == 0) {
return;
}
@@ -1140,7 +1155,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
if (new_attribute) {
/* In case of new attribute, we verify if there really was any motion. */
if (b_mesh.vertices.length() != numverts ||
- memcmp(mP, &mesh->verts[0], sizeof(float3) * numverts) == 0) {
+ memcmp(mP, &mesh->get_verts()[0], sizeof(float3) * numverts) == 0) {
/* no motion, remove attributes again */
if (b_mesh.vertices.length() != numverts) {
VLOG(1) << "Topology differs, disabling motion blur for object " << b_ob.name();
@@ -1156,7 +1171,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
VLOG(1) << "Filling deformation motion for object " << b_ob.name();
/* motion, fill up previous steps that we might have skipped because
* they had no motion, but we need them anyway now */
- float3 *P = &mesh->verts[0];
+ float3 *P = &mesh->get_verts()[0];
float3 *N = (attr_N) ? attr_N->data_float3() : NULL;
for (int step = 0; step < motion_step; step++) {
memcpy(attr_mP->data_float3() + step * numverts, P, sizeof(float3) * numverts);
@@ -1169,7 +1184,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
if (b_mesh.vertices.length() != numverts) {
VLOG(1) << "Topology differs, discarding motion blur for object " << b_ob.name()
<< " at time " << motion_step;
- memcpy(mP, &mesh->verts[0], sizeof(float3) * numverts);
+ memcpy(mP, &mesh->get_verts()[0], sizeof(float3) * numverts);
if (mN != NULL) {
memcpy(mN, attr_N->data_float3(), sizeof(float3) * numverts);
}
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 4146d87ad2e..4a70cbbf41f 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -32,6 +32,7 @@
#include "util/util_foreach.h"
#include "util/util_hash.h"
#include "util/util_logging.h"
+#include "util/util_task.h"
CCL_NAMESPACE_BEGIN
@@ -103,7 +104,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
bool use_particle_hair,
bool show_lights,
BlenderObjectCulling &culling,
- bool *use_portal)
+ bool *use_portal,
+ TaskPool *geom_task_pool)
{
const bool is_instance = b_instance.is_instance();
BL::Object b_ob = b_instance.object();
@@ -181,6 +183,10 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
return NULL;
}
+ /* Use task pool only for non-instances, since sync_dupli_particle accesses
+ * geometry. This restriction should be removed for better performance. */
+ TaskPool *object_geom_task_pool = (is_instance) ? NULL : geom_task_pool;
+
/* key to lookup object */
ObjectKey key(b_parent, persistent_id, b_ob_instance, use_particle_hair);
Object *object;
@@ -193,12 +199,19 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* Set transform at matching motion time step. */
int time_index = object->motion_step(motion_time);
if (time_index >= 0) {
- object->motion[time_index] = tfm;
+ array<Transform> motion = object->get_motion();
+ motion[time_index] = tfm;
+ object->set_motion(motion);
}
/* mesh deformation */
- if (object->geometry)
- sync_geometry_motion(b_depsgraph, b_ob, object, motion_time, use_particle_hair);
+ if (object->get_geometry())
+ sync_geometry_motion(b_depsgraph,
+ b_ob_instance,
+ object,
+ motion_time,
+ use_particle_hair,
+ object_geom_task_pool);
}
return object;
@@ -211,34 +224,36 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
object_updated = true;
/* mesh sync */
- object->geometry = sync_geometry(
- b_depsgraph, b_ob, b_ob_instance, object_updated, use_particle_hair);
+ /* b_ob is owned by the iterator and will go out of scope at the end of the block.
+ * b_ob_instance is the original object and will remain valid for deferred geometry
+ * sync. */
+ Geometry *geometry = sync_geometry(b_depsgraph,
+ b_ob_instance,
+ b_ob_instance,
+ object_updated,
+ use_particle_hair,
+ object_geom_task_pool);
+ object->set_geometry(geometry);
/* special case not tracked by object update flags */
- /* holdout */
- if (use_holdout != object->use_holdout) {
- object->use_holdout = use_holdout;
- scene->object_manager->tag_update(scene);
+ if (sync_object_attributes(b_instance, object)) {
object_updated = true;
}
- if (visibility != object->visibility) {
- object->visibility = visibility;
- object_updated = true;
+ /* holdout */
+ object->set_use_holdout(use_holdout);
+ if (object->use_holdout_is_modified()) {
+ scene->object_manager->tag_update(scene);
}
+ object->set_visibility(visibility);
+
bool is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher");
- if (is_shadow_catcher != object->is_shadow_catcher) {
- object->is_shadow_catcher = is_shadow_catcher;
- object_updated = true;
- }
+ object->set_is_shadow_catcher(is_shadow_catcher);
float shadow_terminator_offset = get_float(cobject, "shadow_terminator_offset");
- if (shadow_terminator_offset != object->shadow_terminator_offset) {
- object->shadow_terminator_offset = shadow_terminator_offset;
- object_updated = true;
- }
+ object->set_shadow_terminator_offset(shadow_terminator_offset);
/* sync the asset name for Cryptomatte */
BL::Object parent = b_ob.parent();
@@ -252,48 +267,49 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
else {
parent_name = b_ob.name();
}
- if (object->asset_name != parent_name) {
- object->asset_name = parent_name;
- object_updated = true;
- }
+ object->set_asset_name(parent_name);
/* object sync
* transform comparison should not be needed, but duplis don't work perfect
* in the depsgraph and may not signal changes, so this is a workaround */
- if (object_updated || (object->geometry && object->geometry->need_update) ||
- tfm != object->tfm) {
+ if (object->is_modified() || object_updated ||
+ (object->get_geometry() && object->get_geometry()->is_modified()) ||
+ tfm != object->get_tfm()) {
object->name = b_ob.name().c_str();
- object->pass_id = b_ob.pass_index();
- object->color = get_float3(b_ob.color());
- object->tfm = tfm;
- object->motion.clear();
+ object->set_pass_id(b_ob.pass_index());
+ object->set_color(get_float3(b_ob.color()));
+ object->set_tfm(tfm);
+ array<Transform> motion;
+ object->set_motion(motion);
/* motion blur */
Scene::MotionType need_motion = scene->need_motion();
- if (need_motion != Scene::MOTION_NONE && object->geometry) {
- Geometry *geom = object->geometry;
- geom->use_motion_blur = false;
- geom->motion_steps = 0;
+ if (need_motion != Scene::MOTION_NONE && object->get_geometry()) {
+ Geometry *geom = object->get_geometry();
+ geom->set_use_motion_blur(false);
+ geom->set_motion_steps(0);
uint motion_steps;
if (need_motion == Scene::MOTION_BLUR) {
motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS);
- geom->motion_steps = motion_steps;
+ geom->set_motion_steps(motion_steps);
if (motion_steps && object_use_deform_motion(b_parent, b_ob)) {
- geom->use_motion_blur = true;
+ geom->set_use_motion_blur(true);
}
}
else {
motion_steps = 3;
- geom->motion_steps = motion_steps;
+ geom->set_motion_steps(motion_steps);
}
- object->motion.clear();
- object->motion.resize(motion_steps, transform_empty());
+ motion.resize(motion_steps, transform_empty());
if (motion_steps) {
- object->motion[motion_steps / 2] = tfm;
+ motion[motion_steps / 2] = tfm;
+
+ /* update motion socket before trying to access object->motion_time */
+ object->set_motion(motion);
for (size_t step = 0; step < motion_steps; step++) {
motion_times.insert(object->motion_time(step));
@@ -303,15 +319,15 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* dupli texture coordinates and random_id */
if (is_instance) {
- object->dupli_generated = 0.5f * get_float3(b_instance.orco()) -
- make_float3(0.5f, 0.5f, 0.5f);
- object->dupli_uv = get_float2(b_instance.uv());
- object->random_id = b_instance.random_id();
+ object->set_dupli_generated(0.5f * get_float3(b_instance.orco()) -
+ make_float3(0.5f, 0.5f, 0.5f));
+ object->set_dupli_uv(get_float2(b_instance.uv()));
+ object->set_random_id(b_instance.random_id());
}
else {
- object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
- object->dupli_uv = make_float2(0.0f, 0.0f);
- object->random_id = hash_uint2(hash_string(object->name.c_str()), 0);
+ object->set_dupli_generated(make_float3(0.0f, 0.0f, 0.0f));
+ object->set_dupli_uv(make_float2(0.0f, 0.0f));
+ object->set_random_id(hash_uint2(hash_string(object->name.c_str()), 0));
}
object->tag_update(scene);
@@ -325,12 +341,141 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
return object;
}
+/* This function mirrors drw_uniform_property_lookup in draw_instance_data.cpp */
+static bool lookup_property(BL::ID b_id, const string &name, float4 *r_value)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ if (!RNA_path_resolve(&b_id.ptr, name.c_str(), &ptr, &prop)) {
+ return false;
+ }
+
+ PropertyType type = RNA_property_type(prop);
+ int arraylen = RNA_property_array_length(&ptr, prop);
+
+ if (arraylen == 0) {
+ float value;
+
+ if (type == PROP_FLOAT)
+ value = RNA_property_float_get(&ptr, prop);
+ else if (type == PROP_INT)
+ value = RNA_property_int_get(&ptr, prop);
+ else
+ return false;
+
+ *r_value = make_float4(value, value, value, 1.0f);
+ return true;
+ }
+ else if (type == PROP_FLOAT && arraylen <= 4) {
+ *r_value = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
+ RNA_property_float_get_array(&ptr, prop, &r_value->x);
+ return true;
+ }
+
+ return false;
+}
+
+/* This function mirrors drw_uniform_attribute_lookup in draw_instance_data.cpp */
+static float4 lookup_instance_property(BL::DepsgraphObjectInstance &b_instance,
+ const string &name,
+ bool use_instancer)
+{
+ string idprop_name = string_printf("[\"%s\"]", name.c_str());
+ float4 value;
+
+ /* If requesting instance data, check the parent particle system and object. */
+ if (use_instancer && b_instance.is_instance()) {
+ BL::ParticleSystem b_psys = b_instance.particle_system();
+
+ if (b_psys) {
+ if (lookup_property(b_psys.settings(), idprop_name, &value) ||
+ lookup_property(b_psys.settings(), name, &value)) {
+ return value;
+ }
+ }
+ if (lookup_property(b_instance.parent(), idprop_name, &value) ||
+ lookup_property(b_instance.parent(), name, &value)) {
+ return value;
+ }
+ }
+
+ /* Check the object and mesh. */
+ BL::Object b_ob = b_instance.object();
+ BL::ID b_data = b_ob.data();
+
+ if (lookup_property(b_ob, idprop_name, &value) || lookup_property(b_ob, name, &value) ||
+ lookup_property(b_data, idprop_name, &value) || lookup_property(b_data, name, &value)) {
+ return value;
+ }
+
+ return make_float4(0.0f);
+}
+
+bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object)
+{
+ /* Find which attributes are needed. */
+ AttributeRequestSet requests = object->get_geometry()->needed_attributes();
+
+ /* Delete attributes that became unnecessary. */
+ vector<ParamValue> &attributes = object->attributes;
+ bool changed = false;
+
+ for (int i = attributes.size() - 1; i >= 0; i--) {
+ if (!requests.find(attributes[i].name())) {
+ attributes.erase(attributes.begin() + i);
+ changed = true;
+ }
+ }
+
+ /* Update attribute values. */
+ foreach (AttributeRequest &req, requests.requests) {
+ ustring name = req.name;
+
+ std::string real_name;
+ BlenderAttributeType type = blender_attribute_name_split_type(name, &real_name);
+
+ if (type != BL::ShaderNodeAttribute::attribute_type_GEOMETRY) {
+ bool use_instancer = (type == BL::ShaderNodeAttribute::attribute_type_INSTANCER);
+ float4 value = lookup_instance_property(b_instance, real_name, use_instancer);
+
+ /* Try finding the existing attribute value. */
+ ParamValue *param = NULL;
+
+ for (size_t i = 0; i < attributes.size(); i++) {
+ if (attributes[i].name() == name) {
+ param = &attributes[i];
+ break;
+ }
+ }
+
+ /* Replace or add the value. */
+ ParamValue new_param(name, TypeDesc::TypeFloat4, 1, &value);
+ assert(new_param.datasize() == sizeof(value));
+
+ if (!param) {
+ changed = true;
+ attributes.push_back(new_param);
+ }
+ else if (memcmp(param->data(), &value, sizeof(value)) != 0) {
+ changed = true;
+ *param = new_param;
+ }
+ }
+ }
+
+ return changed;
+}
+
/* Object Loop */
void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
BL::SpaceView3D &b_v3d,
float motion_time)
{
+ /* Task pool for multithreaded geometry sync. */
+ TaskPool geom_task_pool;
+
/* layer data */
bool motion = motion_time != 0.0f;
@@ -355,8 +500,8 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
const bool show_lights = BlenderViewportParameters(b_v3d).use_scene_lights;
BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
-
BL::Depsgraph::object_instances_iterator b_instance_iter;
+
for (b_depsgraph.object_instances.begin(b_instance_iter);
b_instance_iter != b_depsgraph.object_instances.end() && !cancel;
++b_instance_iter) {
@@ -372,6 +517,11 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
/* Load per-object culling data. */
culling.init_object(scene, b_ob);
+ /* Ensure the object geom supporting the hair is processed before adding
+ * the hair processing task to the task pool, calling .to_mesh() on the
+ * same object in parallel does not work. */
+ const bool sync_hair = b_instance.show_particles() && object_has_particle_hair(b_ob);
+
/* Object itself. */
if (b_instance.show_self()) {
sync_object(b_depsgraph,
@@ -381,11 +531,12 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
false,
show_lights,
culling,
- &use_portal);
+ &use_portal,
+ sync_hair ? NULL : &geom_task_pool);
}
/* Particle hair as separate object. */
- if (b_instance.show_particles() && object_has_particle_hair(b_ob)) {
+ if (sync_hair) {
sync_object(b_depsgraph,
b_view_layer,
b_instance,
@@ -393,12 +544,15 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
true,
show_lights,
culling,
- &use_portal);
+ &use_portal,
+ &geom_task_pool);
}
cancel = progress.get_cancel();
}
+ geom_task_pool.wait_work();
+
progress.set_sync_status("");
if (!cancel && !motion) {
@@ -431,20 +585,18 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render,
if (b_override)
b_cam = b_override;
- Camera prevcam = *(scene->camera);
-
int frame_center = b_scene.frame_current();
float subframe_center = b_scene.frame_subframe();
float frame_center_delta = 0.0f;
if (scene->need_motion() != Scene::MOTION_PASS &&
- scene->camera->motion_position != Camera::MOTION_POSITION_CENTER) {
- float shuttertime = scene->camera->shuttertime;
- if (scene->camera->motion_position == Camera::MOTION_POSITION_END) {
+ scene->camera->get_motion_position() != Camera::MOTION_POSITION_CENTER) {
+ float shuttertime = scene->camera->get_shuttertime();
+ if (scene->camera->get_motion_position() == Camera::MOTION_POSITION_END) {
frame_center_delta = -shuttertime * 0.5f;
}
else {
- assert(scene->camera->motion_position == Camera::MOTION_POSITION_START);
+ assert(scene->camera->get_motion_position() == Camera::MOTION_POSITION_START);
frame_center_delta = shuttertime * 0.5f;
}
@@ -505,10 +657,6 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render,
python_thread_state_restore(python_thread_state);
b_engine.frame_set(frame_center, subframe_center);
python_thread_state_save(python_thread_state);
-
- /* tag camera for motion update */
- if (scene->camera->motion_modified(prevcam))
- scene->camera->tag_update();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_object_cull.cpp b/intern/cycles/blender/blender_object_cull.cpp
index bebecb364eb..cb7827b3c4a 100644
--- a/intern/cycles/blender/blender_object_cull.cpp
+++ b/intern/cycles/blender/blender_object_cull.cpp
@@ -34,10 +34,10 @@ BlenderObjectCulling::BlenderObjectCulling(Scene *scene, BL::Scene &b_scene)
if (b_scene.render().use_simplify()) {
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- use_scene_camera_cull_ = scene->camera->type != CAMERA_PANORAMA &&
+ use_scene_camera_cull_ = scene->camera->get_camera_type() != CAMERA_PANORAMA &&
!b_scene.render().use_multiview() &&
get_boolean(cscene, "use_camera_cull");
- use_scene_distance_cull_ = scene->camera->type != CAMERA_PANORAMA &&
+ use_scene_distance_cull_ = scene->camera->get_camera_type() != CAMERA_PANORAMA &&
!b_scene.render().use_multiview() &&
get_boolean(cscene, "use_distance_cull");
@@ -123,7 +123,7 @@ bool BlenderObjectCulling::test_camera(Scene *scene, float3 bb[8])
bool BlenderObjectCulling::test_distance(Scene *scene, float3 bb[8])
{
- float3 camera_position = transform_get_column(&scene->camera->matrix, 3);
+ float3 camera_position = transform_get_column(&scene->camera->get_matrix(), 3);
float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp
index e5eab1ae62b..ca221b229b4 100644
--- a/intern/cycles/blender/blender_particles.cpp
+++ b/intern/cycles/blender/blender_particles.cpp
@@ -36,10 +36,10 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
if (!b_psys)
return false;
- object->hide_on_missing_motion = true;
+ object->set_hide_on_missing_motion(true);
/* test if we need particle data */
- if (!object->geometry->need_attribute(scene, ATTR_STD_PARTICLE))
+ if (!object->get_geometry()->need_attribute(scene, ATTR_STD_PARTICLE))
return false;
/* don't handle child particles yet */
@@ -56,7 +56,8 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
bool need_update = particle_system_map.add_or_update(&psys, b_ob, b_instance.object(), key);
/* no update needed? */
- if (!need_update && !object->geometry->need_update && !scene->object_manager->need_update)
+ if (!need_update && !object->get_geometry()->is_modified() &&
+ !scene->object_manager->need_update)
return true;
/* first time used in this sync loop? clear and tag update */
@@ -80,10 +81,11 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
psys->particles.push_back_slow(pa);
- if (object->particle_index != psys->particles.size() - 1)
+ object->set_particle_system(psys);
+ object->set_particle_index(psys->particles.size() - 1);
+
+ if (object->particle_index_is_modified())
scene->object_manager->tag_update(scene);
- object->particle_system = psys;
- object->particle_index = psys->particles.size() - 1;
/* return that this object has particle data */
return true;
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 513cac1e0e9..770f4ca51c9 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -442,17 +442,17 @@ void BlenderSession::stamp_view_layer_metadata(Scene *scene, const string &view_
}
/* Write cryptomatte metadata. */
- if (scene->film->cryptomatte_passes & CRYPT_OBJECT) {
+ if (scene->film->get_cryptomatte_passes() & CRYPT_OBJECT) {
add_cryptomatte_layer(b_rr,
view_layer_name + ".CryptoObject",
scene->object_manager->get_cryptomatte_objects(scene));
}
- if (scene->film->cryptomatte_passes & CRYPT_MATERIAL) {
+ if (scene->film->get_cryptomatte_passes() & CRYPT_MATERIAL) {
add_cryptomatte_layer(b_rr,
view_layer_name + ".CryptoMaterial",
scene->shader_manager->get_cryptomatte_materials(scene));
}
- if (scene->film->cryptomatte_passes & CRYPT_ASSET) {
+ if (scene->film->get_cryptomatte_passes() & CRYPT_ASSET) {
add_cryptomatte_layer(b_rr,
view_layer_name + ".CryptoAsset",
scene->object_manager->get_cryptomatte_assets(scene));
@@ -473,6 +473,11 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
{
b_depsgraph = b_depsgraph_;
+ if (session->progress.get_cancel()) {
+ update_status_progress();
+ return;
+ }
+
/* set callback to write out render results */
session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
session->update_render_tile_cb = function_bind(
@@ -503,9 +508,9 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
/* 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;
+ buffer_params.denoising_data_pass = scene->film->get_denoising_data_pass();
+ buffer_params.denoising_clean_pass = scene->film->get_denoising_clean_pass();
+ buffer_params.denoising_prefiltered_pass = scene->film->get_denoising_prefiltered_pass();
BL::RenderResult::views_iterator b_view_iter;
@@ -542,8 +547,9 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
/* Make sure all views have different noise patterns. - hardcoded value just to make it random
*/
if (view_index != 0) {
- scene->integrator->seed += hash_uint2(scene->integrator->seed,
- hash_uint2(view_index * 0xdeadbeef, 0));
+ int seed = scene->integrator->get_seed();
+ seed += hash_uint2(seed, hash_uint2(view_index * 0xdeadbeef, 0));
+ scene->integrator->set_seed(seed);
scene->integrator->tag_update(scene);
}
@@ -715,7 +721,7 @@ void BlenderSession::do_write_update_render_result(BL::RenderLayer &b_rlay,
if (!buffers->copy_from_device())
return;
- float exposure = scene->film->exposure;
+ float exposure = scene->film->get_exposure();
vector<float> pixels(rtile.w * rtile.h * 4);
@@ -832,10 +838,7 @@ void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_)
session->set_denoising(session_params.denoising);
/* Update film if denoising data was enabled or disabled. */
- if (scene->film->denoising_data_pass != buffer_params.denoising_data_pass) {
- scene->film->denoising_data_pass = buffer_params.denoising_data_pass;
- scene->film->tag_update(scene);
- }
+ scene->film->set_denoising_data_pass(buffer_params.denoising_data_pass);
/* reset if needed */
if (scene->need_reset()) {
@@ -894,7 +897,7 @@ bool BlenderSession::draw(int w, int h)
sync->sync_view(b_v3d, b_rv3d, width, height);
- if (scene->camera->need_update)
+ if (scene->camera->is_modified())
reset = true;
session->scene->mutex.unlock();
@@ -1109,8 +1112,11 @@ void BlenderSession::update_resumable_tile_manager(int num_samples)
VLOG(1) << "Samples range start is " << range_start_sample << ", "
<< "number of samples to render is " << range_num_samples;
- scene->integrator->start_sample = rounded_range_start_sample;
- scene->integrator->tag_update(scene);
+ scene->integrator->set_start_sample(rounded_range_start_sample);
+
+ if (scene->integrator->is_modified()) {
+ scene->integrator->tag_update(scene);
+ }
session->tile_manager.range_start_sample = rounded_range_start_sample;
session->tile_manager.range_num_samples = rounded_range_num_samples;
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index c171982b29d..ac86cf3345c 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -42,11 +42,11 @@ typedef map<string, ConvertNode *> ProxyMap;
/* Find */
-void BlenderSync::find_shader(BL::ID &id, vector<Shader *> &used_shaders, Shader *default_shader)
+void BlenderSync::find_shader(BL::ID &id, array<Node *> &used_shaders, Shader *default_shader)
{
Shader *shader = (id) ? shader_map.find(id) : default_shader;
- used_shaders.push_back(shader);
+ used_shaders.push_back_slow(shader);
shader->tag_used(scene);
}
@@ -97,6 +97,53 @@ static ImageAlphaType get_image_alpha_type(BL::Image &b_image)
return (ImageAlphaType)validate_enum_value(value, IMAGE_ALPHA_NUM_TYPES, IMAGE_ALPHA_AUTO);
}
+/* Attribute name translation utilities */
+
+/* Since Eevee needs to know whether the attribute is uniform or varying
+ * at the time it compiles the shader for the material, Blender had to
+ * introduce different namespaces (types) in its attribute node. However,
+ * Cycles already has object attributes that form a uniform namespace with
+ * the more common varying attributes. Without completely reworking the
+ * attribute handling in Cycles to introduce separate namespaces (this could
+ * be especially hard for OSL which directly uses the name string), the
+ * space identifier has to be added to the attribute name as a prefix.
+ *
+ * The prefixes include a control character to ensure the user specified
+ * name can't accidentally include a special prefix.
+ */
+
+static const string_view object_attr_prefix("\x01object:");
+static const string_view instancer_attr_prefix("\x01instancer:");
+
+static ustring blender_attribute_name_add_type(const string &name, BlenderAttributeType type)
+{
+ switch (type) {
+ case BL::ShaderNodeAttribute::attribute_type_OBJECT:
+ return ustring::concat(object_attr_prefix, name);
+ case BL::ShaderNodeAttribute::attribute_type_INSTANCER:
+ return ustring::concat(instancer_attr_prefix, name);
+ default:
+ return ustring(name);
+ }
+}
+
+BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name)
+{
+ string_view sname(name);
+
+ if (sname.substr(0, object_attr_prefix.size()) == object_attr_prefix) {
+ *r_real_name = sname.substr(object_attr_prefix.size());
+ return BL::ShaderNodeAttribute::attribute_type_OBJECT;
+ }
+
+ if (sname.substr(0, instancer_attr_prefix.size()) == instancer_attr_prefix) {
+ *r_real_name = sname.substr(instancer_attr_prefix.size());
+ return BL::ShaderNodeAttribute::attribute_type_INSTANCER;
+ }
+
+ return BL::ShaderNodeAttribute::attribute_type_GEOMETRY;
+}
+
/* Graph */
static BL::NodeSocket get_node_output(BL::Node &b_node, const string &name)
@@ -194,19 +241,19 @@ static void set_default_value(ShaderInput *input,
}
}
-static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping &b_mapping)
+static void get_tex_mapping(TextureNode *mapping, BL::TexMapping &b_mapping)
{
if (!b_mapping)
return;
- mapping->translation = get_float3(b_mapping.translation());
- mapping->rotation = get_float3(b_mapping.rotation());
- mapping->scale = get_float3(b_mapping.scale());
- mapping->type = (TextureMapping::Type)b_mapping.vector_type();
+ mapping->set_tex_mapping_translation(get_float3(b_mapping.translation()));
+ mapping->set_tex_mapping_rotation(get_float3(b_mapping.rotation()));
+ mapping->set_tex_mapping_scale(get_float3(b_mapping.scale()));
+ mapping->set_tex_mapping_type((TextureMapping::Type)b_mapping.vector_type());
- mapping->x_mapping = (TextureMapping::Mapping)b_mapping.mapping_x();
- mapping->y_mapping = (TextureMapping::Mapping)b_mapping.mapping_y();
- mapping->z_mapping = (TextureMapping::Mapping)b_mapping.mapping_z();
+ mapping->set_tex_mapping_x_mapping((TextureMapping::Mapping)b_mapping.mapping_x());
+ mapping->set_tex_mapping_y_mapping((TextureMapping::Mapping)b_mapping.mapping_y());
+ mapping->set_tex_mapping_z_mapping((TextureMapping::Mapping)b_mapping.mapping_z());
}
static ShaderNode *add_node(Scene *scene,
@@ -225,34 +272,48 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeRGBCurve b_curve_node(b_node);
BL::CurveMapping mapping(b_curve_node.mapping());
RGBCurvesNode *curves = graph->create_node<RGBCurvesNode>();
- curvemapping_color_to_array(mapping, curves->curves, RAMP_TABLE_SIZE, true);
- curvemapping_minmax(mapping, true, &curves->min_x, &curves->max_x);
+ array<float3> curve_mapping_curves;
+ float min_x, max_x;
+ curvemapping_color_to_array(mapping, curve_mapping_curves, RAMP_TABLE_SIZE, true);
+ curvemapping_minmax(mapping, true, &min_x, &max_x);
+ curves->set_min_x(min_x);
+ curves->set_max_x(max_x);
+ curves->set_curves(curve_mapping_curves);
node = curves;
}
if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
BL::ShaderNodeVectorCurve b_curve_node(b_node);
BL::CurveMapping mapping(b_curve_node.mapping());
VectorCurvesNode *curves = graph->create_node<VectorCurvesNode>();
- curvemapping_color_to_array(mapping, curves->curves, RAMP_TABLE_SIZE, false);
- curvemapping_minmax(mapping, false, &curves->min_x, &curves->max_x);
+ array<float3> curve_mapping_curves;
+ float min_x, max_x;
+ curvemapping_color_to_array(mapping, curve_mapping_curves, RAMP_TABLE_SIZE, false);
+ curvemapping_minmax(mapping, false, &min_x, &max_x);
+ curves->set_min_x(min_x);
+ curves->set_max_x(max_x);
+ curves->set_curves(curve_mapping_curves);
node = curves;
}
else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) {
RGBRampNode *ramp = graph->create_node<RGBRampNode>();
BL::ShaderNodeValToRGB b_ramp_node(b_node);
BL::ColorRamp b_color_ramp(b_ramp_node.color_ramp());
- colorramp_to_array(b_color_ramp, ramp->ramp, ramp->ramp_alpha, RAMP_TABLE_SIZE);
- ramp->interpolate = b_color_ramp.interpolation() != BL::ColorRamp::interpolation_CONSTANT;
+ array<float3> ramp_values;
+ array<float> ramp_alpha;
+ colorramp_to_array(b_color_ramp, ramp_values, ramp_alpha, RAMP_TABLE_SIZE);
+ ramp->set_ramp(ramp_values);
+ ramp->set_ramp_alpha(ramp_alpha);
+ ramp->set_interpolate(b_color_ramp.interpolation() != BL::ColorRamp::interpolation_CONSTANT);
node = ramp;
}
else if (b_node.is_a(&RNA_ShaderNodeRGB)) {
ColorNode *color = graph->create_node<ColorNode>();
- color->value = get_node_output_rgba(b_node, "Color");
+ color->set_value(get_node_output_rgba(b_node, "Color"));
node = color;
}
else if (b_node.is_a(&RNA_ShaderNodeValue)) {
ValueNode *value = graph->create_node<ValueNode>();
- value->value = get_node_output_value(b_node, "Value");
+ value->set_value(get_node_output_value(b_node, "Value"));
node = value;
}
else if (b_node.is_a(&RNA_ShaderNodeCameraData)) {
@@ -270,8 +331,8 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeMixRGB)) {
BL::ShaderNodeMixRGB b_mix_node(b_node);
MixNode *mix = graph->create_node<MixNode>();
- mix->type = (NodeMix)b_mix_node.blend_type();
- mix->use_clamp = b_mix_node.use_clamp();
+ mix->set_mix_type((NodeMix)b_mix_node.blend_type());
+ mix->set_use_clamp(b_mix_node.use_clamp());
node = mix;
}
else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
@@ -301,43 +362,45 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeMapRange)) {
BL::ShaderNodeMapRange b_map_range_node(b_node);
MapRangeNode *map_range_node = graph->create_node<MapRangeNode>();
- map_range_node->clamp = b_map_range_node.clamp();
- map_range_node->type = (NodeMapRangeType)b_map_range_node.interpolation_type();
+ map_range_node->set_clamp(b_map_range_node.clamp());
+ map_range_node->set_range_type((NodeMapRangeType)b_map_range_node.interpolation_type());
node = map_range_node;
}
else if (b_node.is_a(&RNA_ShaderNodeClamp)) {
BL::ShaderNodeClamp b_clamp_node(b_node);
ClampNode *clamp_node = graph->create_node<ClampNode>();
- clamp_node->type = (NodeClampType)b_clamp_node.clamp_type();
+ clamp_node->set_clamp_type((NodeClampType)b_clamp_node.clamp_type());
node = clamp_node;
}
else if (b_node.is_a(&RNA_ShaderNodeMath)) {
BL::ShaderNodeMath b_math_node(b_node);
MathNode *math_node = graph->create_node<MathNode>();
- math_node->type = (NodeMathType)b_math_node.operation();
- math_node->use_clamp = b_math_node.use_clamp();
+ math_node->set_math_type((NodeMathType)b_math_node.operation());
+ math_node->set_use_clamp(b_math_node.use_clamp());
node = math_node;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) {
BL::ShaderNodeVectorMath b_vector_math_node(b_node);
VectorMathNode *vector_math_node = graph->create_node<VectorMathNode>();
- vector_math_node->type = (NodeVectorMathType)b_vector_math_node.operation();
+ vector_math_node->set_math_type((NodeVectorMathType)b_vector_math_node.operation());
node = vector_math_node;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorRotate)) {
BL::ShaderNodeVectorRotate b_vector_rotate_node(b_node);
VectorRotateNode *vector_rotate_node = graph->create_node<VectorRotateNode>();
- vector_rotate_node->type = (NodeVectorRotateType)b_vector_rotate_node.rotation_type();
- vector_rotate_node->invert = b_vector_rotate_node.invert();
+ vector_rotate_node->set_rotate_type(
+ (NodeVectorRotateType)b_vector_rotate_node.rotation_type());
+ vector_rotate_node->set_invert(b_vector_rotate_node.invert());
node = vector_rotate_node;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
VectorTransformNode *vtransform = graph->create_node<VectorTransformNode>();
- vtransform->type = (NodeVectorTransformType)b_vector_transform_node.vector_type();
- vtransform->convert_from = (NodeVectorTransformConvertSpace)
- b_vector_transform_node.convert_from();
- vtransform->convert_to = (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_to();
+ vtransform->set_transform_type((NodeVectorTransformType)b_vector_transform_node.vector_type());
+ vtransform->set_convert_from(
+ (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_from());
+ vtransform->set_convert_to(
+ (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_to());
node = vtransform;
}
else if (b_node.is_a(&RNA_ShaderNodeNormal)) {
@@ -345,13 +408,13 @@ static ShaderNode *add_node(Scene *scene,
b_node.outputs.begin(out_it);
NormalNode *norm = graph->create_node<NormalNode>();
- norm->direction = get_node_output_vector(b_node, "Normal");
+ norm->set_direction(get_node_output_vector(b_node, "Normal"));
node = norm;
}
else if (b_node.is_a(&RNA_ShaderNodeMapping)) {
BL::ShaderNodeMapping b_mapping_node(b_node);
MappingNode *mapping = graph->create_node<MappingNode>();
- mapping->type = (NodeMappingType)b_mapping_node.vector_type();
+ mapping->set_mapping_type((NodeMappingType)b_mapping_node.vector_type());
node = mapping;
}
else if (b_node.is_a(&RNA_ShaderNodeFresnel)) {
@@ -369,7 +432,8 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeAttribute)) {
BL::ShaderNodeAttribute b_attr_node(b_node);
AttributeNode *attr = graph->create_node<AttributeNode>();
- attr->attribute = b_attr_node.attribute_name();
+ attr->set_attribute(blender_attribute_name_add_type(b_attr_node.attribute_name(),
+ b_attr_node.attribute_type()));
node = attr;
}
else if (b_node.is_a(&RNA_ShaderNodeBackground)) {
@@ -384,16 +448,16 @@ static ShaderNode *add_node(Scene *scene,
switch (b_aniso_node.distribution()) {
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
- aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
+ aniso->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
- aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ aniso->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_ID);
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_MULTI_GGX:
- aniso->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+ aniso->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
- aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
+ aniso->set_distribution(CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
break;
}
@@ -409,16 +473,16 @@ static ShaderNode *add_node(Scene *scene,
switch (b_subsurface_node.falloff()) {
case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
- subsurface->falloff = CLOSURE_BSSRDF_CUBIC_ID;
+ subsurface->set_falloff(CLOSURE_BSSRDF_CUBIC_ID);
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_GAUSSIAN:
- subsurface->falloff = CLOSURE_BSSRDF_GAUSSIAN_ID;
+ subsurface->set_falloff(CLOSURE_BSSRDF_GAUSSIAN_ID);
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY:
- subsurface->falloff = CLOSURE_BSSRDF_BURLEY_ID;
+ subsurface->set_falloff(CLOSURE_BSSRDF_BURLEY_ID);
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK:
- subsurface->falloff = CLOSURE_BSSRDF_RANDOM_WALK_ID;
+ subsurface->set_falloff(CLOSURE_BSSRDF_RANDOM_WALK_ID);
break;
}
@@ -430,19 +494,19 @@ static ShaderNode *add_node(Scene *scene,
switch (b_glossy_node.distribution()) {
case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
- glossy->distribution = CLOSURE_BSDF_REFLECTION_ID;
+ glossy->set_distribution(CLOSURE_BSDF_REFLECTION_ID);
break;
case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
- glossy->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
+ glossy->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
break;
case BL::ShaderNodeBsdfGlossy::distribution_GGX:
- glossy->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ glossy->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_ID);
break;
case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
- glossy->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
+ glossy->set_distribution(CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
break;
case BL::ShaderNodeBsdfGlossy::distribution_MULTI_GGX:
- glossy->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+ glossy->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
break;
}
node = glossy;
@@ -452,16 +516,16 @@ static ShaderNode *add_node(Scene *scene,
GlassBsdfNode *glass = graph->create_node<GlassBsdfNode>();
switch (b_glass_node.distribution()) {
case BL::ShaderNodeBsdfGlass::distribution_SHARP:
- glass->distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
+ glass->set_distribution(CLOSURE_BSDF_SHARP_GLASS_ID);
break;
case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
- glass->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID;
+ glass->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
break;
case BL::ShaderNodeBsdfGlass::distribution_GGX:
- glass->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
+ glass->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
break;
case BL::ShaderNodeBsdfGlass::distribution_MULTI_GGX:
- glass->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+ glass->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
break;
}
node = glass;
@@ -471,13 +535,13 @@ static ShaderNode *add_node(Scene *scene,
RefractionBsdfNode *refraction = graph->create_node<RefractionBsdfNode>();
switch (b_refraction_node.distribution()) {
case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
- refraction->distribution = CLOSURE_BSDF_REFRACTION_ID;
+ refraction->set_distribution(CLOSURE_BSDF_REFRACTION_ID);
break;
case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
- refraction->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ refraction->set_distribution(CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
break;
case BL::ShaderNodeBsdfRefraction::distribution_GGX:
- refraction->distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ refraction->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
break;
}
node = refraction;
@@ -487,10 +551,10 @@ static ShaderNode *add_node(Scene *scene,
ToonBsdfNode *toon = graph->create_node<ToonBsdfNode>();
switch (b_toon_node.component()) {
case BL::ShaderNodeBsdfToon::component_DIFFUSE:
- toon->component = CLOSURE_BSDF_DIFFUSE_TOON_ID;
+ toon->set_component(CLOSURE_BSDF_DIFFUSE_TOON_ID);
break;
case BL::ShaderNodeBsdfToon::component_GLOSSY:
- toon->component = CLOSURE_BSDF_GLOSSY_TOON_ID;
+ toon->set_component(CLOSURE_BSDF_GLOSSY_TOON_ID);
break;
}
node = toon;
@@ -500,10 +564,10 @@ static ShaderNode *add_node(Scene *scene,
HairBsdfNode *hair = graph->create_node<HairBsdfNode>();
switch (b_hair_node.component()) {
case BL::ShaderNodeBsdfHair::component_Reflection:
- hair->component = CLOSURE_BSDF_HAIR_REFLECTION_ID;
+ hair->set_component(CLOSURE_BSDF_HAIR_REFLECTION_ID);
break;
case BL::ShaderNodeBsdfHair::component_Transmission:
- hair->component = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
+ hair->set_component(CLOSURE_BSDF_HAIR_TRANSMISSION_ID);
break;
}
node = hair;
@@ -511,11 +575,11 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeBsdfHairPrincipled)) {
BL::ShaderNodeBsdfHairPrincipled b_principled_hair_node(b_node);
PrincipledHairBsdfNode *principled_hair = graph->create_node<PrincipledHairBsdfNode>();
- principled_hair->parametrization = (NodePrincipledHairParametrization)get_enum(
- b_principled_hair_node.ptr,
- "parametrization",
- NODE_PRINCIPLED_HAIR_NUM,
- NODE_PRINCIPLED_HAIR_REFLECTANCE);
+ principled_hair->set_parametrization(
+ (NodePrincipledHairParametrization)get_enum(b_principled_hair_node.ptr,
+ "parametrization",
+ NODE_PRINCIPLED_HAIR_NUM,
+ NODE_PRINCIPLED_HAIR_REFLECTANCE));
node = principled_hair;
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
@@ -523,18 +587,18 @@ static ShaderNode *add_node(Scene *scene,
PrincipledBsdfNode *principled = graph->create_node<PrincipledBsdfNode>();
switch (b_principled_node.distribution()) {
case BL::ShaderNodeBsdfPrincipled::distribution_GGX:
- principled->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
+ principled->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
break;
case BL::ShaderNodeBsdfPrincipled::distribution_MULTI_GGX:
- principled->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+ principled->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
break;
}
switch (b_principled_node.subsurface_method()) {
case BL::ShaderNodeBsdfPrincipled::subsurface_method_BURLEY:
- principled->subsurface_method = CLOSURE_BSSRDF_PRINCIPLED_ID;
+ principled->set_subsurface_method(CLOSURE_BSSRDF_PRINCIPLED_ID);
break;
case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK:
- principled->subsurface_method = CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID;
+ principled->set_subsurface_method(CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID);
break;
}
node = principled;
@@ -554,9 +618,9 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
BL::ShaderNodeAmbientOcclusion b_ao_node(b_node);
AmbientOcclusionNode *ao = graph->create_node<AmbientOcclusionNode>();
- ao->samples = b_ao_node.samples();
- ao->inside = b_ao_node.inside();
- ao->only_local = b_ao_node.only_local();
+ ao->set_samples(b_ao_node.samples());
+ ao->set_inside(b_ao_node.inside());
+ ao->set_only_local(b_ao_node.only_local());
node = ao;
}
else if (b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
@@ -575,7 +639,7 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeWireframe)) {
BL::ShaderNodeWireframe b_wireframe_node(b_node);
WireframeNode *wire = graph->create_node<WireframeNode>();
- wire->use_pixel_size = b_wireframe_node.use_pixel_size();
+ wire->set_use_pixel_size(b_wireframe_node.use_pixel_size());
node = wire;
}
else if (b_node.is_a(&RNA_ShaderNodeWavelength)) {
@@ -605,13 +669,13 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeVertexColor)) {
BL::ShaderNodeVertexColor b_vertex_color_node(b_node);
VertexColorNode *vertex_color_node = graph->create_node<VertexColorNode>();
- vertex_color_node->layer_name = b_vertex_color_node.layer_name();
+ vertex_color_node->set_layer_name(ustring(b_vertex_color_node.layer_name()));
node = vertex_color_node;
}
else if (b_node.is_a(&RNA_ShaderNodeBump)) {
BL::ShaderNodeBump b_bump_node(b_node);
BumpNode *bump = graph->create_node<BumpNode>();
- bump->invert = b_bump_node.invert();
+ bump->set_invert(b_bump_node.invert());
node = bump;
}
else if (b_node.is_a(&RNA_ShaderNodeScript)) {
@@ -644,25 +708,26 @@ static ShaderNode *add_node(Scene *scene,
BL::ImageUser b_image_user(b_image_node.image_user());
ImageTextureNode *image = graph->create_node<ImageTextureNode>();
- image->interpolation = get_image_interpolation(b_image_node);
- image->extension = get_image_extension(b_image_node);
- image->projection = (NodeImageProjection)b_image_node.projection();
- image->projection_blend = b_image_node.projection_blend();
+ image->set_interpolation(get_image_interpolation(b_image_node));
+ image->set_extension(get_image_extension(b_image_node));
+ image->set_projection((NodeImageProjection)b_image_node.projection());
+ image->set_projection_blend(b_image_node.projection_blend());
BL::TexMapping b_texture_mapping(b_image_node.texture_mapping());
- get_tex_mapping(&image->tex_mapping, b_texture_mapping);
+ get_tex_mapping(image, b_texture_mapping);
if (b_image) {
PointerRNA colorspace_ptr = b_image.colorspace_settings().ptr;
- image->colorspace = get_enum_identifier(colorspace_ptr, "name");
+ image->set_colorspace(ustring(get_enum_identifier(colorspace_ptr, "name")));
- image->animated = b_image_node.image_user().use_auto_refresh();
- image->alpha_type = get_image_alpha_type(b_image);
+ image->set_animated(b_image_node.image_user().use_auto_refresh());
+ image->set_alpha_type(get_image_alpha_type(b_image));
- image->tiles.clear();
+ array<int> tiles;
BL::Image::tiles_iterator b_iter;
for (b_image.tiles.begin(b_iter); b_iter != b_image.tiles.end(); ++b_iter) {
- image->tiles.push_back(b_iter->number());
+ tiles.push_back_slow(b_iter->number());
}
+ image->set_tiles(tiles);
/* builtin images will use callback-based reading because
* they could only be loaded correct from blender side
@@ -684,8 +749,9 @@ static ShaderNode *add_node(Scene *scene,
new BlenderImageLoader(b_image, image_frame), image->image_params());
}
else {
- image->filename = image_user_file_path(
- b_image_user, b_image, b_scene.frame_current(), true);
+ ustring filename = ustring(
+ image_user_file_path(b_image_user, b_image, b_scene.frame_current(), true));
+ image->set_filename(filename);
}
}
node = image;
@@ -696,17 +762,17 @@ static ShaderNode *add_node(Scene *scene,
BL::ImageUser b_image_user(b_env_node.image_user());
EnvironmentTextureNode *env = graph->create_node<EnvironmentTextureNode>();
- env->interpolation = get_image_interpolation(b_env_node);
- env->projection = (NodeEnvironmentProjection)b_env_node.projection();
+ env->set_interpolation(get_image_interpolation(b_env_node));
+ env->set_projection((NodeEnvironmentProjection)b_env_node.projection());
BL::TexMapping b_texture_mapping(b_env_node.texture_mapping());
- get_tex_mapping(&env->tex_mapping, b_texture_mapping);
+ get_tex_mapping(env, b_texture_mapping);
if (b_image) {
PointerRNA colorspace_ptr = b_image.colorspace_settings().ptr;
- env->colorspace = get_enum_identifier(colorspace_ptr, "name");
+ env->set_colorspace(ustring(get_enum_identifier(colorspace_ptr, "name")));
- env->animated = b_env_node.image_user().use_auto_refresh();
- env->alpha_type = get_image_alpha_type(b_image);
+ env->set_animated(b_env_node.image_user().use_auto_refresh());
+ env->set_alpha_type(get_image_alpha_type(b_image));
bool is_builtin = b_image.packed_file() || b_image.source() == BL::Image::source_GENERATED ||
b_image.source() == BL::Image::source_MOVIE ||
@@ -719,8 +785,8 @@ static ShaderNode *add_node(Scene *scene,
env->image_params());
}
else {
- env->filename = image_user_file_path(
- b_image_user, b_image, b_scene.frame_current(), false);
+ env->set_filename(
+ ustring(image_user_file_path(b_image_user, b_image, b_scene.frame_current(), false)));
}
}
node = env;
@@ -728,103 +794,103 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeTexGradient)) {
BL::ShaderNodeTexGradient b_gradient_node(b_node);
GradientTextureNode *gradient = graph->create_node<GradientTextureNode>();
- gradient->type = (NodeGradientType)b_gradient_node.gradient_type();
+ gradient->set_gradient_type((NodeGradientType)b_gradient_node.gradient_type());
BL::TexMapping b_texture_mapping(b_gradient_node.texture_mapping());
- get_tex_mapping(&gradient->tex_mapping, b_texture_mapping);
+ get_tex_mapping(gradient, b_texture_mapping);
node = gradient;
}
else if (b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
VoronoiTextureNode *voronoi = graph->create_node<VoronoiTextureNode>();
- voronoi->dimensions = b_voronoi_node.voronoi_dimensions();
- voronoi->feature = (NodeVoronoiFeature)b_voronoi_node.feature();
- voronoi->metric = (NodeVoronoiDistanceMetric)b_voronoi_node.distance();
+ voronoi->set_dimensions(b_voronoi_node.voronoi_dimensions());
+ voronoi->set_feature((NodeVoronoiFeature)b_voronoi_node.feature());
+ voronoi->set_metric((NodeVoronoiDistanceMetric)b_voronoi_node.distance());
BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
- get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping);
+ get_tex_mapping(voronoi, b_texture_mapping);
node = voronoi;
}
else if (b_node.is_a(&RNA_ShaderNodeTexMagic)) {
BL::ShaderNodeTexMagic b_magic_node(b_node);
MagicTextureNode *magic = graph->create_node<MagicTextureNode>();
- magic->depth = b_magic_node.turbulence_depth();
+ magic->set_depth(b_magic_node.turbulence_depth());
BL::TexMapping b_texture_mapping(b_magic_node.texture_mapping());
- get_tex_mapping(&magic->tex_mapping, b_texture_mapping);
+ get_tex_mapping(magic, b_texture_mapping);
node = magic;
}
else if (b_node.is_a(&RNA_ShaderNodeTexWave)) {
BL::ShaderNodeTexWave b_wave_node(b_node);
WaveTextureNode *wave = graph->create_node<WaveTextureNode>();
- wave->type = (NodeWaveType)b_wave_node.wave_type();
- wave->bands_direction = (NodeWaveBandsDirection)b_wave_node.bands_direction();
- wave->rings_direction = (NodeWaveRingsDirection)b_wave_node.rings_direction();
- wave->profile = (NodeWaveProfile)b_wave_node.wave_profile();
+ wave->set_wave_type((NodeWaveType)b_wave_node.wave_type());
+ wave->set_bands_direction((NodeWaveBandsDirection)b_wave_node.bands_direction());
+ wave->set_rings_direction((NodeWaveRingsDirection)b_wave_node.rings_direction());
+ wave->set_profile((NodeWaveProfile)b_wave_node.wave_profile());
BL::TexMapping b_texture_mapping(b_wave_node.texture_mapping());
- get_tex_mapping(&wave->tex_mapping, b_texture_mapping);
+ get_tex_mapping(wave, b_texture_mapping);
node = wave;
}
else if (b_node.is_a(&RNA_ShaderNodeTexChecker)) {
BL::ShaderNodeTexChecker b_checker_node(b_node);
CheckerTextureNode *checker = graph->create_node<CheckerTextureNode>();
BL::TexMapping b_texture_mapping(b_checker_node.texture_mapping());
- get_tex_mapping(&checker->tex_mapping, b_texture_mapping);
+ get_tex_mapping(checker, b_texture_mapping);
node = checker;
}
else if (b_node.is_a(&RNA_ShaderNodeTexBrick)) {
BL::ShaderNodeTexBrick b_brick_node(b_node);
BrickTextureNode *brick = graph->create_node<BrickTextureNode>();
- brick->offset = b_brick_node.offset();
- brick->offset_frequency = b_brick_node.offset_frequency();
- brick->squash = b_brick_node.squash();
- brick->squash_frequency = b_brick_node.squash_frequency();
+ brick->set_offset(b_brick_node.offset());
+ brick->set_offset_frequency(b_brick_node.offset_frequency());
+ brick->set_squash(b_brick_node.squash());
+ brick->set_squash_frequency(b_brick_node.squash_frequency());
BL::TexMapping b_texture_mapping(b_brick_node.texture_mapping());
- get_tex_mapping(&brick->tex_mapping, b_texture_mapping);
+ get_tex_mapping(brick, b_texture_mapping);
node = brick;
}
else if (b_node.is_a(&RNA_ShaderNodeTexNoise)) {
BL::ShaderNodeTexNoise b_noise_node(b_node);
NoiseTextureNode *noise = graph->create_node<NoiseTextureNode>();
- noise->dimensions = b_noise_node.noise_dimensions();
+ noise->set_dimensions(b_noise_node.noise_dimensions());
BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping());
- get_tex_mapping(&noise->tex_mapping, b_texture_mapping);
+ get_tex_mapping(noise, b_texture_mapping);
node = noise;
}
else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
MusgraveTextureNode *musgrave_node = graph->create_node<MusgraveTextureNode>();
- musgrave_node->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
- musgrave_node->dimensions = b_musgrave_node.musgrave_dimensions();
+ musgrave_node->set_musgrave_type((NodeMusgraveType)b_musgrave_node.musgrave_type());
+ musgrave_node->set_dimensions(b_musgrave_node.musgrave_dimensions());
BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
- get_tex_mapping(&musgrave_node->tex_mapping, b_texture_mapping);
+ get_tex_mapping(musgrave_node, b_texture_mapping);
node = musgrave_node;
}
else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) {
BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
TextureCoordinateNode *tex_coord = graph->create_node<TextureCoordinateNode>();
- tex_coord->from_dupli = b_tex_coord_node.from_instancer();
+ tex_coord->set_from_dupli(b_tex_coord_node.from_instancer());
if (b_tex_coord_node.object()) {
- tex_coord->use_transform = true;
- tex_coord->ob_tfm = get_transform(b_tex_coord_node.object().matrix_world());
+ tex_coord->set_use_transform(true);
+ tex_coord->set_ob_tfm(get_transform(b_tex_coord_node.object().matrix_world()));
}
node = tex_coord;
}
else if (b_node.is_a(&RNA_ShaderNodeTexSky)) {
BL::ShaderNodeTexSky b_sky_node(b_node);
SkyTextureNode *sky = graph->create_node<SkyTextureNode>();
- sky->type = (NodeSkyType)b_sky_node.sky_type();
- sky->sun_direction = normalize(get_float3(b_sky_node.sun_direction()));
- sky->turbidity = b_sky_node.turbidity();
- 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 = 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();
+ sky->set_sky_type((NodeSkyType)b_sky_node.sky_type());
+ sky->set_sun_direction(normalize(get_float3(b_sky_node.sun_direction())));
+ sky->set_turbidity(b_sky_node.turbidity());
+ sky->set_ground_albedo(b_sky_node.ground_albedo());
+ sky->set_sun_disc(b_sky_node.sun_disc());
+ sky->set_sun_size(b_sky_node.sun_size());
+ sky->set_sun_intensity(b_sky_node.sun_intensity());
+ sky->set_sun_elevation(b_sky_node.sun_elevation());
+ sky->set_sun_rotation(b_sky_node.sun_rotation());
+ sky->set_altitude(1000.0f * b_sky_node.altitude());
+ sky->set_air_density(b_sky_node.air_density());
+ sky->set_dust_density(b_sky_node.dust_density());
+ sky->set_ozone_density(b_sky_node.ozone_density());
BL::TexMapping b_texture_mapping(b_sky_node.texture_mapping());
- get_tex_mapping(&sky->tex_mapping, b_texture_mapping);
+ get_tex_mapping(sky, b_texture_mapping);
node = sky;
}
else if (b_node.is_a(&RNA_ShaderNodeTexIES)) {
@@ -832,13 +898,14 @@ static ShaderNode *add_node(Scene *scene,
IESLightNode *ies = graph->create_node<IESLightNode>();
switch (b_ies_node.mode()) {
case BL::ShaderNodeTexIES::mode_EXTERNAL:
- ies->filename = blender_absolute_path(b_data, b_ntree, b_ies_node.filepath());
+ ies->set_filename(ustring(blender_absolute_path(b_data, b_ntree, b_ies_node.filepath())));
break;
case BL::ShaderNodeTexIES::mode_INTERNAL:
- ies->ies = get_text_datablock_content(b_ies_node.ies().ptr);
- if (ies->ies.empty()) {
- ies->ies = "\n";
+ ustring ies_content = ustring(get_text_datablock_content(b_ies_node.ies().ptr));
+ if (ies_content.empty()) {
+ ies_content = "\n";
}
+ ies->set_ies(ies_content);
break;
}
node = ies;
@@ -846,36 +913,36 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeTexWhiteNoise)) {
BL::ShaderNodeTexWhiteNoise b_tex_white_noise_node(b_node);
WhiteNoiseTextureNode *white_noise_node = graph->create_node<WhiteNoiseTextureNode>();
- white_noise_node->dimensions = b_tex_white_noise_node.noise_dimensions();
+ white_noise_node->set_dimensions(b_tex_white_noise_node.noise_dimensions());
node = white_noise_node;
}
else if (b_node.is_a(&RNA_ShaderNodeNormalMap)) {
BL::ShaderNodeNormalMap b_normal_map_node(b_node);
NormalMapNode *nmap = graph->create_node<NormalMapNode>();
- nmap->space = (NodeNormalMapSpace)b_normal_map_node.space();
- nmap->attribute = b_normal_map_node.uv_map();
+ nmap->set_space((NodeNormalMapSpace)b_normal_map_node.space());
+ nmap->set_attribute(ustring(b_normal_map_node.uv_map()));
node = nmap;
}
else if (b_node.is_a(&RNA_ShaderNodeTangent)) {
BL::ShaderNodeTangent b_tangent_node(b_node);
TangentNode *tangent = graph->create_node<TangentNode>();
- tangent->direction_type = (NodeTangentDirectionType)b_tangent_node.direction_type();
- tangent->axis = (NodeTangentAxis)b_tangent_node.axis();
- tangent->attribute = b_tangent_node.uv_map();
+ tangent->set_direction_type((NodeTangentDirectionType)b_tangent_node.direction_type());
+ tangent->set_axis((NodeTangentAxis)b_tangent_node.axis());
+ tangent->set_attribute(ustring(b_tangent_node.uv_map()));
node = tangent;
}
else if (b_node.is_a(&RNA_ShaderNodeUVMap)) {
BL::ShaderNodeUVMap b_uvmap_node(b_node);
UVMapNode *uvm = graph->create_node<UVMapNode>();
- uvm->attribute = b_uvmap_node.uv_map();
- uvm->from_dupli = b_uvmap_node.from_instancer();
+ uvm->set_attribute(ustring(b_uvmap_node.uv_map()));
+ uvm->set_from_dupli(b_uvmap_node.from_instancer());
node = uvm;
}
else if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
PointDensityTextureNode *point_density = graph->create_node<PointDensityTextureNode>();
- point_density->space = (NodeTexVoxelSpace)b_point_density_node.space();
- point_density->interpolation = get_image_interpolation(b_point_density_node);
+ point_density->set_space((NodeTexVoxelSpace)b_point_density_node.space());
+ point_density->set_interpolation(get_image_interpolation(b_point_density_node));
point_density->handle = scene->image_manager->add_image(
new BlenderPointDensityLoader(b_depsgraph, b_point_density_node),
point_density->image_params());
@@ -892,33 +959,33 @@ static ShaderNode *add_node(Scene *scene,
if (b_ob) {
float3 loc, size;
point_density_texture_space(b_depsgraph, b_point_density_node, loc, size);
- point_density->tfm = transform_translate(-loc) * transform_scale(size) *
- transform_inverse(get_transform(b_ob.matrix_world()));
+ point_density->set_tfm(transform_translate(-loc) * transform_scale(size) *
+ transform_inverse(get_transform(b_ob.matrix_world())));
}
}
else if (b_node.is_a(&RNA_ShaderNodeBevel)) {
BL::ShaderNodeBevel b_bevel_node(b_node);
BevelNode *bevel = graph->create_node<BevelNode>();
- bevel->samples = b_bevel_node.samples();
+ bevel->set_samples(b_bevel_node.samples());
node = bevel;
}
else if (b_node.is_a(&RNA_ShaderNodeDisplacement)) {
BL::ShaderNodeDisplacement b_disp_node(b_node);
DisplacementNode *disp = graph->create_node<DisplacementNode>();
- disp->space = (NodeNormalMapSpace)b_disp_node.space();
+ disp->set_space((NodeNormalMapSpace)b_disp_node.space());
node = disp;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorDisplacement)) {
BL::ShaderNodeVectorDisplacement b_disp_node(b_node);
VectorDisplacementNode *disp = graph->create_node<VectorDisplacementNode>();
- disp->space = (NodeNormalMapSpace)b_disp_node.space();
- disp->attribute = "";
+ disp->set_space((NodeNormalMapSpace)b_disp_node.space());
+ disp->set_attribute(ustring(""));
node = disp;
}
else if (b_node.is_a(&RNA_ShaderNodeOutputAOV)) {
BL::ShaderNodeOutputAOV b_aov_node(b_node);
OutputAOVNode *aov = graph->create_node<OutputAOVNode>();
- aov->name = b_aov_node.name();
+ aov->set_name(ustring(b_aov_node.name()));
node = aov;
}
@@ -1245,7 +1312,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
ShaderGraph *graph = new ShaderGraph();
shader->name = b_mat.name().c_str();
- shader->pass_id = b_mat.pass_index();
+ shader->set_pass_id(b_mat.pass_index());
/* create nodes */
if (b_mat.use_nodes() && b_mat.node_tree()) {
@@ -1255,7 +1322,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
}
else {
DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>();
- diffuse->color = get_float3(b_mat.diffuse_color());
+ diffuse->set_color(get_float3(b_mat.diffuse_color()));
graph->add(diffuse);
ShaderNode *out = graph->output();
@@ -1264,13 +1331,13 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
/* settings */
PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles");
- shader->use_mis = get_boolean(cmat, "sample_as_light");
- shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow");
- shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume");
- shader->volume_sampling_method = get_volume_sampling(cmat);
- shader->volume_interpolation_method = get_volume_interpolation(cmat);
- shader->volume_step_rate = get_float(cmat, "volume_step_rate");
- shader->displacement_method = get_displacement_method(cmat);
+ shader->set_use_mis(get_boolean(cmat, "sample_as_light"));
+ shader->set_use_transparent_shadow(get_boolean(cmat, "use_transparent_shadow"));
+ shader->set_heterogeneous_volume(!get_boolean(cmat, "homogeneous_volume"));
+ shader->set_volume_sampling_method(get_volume_sampling(cmat));
+ shader->set_volume_interpolation_method(get_volume_interpolation(cmat));
+ shader->set_volume_step_rate(get_float(cmat, "volume_step_rate"));
+ shader->set_displacement_method(get_displacement_method(cmat));
shader->set_graph(graph);
@@ -1311,7 +1378,6 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all)
{
Background *background = scene->background;
- Background prevbackground = *background;
BL::World b_world = b_scene.world();
@@ -1331,14 +1397,14 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
/* volume */
PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
- shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume");
- shader->volume_sampling_method = get_volume_sampling(cworld);
- shader->volume_interpolation_method = get_volume_interpolation(cworld);
- shader->volume_step_rate = get_float(cworld, "volume_step_size");
+ shader->set_heterogeneous_volume(!get_boolean(cworld, "homogeneous_volume"));
+ shader->set_volume_sampling_method(get_volume_sampling(cworld));
+ shader->set_volume_interpolation_method(get_volume_interpolation(cworld));
+ shader->set_volume_step_rate(get_float(cworld, "volume_step_size"));
}
else if (new_viewport_parameters.use_scene_world && b_world) {
BackgroundNode *background = graph->create_node<BackgroundNode>();
- background->color = get_float3(b_world.color());
+ background->set_color(get_float3(b_world.color()));
graph->add(background);
ShaderNode *out = graph->output();
@@ -1360,29 +1426,32 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
graph->add(light_path);
MixNode *mix_scene_with_background = graph->create_node<MixNode>();
- mix_scene_with_background->color2 = world_color;
+ mix_scene_with_background->set_color2(world_color);
graph->add(mix_scene_with_background);
EnvironmentTextureNode *texture_environment = graph->create_node<EnvironmentTextureNode>();
- texture_environment->tex_mapping.type = TextureMapping::VECTOR;
- texture_environment->tex_mapping.rotation[2] = new_viewport_parameters.studiolight_rotate_z;
- texture_environment->filename = new_viewport_parameters.studiolight_path;
+ texture_environment->set_tex_mapping_type(TextureMapping::VECTOR);
+ float3 rotation_z = texture_environment->get_tex_mapping_rotation();
+ rotation_z[2] = new_viewport_parameters.studiolight_rotate_z;
+ texture_environment->set_tex_mapping_rotation(rotation_z);
+ texture_environment->set_filename(new_viewport_parameters.studiolight_path);
graph->add(texture_environment);
MixNode *mix_intensity = graph->create_node<MixNode>();
- mix_intensity->type = NODE_MIX_MUL;
- mix_intensity->fac = 1.0f;
- mix_intensity->color2 = make_float3(new_viewport_parameters.studiolight_intensity,
- new_viewport_parameters.studiolight_intensity,
- new_viewport_parameters.studiolight_intensity);
+ mix_intensity->set_mix_type(NODE_MIX_MUL);
+ mix_intensity->set_fac(1.0f);
+ mix_intensity->set_color2(make_float3(new_viewport_parameters.studiolight_intensity,
+ new_viewport_parameters.studiolight_intensity,
+ new_viewport_parameters.studiolight_intensity));
graph->add(mix_intensity);
TextureCoordinateNode *texture_coordinate = graph->create_node<TextureCoordinateNode>();
graph->add(texture_coordinate);
MixNode *mix_background_with_environment = graph->create_node<MixNode>();
- mix_background_with_environment->fac = new_viewport_parameters.studiolight_background_alpha;
- mix_background_with_environment->color1 = world_color;
+ mix_background_with_environment->set_fac(
+ new_viewport_parameters.studiolight_background_alpha);
+ mix_background_with_environment->set_color1(world_color);
graph->add(mix_background_with_environment);
ShaderNode *out = graph->output();
@@ -1404,9 +1473,9 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
/* AO */
BL::WorldLighting b_light = b_world.light_settings();
- background->use_ao = b_light.use_ambient_occlusion();
- background->ao_factor = b_light.ao_factor();
- background->ao_distance = b_light.distance();
+ background->set_use_ao(b_light.use_ambient_occlusion());
+ background->set_ao_factor(b_light.ao_factor());
+ background->set_ao_distance(b_light.distance());
/* visibility */
PointerRNA cvisibility = RNA_pointer_get(&b_world.ptr, "cycles_visibility");
@@ -1418,12 +1487,12 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
visibility |= get_boolean(cvisibility, "transmission") ? PATH_RAY_TRANSMIT : 0;
visibility |= get_boolean(cvisibility, "scatter") ? PATH_RAY_VOLUME_SCATTER : 0;
- background->visibility = visibility;
+ background->set_visibility(visibility);
}
else {
- background->use_ao = false;
- background->ao_factor = 0.0f;
- background->ao_distance = FLT_MAX;
+ background->set_use_ao(false);
+ background->set_ao_factor(0.0f);
+ background->set_ao_distance(FLT_MAX);
}
shader->set_graph(graph);
@@ -1432,22 +1501,23 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
}
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- background->transparent = b_scene.render().film_transparent();
+ background->set_transparent(b_scene.render().film_transparent());
- if (background->transparent) {
- background->transparent_glass = get_boolean(cscene, "film_transparent_glass");
- background->transparent_roughness_threshold = get_float(cscene, "film_transparent_roughness");
+ if (background->get_transparent()) {
+ background->set_transparent_glass(get_boolean(cscene, "film_transparent_glass"));
+ background->set_transparent_roughness_threshold(
+ get_float(cscene, "film_transparent_roughness"));
}
else {
- background->transparent_glass = false;
- background->transparent_roughness_threshold = 0.0f;
+ background->set_transparent_glass(false);
+ background->set_transparent_roughness_threshold(0.0f);
}
- background->use_shader = view_layer.use_background_shader |
- viewport_parameters.custom_viewport_parameters();
- background->use_ao = background->use_ao && view_layer.use_background_ao;
+ background->set_use_shader(view_layer.use_background_shader |
+ viewport_parameters.custom_viewport_parameters());
+ background->set_use_ao(background->get_use_ao() && view_layer.use_background_ao);
- if (background->modified(prevbackground))
+ if (background->is_modified())
background->tag_update(scene);
}
@@ -1480,8 +1550,8 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
}
else {
EmissionNode *emission = graph->create_node<EmissionNode>();
- emission->color = make_float3(1.0f, 1.0f, 1.0f);
- emission->strength = 1.0f;
+ emission->set_color(make_float3(1.0f, 1.0f, 1.0f));
+ emission->set_strength(1.0f);
graph->add(emission);
ShaderNode *out = graph->output();
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 0139afb711d..94ff0ff1473 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -118,9 +118,9 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
if (dicing_prop_changed) {
for (const pair<const GeometryKey, Geometry *> &iter : geometry_map.key_to_scene_data()) {
Geometry *geom = iter.second;
- if (geom->type == Geometry::MESH) {
+ if (geom->is_mesh()) {
Mesh *mesh = static_cast<Mesh *>(geom);
- if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
+ if (mesh->get_subdivision_type() != Mesh::SUBDIVISION_NONE) {
PointerRNA id_ptr;
RNA_id_pointer_create((::ID *)iter.first.id, &id_ptr);
geometry_map.set_recalc(BL::ID(id_ptr));
@@ -238,7 +238,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
geometry_synced.clear(); /* use for objects and motion sync */
if (scene->need_motion() == Scene::MOTION_PASS || scene->need_motion() == Scene::MOTION_NONE ||
- scene->camera->motion_position == Camera::MOTION_POSITION_CENTER) {
+ scene->camera->get_motion_position() == Camera::MOTION_POSITION_CENTER) {
sync_objects(b_depsgraph, b_v3d);
}
sync_motion(b_render, b_depsgraph, b_v3d, b_override, width, height, python_thread_state);
@@ -264,70 +264,75 @@ void BlenderSync::sync_integrator()
experimental = (get_enum(cscene, "feature_set") != 0);
Integrator *integrator = scene->integrator;
- Integrator previntegrator = *integrator;
- integrator->min_bounce = get_int(cscene, "min_light_bounces");
- integrator->max_bounce = get_int(cscene, "max_bounces");
+ integrator->set_min_bounce(get_int(cscene, "min_light_bounces"));
+ integrator->set_max_bounce(get_int(cscene, "max_bounces"));
- integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces");
- integrator->max_glossy_bounce = get_int(cscene, "glossy_bounces");
- integrator->max_transmission_bounce = get_int(cscene, "transmission_bounces");
- integrator->max_volume_bounce = get_int(cscene, "volume_bounces");
+ integrator->set_max_diffuse_bounce(get_int(cscene, "diffuse_bounces"));
+ integrator->set_max_glossy_bounce(get_int(cscene, "glossy_bounces"));
+ integrator->set_max_transmission_bounce(get_int(cscene, "transmission_bounces"));
+ integrator->set_max_volume_bounce(get_int(cscene, "volume_bounces"));
- integrator->transparent_min_bounce = get_int(cscene, "min_transparent_bounces");
- integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces");
+ integrator->set_transparent_min_bounce(get_int(cscene, "min_transparent_bounces"));
+ integrator->set_transparent_max_bounce(get_int(cscene, "transparent_max_bounces"));
- integrator->volume_max_steps = get_int(cscene, "volume_max_steps");
- integrator->volume_step_rate = (preview) ? get_float(cscene, "volume_preview_step_rate") :
- get_float(cscene, "volume_step_rate");
+ integrator->set_volume_max_steps(get_int(cscene, "volume_max_steps"));
+ float volume_step_rate = (preview) ? get_float(cscene, "volume_preview_step_rate") :
+ get_float(cscene, "volume_step_rate");
+ integrator->set_volume_step_rate(volume_step_rate);
- integrator->caustics_reflective = get_boolean(cscene, "caustics_reflective");
- integrator->caustics_refractive = get_boolean(cscene, "caustics_refractive");
- integrator->filter_glossy = get_float(cscene, "blur_glossy");
+ integrator->set_caustics_reflective(get_boolean(cscene, "caustics_reflective"));
+ integrator->set_caustics_refractive(get_boolean(cscene, "caustics_refractive"));
+ integrator->set_filter_glossy(get_float(cscene, "blur_glossy"));
- integrator->seed = get_int(cscene, "seed");
+ int seed = get_int(cscene, "seed");
if (get_boolean(cscene, "use_animated_seed")) {
- integrator->seed = hash_uint2(b_scene.frame_current(), get_int(cscene, "seed"));
+ seed = hash_uint2(b_scene.frame_current(), get_int(cscene, "seed"));
if (b_scene.frame_subframe() != 0.0f) {
/* TODO(sergey): Ideally should be some sort of hash_merge,
* but this is good enough for now.
*/
- integrator->seed += hash_uint2((int)(b_scene.frame_subframe() * (float)INT_MAX),
- get_int(cscene, "seed"));
+ seed += hash_uint2((int)(b_scene.frame_subframe() * (float)INT_MAX),
+ get_int(cscene, "seed"));
}
}
- integrator->sampling_pattern = (SamplingPattern)get_enum(
- cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_SOBOL);
+ integrator->set_seed(seed);
- integrator->sample_clamp_direct = get_float(cscene, "sample_clamp_direct");
- integrator->sample_clamp_indirect = get_float(cscene, "sample_clamp_indirect");
+ integrator->set_sample_clamp_direct(get_float(cscene, "sample_clamp_direct"));
+ integrator->set_sample_clamp_indirect(get_float(cscene, "sample_clamp_indirect"));
if (!preview) {
- if (integrator->motion_blur != r.use_motion_blur()) {
+ if (integrator->get_motion_blur() != r.use_motion_blur()) {
scene->object_manager->tag_update(scene);
- scene->camera->tag_update();
+ scene->camera->tag_modified();
}
- integrator->motion_blur = r.use_motion_blur();
+ integrator->set_motion_blur(r.use_motion_blur());
}
- integrator->method = (Integrator::Method)get_enum(
- cscene, "progressive", Integrator::NUM_METHODS, Integrator::PATH);
+ integrator->set_method((Integrator::Method)get_enum(
+ cscene, "progressive", Integrator::NUM_METHODS, Integrator::PATH));
+
+ integrator->set_sample_all_lights_direct(get_boolean(cscene, "sample_all_lights_direct"));
+ integrator->set_sample_all_lights_indirect(get_boolean(cscene, "sample_all_lights_indirect"));
+ integrator->set_light_sampling_threshold(get_float(cscene, "light_sampling_threshold"));
+
+ SamplingPattern sampling_pattern = (SamplingPattern)get_enum(
+ cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_SOBOL);
- integrator->sample_all_lights_direct = get_boolean(cscene, "sample_all_lights_direct");
- integrator->sample_all_lights_indirect = get_boolean(cscene, "sample_all_lights_indirect");
- integrator->light_sampling_threshold = get_float(cscene, "light_sampling_threshold");
+ int adaptive_min_samples = INT_MAX;
if (RNA_boolean_get(&cscene, "use_adaptive_sampling")) {
- integrator->sampling_pattern = SAMPLING_PATTERN_PMJ;
- integrator->adaptive_min_samples = get_int(cscene, "adaptive_min_samples");
- integrator->adaptive_threshold = get_float(cscene, "adaptive_threshold");
+ sampling_pattern = SAMPLING_PATTERN_PMJ;
+ adaptive_min_samples = get_int(cscene, "adaptive_min_samples");
+ integrator->set_adaptive_threshold(get_float(cscene, "adaptive_threshold"));
}
else {
- integrator->adaptive_min_samples = INT_MAX;
- integrator->adaptive_threshold = 0.0f;
+ integrator->set_adaptive_threshold(0.0f);
}
+ integrator->set_sampling_pattern(sampling_pattern);
+
int diffuse_samples = get_int(cscene, "diffuse_samples");
int glossy_samples = get_int(cscene, "glossy_samples");
int transmission_samples = get_int(cscene, "transmission_samples");
@@ -337,39 +342,40 @@ void BlenderSync::sync_integrator()
int volume_samples = get_int(cscene, "volume_samples");
if (get_boolean(cscene, "use_square_samples")) {
- integrator->diffuse_samples = diffuse_samples * diffuse_samples;
- integrator->glossy_samples = glossy_samples * glossy_samples;
- integrator->transmission_samples = transmission_samples * transmission_samples;
- integrator->ao_samples = ao_samples * ao_samples;
- integrator->mesh_light_samples = mesh_light_samples * mesh_light_samples;
- integrator->subsurface_samples = subsurface_samples * subsurface_samples;
- integrator->volume_samples = volume_samples * volume_samples;
- integrator->adaptive_min_samples = min(
- integrator->adaptive_min_samples * integrator->adaptive_min_samples, INT_MAX);
+ integrator->set_diffuse_samples(diffuse_samples * diffuse_samples);
+ integrator->set_glossy_samples(glossy_samples * glossy_samples);
+ integrator->set_transmission_samples(transmission_samples * transmission_samples);
+ integrator->set_ao_samples(ao_samples * ao_samples);
+ integrator->set_mesh_light_samples(mesh_light_samples * mesh_light_samples);
+ integrator->set_subsurface_samples(subsurface_samples * subsurface_samples);
+ integrator->set_volume_samples(volume_samples * volume_samples);
+ adaptive_min_samples = min(adaptive_min_samples * adaptive_min_samples, INT_MAX);
}
else {
- integrator->diffuse_samples = diffuse_samples;
- integrator->glossy_samples = glossy_samples;
- integrator->transmission_samples = transmission_samples;
- integrator->ao_samples = ao_samples;
- integrator->mesh_light_samples = mesh_light_samples;
- integrator->subsurface_samples = subsurface_samples;
- integrator->volume_samples = volume_samples;
+ integrator->set_diffuse_samples(diffuse_samples);
+ integrator->set_glossy_samples(glossy_samples);
+ integrator->set_transmission_samples(transmission_samples);
+ integrator->set_ao_samples(ao_samples);
+ integrator->set_mesh_light_samples(mesh_light_samples);
+ integrator->set_subsurface_samples(subsurface_samples);
+ integrator->set_volume_samples(volume_samples);
}
+ integrator->set_adaptive_min_samples(adaptive_min_samples);
+
if (b_scene.render().use_simplify()) {
if (preview) {
- integrator->ao_bounces = get_int(cscene, "ao_bounces");
+ integrator->set_ao_bounces(get_int(cscene, "ao_bounces"));
}
else {
- integrator->ao_bounces = get_int(cscene, "ao_bounces_render");
+ integrator->set_ao_bounces(get_int(cscene, "ao_bounces_render"));
}
}
else {
- integrator->ao_bounces = 0;
+ integrator->set_ao_bounces(0);
}
- if (integrator->modified(previntegrator))
+ if (integrator->is_modified())
integrator->tag_update(scene);
}
@@ -380,46 +386,42 @@ void BlenderSync::sync_film(BL::SpaceView3D &b_v3d)
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
Film *film = scene->film;
- Film prevfilm = *film;
vector<Pass> prevpasses = scene->passes;
if (b_v3d) {
- film->display_pass = update_viewport_display_passes(b_v3d, scene->passes);
+ film->set_display_pass(update_viewport_display_passes(b_v3d, scene->passes));
}
- film->exposure = get_float(cscene, "film_exposure");
- film->filter_type = (FilterType)get_enum(
- cscene, "pixel_filter_type", FILTER_NUM_TYPES, FILTER_BLACKMAN_HARRIS);
- film->filter_width = (film->filter_type == FILTER_BOX) ? 1.0f :
- get_float(cscene, "filter_width");
+ film->set_exposure(get_float(cscene, "film_exposure"));
+ film->set_filter_type(
+ (FilterType)get_enum(cscene, "pixel_filter_type", FILTER_NUM_TYPES, FILTER_BLACKMAN_HARRIS));
+ float filter_width = (film->get_filter_type() == FILTER_BOX) ? 1.0f :
+ get_float(cscene, "filter_width");
+ film->set_filter_width(filter_width);
if (b_scene.world()) {
BL::WorldMistSettings b_mist = b_scene.world().mist_settings();
- film->mist_start = b_mist.start();
- film->mist_depth = b_mist.depth();
+ film->set_mist_start(b_mist.start());
+ film->set_mist_depth(b_mist.depth());
switch (b_mist.falloff()) {
case BL::WorldMistSettings::falloff_QUADRATIC:
- film->mist_falloff = 2.0f;
+ film->set_mist_falloff(2.0f);
break;
case BL::WorldMistSettings::falloff_LINEAR:
- film->mist_falloff = 1.0f;
+ film->set_mist_falloff(1.0f);
break;
case BL::WorldMistSettings::falloff_INVERSE_QUADRATIC:
- film->mist_falloff = 0.5f;
+ film->set_mist_falloff(0.5f);
break;
}
}
- if (film->modified(prevfilm)) {
- film->tag_update(scene);
- }
-
if (!Pass::equals(prevpasses, scene->passes)) {
film->tag_passes_update(scene, prevpasses, false);
- film->tag_update(scene);
+ film->tag_modified();
}
}
@@ -585,7 +587,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
BL::RenderPass b_pass(*b_pass_iter);
PassType pass_type = get_pass_type(b_pass);
- if (pass_type == PASS_MOTION && scene->integrator->motion_blur)
+ if (pass_type == PASS_MOTION && scene->integrator->get_motion_blur())
continue;
if (pass_type != PASS_NONE)
Pass::add(pass_type, passes, b_pass.name().c_str());
@@ -593,12 +595,12 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles");
- scene->film->denoising_flags = 0;
+ int denoising_flags = 0;
if (denoising.use || denoising.store_passes) {
if (denoising.type == DENOISER_NLM) {
#define MAP_OPTION(name, flag) \
if (!get_boolean(crl, name)) { \
- scene->film->denoising_flags |= flag; \
+ denoising_flags |= flag; \
} \
((void)0)
MAP_OPTION("denoising_diffuse_direct", DENOISING_CLEAN_DIFFUSE_DIR);
@@ -611,6 +613,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
}
b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str());
}
+ scene->film->set_denoising_flags(denoising_flags);
if (denoising.store_passes) {
b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str());
@@ -622,7 +625,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
b_engine.add_pass("Denoising Intensity", 1, "X", b_view_layer.name().c_str());
}
- if (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES) {
+ if (scene->film->get_denoising_flags() & DENOISING_CLEAN_ALL_PASSES) {
b_engine.add_pass("Denoising Clean", 3, "RGB", b_view_layer.name().c_str());
}
}
@@ -665,16 +668,15 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
/* Cryptomatte stores two ID/weight pairs per RGBA layer.
* User facing parameter is the number of pairs. */
int crypto_depth = divide_up(min(16, get_int(crl, "pass_crypto_depth")), 2);
- scene->film->cryptomatte_depth = crypto_depth;
- scene->film->cryptomatte_passes = CRYPT_NONE;
+ scene->film->set_cryptomatte_depth(crypto_depth);
+ CryptomatteType cryptomatte_passes = CRYPT_NONE;
if (get_boolean(crl, "use_pass_crypto_object")) {
for (int i = 0; i < crypto_depth; i++) {
string passname = cryptomatte_prefix + string_printf("Object%02d", i);
b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
}
- scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes |
- CRYPT_OBJECT);
+ cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_OBJECT);
}
if (get_boolean(crl, "use_pass_crypto_material")) {
for (int i = 0; i < crypto_depth; i++) {
@@ -682,8 +684,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
}
- scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes |
- CRYPT_MATERIAL);
+ cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_MATERIAL);
}
if (get_boolean(crl, "use_pass_crypto_asset")) {
for (int i = 0; i < crypto_depth; i++) {
@@ -691,13 +692,12 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
}
- scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes |
- CRYPT_ASSET);
+ cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ASSET);
}
- if (get_boolean(crl, "pass_crypto_accurate") && scene->film->cryptomatte_passes != CRYPT_NONE) {
- scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes |
- CRYPT_ACCURATE);
+ if (get_boolean(crl, "pass_crypto_accurate") && cryptomatte_passes != CRYPT_NONE) {
+ cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ACCURATE);
}
+ scene->film->set_cryptomatte_passes(cryptomatte_passes);
if (adaptive_sampling) {
Pass::add(PASS_ADAPTIVE_AUX_BUFFER, passes);
@@ -721,14 +721,14 @@ 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->set_denoising_data_pass(denoising.use || denoising.store_passes);
+ scene->film->set_denoising_clean_pass(scene->film->get_denoising_flags() &
+ DENOISING_CLEAN_ALL_PASSES);
+ scene->film->set_denoising_prefiltered_pass(denoising.store_passes &&
+ denoising.type == DENOISER_NLM);
- scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold();
+ scene->film->set_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;
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 62fd1ac2351..ccf059d7704 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -50,6 +50,7 @@ class ViewLayer;
class Shader;
class ShaderGraph;
class ShaderNode;
+class TaskPool;
class BlenderSync {
public:
@@ -145,23 +146,20 @@ class BlenderSync {
bool use_particle_hair,
bool show_lights,
BlenderObjectCulling &culling,
- bool *use_portal);
+ bool *use_portal,
+ TaskPool *geom_task_pool);
+
+ bool sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object);
/* Volume */
- void sync_volume(BL::Object &b_ob, Volume *volume, const vector<Shader *> &used_shaders);
+ void sync_volume(BL::Object &b_ob, Volume *volume);
/* Mesh */
- void sync_mesh(BL::Depsgraph b_depsgraph,
- BL::Object b_ob,
- Mesh *mesh,
- const vector<Shader *> &used_shaders);
+ void sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh);
void sync_mesh_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh, int motion_step);
/* Hair */
- void sync_hair(BL::Depsgraph b_depsgraph,
- BL::Object b_ob,
- Hair *hair,
- const vector<Shader *> &used_shaders);
+ void sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair);
void sync_hair_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair, int motion_step);
void sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step = 0);
void sync_particle_hair(
@@ -177,12 +175,15 @@ class BlenderSync {
BL::Object &b_ob,
BL::Object &b_ob_instance,
bool object_updated,
- bool use_particle_hair);
+ bool use_particle_hair,
+ TaskPool *task_pool);
+
void sync_geometry_motion(BL::Depsgraph &b_depsgraph,
BL::Object &b_ob,
Object *object,
float motion_time,
- bool use_particle_hair);
+ bool use_particle_hair,
+ TaskPool *task_pool);
/* Light */
void sync_light(BL::Object &b_parent,
@@ -206,7 +207,7 @@ class BlenderSync {
void free_data_after_sync(BL::Depsgraph &b_depsgraph);
/* util */
- void find_shader(BL::ID &id, vector<Shader *> &used_shaders, Shader *default_shader);
+ void find_shader(BL::ID &id, array<Node *> &used_shaders, Shader *default_shader);
bool BKE_object_is_modified(BL::Object &b_ob);
bool object_is_geometry(BL::Object &b_ob);
bool object_is_light(BL::Object &b_ob);
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 1ea34b41aa2..5185ebae789 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -40,6 +40,9 @@ float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile);
CCL_NAMESPACE_BEGIN
+typedef BL::ShaderNodeAttribute::attribute_type_enum BlenderAttributeType;
+BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name);
+
void python_thread_state_save(void **python_thread_state);
void python_thread_state_restore(void **python_thread_state);
diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp
index e039d8a4895..1843fecd586 100644
--- a/intern/cycles/blender/blender_volume.cpp
+++ b/intern/cycles/blender/blender_volume.cpp
@@ -202,7 +202,7 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Volume *volume, fl
continue;
}
- volume->clipping = b_domain.clipping();
+ volume->set_clipping(b_domain.clipping());
Attribute *attr = volume->attributes.add(std);
@@ -262,9 +262,9 @@ static void sync_volume_object(BL::BlendData &b_data,
BL::VolumeRender b_render(b_volume.render());
- volume->clipping = b_render.clipping();
- volume->step_size = b_render.step_size();
- volume->object_space = (b_render.space() == BL::VolumeRender::space_OBJECT);
+ volume->set_clipping(b_render.clipping());
+ volume->set_step_size(b_render.step_size());
+ volume->set_object_space((b_render.space() == BL::VolumeRender::space_OBJECT));
/* Find grid with matching name. */
BL::Volume::grids_iterator b_grid_iter;
@@ -320,14 +320,11 @@ static vector<int> get_voxel_image_slots(Mesh *mesh)
return slots;
}
-void BlenderSync::sync_volume(BL::Object &b_ob,
- Volume *volume,
- const vector<Shader *> &used_shaders)
+void BlenderSync::sync_volume(BL::Object &b_ob, Volume *volume)
{
vector<int> old_voxel_slots = get_voxel_image_slots(volume);
- volume->clear();
- volume->used_shaders = used_shaders;
+ volume->clear(true);
if (view_layer.use_volumes) {
if (b_ob.type() == BL::Object::type_VOLUME) {
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 222c1c40f92..a51ac4cf4a9 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -209,30 +209,30 @@ void BVH::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility)
/* Primitives. */
if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
/* Curves. */
- const Hair *hair = static_cast<const Hair *>(ob->geometry);
+ const Hair *hair = static_cast<const Hair *>(ob->get_geometry());
int prim_offset = (params.top_level) ? hair->prim_offset : 0;
Hair::Curve curve = hair->get_curve(pidx - prim_offset);
int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
- curve.bounds_grow(k, &hair->curve_keys[0], &hair->curve_radius[0], bbox);
+ curve.bounds_grow(k, &hair->get_curve_keys()[0], &hair->get_curve_radius()[0], bbox);
/* Motion curves. */
- if (hair->use_motion_blur) {
+ if (hair->get_use_motion_blur()) {
Attribute *attr = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr) {
- size_t hair_size = hair->curve_keys.size();
- size_t steps = hair->motion_steps - 1;
+ size_t hair_size = hair->get_curve_keys().size();
+ size_t steps = hair->get_motion_steps() - 1;
float3 *key_steps = attr->data_float3();
for (size_t i = 0; i < steps; i++)
- curve.bounds_grow(k, key_steps + i * hair_size, &hair->curve_radius[0], bbox);
+ curve.bounds_grow(k, key_steps + i * hair_size, &hair->get_curve_radius()[0], bbox);
}
}
}
else {
/* Triangles. */
- const Mesh *mesh = static_cast<const Mesh *>(ob->geometry);
+ const Mesh *mesh = static_cast<const Mesh *>(ob->get_geometry());
int prim_offset = (params.top_level) ? mesh->prim_offset : 0;
Mesh::Triangle triangle = mesh->get_triangle(pidx - prim_offset);
const float3 *vpos = &mesh->verts[0];
@@ -264,7 +264,7 @@ void BVH::pack_triangle(int idx, float4 tri_verts[3])
{
int tob = pack.prim_object[idx];
assert(tob >= 0 && tob < objects.size());
- const Mesh *mesh = static_cast<const Mesh *>(objects[tob]->geometry);
+ const Mesh *mesh = static_cast<const Mesh *>(objects[tob]->get_geometry());
int tidx = pack.prim_index[idx];
Mesh::Triangle t = mesh->get_triangle(tidx);
@@ -329,7 +329,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
*/
for (size_t i = 0; i < pack.prim_index.size(); i++) {
if (pack.prim_index[i] != -1) {
- pack.prim_index[i] += objects[pack.prim_object[i]]->geometry->prim_offset;
+ pack.prim_index[i] += objects[pack.prim_object[i]]->get_geometry()->prim_offset;
}
}
@@ -390,7 +390,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
/* merge */
foreach (Object *ob, objects) {
- Geometry *geom = ob->geometry;
+ Geometry *geom = ob->get_geometry();
/* We assume that if mesh doesn't need own BVH it was already included
* into a top-level BVH and no packing here is needed.
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 360cac59e9b..1727082b7ec 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -169,12 +169,12 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Hair *hair
const size_t num_curves = hair->num_curves();
for (uint j = 0; j < num_curves; j++) {
const Hair::Curve curve = hair->get_curve(j);
- const float *curve_radius = &hair->curve_radius[0];
+ const float *curve_radius = &hair->get_curve_radius()[0];
for (int k = 0; k < curve.num_keys - 1; k++) {
if (curve_attr_mP == NULL) {
/* Really simple logic for static hair. */
BoundBox bounds = BoundBox::empty;
- curve.bounds_grow(k, &hair->curve_keys[0], curve_radius, bounds);
+ curve.bounds_grow(k, &hair->get_curve_keys()[0], curve_radius, bounds);
if (bounds.valid()) {
int packed_type = PRIMITIVE_PACK_SEGMENT(primitive_type, k);
references.push_back(BVHReference(bounds, j, i, packed_type));
@@ -189,9 +189,9 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Hair *hair
*/
/* TODO(sergey): Support motion steps for spatially split BVH. */
BoundBox bounds = BoundBox::empty;
- curve.bounds_grow(k, &hair->curve_keys[0], curve_radius, bounds);
- const size_t num_keys = hair->curve_keys.size();
- const size_t num_steps = hair->motion_steps;
+ curve.bounds_grow(k, &hair->get_curve_keys()[0], curve_radius, bounds);
+ const size_t num_keys = hair->get_curve_keys().size();
+ const size_t num_steps = hair->get_motion_steps();
const float3 *key_steps = curve_attr_mP->data_float3();
for (size_t step = 0; step < num_steps - 1; step++) {
curve.bounds_grow(k, key_steps + step * num_keys, curve_radius, bounds);
@@ -210,10 +210,10 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Hair *hair
*/
const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1;
const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
- const size_t num_steps = hair->motion_steps;
- const float3 *curve_keys = &hair->curve_keys[0];
+ const size_t num_steps = hair->get_motion_steps();
+ const float3 *curve_keys = &hair->get_curve_keys()[0];
const float3 *key_steps = curve_attr_mP->data_float3();
- const size_t num_keys = hair->curve_keys.size();
+ const size_t num_keys = hair->get_curve_keys().size();
/* Calculate bounding box of the previous time step.
* Will be reused later to avoid duplicated work on
* calculating BVH time step boundbox.
@@ -270,11 +270,11 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Hair *hair
void BVHBuild::add_reference_geometry(BoundBox &root, BoundBox &center, Geometry *geom, int i)
{
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
add_reference_triangles(root, center, mesh, i);
}
- else if (geom->type == Geometry::HAIR) {
+ else if (geom->geometry_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
add_reference_curves(root, center, hair, i);
}
@@ -299,11 +299,11 @@ static size_t count_curve_segments(Hair *hair)
static size_t count_primitives(Geometry *geom)
{
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
return mesh->num_triangles();
}
- else if (geom->type == Geometry::HAIR) {
+ else if (geom->geometry_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
return count_curve_segments(hair);
}
@@ -321,14 +321,14 @@ void BVHBuild::add_references(BVHRange &root)
if (!ob->is_traceable()) {
continue;
}
- if (!ob->geometry->is_instanced()) {
- num_alloc_references += count_primitives(ob->geometry);
+ if (!ob->get_geometry()->is_instanced()) {
+ num_alloc_references += count_primitives(ob->get_geometry());
}
else
num_alloc_references++;
}
else {
- num_alloc_references += count_primitives(ob->geometry);
+ num_alloc_references += count_primitives(ob->get_geometry());
}
}
@@ -344,13 +344,13 @@ void BVHBuild::add_references(BVHRange &root)
++i;
continue;
}
- if (!ob->geometry->is_instanced())
- add_reference_geometry(bounds, center, ob->geometry, i);
+ if (!ob->get_geometry()->is_instanced())
+ add_reference_geometry(bounds, center, ob->get_geometry(), i);
else
add_reference_object(bounds, center, ob, i);
}
else
- add_reference_geometry(bounds, center, ob->geometry, i);
+ add_reference_geometry(bounds, center, ob->get_geometry(), i);
i++;
diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp
index 53776a55257..910e3780b2e 100644
--- a/intern/cycles/bvh/bvh_embree.cpp
+++ b/intern/cycles/bvh/bvh_embree.cpp
@@ -300,11 +300,11 @@ static bool rtc_progress_func(void *user_ptr, const double n)
static size_t count_primitives(Geometry *geom)
{
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
return mesh->num_triangles();
}
- else if (geom->type == Geometry::HAIR) {
+ else if (geom->geometry_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
return hair->num_segments();
}
@@ -402,15 +402,15 @@ void BVHEmbree::build(Progress &progress, Stats *stats_)
if (!ob->is_traceable()) {
continue;
}
- if (!ob->geometry->is_instanced()) {
- prim_count += count_primitives(ob->geometry);
+ if (!ob->get_geometry()->is_instanced()) {
+ prim_count += count_primitives(ob->get_geometry());
}
else {
++prim_count;
}
}
else {
- prim_count += count_primitives(ob->geometry);
+ prim_count += count_primitives(ob->get_geometry());
}
}
@@ -429,7 +429,7 @@ void BVHEmbree::build(Progress &progress, Stats *stats_)
++i;
continue;
}
- if (!ob->geometry->is_instanced()) {
+ if (!ob->get_geometry()->is_instanced()) {
add_object(ob, i);
}
else {
@@ -480,15 +480,15 @@ BVHNode *BVHEmbree::widen_children_nodes(const BVHNode * /*root*/)
void BVHEmbree::add_object(Object *ob, int i)
{
- Geometry *geom = ob->geometry;
+ Geometry *geom = ob->get_geometry();
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
if (mesh->num_triangles() > 0) {
add_triangles(ob, mesh, i);
}
}
- else if (geom->type == Geometry::HAIR) {
+ else if (geom->geometry_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
if (hair->num_curves() > 0) {
add_curves(ob, hair, i);
@@ -498,17 +498,17 @@ void BVHEmbree::add_object(Object *ob, int i)
void BVHEmbree::add_instance(Object *ob, int i)
{
- if (!ob || !ob->geometry) {
+ if (!ob || !ob->get_geometry()) {
assert(0);
return;
}
- BVHEmbree *instance_bvh = (BVHEmbree *)(ob->geometry->bvh);
+ BVHEmbree *instance_bvh = (BVHEmbree *)(ob->get_geometry()->bvh);
if (instance_bvh->top_level != this) {
instance_bvh->top_level = this;
}
- const size_t num_object_motion_steps = ob->use_motion() ? ob->motion.size() : 1;
+ const size_t num_object_motion_steps = ob->use_motion() ? ob->get_motion().size() : 1;
const size_t num_motion_steps = min(num_object_motion_steps, RTC_MAX_TIME_STEP_COUNT);
assert(num_object_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
@@ -517,8 +517,8 @@ void BVHEmbree::add_instance(Object *ob, int i)
rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
if (ob->use_motion()) {
- array<DecomposedTransform> decomp(ob->motion.size());
- transform_motion_decompose(decomp.data(), ob->motion.data(), ob->motion.size());
+ array<DecomposedTransform> decomp(ob->get_motion().size());
+ transform_motion_decompose(decomp.data(), ob->get_motion().data(), ob->get_motion().size());
for (size_t step = 0; step < num_motion_steps; ++step) {
RTCQuaternionDecomposition rtc_decomp;
rtcInitQuaternionDecomposition(&rtc_decomp);
@@ -534,7 +534,8 @@ void BVHEmbree::add_instance(Object *ob, int i)
}
}
else {
- rtcSetGeometryTransform(geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float *)&ob->tfm);
+ rtcSetGeometryTransform(
+ geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float *)&ob->get_tfm());
}
pack.prim_index.push_back_slow(-1);
@@ -558,7 +559,7 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
if (mesh->has_motion_blur()) {
attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_mP) {
- num_geometry_motion_steps = mesh->motion_steps;
+ num_geometry_motion_steps = mesh->get_motion_steps();
}
}
@@ -620,7 +621,7 @@ void BVHEmbree::set_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh, con
if (mesh->has_motion_blur()) {
attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_mP) {
- num_motion_steps = mesh->motion_steps;
+ num_motion_steps = mesh->get_motion_steps();
t_mid = (num_motion_steps - 1) / 2;
if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) {
assert(0);
@@ -672,7 +673,7 @@ void BVHEmbree::set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, c
if (hair->has_motion_blur()) {
attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_mP) {
- num_motion_steps = hair->motion_steps;
+ num_motion_steps = hair->get_motion_steps();
}
}
@@ -689,11 +690,11 @@ void BVHEmbree::set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, c
/* Copy the CV data to Embree */
const int t_mid = (num_motion_steps - 1) / 2;
- const float *curve_radius = &hair->curve_radius[0];
+ const float *curve_radius = &hair->get_curve_radius()[0];
for (int t = 0; t < num_motion_steps; ++t) {
const float3 *verts;
if (t == t_mid || attr_mP == NULL) {
- verts = &hair->curve_keys[0];
+ verts = &hair->get_curve_keys()[0];
}
else {
int t_ = (t > t_mid) ? (t - 1) : t;
@@ -741,7 +742,7 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
if (hair->has_motion_blur()) {
attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_mP) {
- num_geometry_motion_steps = hair->motion_steps;
+ num_geometry_motion_steps = hair->get_motion_steps();
}
}
@@ -826,7 +827,7 @@ void BVHEmbree::pack_nodes(const BVHNode *)
for (size_t i = 0; i < pack.prim_index.size(); ++i) {
if (pack.prim_index[i] != -1) {
- pack.prim_index[i] += objects[pack.prim_object[i]]->geometry->prim_offset;
+ pack.prim_index[i] += objects[pack.prim_object[i]]->get_geometry()->prim_offset;
}
}
@@ -843,7 +844,7 @@ void BVHEmbree::pack_nodes(const BVHNode *)
map<Geometry *, int> geometry_map;
foreach (Object *ob, objects) {
- Geometry *geom = ob->geometry;
+ Geometry *geom = ob->get_geometry();
BVH *bvh = geom->bvh;
if (geom->need_build_bvh(BVH_LAYOUT_EMBREE)) {
@@ -873,7 +874,7 @@ void BVHEmbree::pack_nodes(const BVHNode *)
/* merge */
foreach (Object *ob, objects) {
- Geometry *geom = ob->geometry;
+ Geometry *geom = ob->get_geometry();
/* We assume that if mesh doesn't need own BVH it was already included
* into a top-level BVH and no packing here is needed.
@@ -948,10 +949,10 @@ void BVHEmbree::refit_nodes()
/* Update all vertex buffers, then tell Embree to rebuild/-fit the BVHs. */
unsigned geom_id = 0;
foreach (Object *ob, objects) {
- if (!params.top_level || (ob->is_traceable() && !ob->geometry->is_instanced())) {
- Geometry *geom = ob->geometry;
+ if (!params.top_level || (ob->is_traceable() && !ob->get_geometry()->is_instanced())) {
+ Geometry *geom = ob->get_geometry();
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
if (mesh->num_triangles() > 0) {
RTCGeometry geom = rtcGetGeometry(scene, geom_id);
@@ -959,7 +960,7 @@ void BVHEmbree::refit_nodes()
rtcCommitGeometry(geom);
}
}
- else if (geom->type == Geometry::HAIR) {
+ else if (geom->geometry_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
if (hair->num_curves() > 0) {
RTCGeometry geom = rtcGetGeometry(scene, geom_id + 1);
diff --git a/intern/cycles/bvh/bvh_optix.cpp b/intern/cycles/bvh/bvh_optix.cpp
index 0527c0eeda8..52fc9c0a50d 100644
--- a/intern/cycles/bvh/bvh_optix.cpp
+++ b/intern/cycles/bvh/bvh_optix.cpp
@@ -37,6 +37,9 @@ BVHOptiX::BVHOptiX(const BVHParams &params_,
const vector<Object *> &objects_)
: BVH(params_, geometry_, objects_)
{
+ optix_handle = 0;
+ optix_data_handle = 0;
+ do_refit = false;
}
BVHOptiX::~BVHOptiX()
@@ -66,7 +69,7 @@ void BVHOptiX::pack_blas()
assert(geometry.size() == 1 && objects.size() == 1); // These are built per-mesh
Geometry *const geom = geometry[0];
- if (geom->type == Geometry::HAIR) {
+ if (geom->geometry_type == Geometry::HAIR) {
Hair *const hair = static_cast<Hair *const>(geom);
if (hair->num_curves() > 0) {
const size_t num_curves = hair->num_curves();
@@ -77,7 +80,7 @@ void BVHOptiX::pack_blas()
// 'pack.prim_time' is only used in geom_curve_intersect.h
// It is not needed because of OPTIX_MOTION_FLAG_[START|END]_VANISH
- uint type = (hair->use_motion_blur &&
+ uint type = (hair->get_use_motion_blur() &&
hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) ?
((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON :
PRIMITIVE_MOTION_CURVE_THICK) :
@@ -95,7 +98,7 @@ void BVHOptiX::pack_blas()
}
}
}
- else if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ else if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *const mesh = static_cast<Mesh *const>(geom);
if (mesh->num_triangles() > 0) {
const size_t num_triangles = mesh->num_triangles();
@@ -104,7 +107,7 @@ void BVHOptiX::pack_blas()
pack.prim_object.reserve(pack.prim_object.size() + num_triangles);
uint type = PRIMITIVE_TRIANGLE;
- if (mesh->use_motion_blur && mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION))
+ if (mesh->get_use_motion_blur() && mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION))
type = PRIMITIVE_MOTION_TRIANGLE;
for (size_t k = 0; k < num_triangles; ++k) {
@@ -116,14 +119,14 @@ void BVHOptiX::pack_blas()
}
// Initialize visibility to zero and later update it during top-level build
- uint prev_visibility = objects[0]->visibility;
- objects[0]->visibility = 0;
+ uint prev_visibility = objects[0]->get_visibility();
+ objects[0]->set_visibility(0);
// Update 'pack.prim_tri_index', 'pack.prim_tri_verts' and 'pack.prim_visibility'
pack_primitives();
// Reset visibility after packing
- objects[0]->visibility = prev_visibility;
+ objects[0]->set_visibility(prev_visibility);
}
void BVHOptiX::pack_tlas()
@@ -167,7 +170,7 @@ void BVHOptiX::pack_tlas()
int object_index = 0; // Unused for instanced geometry
int object_visibility = 0;
foreach (Object *ob, objects) {
- if (ob->geometry == geom) {
+ if (ob->get_geometry() == geom) {
object_visibility |= ob->visibility_for_tracing();
if (!geom->is_instanced()) {
object_index = ob->get_device_index();
@@ -216,8 +219,7 @@ void BVHOptiX::pack_nodes(const BVHNode *)
void BVHOptiX::refit_nodes()
{
- // TODO(pmours): Implement?
- VLOG(1) << "Refit is not yet implemented for OptiX BVH.";
+ do_refit = true;
}
BVHNode *BVHOptiX::widen_children_nodes(const BVHNode *)
diff --git a/intern/cycles/bvh/bvh_optix.h b/intern/cycles/bvh/bvh_optix.h
index e4745b093b5..663cba67260 100644
--- a/intern/cycles/bvh/bvh_optix.h
+++ b/intern/cycles/bvh/bvh_optix.h
@@ -33,6 +33,10 @@ class BVHOptiX : public BVH {
friend class BVH;
public:
+ uint64_t optix_handle;
+ uint64_t optix_data_handle;
+ bool do_refit;
+
BVHOptiX(const BVHParams &params,
const vector<Geometry *> &geometry,
const vector<Object *> &objects);
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index 2f1960d664e..834b07440d8 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -392,8 +392,8 @@ void BVHSpatialSplit::split_curve_primitive(const Hair *hair,
Hair::Curve curve = hair->get_curve(prim_index);
const int k0 = curve.first_key + segment_index;
const int k1 = k0 + 1;
- float3 v0 = hair->curve_keys[k0];
- float3 v1 = hair->curve_keys[k1];
+ float3 v0 = hair->get_curve_keys()[k0];
+ float3 v1 = hair->get_curve_keys()[k1];
if (tfm != NULL) {
v0 = transform_point(tfm, v0);
@@ -456,21 +456,22 @@ void BVHSpatialSplit::split_curve_reference(const BVHReference &ref,
void BVHSpatialSplit::split_object_reference(
const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds)
{
- Geometry *geom = object->geometry;
+ Geometry *geom = object->get_geometry();
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
for (int tri_idx = 0; tri_idx < mesh->num_triangles(); ++tri_idx) {
- split_triangle_primitive(mesh, &object->tfm, tri_idx, dim, pos, left_bounds, right_bounds);
+ split_triangle_primitive(
+ mesh, &object->get_tfm(), tri_idx, dim, pos, left_bounds, right_bounds);
}
}
- else if (geom->type == Geometry::HAIR) {
+ else if (geom->geometry_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
for (int curve_idx = 0; curve_idx < hair->num_curves(); ++curve_idx) {
Hair::Curve curve = hair->get_curve(curve_idx);
for (int segment_idx = 0; segment_idx < curve.num_keys - 1; ++segment_idx) {
split_curve_primitive(
- hair, &object->tfm, curve_idx, segment_idx, dim, pos, left_bounds, right_bounds);
+ hair, &object->get_tfm(), curve_idx, segment_idx, dim, pos, left_bounds, right_bounds);
}
}
}
@@ -491,11 +492,11 @@ void BVHSpatialSplit::split_reference(const BVHBuild &builder,
const Object *ob = builder.objects[ref.prim_object()];
if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
- Mesh *mesh = static_cast<Mesh *>(ob->geometry);
+ Mesh *mesh = static_cast<Mesh *>(ob->get_geometry());
split_triangle_reference(ref, mesh, dim, pos, left_bounds, right_bounds);
}
else if (ref.prim_type() & PRIMITIVE_ALL_CURVE) {
- Hair *hair = static_cast<Hair *>(ob->geometry);
+ Hair *hair = static_cast<Hair *>(ob->get_geometry());
split_curve_reference(ref, hair, dim, pos, left_bounds, right_bounds);
}
else {
diff --git a/intern/cycles/bvh/bvh_unaligned.cpp b/intern/cycles/bvh/bvh_unaligned.cpp
index c969b361643..38e55307848 100644
--- a/intern/cycles/bvh/bvh_unaligned.cpp
+++ b/intern/cycles/bvh/bvh_unaligned.cpp
@@ -72,10 +72,10 @@ bool BVHUnaligned::compute_aligned_space(const BVHReference &ref, Transform *ali
if (type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_CURVE_THICK)) {
const int curve_index = ref.prim_index();
const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
- const Hair *hair = static_cast<const Hair *>(object->geometry);
+ const Hair *hair = static_cast<const Hair *>(object->get_geometry());
const Hair::Curve &curve = hair->get_curve(curve_index);
const int key = curve.first_key + segment;
- const float3 v1 = hair->curve_keys[key], v2 = hair->curve_keys[key + 1];
+ const float3 v1 = hair->get_curve_keys()[key], v2 = hair->get_curve_keys()[key + 1];
float length;
const float3 axis = normalize_len(v2 - v1, &length);
if (length > 1e-6f) {
@@ -98,10 +98,10 @@ BoundBox BVHUnaligned::compute_aligned_prim_boundbox(const BVHReference &prim,
if (type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_CURVE_THICK)) {
const int curve_index = prim.prim_index();
const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
- const Hair *hair = static_cast<const Hair *>(object->geometry);
+ const Hair *hair = static_cast<const Hair *>(object->get_geometry());
const Hair::Curve &curve = hair->get_curve(curve_index);
curve.bounds_grow(
- segment, &hair->curve_keys[0], &hair->curve_radius[0], aligned_space, bounds);
+ segment, &hair->get_curve_keys()[0], &hair->get_curve_radius()[0], aligned_space, bounds);
}
else {
bounds = prim.bounds().transformed(&aligned_space);
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index cc54f64b1bb..928249931a3 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -39,6 +39,7 @@ set(SRC
device_cpu.cpp
device_cuda.cpp
device_denoising.cpp
+ device_dummy.cpp
device_memory.cpp
device_multi.cpp
device_opencl.cpp
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 407f73e8451..eb8fb8040e3 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -375,7 +375,7 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool
}
#endif
- Device *device;
+ Device *device = NULL;
switch (info.type) {
case DEVICE_CPU:
@@ -385,16 +385,12 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool
case DEVICE_CUDA:
if (device_cuda_init())
device = device_cuda_create(info, stats, profiler, background);
- else
- device = NULL;
break;
#endif
#ifdef WITH_OPTIX
case DEVICE_OPTIX:
if (device_optix_init())
device = device_optix_create(info, stats, profiler, background);
- else
- device = NULL;
break;
#endif
#ifdef WITH_NETWORK
@@ -406,12 +402,14 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool
case DEVICE_OPENCL:
if (device_opencl_init())
device = device_opencl_create(info, stats, profiler, background);
- else
- device = NULL;
break;
#endif
default:
- return NULL;
+ break;
+ }
+
+ if (device == NULL) {
+ device = device_dummy_create(info, stats, profiler, background);
}
return device;
@@ -549,6 +547,14 @@ vector<DeviceInfo> Device::available_devices(uint mask)
return devices;
}
+DeviceInfo Device::dummy_device(const string &error_msg)
+{
+ DeviceInfo info;
+ info.type = DEVICE_DUMMY;
+ info.error_msg = error_msg;
+ return info;
+}
+
string Device::device_capabilities(uint mask)
{
thread_scoped_lock lock(device_mutex);
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index ddf608aa430..2006db02ce7 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -48,6 +48,7 @@ enum DeviceType {
DEVICE_NETWORK,
DEVICE_MULTI,
DEVICE_OPTIX,
+ DEVICE_DUMMY,
};
enum DeviceTypeMask {
@@ -87,6 +88,7 @@ class DeviceInfo {
int cpu_threads;
vector<DeviceInfo> multi_devices;
vector<DeviceInfo> denoising_devices;
+ string error_msg;
DeviceInfo()
{
@@ -471,6 +473,7 @@ class Device {
static string string_from_type(DeviceType type);
static vector<DeviceType> available_types();
static vector<DeviceInfo> available_devices(uint device_type_mask = DEVICE_MASK_ALL);
+ static DeviceInfo dummy_device(const string &error_msg = "");
static string device_capabilities(uint device_type_mask = DEVICE_MASK_ALL);
static DeviceInfo get_multi_device(const vector<DeviceInfo> &subdevices,
int threads,
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index 23aedcd0c48..6912ac1e638 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -932,6 +932,11 @@ class CPUDevice : public Device {
break;
}
+ if (tile.stealing_state == RenderTile::CAN_BE_STOLEN && task.get_tile_stolen()) {
+ tile.stealing_state = RenderTile::WAS_STOLEN;
+ break;
+ }
+
if (tile.task == RenderTile::PATH_TRACE) {
for (int y = tile.y; y < tile.y + tile.h; y++) {
for (int x = tile.x; x < tile.x + tile.w; x++) {
diff --git a/intern/cycles/device/device_dummy.cpp b/intern/cycles/device/device_dummy.cpp
new file mode 100644
index 00000000000..5112fc152e5
--- /dev/null
+++ b/intern/cycles/device/device_dummy.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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 "device/device.h"
+#include "device/device_intern.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Dummy device for when creating an appropriate rendering device fails. */
+
+class DummyDevice : public Device {
+ public:
+ DummyDevice(DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool background_)
+ : Device(info_, stats_, profiler_, background_)
+ {
+ error_msg = info.error_msg;
+ }
+
+ ~DummyDevice()
+ {
+ }
+
+ virtual BVHLayoutMask get_bvh_layout_mask() const override
+ {
+ return 0;
+ }
+
+ virtual void mem_alloc(device_memory &) override
+ {
+ }
+
+ virtual void mem_copy_to(device_memory &) override
+ {
+ }
+
+ virtual void mem_copy_from(device_memory &, int, int, int, int) override
+ {
+ }
+
+ virtual void mem_zero(device_memory &) override
+ {
+ }
+
+ virtual void mem_free(device_memory &) override
+ {
+ }
+
+ virtual void const_copy_to(const char *, void *, size_t) override
+ {
+ }
+
+ virtual void task_add(DeviceTask &) override
+ {
+ }
+
+ virtual void task_wait() override
+ {
+ }
+
+ virtual void task_cancel() override
+ {
+ }
+};
+
+Device *device_dummy_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background)
+{
+ return new DummyDevice(info, stats, profiler, background);
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h
index 94d63e8f333..ecc79c5d7ee 100644
--- a/intern/cycles/device/device_intern.h
+++ b/intern/cycles/device/device_intern.h
@@ -35,6 +35,7 @@ bool device_cuda_init();
Device *device_cuda_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
bool device_optix_init();
Device *device_optix_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
+Device *device_dummy_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
Device *device_network_create(DeviceInfo &info,
Stats &stats,
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h
index 32654e62a6f..00b2aa864aa 100644
--- a/intern/cycles/device/device_memory.h
+++ b/intern/cycles/device/device_memory.h
@@ -450,6 +450,14 @@ template<typename T> class device_vector : public device_memory {
device_zero();
}
+ void move_device(Device *new_device)
+ {
+ copy_from_device();
+ device_free();
+ device = new_device;
+ copy_to_device();
+ }
+
protected:
size_t size(size_t width, size_t height, size_t depth)
{
diff --git a/intern/cycles/device/device_optix.cpp b/intern/cycles/device/device_optix.cpp
index 43b1fb30baf..95234845f98 100644
--- a/intern/cycles/device/device_optix.cpp
+++ b/intern/cycles/device/device_optix.cpp
@@ -18,6 +18,7 @@
#ifdef WITH_OPTIX
# include "bvh/bvh.h"
+# include "bvh/bvh_optix.h"
# include "device/cuda/device_cuda.h"
# include "device/device_denoising.h"
# include "device/device_intern.h"
@@ -137,9 +138,6 @@ class OptiXDevice : public CUDADevice {
PG_HITD_MOTION,
PG_HITS_MOTION,
# endif
-# ifdef WITH_CYCLES_DEBUG
- PG_EXCP,
-# endif
PG_BAKE, // kernel_bake_evaluate
PG_DISP, // kernel_displace_evaluate
PG_BACK, // kernel_background_evaluate
@@ -232,6 +230,9 @@ class OptiXDevice : public CUDADevice {
}
};
# endif
+# if OPTIX_ABI_VERSION >= 41 && defined(WITH_CYCLES_DEBUG)
+ options.validationMode = OPTIX_DEVICE_CONTEXT_VALIDATION_MODE_ALL;
+# endif
check_result_optix(optixDeviceContextCreate(cuContext, &options, &context));
# ifdef WITH_CYCLES_LOGGING
check_result_optix(optixDeviceContextSetLogCallback(
@@ -368,6 +369,12 @@ class OptiXDevice : public CUDADevice {
module_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_LEVEL_3;
module_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_LINEINFO;
# endif
+
+# if OPTIX_ABI_VERSION >= 41
+ module_options.boundValues = nullptr;
+ module_options.numBoundValues = 0;
+# endif
+
OptixPipelineCompileOptions pipeline_options;
// Default to no motion blur and two-level graph, since it is the fastest option
pipeline_options.usesMotionBlur = false;
@@ -375,12 +382,7 @@ class OptiXDevice : public CUDADevice {
OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_LEVEL_INSTANCING;
pipeline_options.numPayloadValues = 6;
pipeline_options.numAttributeValues = 2; // u, v
-# ifdef WITH_CYCLES_DEBUG
- pipeline_options.exceptionFlags = OPTIX_EXCEPTION_FLAG_STACK_OVERFLOW |
- OPTIX_EXCEPTION_FLAG_TRACE_DEPTH;
-# else
pipeline_options.exceptionFlags = OPTIX_EXCEPTION_FLAG_NONE;
-# endif
pipeline_options.pipelineLaunchParamsVariableName = "__params"; // See kernel_globals.h
# if OPTIX_ABI_VERSION >= 36
@@ -505,12 +507,6 @@ class OptiXDevice : public CUDADevice {
group_descs[PG_HITL].hitgroup.entryFunctionNameAH = "__anyhit__kernel_optix_local_hit";
}
-# ifdef WITH_CYCLES_DEBUG
- group_descs[PG_EXCP].kind = OPTIX_PROGRAM_GROUP_KIND_EXCEPTION;
- group_descs[PG_EXCP].exception.module = optix_module;
- group_descs[PG_EXCP].exception.entryFunctionName = "__exception__kernel_optix_exception";
-# endif
-
if (requested_features.use_baking) {
group_descs[PG_BAKE].kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
group_descs[PG_BAKE].raygen.module = optix_module;
@@ -578,9 +574,6 @@ class OptiXDevice : public CUDADevice {
groups[PG_HITD_MOTION],
groups[PG_HITS_MOTION],
# endif
-# ifdef WITH_CYCLES_DEBUG
- groups[PG_EXCP],
-# endif
};
check_result_optix_ret(
optixPipelineCreate(context,
@@ -618,9 +611,6 @@ class OptiXDevice : public CUDADevice {
groups[PG_HITD_MOTION],
groups[PG_HITS_MOTION],
# endif
-# ifdef WITH_CYCLES_DEBUG
- groups[PG_EXCP],
-# endif
};
check_result_optix_ret(
optixPipelineCreate(context,
@@ -734,9 +724,6 @@ class OptiXDevice : public CUDADevice {
OptixShaderBindingTable sbt_params = {};
sbt_params.raygenRecord = sbt_data.device_pointer + PG_RGEN * sizeof(SbtRecord);
-# ifdef WITH_CYCLES_DEBUG
- sbt_params.exceptionRecord = sbt_data.device_pointer + PG_EXCP * sizeof(SbtRecord);
-# endif
sbt_params.missRecordBase = sbt_data.device_pointer + PG_MISS * sizeof(SbtRecord);
sbt_params.missRecordStrideInBytes = sizeof(SbtRecord);
sbt_params.missRecordCount = 1;
@@ -1064,9 +1051,6 @@ class OptiXDevice : public CUDADevice {
OptixShaderBindingTable sbt_params = {};
sbt_params.raygenRecord = sbt_data.device_pointer + rgen_index * sizeof(SbtRecord);
-# ifdef WITH_CYCLES_DEBUG
- sbt_params.exceptionRecord = sbt_data.device_pointer + PG_EXCP * sizeof(SbtRecord);
-# endif
sbt_params.missRecordBase = sbt_data.device_pointer + PG_MISS * sizeof(SbtRecord);
sbt_params.missRecordStrideInBytes = sizeof(SbtRecord);
sbt_params.missRecordCount = 1;
@@ -1095,23 +1079,23 @@ class OptiXDevice : public CUDADevice {
bool build_optix_bvh(const OptixBuildInput &build_input,
uint16_t num_motion_steps,
- OptixTraversableHandle &out_handle)
+ OptixTraversableHandle &out_handle,
+ CUdeviceptr &out_data,
+ OptixBuildOperation operation)
{
- out_handle = 0;
-
const CUDAContextScope scope(cuContext);
// Compute memory usage
OptixAccelBufferSizes sizes = {};
OptixAccelBuildOptions options;
- options.operation = OPTIX_BUILD_OPERATION_BUILD;
+ options.operation = operation;
if (background) {
// Prefer best performance and lowest memory consumption in background
options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE | OPTIX_BUILD_FLAG_ALLOW_COMPACTION;
}
else {
// Prefer fast updates in viewport
- options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_BUILD;
+ options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_BUILD | OPTIX_BUILD_FLAG_ALLOW_UPDATE;
}
options.motionOptions.numKeys = num_motion_steps;
@@ -1136,8 +1120,10 @@ class OptiXDevice : public CUDADevice {
move_textures_to_host(size - free, false);
}
- CUdeviceptr out_data = 0;
- check_result_cuda_ret(cuMemAlloc(&out_data, sizes.outputSizeInBytes));
+ if (operation == OPTIX_BUILD_OPERATION_BUILD) {
+ check_result_cuda_ret(cuMemAlloc(&out_data, sizes.outputSizeInBytes));
+ }
+
as_mem.push_back(out_data);
// Finally build the acceleration structure
@@ -1204,23 +1190,49 @@ class OptiXDevice : public CUDADevice {
unordered_map<Geometry *, OptixTraversableHandle> geometry;
geometry.reserve(bvh->geometry.size());
- // Free all previous acceleration structures
+ // Free all previous acceleration structures which can not be refit
+ std::set<CUdeviceptr> refit_mem;
+
+ for (Geometry *geom : bvh->geometry) {
+ if (static_cast<BVHOptiX *>(geom->bvh)->do_refit) {
+ refit_mem.insert(static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle);
+ }
+ }
+
for (CUdeviceptr mem : as_mem) {
- cuMemFree(mem);
+ if (refit_mem.find(mem) == refit_mem.end()) {
+ cuMemFree(mem);
+ }
}
+
as_mem.clear();
// Build bottom level acceleration structures (BLAS)
// Note: Always keep this logic in sync with bvh_optix.cpp!
for (Object *ob : bvh->objects) {
// Skip geometry for which acceleration structure already exists
- Geometry *geom = ob->geometry;
+ Geometry *geom = ob->get_geometry();
if (geometry.find(geom) != geometry.end())
continue;
- if (geom->type == Geometry::HAIR) {
+ OptixTraversableHandle handle;
+ OptixBuildOperation operation;
+ CUdeviceptr out_data;
+ // Refit is only possible in viewport for now.
+ if (static_cast<BVHOptiX *>(geom->bvh)->do_refit && !background) {
+ out_data = static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle;
+ handle = static_cast<BVHOptiX *>(geom->bvh)->optix_handle;
+ operation = OPTIX_BUILD_OPERATION_UPDATE;
+ }
+ else {
+ out_data = 0;
+ handle = 0;
+ operation = OPTIX_BUILD_OPERATION_BUILD;
+ }
+
+ if (geom->geometry_type == Geometry::HAIR) {
// Build BLAS for curve primitives
- Hair *const hair = static_cast<Hair *const>(ob->geometry);
+ Hair *const hair = static_cast<Hair *const>(ob->get_geometry());
if (hair->num_curves() == 0) {
continue;
}
@@ -1229,8 +1241,8 @@ class OptiXDevice : public CUDADevice {
size_t num_motion_steps = 1;
Attribute *motion_keys = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (motion_blur && hair->use_motion_blur && motion_keys) {
- num_motion_steps = hair->motion_steps;
+ if (motion_blur && hair->get_use_motion_blur() && motion_keys) {
+ num_motion_steps = hair->get_motion_steps();
}
device_vector<OptixAabb> aabb_data(this, "temp_aabb_data", MEM_READ_ONLY);
@@ -1250,16 +1262,19 @@ class OptiXDevice : public CUDADevice {
// Get AABBs for each motion step
for (size_t step = 0; step < num_motion_steps; ++step) {
// The center step for motion vertices is not stored in the attribute
- const float3 *keys = hair->curve_keys.data();
+ const float3 *keys = hair->get_curve_keys().data();
size_t center_step = (num_motion_steps - 1) / 2;
if (step != center_step) {
size_t attr_offset = (step > center_step) ? step - 1 : step;
// Technically this is a float4 array, but sizeof(float3) is the same as sizeof(float4)
- keys = motion_keys->data_float3() + attr_offset * hair->curve_keys.size();
+ keys = motion_keys->data_float3() + attr_offset * hair->get_curve_keys().size();
}
for (size_t j = 0, i = 0; j < hair->num_curves(); ++j) {
const Hair::Curve curve = hair->get_curve(j);
+# if OPTIX_ABI_VERSION >= 36
+ const array<float> &curve_radius = hair->get_curve_radius();
+# endif
for (int segment = 0; segment < curve.num_segments(); ++segment, ++i) {
# if OPTIX_ABI_VERSION >= 36
@@ -1272,10 +1287,8 @@ class OptiXDevice : public CUDADevice {
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]);
+ const float4 pw = make_float4(
+ curve_radius[ka], curve_radius[k0], curve_radius[k1], curve_radius[kb]);
// Convert Catmull-Rom data to Bezier spline
static const float4 cr2bsp0 = make_float4(+7, -4, +5, -2) / 6.f;
@@ -1298,7 +1311,7 @@ class OptiXDevice : public CUDADevice {
# endif
{
BoundBox bounds = BoundBox::empty;
- curve.bounds_grow(segment, keys, hair->curve_radius.data(), bounds);
+ curve.bounds_grow(segment, keys, hair->get_curve_radius().data(), bounds);
const size_t index = step * num_segments + i;
aabb_data[index].minX = bounds.min.x;
@@ -1381,37 +1394,41 @@ class OptiXDevice : public CUDADevice {
}
// Allocate memory for new BLAS and build it
- OptixTraversableHandle handle;
- if (build_optix_bvh(build_input, num_motion_steps, handle)) {
- geometry.insert({ob->geometry, handle});
+ if (build_optix_bvh(build_input, num_motion_steps, handle, out_data, operation)) {
+ geometry.insert({ob->get_geometry(), handle});
+ static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle = out_data;
+ static_cast<BVHOptiX *>(geom->bvh)->optix_handle = handle;
+ static_cast<BVHOptiX *>(geom->bvh)->do_refit = false;
}
else {
return false;
}
}
- else if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ else if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
// Build BLAS for triangle primitives
- Mesh *const mesh = static_cast<Mesh *const>(ob->geometry);
+ Mesh *const mesh = static_cast<Mesh *const>(ob->get_geometry());
if (mesh->num_triangles() == 0) {
continue;
}
- const size_t num_verts = mesh->verts.size();
+ const size_t num_verts = mesh->get_verts().size();
size_t num_motion_steps = 1;
Attribute *motion_keys = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (motion_blur && mesh->use_motion_blur && motion_keys) {
- num_motion_steps = mesh->motion_steps;
+ if (motion_blur && mesh->get_use_motion_blur() && motion_keys) {
+ num_motion_steps = mesh->get_motion_steps();
}
device_vector<int> index_data(this, "temp_index_data", MEM_READ_ONLY);
- index_data.alloc(mesh->triangles.size());
- memcpy(index_data.data(), mesh->triangles.data(), mesh->triangles.size() * sizeof(int));
+ index_data.alloc(mesh->get_triangles().size());
+ memcpy(index_data.data(),
+ mesh->get_triangles().data(),
+ mesh->get_triangles().size() * sizeof(int));
device_vector<float3> vertex_data(this, "temp_vertex_data", MEM_READ_ONLY);
vertex_data.alloc(num_verts * num_motion_steps);
for (size_t step = 0; step < num_motion_steps; ++step) {
- const float3 *verts = mesh->verts.data();
+ const float3 *verts = mesh->get_verts().data();
size_t center_step = (num_motion_steps - 1) / 2;
// The center step for motion vertices is not stored in the attribute
@@ -1453,9 +1470,11 @@ class OptiXDevice : public CUDADevice {
build_input.triangleArray.primitiveIndexOffset = mesh->optix_prim_offset;
// Allocate memory for new BLAS and build it
- OptixTraversableHandle handle;
- if (build_optix_bvh(build_input, num_motion_steps, handle)) {
- geometry.insert({ob->geometry, handle});
+ if (build_optix_bvh(build_input, num_motion_steps, handle, out_data, operation)) {
+ geometry.insert({ob->get_geometry(), handle});
+ static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle = out_data;
+ static_cast<BVHOptiX *>(geom->bvh)->optix_handle = handle;
+ static_cast<BVHOptiX *>(geom->bvh)->do_refit = false;
}
else {
return false;
@@ -1464,8 +1483,10 @@ class OptiXDevice : public CUDADevice {
}
// Fill instance descriptions
+# if OPTIX_ABI_VERSION < 41
device_vector<OptixAabb> aabbs(this, "tlas_aabbs", MEM_READ_ONLY);
aabbs.alloc(bvh->objects.size());
+# endif
device_vector<OptixInstance> instances(this, "tlas_instances", MEM_READ_ONLY);
instances.alloc(bvh->objects.size());
@@ -1475,12 +1496,13 @@ class OptiXDevice : public CUDADevice {
continue;
// Create separate instance for triangle/curve meshes of an object
- auto handle_it = geometry.find(ob->geometry);
+ const auto handle_it = geometry.find(ob->get_geometry());
if (handle_it == geometry.end()) {
continue;
}
OptixTraversableHandle handle = handle_it->second;
+# if OPTIX_ABI_VERSION < 41
OptixAabb &aabb = aabbs[num_instances];
aabb.minX = ob->bounds.min.x;
aabb.minY = ob->bounds.min.y;
@@ -1488,6 +1510,7 @@ class OptiXDevice : public CUDADevice {
aabb.maxX = ob->bounds.max.x;
aabb.maxY = ob->bounds.max.y;
aabb.maxZ = ob->bounds.max.z;
+# endif
OptixInstance &instance = instances[num_instances++];
memset(&instance, 0, sizeof(instance));
@@ -1503,18 +1526,19 @@ class OptiXDevice : public CUDADevice {
// 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) {
+ if (ob->get_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) {
+ if (ob->get_geometry()->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) {
+ if (motion_blur && ob->get_geometry()->has_motion_blur() &&
+ DebugFlags().optix.curves_api &&
+ static_cast<const Hair *>(ob->get_geometry())->curve_shape == CURVE_THICK) {
// Select between motion blur and non-motion blur built-in intersection module
instance.sbtOffset = PG_HITD_MOTION - PG_HITD;
}
@@ -1523,7 +1547,7 @@ class OptiXDevice : public CUDADevice {
// Insert motion traversable if object has motion
if (motion_blur && ob->use_motion()) {
- size_t motion_keys = max(ob->motion.size(), 2) - 2;
+ size_t motion_keys = max(ob->get_motion().size(), 2) - 2;
size_t motion_transform_size = sizeof(OptixSRTMotionTransform) +
motion_keys * sizeof(OptixSRTData);
@@ -1537,16 +1561,17 @@ class OptiXDevice : public CUDADevice {
OptixSRTMotionTransform &motion_transform = *reinterpret_cast<OptixSRTMotionTransform *>(
new uint8_t[motion_transform_size]);
motion_transform.child = handle;
- motion_transform.motionOptions.numKeys = ob->motion.size();
+ motion_transform.motionOptions.numKeys = ob->get_motion().size();
motion_transform.motionOptions.flags = OPTIX_MOTION_FLAG_NONE;
motion_transform.motionOptions.timeBegin = 0.0f;
motion_transform.motionOptions.timeEnd = 1.0f;
OptixSRTData *const srt_data = motion_transform.srtData;
- array<DecomposedTransform> decomp(ob->motion.size());
- transform_motion_decompose(decomp.data(), ob->motion.data(), ob->motion.size());
+ array<DecomposedTransform> decomp(ob->get_motion().size());
+ transform_motion_decompose(
+ decomp.data(), ob->get_motion().data(), ob->get_motion().size());
- for (size_t i = 0; i < ob->motion.size(); ++i) {
+ for (size_t i = 0; i < ob->get_motion().size(); ++i) {
// Scale
srt_data[i].sx = decomp[i].y.w; // scale.x.x
srt_data[i].sy = decomp[i].z.w; // scale.y.y
@@ -1593,9 +1618,9 @@ class OptiXDevice : public CUDADevice {
else {
instance.traversableHandle = handle;
- if (ob->geometry->is_instanced()) {
+ if (ob->get_geometry()->is_instanced()) {
// Set transform matrix
- memcpy(instance.transform, &ob->tfm, sizeof(instance.transform));
+ memcpy(instance.transform, &ob->get_tfm(), sizeof(instance.transform));
}
else {
// Disable instance transform if geometry already has it applied to vertex data
@@ -1608,20 +1633,26 @@ class OptiXDevice : public CUDADevice {
}
// Upload instance descriptions
+# if OPTIX_ABI_VERSION < 41
aabbs.resize(num_instances);
aabbs.copy_to_device();
+# endif
instances.resize(num_instances);
instances.copy_to_device();
// Build top-level acceleration structure (TLAS)
OptixBuildInput build_input = {};
build_input.type = OPTIX_BUILD_INPUT_TYPE_INSTANCES;
- build_input.instanceArray.instances = instances.device_pointer;
- build_input.instanceArray.numInstances = num_instances;
+# if OPTIX_ABI_VERSION < 41 // Instance AABBs no longer need to be set since OptiX 7.2
build_input.instanceArray.aabbs = aabbs.device_pointer;
build_input.instanceArray.numAabbs = num_instances;
+# endif
+ build_input.instanceArray.instances = instances.device_pointer;
+ build_input.instanceArray.numInstances = num_instances;
- return build_optix_bvh(build_input, 0, tlas_handle);
+ CUdeviceptr out_data = 0;
+ tlas_handle = 0;
+ return build_optix_bvh(build_input, 0, tlas_handle, out_data, OPTIX_BUILD_OPERATION_BUILD);
}
void const_copy_to(const char *name, void *host, size_t size) override
@@ -1725,8 +1756,8 @@ bool device_optix_init()
const OptixResult result = optixInit();
if (result == OPTIX_ERROR_UNSUPPORTED_ABI_VERSION) {
- VLOG(1) << "OptiX initialization failed because driver does not support ABI version "
- << OPTIX_ABI_VERSION;
+ VLOG(1) << "OptiX initialization failed because the installed NVIDIA driver is too old. "
+ "Please update to the latest driver first!";
return false;
}
else if (result != OPTIX_SUCCESS) {
diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h
index fd380788282..f819f84eb43 100644
--- a/intern/cycles/device/device_task.h
+++ b/intern/cycles/device/device_task.h
@@ -159,6 +159,7 @@ class DeviceTask {
function<void(RenderTile &)> update_tile_sample;
function<void(RenderTile &)> release_tile;
function<bool()> get_cancel;
+ function<bool()> get_tile_stolen;
function<void(RenderTileNeighbors &, Device *)> map_neighbor_tiles;
function<void(RenderTileNeighbors &, Device *)> unmap_neighbor_tiles;
diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp
index f239040ee3d..0f073ed9b63 100644
--- a/intern/cycles/graph/node.cpp
+++ b/intern/cycles/graph/node.cpp
@@ -52,11 +52,6 @@ Node::~Node()
{
}
-template<typename T> static T &get_socket_value(const Node *node, const SocketType &socket)
-{
- return (T &)*(((char *)node) + socket.struct_offset);
-}
-
#ifndef NDEBUG
static bool is_socket_float3(const SocketType &socket)
{
@@ -387,6 +382,87 @@ void Node::copy_value(const SocketType &socket, const Node &other, const SocketT
}
}
+void Node::set_value(const SocketType &socket, const Node &other, const SocketType &other_socket)
+{
+ assert(socket.type == other_socket.type);
+ (void)other_socket;
+
+ if (socket.is_array()) {
+ switch (socket.type) {
+ case SocketType::BOOLEAN_ARRAY:
+ set(socket, get_socket_value<array<bool>>(&other, socket));
+ break;
+ case SocketType::FLOAT_ARRAY:
+ set(socket, get_socket_value<array<float>>(&other, socket));
+ break;
+ case SocketType::INT_ARRAY:
+ set(socket, get_socket_value<array<int>>(&other, socket));
+ break;
+ case SocketType::COLOR_ARRAY:
+ case SocketType::VECTOR_ARRAY:
+ case SocketType::POINT_ARRAY:
+ case SocketType::NORMAL_ARRAY:
+ set(socket, get_socket_value<array<float3>>(&other, socket));
+ break;
+ case SocketType::POINT2_ARRAY:
+ set(socket, get_socket_value<array<float2>>(&other, socket));
+ break;
+ case SocketType::STRING_ARRAY:
+ set(socket, get_socket_value<array<ustring>>(&other, socket));
+ break;
+ case SocketType::TRANSFORM_ARRAY:
+ set(socket, get_socket_value<array<Transform>>(&other, socket));
+ break;
+ case SocketType::NODE_ARRAY:
+ set(socket, get_socket_value<array<Node *>>(&other, socket));
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else {
+ switch (socket.type) {
+ case SocketType::BOOLEAN:
+ set(socket, get_socket_value<bool>(&other, socket));
+ break;
+ case SocketType::FLOAT:
+ set(socket, get_socket_value<float>(&other, socket));
+ break;
+ case SocketType::INT:
+ set(socket, get_socket_value<int>(&other, socket));
+ break;
+ case SocketType::UINT:
+ set(socket, get_socket_value<uint>(&other, socket));
+ break;
+ case SocketType::COLOR:
+ case SocketType::VECTOR:
+ case SocketType::POINT:
+ case SocketType::NORMAL:
+ set(socket, get_socket_value<float3>(&other, socket));
+ break;
+ case SocketType::POINT2:
+ set(socket, get_socket_value<float2>(&other, socket));
+ break;
+ case SocketType::STRING:
+ set(socket, get_socket_value<ustring>(&other, socket));
+ break;
+ case SocketType::ENUM:
+ set(socket, get_socket_value<int>(&other, socket));
+ break;
+ case SocketType::TRANSFORM:
+ set(socket, get_socket_value<Transform>(&other, socket));
+ break;
+ case SocketType::NODE:
+ set(socket, get_socket_value<Node *>(&other, socket));
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+}
+
template<typename T>
static bool is_array_equal(const Node *node, const Node *other, const SocketType &socket)
{
diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h
index 16bd5e4358a..2fc9a1e0281 100644
--- a/intern/cycles/graph/node.h
+++ b/intern/cycles/graph/node.h
@@ -29,6 +29,66 @@ struct Node;
struct NodeType;
struct Transform;
+/* Note: in the following macros we use "type const &" instead of "const type &"
+ * to avoid issues when pasting a pointer type. */
+#define NODE_SOCKET_API_BASE_METHODS(type_, name, string_name) \
+ const SocketType *get_##name##_socket() const \
+ { \
+ static const SocketType *socket = type->find_input(ustring(string_name)); \
+ return socket; \
+ } \
+ bool name##_is_modified() const \
+ { \
+ const SocketType *socket = get_##name##_socket(); \
+ return socket_is_modified(*socket); \
+ } \
+ void tag_##name##_modified() \
+ { \
+ const SocketType *socket = get_##name##_socket(); \
+ socket_modified |= socket->modified_flag_bit; \
+ } \
+ type_ const &get_##name() const \
+ { \
+ const SocketType *socket = get_##name##_socket(); \
+ return get_socket_value<type_>(this, *socket); \
+ }
+
+#define NODE_SOCKET_API_BASE(type_, name, string_name) \
+ protected: \
+ type_ name; \
+\
+ public: \
+ NODE_SOCKET_API_BASE_METHODS(type_, name, string_name)
+
+#define NODE_SOCKET_API(type_, name) \
+ NODE_SOCKET_API_BASE(type_, name, #name) \
+ void set_##name(type_ value) \
+ { \
+ const SocketType *socket = get_##name##_socket(); \
+ this->set(*socket, value); \
+ }
+
+#define NODE_SOCKET_API_ARRAY(type_, name) \
+ NODE_SOCKET_API_BASE(type_, name, #name) \
+ void set_##name(type_ &value) \
+ { \
+ const SocketType *socket = get_##name##_socket(); \
+ this->set(*socket, value); \
+ } \
+ type_ &get_##name() \
+ { \
+ const SocketType *socket = get_##name##_socket(); \
+ return get_socket_value<type_>(this, *socket); \
+ }
+
+#define NODE_SOCKET_API_STRUCT_MEMBER(type_, name, member) \
+ NODE_SOCKET_API_BASE_METHODS(type_, name##_##member, #name "." #member) \
+ void set_##name##_##member(type_ value) \
+ { \
+ const SocketType *socket = get_##name##_##member##_socket(); \
+ this->set(*socket, value); \
+ }
+
/* Node */
struct NodeOwner {
@@ -88,6 +148,7 @@ struct Node {
void set_default_value(const SocketType &input);
bool equals_value(const Node &other, const SocketType &input) const;
void copy_value(const SocketType &input, const Node &other, const SocketType &other_input);
+ void set_value(const SocketType &input, const Node &other, const SocketType &other_input);
/* equals */
bool equals(const Node &other) const;
@@ -119,6 +180,11 @@ struct Node {
protected:
const NodeOwner *owner;
+ template<typename T> static T &get_socket_value(const Node *node, const SocketType &socket)
+ {
+ return (T &)*(((char *)node) + socket.struct_offset);
+ }
+
SocketModifiedFlags socket_modified;
template<typename T> void set_if_different(const SocketType &input, T value);
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 26d7a7eee71..c39c67afb5a 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -649,13 +649,13 @@ include_directories(SYSTEM ${INC_SYS})
if(WITH_COMPILER_ASAN)
if(CMAKE_COMPILER_IS_GNUCC AND (NOT WITH_CYCLES_KERNEL_ASAN))
# GCC hangs compiling the big kernel files with asan and release, so disable by default.
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fno-sanitize=all")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-sanitize=vptr")
+ string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -fno-sanitize=all")
+ string(APPEND CMAKE_CXX_FLAGS_DEBUG " -fno-sanitize=vptr")
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
# With OSL, Cycles disables rtti in some modules, wich then breaks at linking
# when trying to use vptr sanitizer (included into 'undefined' general option).
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fno-sanitize=vptr")
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-sanitize=vptr")
+ string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -fno-sanitize=vptr")
+ string(APPEND CMAKE_CXX_FLAGS_DEBUG " -fno-sanitize=vptr")
endif()
endif()
diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h
index e1b0e6fb81c..b37797ac21b 100644
--- a/intern/cycles/kernel/geom/geom_attribute.h
+++ b/intern/cycles/kernel/geom/geom_attribute.h
@@ -66,9 +66,17 @@ ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg,
while (attr_map.x != id) {
if (UNLIKELY(attr_map.x == ATTR_STD_NONE)) {
- return attribute_not_found();
+ if (UNLIKELY(attr_map.y == 0)) {
+ return attribute_not_found();
+ }
+ else {
+ /* Chain jump to a different part of the table. */
+ attr_offset = attr_map.z;
+ }
+ }
+ else {
+ attr_offset += ATTR_PRIM_TYPES;
}
- attr_offset += ATTR_PRIM_TYPES;
attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
}
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index 6ff0c7f2044..b5a62a31ca9 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -28,18 +28,7 @@ CCL_NAMESPACE_BEGIN
ccl_device float curve_attribute_float(
KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
{
- if (desc.element == ATTR_ELEMENT_CURVE) {
-# ifdef __RAY_DIFFERENTIALS__
- if (dx)
- *dx = 0.0f;
- if (dy)
- *dy = 0.0f;
-# endif
-
- return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim);
- }
- else if (desc.element == ATTR_ELEMENT_CURVE_KEY ||
- desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
+ if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) {
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
@@ -56,16 +45,6 @@ ccl_device float curve_attribute_float(
return (1.0f - sd->u) * f0 + sd->u * f1;
}
- else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
-# ifdef __RAY_DIFFERENTIALS__
- if (dx)
- *dx = 0.0f;
- if (dy)
- *dy = 0.0f;
-# endif
-
- return kernel_tex_fetch(__attributes_float, desc.offset);
- }
else {
# ifdef __RAY_DIFFERENTIALS__
if (dx)
@@ -74,7 +53,14 @@ ccl_device float curve_attribute_float(
*dy = 0.0f;
# endif
- return 0.0f;
+ if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) {
+ const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
+ desc.offset;
+ return kernel_tex_fetch(__attributes_float, offset);
+ }
+ else {
+ return 0.0f;
+ }
}
}
@@ -84,22 +70,7 @@ ccl_device float2 curve_attribute_float2(KernelGlobals *kg,
float2 *dx,
float2 *dy)
{
- if (desc.element == ATTR_ELEMENT_CURVE) {
- /* idea: we can't derive any useful differentials here, but for tiled
- * mipmap image caching it would be useful to avoid reading the highest
- * detail level always. maybe a derivative based on the hair density
- * could be computed somehow? */
-# ifdef __RAY_DIFFERENTIALS__
- if (dx)
- *dx = make_float2(0.0f, 0.0f);
- if (dy)
- *dy = make_float2(0.0f, 0.0f);
-# endif
-
- return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim);
- }
- else if (desc.element == ATTR_ELEMENT_CURVE_KEY ||
- desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
+ if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) {
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
@@ -116,17 +87,11 @@ ccl_device float2 curve_attribute_float2(KernelGlobals *kg,
return (1.0f - sd->u) * f0 + sd->u * f1;
}
- else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
-# ifdef __RAY_DIFFERENTIALS__
- if (dx)
- *dx = make_float2(0.0f, 0.0f);
- if (dy)
- *dy = make_float2(0.0f, 0.0f);
-# endif
-
- return kernel_tex_fetch(__attributes_float2, desc.offset);
- }
else {
+ /* idea: we can't derive any useful differentials here, but for tiled
+ * mipmap image caching it would be useful to avoid reading the highest
+ * detail level always. maybe a derivative based on the hair density
+ * could be computed somehow? */
# ifdef __RAY_DIFFERENTIALS__
if (dx)
*dx = make_float2(0.0f, 0.0f);
@@ -134,7 +99,14 @@ ccl_device float2 curve_attribute_float2(KernelGlobals *kg,
*dy = make_float2(0.0f, 0.0f);
# endif
- return make_float2(0.0f, 0.0f);
+ if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) {
+ const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
+ desc.offset;
+ return kernel_tex_fetch(__attributes_float2, offset);
+ }
+ else {
+ return make_float2(0.0f, 0.0f);
+ }
}
}
@@ -144,22 +116,7 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg,
float3 *dx,
float3 *dy)
{
- if (desc.element == ATTR_ELEMENT_CURVE) {
- /* idea: we can't derive any useful differentials here, but for tiled
- * mipmap image caching it would be useful to avoid reading the highest
- * detail level always. maybe a derivative based on the hair density
- * could be computed somehow? */
-# ifdef __RAY_DIFFERENTIALS__
- if (dx)
- *dx = make_float3(0.0f, 0.0f, 0.0f);
- if (dy)
- *dy = make_float3(0.0f, 0.0f, 0.0f);
-# endif
-
- return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim));
- }
- else if (desc.element == ATTR_ELEMENT_CURVE_KEY ||
- desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
+ if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) {
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
@@ -176,16 +133,6 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg,
return (1.0f - sd->u) * f0 + sd->u * f1;
}
- else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
-# ifdef __RAY_DIFFERENTIALS__
- if (dx)
- *dx = make_float3(0.0f, 0.0f, 0.0f);
- if (dy)
- *dy = make_float3(0.0f, 0.0f, 0.0f);
-# endif
-
- return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset));
- }
else {
# ifdef __RAY_DIFFERENTIALS__
if (dx)
@@ -194,7 +141,14 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg,
*dy = make_float3(0.0f, 0.0f, 0.0f);
# endif
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) {
+ const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
+ desc.offset;
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset));
+ }
+ else {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
}
@@ -204,22 +158,7 @@ ccl_device float4 curve_attribute_float4(KernelGlobals *kg,
float4 *dx,
float4 *dy)
{
- if (desc.element == ATTR_ELEMENT_CURVE) {
- /* idea: we can't derive any useful differentials here, but for tiled
- * mipmap image caching it would be useful to avoid reading the highest
- * detail level always. maybe a derivative based on the hair density
- * could be computed somehow? */
-# ifdef __RAY_DIFFERENTIALS__
- if (dx)
- *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- if (dy)
- *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-# endif
-
- return kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim);
- }
- else if (desc.element == ATTR_ELEMENT_CURVE_KEY ||
- desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
+ if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) {
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
@@ -236,16 +175,6 @@ ccl_device float4 curve_attribute_float4(KernelGlobals *kg,
return (1.0f - sd->u) * f0 + sd->u * f1;
}
- else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
-# ifdef __RAY_DIFFERENTIALS__
- if (dx)
- *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- if (dy)
- *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-# endif
-
- return kernel_tex_fetch(__attributes_float3, desc.offset);
- }
else {
# ifdef __RAY_DIFFERENTIALS__
if (dx)
@@ -254,7 +183,14 @@ ccl_device float4 curve_attribute_float4(KernelGlobals *kg,
*dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
# endif
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) {
+ const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
+ desc.offset;
+ return kernel_tex_fetch(__attributes_float3, offset);
+ }
+ else {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
}
}
diff --git a/intern/cycles/kernel/geom/geom_patch.h b/intern/cycles/kernel/geom/geom_patch.h
index 8b4b91b96c8..1de05fa9e0d 100644
--- a/intern/cycles/kernel/geom/geom_patch.h
+++ b/intern/cycles/kernel/geom/geom_patch.h
@@ -380,6 +380,43 @@ ccl_device float3 patch_eval_float3(KernelGlobals *kg,
return val;
}
+ccl_device float4 patch_eval_float4(KernelGlobals *kg,
+ const ShaderData *sd,
+ int offset,
+ int patch,
+ float u,
+ float v,
+ int channel,
+ float4 *du,
+ float4 *dv)
+{
+ int indices[PATCH_MAX_CONTROL_VERTS];
+ float weights[PATCH_MAX_CONTROL_VERTS];
+ float weights_du[PATCH_MAX_CONTROL_VERTS];
+ float weights_dv[PATCH_MAX_CONTROL_VERTS];
+
+ int num_control = patch_eval_control_verts(
+ kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
+
+ float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ if (du)
+ *du = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ if (dv)
+ *dv = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ for (int i = 0; i < num_control; i++) {
+ float4 v = kernel_tex_fetch(__attributes_float3, offset + indices[i]);
+
+ val += v * weights[i];
+ if (du)
+ *du += v * weights_du[i];
+ if (dv)
+ *dv += v * weights_dv[i];
+ }
+
+ return val;
+}
+
ccl_device float4 patch_eval_uchar4(KernelGlobals *kg,
const ShaderData *sd,
int offset,
diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h
index 997abf438d0..2c31e5cee03 100644
--- a/intern/cycles/kernel/geom/geom_primitive.h
+++ b/intern/cycles/kernel/geom/geom_primitive.h
@@ -21,38 +21,11 @@
CCL_NAMESPACE_BEGIN
-/* Generic primitive attribute reading functions */
-ccl_device_inline float primitive_attribute_float(
- KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
-{
- if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if (subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float(kg, sd, desc, dx, dy);
- }
-#ifdef __HAIR__
- else if (sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float(kg, sd, desc, dx, dy);
- }
-#endif
-#ifdef __VOLUME__
- else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- if (dx)
- *dx = 0.0f;
- if (dy)
- *dy = 0.0f;
- return volume_attribute_float(kg, sd, desc);
- }
-#endif
- else {
- if (dx)
- *dx = 0.0f;
- if (dy)
- *dy = 0.0f;
- return 0.0f;
- }
-}
+/* Surface Attributes
+ *
+ * Read geometry attributes for surface shading. This is distinct from volume
+ * attributes for performance, mainly for GPU performance to avoid bringing in
+ * heavy volume interpolation code. */
ccl_device_inline float primitive_surface_attribute_float(
KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
@@ -77,25 +50,11 @@ ccl_device_inline float primitive_surface_attribute_float(
}
}
-#ifdef __VOLUME__
-ccl_device_inline float primitive_volume_attribute_float(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc)
-{
- if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- return volume_attribute_float(kg, sd, desc);
- }
- else {
- return 0.0f;
- }
-}
-#endif
-
-ccl_device_inline float2 primitive_attribute_float2(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc,
- float2 *dx,
- float2 *dy)
+ccl_device_inline float2 primitive_surface_attribute_float2(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc,
+ float2 *dx,
+ float2 *dy)
{
if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
if (subd_triangle_patch(kg, sd) == ~0)
@@ -108,16 +67,6 @@ ccl_device_inline float2 primitive_attribute_float2(KernelGlobals *kg,
return curve_attribute_float2(kg, sd, desc, dx, dy);
}
#endif
-#ifdef __VOLUME__
- else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- kernel_assert(0);
- if (dx)
- *dx = make_float2(0.0f, 0.0f);
- if (dy)
- *dy = make_float2(0.0f, 0.0f);
- return make_float2(0.0f, 0.0f);
- }
-#endif
else {
if (dx)
*dx = make_float2(0.0f, 0.0f);
@@ -127,11 +76,11 @@ ccl_device_inline float2 primitive_attribute_float2(KernelGlobals *kg,
}
}
-ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc,
- float3 *dx,
- float3 *dy)
+ccl_device_inline float3 primitive_surface_attribute_float3(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc,
+ float3 *dx,
+ float3 *dy)
{
if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
if (subd_triangle_patch(kg, sd) == ~0)
@@ -144,15 +93,6 @@ ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
return curve_attribute_float3(kg, sd, desc, dx, dy);
}
#endif
-#ifdef __VOLUME__
- else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- if (dx)
- *dx = make_float3(0.0f, 0.0f, 0.0f);
- if (dy)
- *dy = make_float3(0.0f, 0.0f, 0.0f);
- return volume_attribute_float3(kg, sd, desc);
- }
-#endif
else {
if (dx)
*dx = make_float3(0.0f, 0.0f, 0.0f);
@@ -162,11 +102,11 @@ ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
}
}
-ccl_device_inline float4 primitive_attribute_float4(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc,
- float4 *dx,
- float4 *dy)
+ccl_device_inline float4 primitive_surface_attribute_float4(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc,
+ float4 *dx,
+ float4 *dy)
{
if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
if (subd_triangle_patch(kg, sd) == ~0)
@@ -188,68 +128,52 @@ ccl_device_inline float4 primitive_attribute_float4(KernelGlobals *kg,
}
}
-ccl_device_inline float2 primitive_surface_attribute_float2(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc,
- float2 *dx,
- float2 *dy)
+#ifdef __VOLUME__
+/* Volume Attributes
+ *
+ * Read geometry attributes for volume shading. This is distinct from surface
+ * attributes for performance, mainly for GPU performance to avoid bringing in
+ * heavy volume interpolation code. */
+
+ccl_device_inline bool primitive_is_volume_attribute(const ShaderData *sd,
+ const AttributeDescriptor desc)
{
- if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if (subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float2(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float2(kg, sd, desc, dx, dy);
- }
-#ifdef __HAIR__
- else if (sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float2(kg, sd, desc, dx, dy);
+ return (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL);
+}
+
+ccl_device_inline float primitive_volume_attribute_float(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc)
+{
+ if (primitive_is_volume_attribute(sd, desc)) {
+ return volume_attribute_value_to_float(volume_attribute_float4(kg, sd, desc));
}
-#endif
else {
- if (dx)
- *dx = make_float2(0.0f, 0.0f);
- if (dy)
- *dy = make_float2(0.0f, 0.0f);
- return make_float2(0.0f, 0.0f);
+ return 0.0f;
}
}
-ccl_device_inline float3 primitive_surface_attribute_float3(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc,
- float3 *dx,
- float3 *dy)
+ccl_device_inline float3 primitive_volume_attribute_float3(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc)
{
- if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if (subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float3(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float3(kg, sd, desc, dx, dy);
- }
-#ifdef __HAIR__
- else if (sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float3(kg, sd, desc, dx, dy);
+ if (primitive_is_volume_attribute(sd, desc)) {
+ return volume_attribute_value_to_float3(volume_attribute_float4(kg, sd, desc));
}
-#endif
else {
- if (dx)
- *dx = make_float3(0.0f, 0.0f, 0.0f);
- if (dy)
- *dy = make_float3(0.0f, 0.0f, 0.0f);
return make_float3(0.0f, 0.0f, 0.0f);
}
}
-#ifdef __VOLUME__
-ccl_device_inline float3 primitive_volume_attribute_float3(KernelGlobals *kg,
+ccl_device_inline float4 primitive_volume_attribute_float4(KernelGlobals *kg,
const ShaderData *sd,
const AttributeDescriptor desc)
{
- if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- return volume_attribute_float3(kg, sd, desc);
+ if (primitive_is_volume_attribute(sd, desc)) {
+ return volume_attribute_float4(kg, sd, desc);
}
else {
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
}
#endif
diff --git a/intern/cycles/kernel/geom/geom_subd_triangle.h b/intern/cycles/kernel/geom/geom_subd_triangle.h
index 3eef9857ae3..2a569852659 100644
--- a/intern/cycles/kernel/geom/geom_subd_triangle.h
+++ b/intern/cycles/kernel/geom/geom_subd_triangle.h
@@ -539,9 +539,13 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg,
/* p is [s, t] */
float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
- float4 dads, dadt;
-
- float4 a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
+ float4 a, dads, dadt;
+ if (desc.type == NODE_ATTR_RGBA) {
+ a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
+ }
+ else {
+ a = patch_eval_float4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
+ }
# ifdef __RAY_DIFFERENTIALS__
if (dx || dy) {
@@ -570,25 +574,70 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg,
}
}
# endif
+
return a;
}
else
#endif /* __PATCH_EVAL__ */
- if (desc.element == ATTR_ELEMENT_CORNER_BYTE) {
+ if (desc.element == ATTR_ELEMENT_FACE) {
+ if (dx)
+ *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ return kernel_tex_fetch(__attributes_float3,
+ desc.offset + subd_triangle_patch_face(kg, patch));
+ }
+ else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+
+ uint4 v = subd_triangle_patch_indices(kg, patch);
+
+ float4 f0 = kernel_tex_fetch(__attributes_float3, desc.offset + v.x);
+ float4 f1 = kernel_tex_fetch(__attributes_float3, desc.offset + v.y);
+ float4 f2 = kernel_tex_fetch(__attributes_float3, desc.offset + v.z);
+ float4 f3 = kernel_tex_fetch(__attributes_float3, desc.offset + v.w);
+
+ if (subd_triangle_patch_num_corners(kg, patch) != 4) {
+ f1 = (f1 + f0) * 0.5f;
+ f3 = (f3 + f0) * 0.5f;
+ }
+
+ float4 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+ float4 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+ float4 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+
+#ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = sd->du.dx * a + sd->dv.dx * b - (sd->du.dx + sd->dv.dx) * c;
+ if (dy)
+ *dy = sd->du.dy * a + sd->dv.dy * b - (sd->du.dy + sd->dv.dy) * c;
+#endif
+
+ return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
+ }
+ else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
float2 uv[3];
subd_triangle_patch_uv(kg, sd, uv);
int corners[4];
subd_triangle_patch_corners(kg, patch, corners);
- float4 f0 = color_uchar4_to_float4(
- kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset));
- float4 f1 = color_uchar4_to_float4(
- kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset));
- float4 f2 = color_uchar4_to_float4(
- kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset));
- float4 f3 = color_uchar4_to_float4(
- kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset));
+ float4 f0, f1, f2, f3;
+
+ if (desc.element == ATTR_ELEMENT_CORNER_BYTE) {
+ f0 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset));
+ f1 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset));
+ f2 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset));
+ f3 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset));
+ }
+ else {
+ f0 = kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset);
+ f1 = kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset);
+ f2 = kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset);
+ f3 = kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset);
+ }
if (subd_triangle_patch_num_corners(kg, patch) != 4) {
f1 = (f1 + f0) * 0.5f;
@@ -614,7 +663,7 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg,
if (dy)
*dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- return color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, desc.offset));
+ return kernel_tex_fetch(__attributes_float3, desc.offset);
}
else {
if (dx)
diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h
index 0278f3ade8e..2d9da23371e 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -114,35 +114,21 @@ ccl_device_inline void triangle_dPdudv(KernelGlobals *kg,
ccl_device float triangle_attribute_float(
KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
{
- if (desc.element == ATTR_ELEMENT_FACE) {
- if (dx)
- *dx = 0.0f;
- if (dy)
- *dy = 0.0f;
-
- return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim);
- }
- else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
-
- float f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x);
- float f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y);
- float f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z);
-
-#ifdef __RAY_DIFFERENTIALS__
- if (dx)
- *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
- if (dy)
- *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
-#endif
-
- return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
- }
- else if (desc.element == ATTR_ELEMENT_CORNER) {
- int tri = desc.offset + sd->prim * 3;
- float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
- float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
- float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
+ if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION | ATTR_ELEMENT_CORNER)) {
+ float f0, f1, f2;
+
+ if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) {
+ const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
+ f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x);
+ f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y);
+ f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z);
+ }
+ else {
+ const int tri = desc.offset + sd->prim * 3;
+ f0 = kernel_tex_fetch(__attributes_float, tri + 0);
+ f1 = kernel_tex_fetch(__attributes_float, tri + 1);
+ f2 = kernel_tex_fetch(__attributes_float, tri + 2);
+ }
#ifdef __RAY_DIFFERENTIALS__
if (dx)
@@ -153,21 +139,22 @@ ccl_device float triangle_attribute_float(
return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
}
- else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
- if (dx)
- *dx = 0.0f;
- if (dy)
- *dy = 0.0f;
-
- return kernel_tex_fetch(__attributes_float, desc.offset);
- }
else {
+#ifdef __RAY_DIFFERENTIALS__
if (dx)
*dx = 0.0f;
if (dy)
*dy = 0.0f;
+#endif
- return 0.0f;
+ if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) {
+ const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim :
+ desc.offset;
+ return kernel_tex_fetch(__attributes_float, offset);
+ }
+ else {
+ return 0.0f;
+ }
}
}
@@ -177,35 +164,17 @@ ccl_device float2 triangle_attribute_float2(KernelGlobals *kg,
float2 *dx,
float2 *dy)
{
- if (desc.element == ATTR_ELEMENT_FACE) {
- if (dx)
- *dx = make_float2(0.0f, 0.0f);
- if (dy)
- *dy = make_float2(0.0f, 0.0f);
-
- return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim);
- }
- else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
-
- float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.x);
- float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.y);
- float2 f2 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.z);
-
-#ifdef __RAY_DIFFERENTIALS__
- if (dx)
- *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
- if (dy)
- *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
-#endif
-
- return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
- }
- else if (desc.element == ATTR_ELEMENT_CORNER) {
- int tri = desc.offset + sd->prim * 3;
+ if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION | ATTR_ELEMENT_CORNER)) {
float2 f0, f1, f2;
- if (desc.element == ATTR_ELEMENT_CORNER) {
+ if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) {
+ const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
+ f0 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.x);
+ f1 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.y);
+ f2 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.z);
+ }
+ else {
+ const int tri = desc.offset + sd->prim * 3;
f0 = kernel_tex_fetch(__attributes_float2, tri + 0);
f1 = kernel_tex_fetch(__attributes_float2, tri + 1);
f2 = kernel_tex_fetch(__attributes_float2, tri + 2);
@@ -220,21 +189,22 @@ ccl_device float2 triangle_attribute_float2(KernelGlobals *kg,
return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
}
- else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
- if (dx)
- *dx = make_float2(0.0f, 0.0f);
- if (dy)
- *dy = make_float2(0.0f, 0.0f);
-
- return kernel_tex_fetch(__attributes_float2, desc.offset);
- }
else {
+#ifdef __RAY_DIFFERENTIALS__
if (dx)
*dx = make_float2(0.0f, 0.0f);
if (dy)
*dy = make_float2(0.0f, 0.0f);
+#endif
- return make_float2(0.0f, 0.0f);
+ if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) {
+ const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim :
+ desc.offset;
+ return kernel_tex_fetch(__attributes_float2, offset);
+ }
+ else {
+ return make_float2(0.0f, 0.0f);
+ }
}
}
@@ -244,40 +214,21 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg,
float3 *dx,
float3 *dy)
{
- if (desc.element == ATTR_ELEMENT_FACE) {
- if (dx)
- *dx = make_float3(0.0f, 0.0f, 0.0f);
- if (dy)
- *dy = make_float3(0.0f, 0.0f, 0.0f);
-
- return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim));
- }
- else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
-
- float3 f0 = float4_to_float3(
- kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x));
- float3 f1 = float4_to_float3(
- kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y));
- float3 f2 = float4_to_float3(
- kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z));
-
-#ifdef __RAY_DIFFERENTIALS__
- if (dx)
- *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
- if (dy)
- *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
-#endif
-
- return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
- }
- else if (desc.element == ATTR_ELEMENT_CORNER) {
- int tri = desc.offset + sd->prim * 3;
+ if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION | ATTR_ELEMENT_CORNER)) {
float3 f0, f1, f2;
- f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
- f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
- f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
+ if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) {
+ const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
+ f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x));
+ f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y));
+ f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z));
+ }
+ else {
+ const int tri = desc.offset + sd->prim * 3;
+ f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
+ f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
+ f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
+ }
#ifdef __RAY_DIFFERENTIALS__
if (dx)
@@ -288,21 +239,22 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg,
return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
}
- else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
- if (dx)
- *dx = make_float3(0.0f, 0.0f, 0.0f);
- if (dy)
- *dy = make_float3(0.0f, 0.0f, 0.0f);
-
- return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset));
- }
else {
+#ifdef __RAY_DIFFERENTIALS__
if (dx)
*dx = make_float3(0.0f, 0.0f, 0.0f);
if (dy)
*dy = make_float3(0.0f, 0.0f, 0.0f);
+#endif
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) {
+ const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim :
+ desc.offset;
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset));
+ }
+ else {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
}
@@ -312,21 +264,29 @@ ccl_device float4 triangle_attribute_float4(KernelGlobals *kg,
float4 *dx,
float4 *dy)
{
- if (desc.element == ATTR_ELEMENT_CORNER_BYTE || desc.element == ATTR_ELEMENT_VERTEX) {
+ if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION | ATTR_ELEMENT_CORNER |
+ ATTR_ELEMENT_CORNER_BYTE)) {
float4 f0, f1, f2;
- if (desc.element == ATTR_ELEMENT_CORNER_BYTE) {
- int tri = desc.offset + sd->prim * 3;
- f0 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 0));
- f1 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 1));
- f2 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 2));
- }
- else {
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
+ if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) {
+ const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
f0 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x);
f1 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y);
f2 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z);
}
+ else {
+ const int tri = desc.offset + sd->prim * 3;
+ if (desc.element == ATTR_ELEMENT_CORNER) {
+ f0 = kernel_tex_fetch(__attributes_float3, tri + 0);
+ f1 = kernel_tex_fetch(__attributes_float3, tri + 1);
+ f2 = kernel_tex_fetch(__attributes_float3, tri + 2);
+ }
+ else {
+ f0 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 0));
+ f1 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 1));
+ f2 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 2));
+ }
+ }
#ifdef __RAY_DIFFERENTIALS__
if (dx)
@@ -337,21 +297,22 @@ ccl_device float4 triangle_attribute_float4(KernelGlobals *kg,
return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
}
- else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
- if (dx)
- *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- if (dy)
- *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-
- return color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, desc.offset));
- }
else {
+#ifdef __RAY_DIFFERENTIALS__
if (dx)
*dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
if (dy)
*dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+#endif
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) {
+ const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim :
+ desc.offset;
+ return kernel_tex_fetch(__attributes_float3, offset);
+ }
+ else {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
}
}
diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h
index f43a7841b46..13b027a5f6c 100644
--- a/intern/cycles/kernel/geom/geom_volume.h
+++ b/intern/cycles/kernel/geom/geom_volume.h
@@ -47,38 +47,39 @@ ccl_device_inline float3 volume_normalized_position(KernelGlobals *kg,
return P;
}
-ccl_device float volume_attribute_float(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc)
+ccl_device float volume_attribute_value_to_float(const float4 value)
{
- /* todo: optimize this so we don't have to transform both here and in
- * kernel_tex_image_interp_3d when possible. Also could optimize for the
- * common case where transform is translation/scale only. */
- float3 P = sd->P;
- object_inverse_position_transform(kg, sd, &P);
- InterpolationType interp = (sd->flag & SD_VOLUME_CUBIC) ? INTERPOLATION_CUBIC :
- INTERPOLATION_NONE;
- float4 r = kernel_tex_image_interp_3d(kg, desc.offset, P, interp);
- return average(float4_to_float3(r));
+ return average(float4_to_float3(value));
}
-ccl_device float3 volume_attribute_float3(KernelGlobals *kg,
+ccl_device float volume_attribute_value_to_alpha(const float4 value)
+{
+ return value.w;
+}
+
+ccl_device float3 volume_attribute_value_to_float3(const float4 value)
+{
+ if (value.w > 1e-6f && value.w != 1.0f) {
+ /* For RGBA colors, unpremultiply after interpolation. */
+ return float4_to_float3(value) / value.w;
+ }
+ else {
+ return float4_to_float3(value);
+ }
+}
+
+ccl_device float4 volume_attribute_float4(KernelGlobals *kg,
const ShaderData *sd,
const AttributeDescriptor desc)
{
+ /* todo: optimize this so we don't have to transform both here and in
+ * kernel_tex_image_interp_3d when possible. Also could optimize for the
+ * common case where transform is translation/scale only. */
float3 P = sd->P;
object_inverse_position_transform(kg, sd, &P);
InterpolationType interp = (sd->flag & SD_VOLUME_CUBIC) ? INTERPOLATION_CUBIC :
INTERPOLATION_NONE;
- float4 r = kernel_tex_image_interp_3d(kg, desc.offset, P, interp);
-
- if (r.w > 1e-6f && r.w != 1.0f) {
- /* For RGBA colors, unpremultiply after interpolation. */
- return float4_to_float3(r) / r.w;
- }
- else {
- return float4_to_float3(r);
- }
+ return kernel_tex_image_interp_3d(kg, desc.offset, P, interp);
}
#endif
diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h
index 4094e173da9..ea3b78b7cef 100644
--- a/intern/cycles/kernel/kernel_compat_cuda.h
+++ b/intern/cycles/kernel/kernel_compat_cuda.h
@@ -32,8 +32,12 @@
/* Manual definitions so we can compile without CUDA toolkit. */
+#ifdef __CUDACC_RTC__
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
+#else
+# include <stdint.h>
+#endif
typedef unsigned short half;
typedef unsigned long long CUtexObject;
diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h
index ba7ab43a47a..1848f6059b6 100644
--- a/intern/cycles/kernel/kernel_compat_opencl.h
+++ b/intern/cycles/kernel/kernel_compat_opencl.h
@@ -48,7 +48,7 @@
#define ccl_align(n) __attribute__((aligned(n)))
#define ccl_optional_struct_init
-#if __OPENCL_VERSION__ >= 200
+#if __OPENCL_VERSION__ >= 200 && !defined(__NV_CL_C_VERSION)
# define ccl_loop_no_unroll __attribute__((opencl_unroll_hint(1)))
#else
# define ccl_loop_no_unroll
diff --git a/intern/cycles/kernel/kernel_compat_optix.h b/intern/cycles/kernel/kernel_compat_optix.h
index e58d8b2aa63..064c99ca100 100644
--- a/intern/cycles/kernel/kernel_compat_optix.h
+++ b/intern/cycles/kernel/kernel_compat_optix.h
@@ -31,8 +31,12 @@
# define ATTR_FALLTHROUGH
#endif
+#ifdef __CUDACC_RTC__
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
+#else
+# include <stdint.h>
+#endif
typedef unsigned short half;
typedef unsigned long long CUtexObject;
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 77e134da4b0..8e2b0e46a66 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -733,18 +733,18 @@ typedef enum AttributePrimitive {
} AttributePrimitive;
typedef enum AttributeElement {
- ATTR_ELEMENT_NONE,
- ATTR_ELEMENT_OBJECT,
- ATTR_ELEMENT_MESH,
- ATTR_ELEMENT_FACE,
- ATTR_ELEMENT_VERTEX,
- ATTR_ELEMENT_VERTEX_MOTION,
- ATTR_ELEMENT_CORNER,
- ATTR_ELEMENT_CORNER_BYTE,
- ATTR_ELEMENT_CURVE,
- ATTR_ELEMENT_CURVE_KEY,
- ATTR_ELEMENT_CURVE_KEY_MOTION,
- ATTR_ELEMENT_VOXEL
+ ATTR_ELEMENT_NONE = 0,
+ ATTR_ELEMENT_OBJECT = (1 << 0),
+ ATTR_ELEMENT_MESH = (1 << 1),
+ ATTR_ELEMENT_FACE = (1 << 2),
+ ATTR_ELEMENT_VERTEX = (1 << 3),
+ ATTR_ELEMENT_VERTEX_MOTION = (1 << 4),
+ ATTR_ELEMENT_CORNER = (1 << 5),
+ ATTR_ELEMENT_CORNER_BYTE = (1 << 6),
+ ATTR_ELEMENT_CURVE = (1 << 7),
+ ATTR_ELEMENT_CURVE_KEY = (1 << 8),
+ ATTR_ELEMENT_CURVE_KEY_MOTION = (1 << 9),
+ ATTR_ELEMENT_VOXEL = (1 << 10)
} AttributeElement;
typedef enum AttributeStandard {
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
index 347d0fec7f5..b97400a443a 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
@@ -28,7 +28,6 @@ CCL_NAMESPACE_BEGIN
* instruction sets. */
namespace {
-template<typename T> struct TextureInterpolator {
#define SET_CUBIC_SPLINE_WEIGHTS(u, t) \
{ \
u[0] = (((-1.0f / 6.0f) * t + 0.5f) * t - 0.5f) * t + (1.0f / 6.0f); \
@@ -38,6 +37,15 @@ template<typename T> struct TextureInterpolator {
} \
(void)0
+ccl_always_inline float frac(float x, int *ix)
+{
+ int i = float_to_int(x) - ((x < 0.0f) ? 1 : 0);
+ *ix = i;
+ return x - (float)i;
+}
+
+template<typename T> struct TextureInterpolator {
+
static ccl_always_inline float4 read(float4 r)
{
return r;
@@ -106,13 +114,6 @@ template<typename T> struct TextureInterpolator {
return clamp(x, 0, width - 1);
}
- static ccl_always_inline float frac(float x, int *ix)
- {
- int i = float_to_int(x) - ((x < 0.0f) ? 1 : 0);
- *ix = i;
- return x - (float)i;
- }
-
/* ******** 2D interpolation ******** */
static ccl_always_inline float4 interp_closest(const TextureInfo &info, float x, float y)
@@ -370,7 +371,7 @@ template<typename T> struct TextureInterpolator {
static ccl_never_inline
#endif
float4
- interp_3d_tricubic(const TextureInfo &info, float x, float y, float z)
+ interp_3d_cubic(const TextureInfo &info, float x, float y, float z)
{
int width = info.width;
int height = info.height;
@@ -469,14 +470,16 @@ template<typename T> struct TextureInterpolator {
case INTERPOLATION_LINEAR:
return interp_3d_linear(info, x, y, z);
default:
- return interp_3d_tricubic(info, x, y, z);
+ return interp_3d_cubic(info, x, y, z);
}
}
-#undef SET_CUBIC_SPLINE_WEIGHTS
};
#ifdef WITH_NANOVDB
template<typename T> struct NanoVDBInterpolator {
+
+ typedef nanovdb::ReadAccessor<nanovdb::NanoRoot<T>> ReadAccessorT;
+
static ccl_always_inline float4 read(float r)
{
return make_float4(r, r, r, 1.0f);
@@ -487,30 +490,93 @@ template<typename T> struct NanoVDBInterpolator {
return make_float4(r[0], r[1], r[2], 1.0f);
}
+ static ccl_always_inline float4 interp_3d_closest(ReadAccessorT acc, float x, float y, float z)
+ {
+ const nanovdb::Vec3f xyz(x, y, z);
+ return read(nanovdb::NearestNeighborSampler<ReadAccessorT, false>(acc)(xyz));
+ }
+
+ static ccl_always_inline float4 interp_3d_linear(ReadAccessorT acc, float x, float y, float z)
+ {
+ const nanovdb::Vec3f xyz(x - 0.5f, y - 0.5f, z - 0.5f);
+ return read(nanovdb::TrilinearSampler<ReadAccessorT, false>(acc)(xyz));
+ }
+
+# if defined(__GNUC__) || defined(__clang__)
+ static ccl_always_inline
+# else
+ static ccl_never_inline
+# endif
+ float4
+ interp_3d_cubic(ReadAccessorT acc, float x, float y, float z)
+ {
+ int ix, iy, iz;
+ int nix, niy, niz;
+ int pix, piy, piz;
+ int nnix, nniy, nniz;
+ /* Tricubic b-spline interpolation. */
+ const float tx = frac(x - 0.5f, &ix);
+ const float ty = frac(y - 0.5f, &iy);
+ const float tz = frac(z - 0.5f, &iz);
+ pix = ix - 1;
+ piy = iy - 1;
+ piz = iz - 1;
+ nix = ix + 1;
+ niy = iy + 1;
+ niz = iz + 1;
+ nnix = ix + 2;
+ nniy = iy + 2;
+ nniz = iz + 2;
+
+ const int xc[4] = {pix, ix, nix, nnix};
+ const int yc[4] = {piy, iy, niy, nniy};
+ const int zc[4] = {piz, iz, niz, nniz};
+ float u[4], v[4], w[4];
+
+ /* Some helper macro to keep code reasonable size,
+ * let compiler to inline all the matrix multiplications.
+ */
+# define DATA(x, y, z) (read(acc.getValue(nanovdb::Coord(xc[x], yc[y], zc[z]))))
+# define COL_TERM(col, row) \
+ (v[col] * (u[0] * DATA(0, col, row) + u[1] * DATA(1, col, row) + u[2] * DATA(2, col, row) + \
+ u[3] * DATA(3, col, row)))
+# define ROW_TERM(row) \
+ (w[row] * (COL_TERM(0, row) + COL_TERM(1, row) + COL_TERM(2, row) + COL_TERM(3, row)))
+
+ SET_CUBIC_SPLINE_WEIGHTS(u, tx);
+ SET_CUBIC_SPLINE_WEIGHTS(v, ty);
+ SET_CUBIC_SPLINE_WEIGHTS(w, tz);
+
+ /* Actual interpolation. */
+ return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3);
+
+# undef COL_TERM
+# undef ROW_TERM
+# undef DATA
+ }
+
static ccl_always_inline float4
interp_3d(const TextureInfo &info, float x, float y, float z, InterpolationType interp)
{
- nanovdb::NanoGrid<T> *const grid = (nanovdb::NanoGrid<T> *)info.data;
- const nanovdb::NanoRoot<T> &root = grid->tree().root();
+ using namespace nanovdb;
- const nanovdb::Coord off(root.bbox().min());
- const nanovdb::Coord dim(root.bbox().dim());
- const nanovdb::Vec3f xyz(off[0] + x * dim[0], off[1] + y * dim[1], off[2] + z * dim[2]);
+ NanoGrid<T> *const grid = (NanoGrid<T> *)info.data;
+ const NanoRoot<T> &root = grid->tree().root();
- typedef nanovdb::ReadAccessor<nanovdb::NanoRoot<T>> ReadAccessorT;
switch ((interp == INTERPOLATION_NONE) ? info.interpolation : interp) {
- default:
- case INTERPOLATION_LINEAR:
- return read(nanovdb::SampleFromVoxels<ReadAccessorT, 1, false>(root)(xyz));
case INTERPOLATION_CLOSEST:
- return read(nanovdb::SampleFromVoxels<ReadAccessorT, 0, false>(root)(xyz));
- case INTERPOLATION_CUBIC:
- return read(nanovdb::SampleFromVoxels<ReadAccessorT, 3, false>(root)(xyz));
+ return interp_3d_closest(root, x, y, z);
+ case INTERPOLATION_LINEAR:
+ return interp_3d_linear(root, x, y, z);
+ default:
+ return interp_3d_cubic(root, x, y, z);
}
}
};
#endif
+#undef SET_CUBIC_SPLINE_WEIGHTS
+
ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, float y)
{
const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
diff --git a/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h b/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h
index 5a005a3f65b..b8aaacba960 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h
+++ b/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h
@@ -24,17 +24,14 @@ ccl_device float cubic_w0(float a)
{
return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f);
}
-
ccl_device float cubic_w1(float a)
{
return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f);
}
-
ccl_device float cubic_w2(float a)
{
return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f);
}
-
ccl_device float cubic_w3(float a)
{
return (1.0f / 6.0f) * (a * a * a);
@@ -45,7 +42,6 @@ ccl_device float cubic_g0(float a)
{
return cubic_w0(a) + cubic_w1(a);
}
-
ccl_device float cubic_g1(float a)
{
return cubic_w2(a) + cubic_w3(a);
@@ -54,13 +50,11 @@ ccl_device float cubic_g1(float a)
/* h0 and h1 are the two offset functions */
ccl_device float cubic_h0(float a)
{
- /* Note +0.5 offset to compensate for CUDA linear filtering convention. */
- return -1.0f + cubic_w1(a) / (cubic_w0(a) + cubic_w1(a)) + 0.5f;
+ return (cubic_w1(a) / cubic_g0(a)) - 1.0f;
}
-
ccl_device float cubic_h1(float a)
{
- return 1.0f + cubic_w3(a) / (cubic_w2(a) + cubic_w3(a)) + 0.5f;
+ return (cubic_w3(a) / cubic_g1(a)) + 1.0f;
}
/* Fast bicubic texture lookup using 4 bilinear lookups, adapted from CUDA samples. */
@@ -79,10 +73,11 @@ ccl_device T kernel_tex_image_interp_bicubic(const TextureInfo &info, float x, f
float g0x = cubic_g0(fx);
float g1x = cubic_g1(fx);
- float x0 = (px + cubic_h0(fx)) / info.width;
- float x1 = (px + cubic_h1(fx)) / info.width;
- float y0 = (py + cubic_h0(fy)) / info.height;
- float y1 = (py + cubic_h1(fy)) / info.height;
+ /* Note +0.5 offset to compensate for CUDA linear filtering convention. */
+ float x0 = (px + cubic_h0(fx) + 0.5f) / info.width;
+ float x1 = (px + cubic_h1(fx) + 0.5f) / info.width;
+ float y0 = (py + cubic_h0(fy) + 0.5f) / info.height;
+ float y1 = (py + cubic_h1(fy) + 0.5f) / info.height;
return cubic_g0(fy) * (g0x * tex2D<T>(tex, x0, y0) + g1x * tex2D<T>(tex, x1, y0)) +
cubic_g1(fy) * (g0x * tex2D<T>(tex, x0, y1) + g1x * tex2D<T>(tex, x1, y1));
@@ -90,7 +85,7 @@ ccl_device T kernel_tex_image_interp_bicubic(const TextureInfo &info, float x, f
/* Fast tricubic texture lookup using 8 trilinear lookups. */
template<typename T>
-ccl_device T kernel_tex_image_interp_bicubic_3d(const TextureInfo &info, float x, float y, float z)
+ccl_device T kernel_tex_image_interp_tricubic(const TextureInfo &info, float x, float y, float z)
{
CUtexObject tex = (CUtexObject)info.data;
@@ -112,12 +107,13 @@ ccl_device T kernel_tex_image_interp_bicubic_3d(const TextureInfo &info, float x
float g0z = cubic_g0(fz);
float g1z = cubic_g1(fz);
- float x0 = (px + cubic_h0(fx)) / info.width;
- float x1 = (px + cubic_h1(fx)) / info.width;
- float y0 = (py + cubic_h0(fy)) / info.height;
- float y1 = (py + cubic_h1(fy)) / info.height;
- float z0 = (pz + cubic_h0(fz)) / info.depth;
- float z1 = (pz + cubic_h1(fz)) / info.depth;
+ /* Note +0.5 offset to compensate for CUDA linear filtering convention. */
+ float x0 = (px + cubic_h0(fx) + 0.5f) / info.width;
+ float x1 = (px + cubic_h1(fx) + 0.5f) / info.width;
+ float y0 = (py + cubic_h0(fy) + 0.5f) / info.height;
+ float y1 = (py + cubic_h1(fy) + 0.5f) / info.height;
+ float z0 = (pz + cubic_h0(fz) + 0.5f) / info.depth;
+ float z1 = (pz + cubic_h1(fz) + 0.5f) / info.depth;
return g0z * (g0y * (g0x * tex3D<T>(tex, x0, y0, z0) + g1x * tex3D<T>(tex, x1, y0, z0)) +
g1y * (g0x * tex3D<T>(tex, x0, y1, z0) + g1x * tex3D<T>(tex, x1, y1, z0))) +
@@ -126,26 +122,56 @@ ccl_device T kernel_tex_image_interp_bicubic_3d(const TextureInfo &info, float x
}
#ifdef WITH_NANOVDB
+template<typename T, typename S>
+ccl_device T kernel_tex_image_interp_tricubic_nanovdb(S &s, float x, float y, float z)
+{
+ float px = floor(x);
+ float py = floor(y);
+ float pz = floor(z);
+ float fx = x - px;
+ float fy = y - py;
+ float fz = z - pz;
+
+ float g0x = cubic_g0(fx);
+ float g1x = cubic_g1(fx);
+ float g0y = cubic_g0(fy);
+ float g1y = cubic_g1(fy);
+ float g0z = cubic_g0(fz);
+ float g1z = cubic_g1(fz);
+
+ float x0 = px + cubic_h0(fx);
+ float x1 = px + cubic_h1(fx);
+ float y0 = py + cubic_h0(fy);
+ float y1 = py + cubic_h1(fy);
+ float z0 = pz + cubic_h0(fz);
+ float z1 = pz + cubic_h1(fz);
+
+ using namespace nanovdb;
+
+ return g0z * (g0y * (g0x * s(Vec3f(x0, y0, z0)) + g1x * s(Vec3f(x1, y0, z0))) +
+ g1y * (g0x * s(Vec3f(x0, y1, z0)) + g1x * s(Vec3f(x1, y1, z0)))) +
+ g1z * (g0y * (g0x * s(Vec3f(x0, y0, z1)) + g1x * s(Vec3f(x1, y0, z1))) +
+ g1y * (g0x * s(Vec3f(x0, y1, z1)) + g1x * s(Vec3f(x1, y1, z1))));
+}
+
template<typename T>
ccl_device_inline T kernel_tex_image_interp_nanovdb(
const TextureInfo &info, float x, float y, float z, uint interpolation)
{
- nanovdb::NanoGrid<T> *const grid = (nanovdb::NanoGrid<T> *)info.data;
- const nanovdb::NanoRoot<T> &root = grid->tree().root();
+ using namespace nanovdb;
+ typedef ReadAccessor<NanoRoot<T>> ReadAccessorT;
- const nanovdb::Coord off(root.bbox().min());
- const nanovdb::Coord dim(root.bbox().dim());
- const nanovdb::Vec3f xyz(off[0] + x * dim[0], off[1] + y * dim[1], off[2] + z * dim[2]);
+ NanoGrid<T> *const grid = (NanoGrid<T> *)info.data;
+ const NanoRoot<T> &root = grid->tree().root();
- typedef nanovdb::ReadAccessor<nanovdb::NanoRoot<T>> ReadAccessorT;
switch (interpolation) {
- default:
- case INTERPOLATION_LINEAR:
- return nanovdb::SampleFromVoxels<ReadAccessorT, 1, false>(root)(xyz);
case INTERPOLATION_CLOSEST:
- return nanovdb::SampleFromVoxels<ReadAccessorT, 0, false>(root)(xyz);
- case INTERPOLATION_CUBIC:
- return nanovdb::SampleFromVoxels<ReadAccessorT, 3, false>(root)(xyz);
+ return NearestNeighborSampler<ReadAccessorT, false>(root)(Vec3f(x, y, z));
+ case INTERPOLATION_LINEAR:
+ return TrilinearSampler<ReadAccessorT, false>(root)(Vec3f(x - 0.5f, y - 0.5f, z - 0.5f));
+ default:
+ TrilinearSampler<ReadAccessorT, false> s(root);
+ return kernel_tex_image_interp_tricubic_nanovdb<T>(s, x - 0.5f, y - 0.5f, z - 0.5f);
}
}
#endif
@@ -214,7 +240,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg,
if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 ||
texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
if (interpolation == INTERPOLATION_CUBIC) {
- return kernel_tex_image_interp_bicubic_3d<float4>(info, x, y, z);
+ return kernel_tex_image_interp_tricubic<float4>(info, x, y, z);
}
else {
CUtexObject tex = (CUtexObject)info.data;
@@ -225,7 +251,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg,
float f;
if (interpolation == INTERPOLATION_CUBIC) {
- f = kernel_tex_image_interp_bicubic_3d<float>(info, x, y, z);
+ f = kernel_tex_image_interp_tricubic<float>(info, x, y, z);
}
else {
CUtexObject tex = (CUtexObject)info.data;
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
index 2f44f249c5f..f39998299ef 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
+++ b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
@@ -16,7 +16,6 @@
#ifdef WITH_NANOVDB
# include "nanovdb/CNanoVDB.h"
-# include "nanovdb/util/CSampleFromVoxels.h"
#endif
/* For OpenCL we do manual lookup and interpolation. */
@@ -47,95 +46,128 @@ ccl_device_inline int svm_image_texture_wrap_clamp(int x, int width)
return clamp(x, 0, width - 1);
}
-ccl_device_inline float4 svm_image_texture_read(KernelGlobals *kg,
- const ccl_global TextureInfo *info,
- int id,
- int offset)
+ccl_device_inline float4 svm_image_texture_read(
+ KernelGlobals *kg, const ccl_global TextureInfo *info, void *acc, int x, int y, int z)
{
+ const int data_offset = x + info->width * y + info->width * info->height * z;
const int texture_type = info->data_type;
/* Float4 */
if (texture_type == IMAGE_DATA_TYPE_FLOAT4) {
- return tex_fetch(float4, info, offset);
+ return tex_fetch(float4, info, data_offset);
}
/* Byte4 */
else if (texture_type == IMAGE_DATA_TYPE_BYTE4) {
- uchar4 r = tex_fetch(uchar4, info, offset);
+ uchar4 r = tex_fetch(uchar4, info, data_offset);
float f = 1.0f / 255.0f;
return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
}
/* Ushort4 */
else if (texture_type == IMAGE_DATA_TYPE_USHORT4) {
- ushort4 r = tex_fetch(ushort4, info, offset);
+ ushort4 r = tex_fetch(ushort4, info, data_offset);
float f = 1.0f / 65535.f;
return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
}
/* Float */
else if (texture_type == IMAGE_DATA_TYPE_FLOAT) {
- float f = tex_fetch(float, info, offset);
+ float f = tex_fetch(float, info, data_offset);
return make_float4(f, f, f, 1.0f);
}
/* UShort */
else if (texture_type == IMAGE_DATA_TYPE_USHORT) {
- ushort r = tex_fetch(ushort, info, offset);
+ ushort r = tex_fetch(ushort, info, data_offset);
float f = r * (1.0f / 65535.0f);
return make_float4(f, f, f, 1.0f);
}
- /* Byte */
+#ifdef WITH_NANOVDB
+ /* NanoVDB Float */
+ else if (texture_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT) {
+ cnanovdb_coord coord;
+ coord.mVec[0] = x;
+ coord.mVec[1] = y;
+ coord.mVec[2] = z;
+ float f = cnanovdb_readaccessor_getValueF((cnanovdb_readaccessor *)acc, &coord);
+ return make_float4(f, f, f, 1.0f);
+ }
+ /* NanoVDB Float3 */
+ else if (texture_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
+ cnanovdb_coord coord;
+ coord.mVec[0] = x;
+ coord.mVec[1] = y;
+ coord.mVec[2] = z;
+ cnanovdb_Vec3F f = cnanovdb_readaccessor_getValueF3((cnanovdb_readaccessor *)acc, &coord);
+ return make_float4(f.mVec[0], f.mVec[1], f.mVec[2], 1.0f);
+ }
+#endif
#ifdef __KERNEL_CL_KHR_FP16__
- /* half and half4 are optional in OpenCL */
+ /* Half and Half4 are optional in OpenCL */
else if (texture_type == IMAGE_DATA_TYPE_HALF) {
- float f = tex_fetch(half, info, offset);
+ float f = tex_fetch(half, info, data_offset);
return make_float4(f, f, f, 1.0f);
}
else if (texture_type == IMAGE_DATA_TYPE_HALF4) {
- half4 r = tex_fetch(half4, info, offset);
+ half4 r = tex_fetch(half4, info, data_offset);
return make_float4(r.x, r.y, r.z, r.w);
}
#endif
+ /* Byte */
else {
- uchar r = tex_fetch(uchar, info, offset);
+ uchar r = tex_fetch(uchar, info, data_offset);
float f = r * (1.0f / 255.0f);
return make_float4(f, f, f, 1.0f);
}
}
-ccl_device_inline float4 svm_image_texture_read_2d(KernelGlobals *kg, int id, int x, int y)
+ccl_device_inline float4
+svm_image_texture_read_2d(KernelGlobals *kg, int id, void *acc, int x, int y)
{
const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
- /* Wrap */
- if (info->extension == EXTENSION_REPEAT) {
- x = svm_image_texture_wrap_periodic(x, info->width);
- y = svm_image_texture_wrap_periodic(y, info->height);
- }
- else {
- x = svm_image_texture_wrap_clamp(x, info->width);
- y = svm_image_texture_wrap_clamp(y, info->height);
+#ifdef WITH_NANOVDB
+ if (info->data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
+ info->data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
+#endif
+ /* Wrap */
+ if (info->extension == EXTENSION_REPEAT) {
+ x = svm_image_texture_wrap_periodic(x, info->width);
+ y = svm_image_texture_wrap_periodic(y, info->height);
+ }
+ else {
+ x = svm_image_texture_wrap_clamp(x, info->width);
+ y = svm_image_texture_wrap_clamp(y, info->height);
+ }
+#ifdef WITH_NANOVDB
}
+#endif
- int offset = x + info->width * y;
- return svm_image_texture_read(kg, info, id, offset);
+ return svm_image_texture_read(kg, info, acc, x, y, 0);
}
-ccl_device_inline float4 svm_image_texture_read_3d(KernelGlobals *kg, int id, int x, int y, int z)
+ccl_device_inline float4
+svm_image_texture_read_3d(KernelGlobals *kg, int id, void *acc, int x, int y, int z)
{
const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
- /* Wrap */
- if (info->extension == EXTENSION_REPEAT) {
- x = svm_image_texture_wrap_periodic(x, info->width);
- y = svm_image_texture_wrap_periodic(y, info->height);
- z = svm_image_texture_wrap_periodic(z, info->depth);
- }
- else {
- x = svm_image_texture_wrap_clamp(x, info->width);
- y = svm_image_texture_wrap_clamp(y, info->height);
- z = svm_image_texture_wrap_clamp(z, info->depth);
+#ifdef WITH_NANOVDB
+ if (info->data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
+ info->data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
+#endif
+ /* Wrap */
+ if (info->extension == EXTENSION_REPEAT) {
+ x = svm_image_texture_wrap_periodic(x, info->width);
+ y = svm_image_texture_wrap_periodic(y, info->height);
+ z = svm_image_texture_wrap_periodic(z, info->depth);
+ }
+ else {
+ x = svm_image_texture_wrap_clamp(x, info->width);
+ y = svm_image_texture_wrap_clamp(y, info->height);
+ z = svm_image_texture_wrap_clamp(z, info->depth);
+ }
+#ifdef WITH_NANOVDB
}
+#endif
- int offset = x + info->width * y + info->width * info->height * z;
- return svm_image_texture_read(kg, info, id, offset);
+ return svm_image_texture_read(kg, info, acc, x, y, z);
}
ccl_device_inline float svm_image_texture_frac(float x, int *ix)
@@ -170,7 +202,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, fl
svm_image_texture_frac(x * info->width, &ix);
svm_image_texture_frac(y * info->height, &iy);
- return svm_image_texture_read_2d(kg, id, ix, iy);
+ return svm_image_texture_read_2d(kg, id, NULL, ix, iy);
}
else if (info->interpolation == INTERPOLATION_LINEAR) {
/* Bilinear interpolation. */
@@ -179,10 +211,10 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, fl
float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy);
float4 r;
- r = (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_2d(kg, id, ix, iy);
- r += (1.0f - ty) * tx * svm_image_texture_read_2d(kg, id, ix + 1, iy);
- r += ty * (1.0f - tx) * svm_image_texture_read_2d(kg, id, ix, iy + 1);
- r += ty * tx * svm_image_texture_read_2d(kg, id, ix + 1, iy + 1);
+ r = (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_2d(kg, id, NULL, ix, iy);
+ r += (1.0f - ty) * tx * svm_image_texture_read_2d(kg, id, NULL, ix + 1, iy);
+ r += ty * (1.0f - tx) * svm_image_texture_read_2d(kg, id, NULL, ix, iy + 1);
+ r += ty * tx * svm_image_texture_read_2d(kg, id, NULL, ix + 1, iy + 1);
return r;
}
else {
@@ -200,7 +232,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, fl
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
float weight = u[x] * v[y];
- r += weight * svm_image_texture_read_2d(kg, id, ix + x - 1, iy + y - 1);
+ r += weight * svm_image_texture_read_2d(kg, id, NULL, ix + x - 1, iy + y - 1);
}
}
return r;
@@ -216,113 +248,68 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float3 P
P = transform_point(&tfm, P);
}
- const float x = P.x;
- const float y = P.y;
- const float z = P.z;
-
- if (info->extension == EXTENSION_CLIP) {
- if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) {
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- }
+ float x = P.x;
+ float y = P.y;
+ float z = P.z;
uint interpolation = (interp == INTERPOLATION_NONE) ? info->interpolation : interp;
#ifdef WITH_NANOVDB
- if (info->data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT) {
+ cnanovdb_readaccessor acc;
+ if (info->data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT ||
+ info->data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
ccl_global cnanovdb_griddata *grid =
(ccl_global cnanovdb_griddata *)(kg->buffers[info->cl_buffer] + info->data);
- const ccl_global cnanovdb_rootdataF *root = cnanovdb_treedata_rootF(
- cnanovdb_griddata_tree(grid));
-
- cnanovdb_Vec3F xyz;
- xyz.mVec[0] = root->mBBox_min.mVec[0] +
- x * (root->mBBox_max.mVec[0] - root->mBBox_min.mVec[0]);
- xyz.mVec[1] = root->mBBox_min.mVec[1] +
- y * (root->mBBox_max.mVec[1] - root->mBBox_min.mVec[1]);
- xyz.mVec[2] = root->mBBox_min.mVec[2] +
- z * (root->mBBox_max.mVec[2] - root->mBBox_min.mVec[2]);
-
- cnanovdb_readaccessor acc;
- cnanovdb_readaccessor_init(&acc, root);
-
- float value;
- switch (interpolation) {
- default:
- case INTERPOLATION_LINEAR:
- value = cnanovdb_sampleF_trilinear(&acc, &xyz);
- break;
- case INTERPOLATION_CLOSEST:
- value = cnanovdb_sampleF_nearest(&acc, &xyz);
- break;
- }
- return make_float4(value, value, value, 1.0f);
+ cnanovdb_readaccessor_init(&acc, cnanovdb_treedata_rootF(cnanovdb_griddata_tree(grid)));
}
- if (info->data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
- ccl_global cnanovdb_griddata *grid =
- (ccl_global cnanovdb_griddata *)(kg->buffers[info->cl_buffer] + info->data);
- const ccl_global cnanovdb_rootdataF3 *root = cnanovdb_treedata_rootF3(
- cnanovdb_griddata_tree(grid));
-
- cnanovdb_Vec3F xyz;
- xyz.mVec[0] = root->mBBox_min.mVec[0] +
- x * (root->mBBox_max.mVec[0] - root->mBBox_min.mVec[0]);
- xyz.mVec[1] = root->mBBox_min.mVec[1] +
- y * (root->mBBox_max.mVec[1] - root->mBBox_min.mVec[1]);
- xyz.mVec[2] = root->mBBox_min.mVec[2] +
- z * (root->mBBox_max.mVec[2] - root->mBBox_min.mVec[2]);
-
- cnanovdb_readaccessor acc;
- cnanovdb_readaccessor_init(&acc, root);
-
- cnanovdb_Vec3F value;
- switch (interpolation) {
- default:
- case INTERPOLATION_LINEAR:
- value = cnanovdb_sampleF3_trilinear(&acc, &xyz);
- break;
- case INTERPOLATION_CLOSEST:
- value = cnanovdb_sampleF3_nearest(&acc, &xyz);
- break;
+ else {
+ if (info->extension == EXTENSION_CLIP) {
+ if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
}
- return make_float4(value.mVec[0], value.mVec[1], value.mVec[2], 1.0f);
+
+ x *= info->width;
+ y *= info->height;
+ z *= info->depth;
}
#endif
if (interpolation == INTERPOLATION_CLOSEST) {
/* Closest interpolation. */
int ix, iy, iz;
- svm_image_texture_frac(x * info->width, &ix);
- svm_image_texture_frac(y * info->height, &iy);
- svm_image_texture_frac(z * info->depth, &iz);
+ svm_image_texture_frac(x, &ix);
+ svm_image_texture_frac(y, &iy);
+ svm_image_texture_frac(z, &iz);
- return svm_image_texture_read_3d(kg, id, ix, iy, iz);
+ return svm_image_texture_read_3d(kg, id, &acc, ix, iy, iz);
}
else if (interpolation == INTERPOLATION_LINEAR) {
- /* Bilinear interpolation. */
+ /* Trilinear interpolation. */
int ix, iy, iz;
- float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix);
- float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy);
- float tz = svm_image_texture_frac(z * info->depth - 0.5f, &iz);
+ float tx = svm_image_texture_frac(x - 0.5f, &ix);
+ float ty = svm_image_texture_frac(y - 0.5f, &iy);
+ float tz = svm_image_texture_frac(z - 0.5f, &iz);
float4 r;
- r = (1.0f - tz) * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy, iz);
- r += (1.0f - tz) * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy, iz);
- r += (1.0f - tz) * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy + 1, iz);
- r += (1.0f - tz) * ty * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy + 1, iz);
-
- r += tz * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy, iz + 1);
- r += tz * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy, iz + 1);
- r += tz * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy + 1, iz + 1);
- r += tz * ty * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy + 1, iz + 1);
+ r = (1.0f - tz) * (1.0f - ty) * (1.0f - tx) *
+ svm_image_texture_read_3d(kg, id, &acc, ix, iy, iz);
+ r += (1.0f - tz) * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, &acc, ix + 1, iy, iz);
+ r += (1.0f - tz) * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, &acc, ix, iy + 1, iz);
+ r += (1.0f - tz) * ty * tx * svm_image_texture_read_3d(kg, id, &acc, ix + 1, iy + 1, iz);
+
+ r += tz * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(kg, id, &acc, ix, iy, iz + 1);
+ r += tz * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, &acc, ix + 1, iy, iz + 1);
+ r += tz * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, &acc, ix, iy + 1, iz + 1);
+ r += tz * ty * tx * svm_image_texture_read_3d(kg, id, &acc, ix + 1, iy + 1, iz + 1);
return r;
}
else {
- /* Bicubic interpolation. */
+ /* Tricubic interpolation. */
int ix, iy, iz;
- float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix);
- float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy);
- float tz = svm_image_texture_frac(z * info->depth - 0.5f, &iz);
+ float tx = svm_image_texture_frac(x - 0.5f, &ix);
+ float ty = svm_image_texture_frac(y - 0.5f, &iy);
+ float tz = svm_image_texture_frac(z - 0.5f, &iz);
float u[4], v[4], w[4];
SET_CUBIC_SPLINE_WEIGHTS(u, tx);
@@ -335,7 +322,8 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float3 P
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
float weight = u[x] * v[y] * w[z];
- r += weight * svm_image_texture_read_3d(kg, id, ix + x - 1, iy + y - 1, iz + z - 1);
+ r += weight *
+ svm_image_texture_read_3d(kg, id, &acc, ix + x - 1, iy + y - 1, iz + z - 1);
}
}
}
diff --git a/intern/cycles/kernel/kernels/optix/kernel_optix.cu b/intern/cycles/kernel/kernels/optix/kernel_optix.cu
index 3b166e59dfd..fd9065098dd 100644
--- a/intern/cycles/kernel/kernels/optix/kernel_optix.cu
+++ b/intern/cycles/kernel/kernels/optix/kernel_optix.cu
@@ -320,10 +320,3 @@ extern "C" __global__ void __intersection__curve_all()
optix_intersection_curve(prim, type);
}
#endif
-
-#ifdef __KERNEL_DEBUG__
-extern "C" __global__ void __exception__kernel_optix_exception()
-{
- printf("Unhandled exception occured: code %d!\n", optixGetExceptionCode());
-}
-#endif
diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt
index 8144d480589..3b2d639f3a5 100644
--- a/intern/cycles/kernel/osl/CMakeLists.txt
+++ b/intern/cycles/kernel/osl/CMakeLists.txt
@@ -47,7 +47,7 @@ set(LIB
)
# OSL and LLVM are built without RTTI
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RTTI_DISABLE_FLAGS}")
+string(APPEND CMAKE_CXX_FLAGS " ${RTTI_DISABLE_FLAGS}")
if(APPLE)
# Disable allocation warning on macOS prior to 10.14: the OSLRenderServices
@@ -55,7 +55,7 @@ if(APPLE)
# unordered_map_concurrent). This is not something what the SDK supportsm, but
# since we take care of allocations ourselves is is OK to ignore the
# diagnostic message.
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -faligned-allocation")
+ string(APPEND CMAKE_CXX_FLAGS " -faligned-allocation")
endif()
include_directories(${INC})
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index aee1e3a244e..2a4a1dfe325 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -403,8 +403,28 @@ bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals *sg,
static bool set_attribute_float2(float2 f[3], TypeDesc type, bool derivatives, void *val)
{
- if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
- type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
+ if (type == TypeFloatArray4) {
+ float *fval = (float *)val;
+ fval[0] = f[0].x;
+ fval[1] = f[0].y;
+ fval[2] = 0.0f;
+ fval[3] = 1.0f;
+
+ if (derivatives) {
+ fval[4] = f[1].x;
+ fval[5] = f[1].y;
+ fval[6] = 0.0f;
+ fval[7] = 0.0f;
+
+ fval[8] = f[2].x;
+ fval[9] = f[2].y;
+ fval[10] = 0.0f;
+ fval[11] = 0.0f;
+ }
+ return true;
+ }
+ else if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+ type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
float *fval = (float *)val;
fval[0] = f[0].x;
@@ -438,10 +458,41 @@ static bool set_attribute_float2(float2 f[3], TypeDesc type, bool derivatives, v
return false;
}
+static bool set_attribute_float2(float2 f, TypeDesc type, bool derivatives, void *val)
+{
+ float2 fv[3];
+
+ fv[0] = f;
+ fv[1] = make_float2(0.0f, 0.0f);
+ fv[2] = make_float2(0.0f, 0.0f);
+
+ return set_attribute_float2(fv, type, derivatives, val);
+}
+
static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val)
{
- if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
- type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
+ if (type == TypeFloatArray4) {
+ float *fval = (float *)val;
+ fval[0] = f[0].x;
+ fval[1] = f[0].y;
+ fval[2] = f[0].z;
+ fval[3] = 1.0f;
+
+ if (derivatives) {
+ fval[4] = f[1].x;
+ fval[5] = f[1].y;
+ fval[6] = f[1].z;
+ fval[7] = 0.0f;
+
+ fval[8] = f[2].x;
+ fval[9] = f[2].y;
+ fval[10] = f[2].z;
+ fval[11] = 0.0f;
+ }
+ return true;
+ }
+ else if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+ type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
float *fval = (float *)val;
fval[0] = f[0].x;
@@ -545,14 +596,45 @@ static bool set_attribute_float4(float4 f[3], TypeDesc type, bool derivatives, v
return false;
}
+static bool set_attribute_float4(float4 f, TypeDesc type, bool derivatives, void *val)
+{
+ float4 fv[3];
+
+ fv[0] = f;
+ fv[1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ fv[2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ return set_attribute_float4(fv, type, derivatives, val);
+}
+
static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val)
{
- if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
- type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
+ if (type == TypeFloatArray4) {
float *fval = (float *)val;
fval[0] = f[0];
- fval[1] = f[1];
- fval[2] = f[2];
+ fval[1] = f[0];
+ fval[2] = f[0];
+ fval[3] = 1.0f;
+
+ if (derivatives) {
+ fval[4] = f[1];
+ fval[5] = f[1];
+ fval[6] = f[1];
+ fval[7] = 0.0f;
+
+ fval[8] = f[2];
+ fval[9] = f[2];
+ fval[10] = f[2];
+ fval[11] = 0.0f;
+ }
+ return true;
+ }
+ else if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+ type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
+ float *fval = (float *)val;
+ fval[0] = f[0];
+ fval[1] = f[0];
+ fval[2] = f[0];
if (derivatives) {
fval[3] = f[1];
@@ -675,26 +757,50 @@ static bool get_primitive_attribute(KernelGlobals *kg,
if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) {
float3 fval[3];
- fval[0] = primitive_attribute_float3(
- kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ if (primitive_is_volume_attribute(sd, attr.desc)) {
+ fval[0] = primitive_volume_attribute_float3(kg, sd, attr.desc);
+ }
+ else {
+ memset(fval, 0, sizeof(fval));
+ fval[0] = primitive_surface_attribute_float3(
+ kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ }
return set_attribute_float3(fval, type, derivatives, val);
}
else if (attr.type == TypeFloat2) {
- float2 fval[3];
- fval[0] = primitive_attribute_float2(
- kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
- return set_attribute_float2(fval, type, derivatives, val);
+ if (primitive_is_volume_attribute(sd, attr.desc)) {
+ assert(!"Float2 attribute not support for volumes");
+ return false;
+ }
+ else {
+ float2 fval[3];
+ fval[0] = primitive_surface_attribute_float2(
+ kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ return set_attribute_float2(fval, type, derivatives, val);
+ }
}
else if (attr.type == TypeDesc::TypeFloat) {
float fval[3];
- fval[0] = primitive_attribute_float(
- kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ if (primitive_is_volume_attribute(sd, attr.desc)) {
+ memset(fval, 0, sizeof(fval));
+ fval[0] = primitive_volume_attribute_float(kg, sd, attr.desc);
+ }
+ else {
+ fval[0] = primitive_surface_attribute_float(
+ kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ }
return set_attribute_float(fval, type, derivatives, val);
}
- else if (attr.type == TypeRGBA) {
+ else if (attr.type == TypeDesc::TypeFloat4 || attr.type == TypeRGBA) {
float4 fval[3];
- fval[0] = primitive_attribute_float4(
- kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ if (primitive_is_volume_attribute(sd, attr.desc)) {
+ memset(fval, 0, sizeof(fval));
+ fval[0] = primitive_volume_attribute_float4(kg, sd, attr.desc);
+ }
+ else {
+ fval[0] = primitive_surface_attribute_float4(
+ kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ }
return set_attribute_float4(fval, type, derivatives, val);
}
else {
@@ -718,13 +824,37 @@ static bool get_mesh_attribute(KernelGlobals *kg,
}
}
-static void get_object_attribute(const OSLGlobals::Attribute &attr, bool derivatives, void *val)
+static bool get_object_attribute(const OSLGlobals::Attribute &attr,
+ TypeDesc type,
+ bool derivatives,
+ void *val)
{
- size_t datasize = attr.value.datasize();
+ if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
+ attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) {
+ return set_attribute_float3(*(float3 *)attr.value.data(), type, derivatives, val);
+ }
+ else if (attr.type == TypeFloat2) {
+ return set_attribute_float2(*(float2 *)attr.value.data(), type, derivatives, val);
+ }
+ else if (attr.type == TypeDesc::TypeFloat) {
+ return set_attribute_float(*(float *)attr.value.data(), type, derivatives, val);
+ }
+ else if (attr.type == TypeRGBA || attr.type == TypeDesc::TypeFloat4) {
+ return set_attribute_float4(*(float4 *)attr.value.data(), type, derivatives, val);
+ }
+ else if (attr.type == type) {
+ size_t datasize = attr.value.datasize();
+
+ memcpy(val, attr.value.data(), datasize);
+ if (derivatives) {
+ memset((char *)val + datasize, 0, datasize * 2);
+ }
- memcpy(val, attr.value.data(), datasize);
- if (derivatives)
- memset((char *)val + datasize, 0, datasize * 2);
+ return true;
+ }
+ else {
+ return false;
+ }
}
bool OSLRenderServices::get_object_standard_attribute(
@@ -987,8 +1117,7 @@ bool OSLRenderServices::get_attribute(
}
else {
/* object attribute */
- get_object_attribute(attr, derivatives, val);
- return true;
+ return get_object_attribute(attr, type, derivatives, val);
}
}
else {
diff --git a/intern/cycles/kernel/shaders/node_attribute.osl b/intern/cycles/kernel/shaders/node_attribute.osl
index abec8ebfbf0..205d0a21bed 100644
--- a/intern/cycles/kernel/shaders/node_attribute.osl
+++ b/intern/cycles/kernel/shaders/node_attribute.osl
@@ -20,20 +20,26 @@ shader node_attribute(string bump_offset = "center",
string name = "",
output point Vector = point(0.0, 0.0, 0.0),
output color Color = 0.0,
- output float Fac = 0.0)
+ output float Fac = 0.0,
+ output float Alpha = 0.0)
{
- getattribute(name, Color);
+ float data[4];
+ getattribute(name, data);
+ Color = color(data[0], data[1], data[2]);
Vector = point(Color);
getattribute(name, Fac);
+ Alpha = data[3];
if (bump_offset == "dx") {
Color += Dx(Color);
Vector += Dx(Vector);
Fac += Dx(Fac);
+ Alpha += Dx(Alpha);
}
else if (bump_offset == "dy") {
Color += Dy(Color);
Vector += Dy(Vector);
Fac += Dy(Fac);
+ Alpha += Dy(Alpha);
}
}
diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h
index fc7a3ba3f5a..f598bfb8f8f 100644
--- a/intern/cycles/kernel/svm/svm_attribute.h
+++ b/intern/cycles/kernel/svm/svm_attribute.h
@@ -19,10 +19,10 @@ CCL_NAMESPACE_BEGIN
/* Attribute Node */
ccl_device AttributeDescriptor svm_node_attr_init(
- KernelGlobals *kg, ShaderData *sd, uint4 node, NodeAttributeType *type, uint *out_offset)
+ KernelGlobals *kg, ShaderData *sd, uint4 node, NodeAttributeOutputType *type, uint *out_offset)
{
*out_offset = node.z;
- *type = (NodeAttributeType)node.w;
+ *type = (NodeAttributeOutputType)node.w;
AttributeDescriptor desc;
@@ -46,144 +46,234 @@ ccl_device AttributeDescriptor svm_node_attr_init(
ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- NodeAttributeType type = NODE_ATTR_FLOAT;
+ NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
uint out_offset = 0;
AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
- /* fetch and store attribute */
- if (desc.type == NODE_ATTR_FLOAT) {
- float f = primitive_attribute_float(kg, sd, desc, NULL, NULL);
- if (type == NODE_ATTR_FLOAT) {
+#ifdef __VOLUME__
+ /* Volumes
+ * NOTE: moving this into its own node type might help improve performance. */
+ if (primitive_is_volume_attribute(sd, desc)) {
+ const float4 value = volume_attribute_float4(kg, sd, desc);
+
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
+ const float f = volume_attribute_value_to_float(value);
stack_store_float(stack, out_offset, f);
}
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
+ const float3 f = volume_attribute_value_to_float3(value);
+ stack_store_float3(stack, out_offset, f);
+ }
else {
+ const float f = volume_attribute_value_to_alpha(value);
+ stack_store_float(stack, out_offset, f);
+ }
+ return;
+ }
+#endif
+
+ /* Surface. */
+ if (desc.type == NODE_ATTR_FLOAT) {
+ float f = primitive_surface_attribute_float(kg, sd, desc, NULL, NULL);
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
+ stack_store_float(stack, out_offset, f);
+ }
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f, f, f));
}
+ else {
+ stack_store_float(stack, out_offset, 1.0f);
+ }
}
else if (desc.type == NODE_ATTR_FLOAT2) {
- float2 f = primitive_attribute_float2(kg, sd, desc, NULL, NULL);
- if (type == NODE_ATTR_FLOAT) {
+ float2 f = primitive_surface_attribute_float2(kg, sd, desc, NULL, NULL);
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, f.x);
}
- else {
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, 0.0f));
}
+ else {
+ stack_store_float(stack, out_offset, 1.0f);
+ }
}
- else if (desc.type == NODE_ATTR_RGBA) {
- float4 f = primitive_attribute_float4(kg, sd, desc, NULL, NULL);
- if (type == NODE_ATTR_FLOAT) {
+ else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
+ float4 f = primitive_surface_attribute_float4(kg, sd, desc, NULL, NULL);
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(float4_to_float3(f)));
}
- else {
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, float4_to_float3(f));
}
+ else {
+ stack_store_float(stack, out_offset, f.w);
+ }
}
else {
- float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
- if (type == NODE_ATTR_FLOAT) {
+ float3 f = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(f));
}
- else {
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, f);
}
+ else {
+ stack_store_float(stack, out_offset, 1.0f);
+ }
}
}
ccl_device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- NodeAttributeType type = NODE_ATTR_FLOAT;
+ NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
uint out_offset = 0;
AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
- /* fetch and store attribute */
+#ifdef __VOLUME__
+ /* Volume */
+ if (primitive_is_volume_attribute(sd, desc)) {
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
+ stack_store_float(stack, out_offset, 0.0f);
+ }
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
+ stack_store_float3(stack, out_offset, make_float3(0.0f, 0.0f, 0.0f));
+ }
+ else {
+ stack_store_float(stack, out_offset, 1.0f);
+ }
+ return;
+ }
+#endif
+
+ /* Surface */
if (desc.type == NODE_ATTR_FLOAT) {
float dx;
float f = primitive_surface_attribute_float(kg, sd, desc, &dx, NULL);
- if (type == NODE_ATTR_FLOAT) {
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, f + dx);
}
- else {
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f + dx, f + dx, f + dx));
}
+ else {
+ stack_store_float(stack, out_offset, 1.0f);
+ }
}
else if (desc.type == NODE_ATTR_FLOAT2) {
float2 dx;
- float2 f = primitive_attribute_float2(kg, sd, desc, &dx, NULL);
- if (type == NODE_ATTR_FLOAT) {
+ float2 f = primitive_surface_attribute_float2(kg, sd, desc, &dx, NULL);
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, f.x + dx.x);
}
- else {
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f.x + dx.x, f.y + dx.y, 0.0f));
}
+ else {
+ stack_store_float(stack, out_offset, 1.0f);
+ }
}
- else if (desc.type == NODE_ATTR_RGBA) {
+ else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
float4 dx;
- float4 f = primitive_attribute_float4(kg, sd, desc, &dx, NULL);
- if (type == NODE_ATTR_FLOAT) {
+ float4 f = primitive_surface_attribute_float4(kg, sd, desc, &dx, NULL);
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(float4_to_float3(f + dx)));
}
- else {
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, float4_to_float3(f + dx));
}
+ else {
+ stack_store_float(stack, out_offset, f.w + dx.w);
+ }
}
else {
float3 dx;
float3 f = primitive_surface_attribute_float3(kg, sd, desc, &dx, NULL);
- if (type == NODE_ATTR_FLOAT) {
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(f + dx));
}
- else {
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, f + dx);
}
+ else {
+ stack_store_float(stack, out_offset, 1.0f);
+ }
}
}
ccl_device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- NodeAttributeType type = NODE_ATTR_FLOAT;
+ NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
uint out_offset = 0;
AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
- /* fetch and store attribute */
+#ifdef __VOLUME__
+ /* Volume */
+ if (primitive_is_volume_attribute(sd, desc)) {
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
+ stack_store_float(stack, out_offset, 0.0f);
+ }
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
+ stack_store_float3(stack, out_offset, make_float3(0.0f, 0.0f, 0.0f));
+ }
+ else {
+ stack_store_float(stack, out_offset, 1.0f);
+ }
+ return;
+ }
+#endif
+
+ /* Surface */
if (desc.type == NODE_ATTR_FLOAT) {
float dy;
float f = primitive_surface_attribute_float(kg, sd, desc, NULL, &dy);
- if (type == NODE_ATTR_FLOAT) {
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, f + dy);
}
- else {
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f + dy, f + dy, f + dy));
}
+ else {
+ stack_store_float(stack, out_offset, 1.0f);
+ }
}
else if (desc.type == NODE_ATTR_FLOAT2) {
float2 dy;
- float2 f = primitive_attribute_float2(kg, sd, desc, NULL, &dy);
- if (type == NODE_ATTR_FLOAT) {
+ float2 f = primitive_surface_attribute_float2(kg, sd, desc, NULL, &dy);
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, f.x + dy.x);
}
- else {
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f.x + dy.x, f.y + dy.y, 0.0f));
}
+ else {
+ stack_store_float(stack, out_offset, 1.0f);
+ }
}
- else if (desc.type == NODE_ATTR_RGBA) {
+ else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
float4 dy;
- float4 f = primitive_attribute_float4(kg, sd, desc, NULL, &dy);
- if (type == NODE_ATTR_FLOAT) {
+ float4 f = primitive_surface_attribute_float4(kg, sd, desc, NULL, &dy);
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(float4_to_float3(f + dy)));
}
- else {
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, float4_to_float3(f + dy));
}
+ else {
+ stack_store_float(stack, out_offset, f.w + dy.w);
+ }
}
else {
float3 dy;
float3 f = primitive_surface_attribute_float3(kg, sd, desc, NULL, &dy);
- if (type == NODE_ATTR_FLOAT) {
+ if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(f + dy));
}
- else {
+ else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, f + dy);
}
+ else {
+ stack_store_float(stack, out_offset, 1.0f);
+ }
}
}
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index f1ebb37e23e..c228df14985 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -157,10 +157,17 @@ typedef enum ShaderNodeType {
* match the switch case order in svm.h. */
} ShaderNodeType;
+typedef enum NodeAttributeOutputType {
+ NODE_ATTR_OUTPUT_FLOAT3 = 0,
+ NODE_ATTR_OUTPUT_FLOAT,
+ NODE_ATTR_OUTPUT_FLOAT_ALPHA,
+} NodeAttributeOutputType;
+
typedef enum NodeAttributeType {
NODE_ATTR_FLOAT = 0,
NODE_ATTR_FLOAT2,
NODE_ATTR_FLOAT3,
+ NODE_ATTR_FLOAT4,
NODE_ATTR_RGBA,
NODE_ATTR_MATRIX
} NodeAttributeType;
diff --git a/intern/cycles/kernel/svm/svm_vertex_color.h b/intern/cycles/kernel/svm/svm_vertex_color.h
index 3c105b1cbfa..0aa45835522 100644
--- a/intern/cycles/kernel/svm/svm_vertex_color.h
+++ b/intern/cycles/kernel/svm/svm_vertex_color.h
@@ -25,7 +25,7 @@ ccl_device void svm_node_vertex_color(KernelGlobals *kg,
{
AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id);
if (descriptor.offset != ATTR_STD_NOT_FOUND) {
- float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, NULL, NULL);
+ float4 vertex_color = primitive_surface_attribute_float4(kg, sd, descriptor, NULL, NULL);
stack_store_float3(stack, color_offset, float4_to_float3(vertex_color));
stack_store_float(stack, alpha_offset, vertex_color.w);
}
@@ -51,7 +51,7 @@ ccl_device_noinline
AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id);
if (descriptor.offset != ATTR_STD_NOT_FOUND) {
float4 dx;
- float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, &dx, NULL);
+ float4 vertex_color = primitive_surface_attribute_float4(kg, sd, descriptor, &dx, NULL);
vertex_color += dx;
stack_store_float3(stack, color_offset, float4_to_float3(vertex_color));
stack_store_float(stack, alpha_offset, vertex_color.w);
@@ -78,7 +78,7 @@ ccl_device_noinline
AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id);
if (descriptor.offset != ATTR_STD_NOT_FOUND) {
float4 dy;
- float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, NULL, &dy);
+ float4 vertex_color = primitive_surface_attribute_float4(kg, sd, descriptor, NULL, &dy);
vertex_color += dy;
stack_store_float3(stack, color_offset, float4_to_float3(vertex_color));
stack_store_float(stack, alpha_offset, vertex_color.w);
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index cdef1036647..b478aae9ae2 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -34,7 +34,7 @@ Attribute::Attribute(
assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix || type == TypeFloat2 ||
- type == TypeRGBA);
+ type == TypeFloat4 || type == TypeRGBA);
if (element == ATTR_ELEMENT_VOXEL) {
buffer.resize(sizeof(ImageHandle));
@@ -167,62 +167,62 @@ size_t Attribute::element_size(Geometry *geom, AttributePrimitive prim) const
size = 1;
break;
case ATTR_ELEMENT_VERTEX:
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
- size = mesh->verts.size() + mesh->num_ngons;
+ size = mesh->get_verts().size() + mesh->get_num_ngons();
if (prim == ATTR_PRIM_SUBD) {
- size -= mesh->num_subd_verts;
+ size -= mesh->get_num_subd_verts();
}
}
break;
case ATTR_ELEMENT_VERTEX_MOTION:
- if (geom->type == Geometry::MESH) {
+ if (geom->geometry_type == Geometry::MESH) {
Mesh *mesh = static_cast<Mesh *>(geom);
- size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1);
+ size = (mesh->get_verts().size() + mesh->get_num_ngons()) * (mesh->get_motion_steps() - 1);
if (prim == ATTR_PRIM_SUBD) {
- size -= mesh->num_subd_verts * (mesh->motion_steps - 1);
+ size -= mesh->get_num_subd_verts() * (mesh->get_motion_steps() - 1);
}
}
break;
case ATTR_ELEMENT_FACE:
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
if (prim == ATTR_PRIM_GEOMETRY) {
size = mesh->num_triangles();
}
else {
- size = mesh->subd_faces.size() + mesh->num_ngons;
+ size = mesh->get_num_subd_faces() + mesh->get_num_ngons();
}
}
break;
case ATTR_ELEMENT_CORNER:
case ATTR_ELEMENT_CORNER_BYTE:
- if (geom->type == Geometry::MESH) {
+ if (geom->geometry_type == Geometry::MESH) {
Mesh *mesh = static_cast<Mesh *>(geom);
if (prim == ATTR_PRIM_GEOMETRY) {
size = mesh->num_triangles() * 3;
}
else {
- size = mesh->subd_face_corners.size() + mesh->num_ngons;
+ size = mesh->get_subd_face_corners().size() + mesh->get_num_ngons();
}
}
break;
case ATTR_ELEMENT_CURVE:
- if (geom->type == Geometry::HAIR) {
+ if (geom->geometry_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
size = hair->num_curves();
}
break;
case ATTR_ELEMENT_CURVE_KEY:
- if (geom->type == Geometry::HAIR) {
+ if (geom->geometry_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
- size = hair->curve_keys.size();
+ size = hair->get_curve_keys().size();
}
break;
case ATTR_ELEMENT_CURVE_KEY_MOTION:
- if (geom->type == Geometry::HAIR) {
+ if (geom->geometry_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
- size = hair->curve_keys.size() * (hair->motion_steps - 1);
+ size = hair->get_curve_keys().size() * (hair->get_motion_steps() - 1);
}
break;
default:
@@ -445,7 +445,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
if (name == ustring())
name = Attribute::standard_name(std);
- if (geometry->type == Geometry::MESH) {
+ if (geometry->geometry_type == Geometry::MESH) {
switch (std) {
case ATTR_STD_VERTEX_NORMAL:
attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
@@ -496,7 +496,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
break;
}
}
- else if (geometry->type == Geometry::VOLUME) {
+ else if (geometry->geometry_type == Geometry::VOLUME) {
switch (std) {
case ATTR_STD_VERTEX_NORMAL:
attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
@@ -521,7 +521,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
break;
}
}
- else if (geometry->type == Geometry::HAIR) {
+ else if (geometry->geometry_type == Geometry::HAIR) {
switch (std) {
case ATTR_STD_UV:
attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index 5871fa04a31..9990a1325a7 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -177,6 +177,7 @@ class AttributeSet {
list<Attribute> attributes;
AttributeSet(Geometry *geometry, AttributePrimitive prim);
+ AttributeSet(AttributeSet &&) = default;
~AttributeSet();
Attribute *add(ustring name, TypeDesc type, AttributeElement element);
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index d2463454522..7bdcb1578c3 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -54,7 +54,6 @@ NODE_DEFINE(Background)
Background::Background() : Node(node_type)
{
- need_update = true;
shader = NULL;
}
@@ -64,7 +63,7 @@ Background::~Background()
void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
- if (!need_update)
+ if (!is_modified())
return;
scoped_callback_timer timer([scene](double time) {
@@ -102,7 +101,7 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
else
kbackground->volume_shader = SHADER_NONE;
- kbackground->volume_step_size = volume_step_size * scene->integrator->volume_step_rate;
+ kbackground->volume_step_size = volume_step_size * scene->integrator->get_volume_step_rate();
/* No background node, make world shader invisible to all rays, to skip evaluation in kernel. */
if (bg_shader->graph->nodes.size() <= 1) {
@@ -122,22 +121,17 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
}
- need_update = false;
+ clear_modified();
}
void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
}
-bool Background::modified(const Background &background)
-{
- return !Node::equals(background);
-}
-
void Background::tag_update(Scene *scene)
{
scene->integrator->tag_update(scene);
- need_update = true;
+ tag_modified();
}
Shader *Background::get_shader(const Scene *scene)
diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h
index c2ca1f75179..e89ffbc2445 100644
--- a/intern/cycles/render/background.h
+++ b/intern/cycles/render/background.h
@@ -32,22 +32,20 @@ class Background : public Node {
public:
NODE_DECLARE
- float ao_factor;
- float ao_distance;
+ NODE_SOCKET_API(float, ao_factor)
+ NODE_SOCKET_API(float, ao_distance)
- bool use_shader;
- bool use_ao;
+ NODE_SOCKET_API(bool, use_shader)
+ NODE_SOCKET_API(bool, use_ao)
- uint visibility;
- Shader *shader;
+ NODE_SOCKET_API(uint, visibility)
+ NODE_SOCKET_API(Shader *, shader)
- bool transparent;
- bool transparent_glass;
- float transparent_roughness_threshold;
+ NODE_SOCKET_API(bool, transparent)
+ NODE_SOCKET_API(bool, transparent_glass)
+ NODE_SOCKET_API(float, transparent_roughness_threshold)
- float volume_step_size;
-
- bool need_update;
+ NODE_SOCKET_API(float, volume_step_size)
Background();
~Background();
@@ -55,7 +53,6 @@ class Background : public Node {
void device_update(Device *device, DeviceScene *dscene, Scene *scene);
void device_free(Device *device, DeviceScene *dscene);
- bool modified(const Background &background);
void tag_update(Scene *scene);
Shader *get_shader(const Scene *scene);
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index 05f52159671..439ebdedb8e 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -33,10 +33,11 @@ static int aa_samples(Scene *scene, Object *object, ShaderEvalType type)
}
else if (type == SHADER_EVAL_NORMAL) {
/* Only antialias normal if mesh has bump mapping. */
- if (object->geometry) {
- foreach (Shader *shader, object->geometry->used_shaders) {
+ if (object->get_geometry()) {
+ foreach (Node *node, object->get_geometry()->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
if (shader->has_bump) {
- return scene->integrator->aa_samples;
+ return scene->integrator->get_aa_samples();
}
}
}
@@ -44,7 +45,7 @@ static int aa_samples(Scene *scene, Object *object, ShaderEvalType type)
return 1;
}
else {
- return scene->integrator->aa_samples;
+ return scene->integrator->get_aa_samples();
}
}
@@ -112,7 +113,7 @@ void BakeManager::set(Scene *scene,
}
/* create device and update scene */
- scene->film->tag_update(scene);
+ scene->film->tag_modified();
scene->integrator->tag_update(scene);
need_update = true;
@@ -140,8 +141,8 @@ void BakeManager::device_update(Device * /*device*/,
int object_index = 0;
foreach (Object *object, scene->objects) {
- const Geometry *geom = object->geometry;
- if (object->name == object_name && geom->type == Geometry::MESH) {
+ const Geometry *geom = object->get_geometry();
+ if (object->name == object_name && geom->geometry_type == Geometry::MESH) {
kbake->object_index = object_index;
kbake->tri_offset = geom->prim_offset;
kintegrator->aa_samples = aa_samples(scene, object, type);
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index 3607300cee6..045931ffdac 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -125,6 +125,7 @@ RenderTile::RenderTile()
buffer = 0;
buffers = NULL;
+ stealing_state = NO_STEALING;
}
/* Render Buffers */
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 425400a2c08..4ffc628bb52 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -146,6 +146,9 @@ class RenderTile {
device_ptr buffer;
int device_size;
+ typedef enum { NO_STEALING = 0, CAN_BE_STOLEN = 1, WAS_STOLEN = 2 } StealingState;
+ StealingState stealing_state;
+
RenderBuffers *buffers;
RenderTile();
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 0f2befae320..92cf712d32a 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -98,7 +98,7 @@ NODE_DEFINE(Camera)
type_enum.insert("perspective", CAMERA_PERSPECTIVE);
type_enum.insert("orthograph", CAMERA_ORTHOGRAPHIC);
type_enum.insert("panorama", CAMERA_PANORAMA);
- SOCKET_ENUM(type, "Type", type_enum, CAMERA_PERSPECTIVE);
+ SOCKET_ENUM(camera_type, "Type", type_enum, CAMERA_PERSPECTIVE);
static NodeEnum panorama_type_enum;
panorama_type_enum.insert("equirectangular", PANORAMA_EQUIRECTANGULAR);
@@ -148,8 +148,18 @@ NODE_DEFINE(Camera)
SOCKET_FLOAT(border.bottom, "Border Bottom", 0);
SOCKET_FLOAT(border.top, "Border Top", 0);
+ SOCKET_FLOAT(viewport_camera_border.left, "Viewport Border Left", 0);
+ SOCKET_FLOAT(viewport_camera_border.right, "Viewport Border Right", 0);
+ SOCKET_FLOAT(viewport_camera_border.bottom, "Viewport Border Bottom", 0);
+ SOCKET_FLOAT(viewport_camera_border.top, "Viewport Border Top", 0);
+
SOCKET_FLOAT(offscreen_dicing_scale, "Offscreen Dicing Scale", 1.0f);
+ SOCKET_INT(full_width, "Full Width", 1024);
+ SOCKET_INT(full_height, "Full Height", 512);
+
+ SOCKET_BOOLEAN(use_perspective_motion, "Use Perspective Motion", false);
+
return type;
}
@@ -182,7 +192,6 @@ Camera::Camera() : Node(node_type)
dx = make_float3(0.0f, 0.0f, 0.0f);
dy = make_float3(0.0f, 0.0f, 0.0f);
- need_update = true;
need_device_update = true;
need_flags_update = true;
previous_need_motion = -1;
@@ -196,7 +205,7 @@ Camera::~Camera()
void Camera::compute_auto_viewplane()
{
- if (type == CAMERA_PANORAMA) {
+ if (camera_type == CAMERA_PANORAMA) {
viewplane.left = 0.0f;
viewplane.right = 1.0f;
viewplane.bottom = 0.0f;
@@ -230,7 +239,7 @@ void Camera::update(Scene *scene)
need_device_update = true;
}
- if (!need_update)
+ if (!is_modified())
return;
scoped_callback_timer timer([scene](double time) {
@@ -257,9 +266,9 @@ void Camera::update(Scene *scene)
/* screen to camera */
ProjectionTransform cameratoscreen;
- if (type == CAMERA_PERSPECTIVE)
+ if (camera_type == CAMERA_PERSPECTIVE)
cameratoscreen = projection_perspective(fov, nearclip, farclip);
- else if (type == CAMERA_ORTHOGRAPHIC)
+ else if (camera_type == CAMERA_ORTHOGRAPHIC)
cameratoscreen = projection_orthographic(nearclip, farclip);
else
cameratoscreen = projection_identity();
@@ -284,13 +293,13 @@ void Camera::update(Scene *scene)
worldtoraster = ndctoraster * worldtondc;
/* differentials */
- if (type == CAMERA_ORTHOGRAPHIC) {
+ if (camera_type == CAMERA_ORTHOGRAPHIC) {
dx = transform_perspective_direction(&rastertocamera, make_float3(1, 0, 0));
dy = transform_perspective_direction(&rastertocamera, make_float3(0, 1, 0));
full_dx = transform_perspective_direction(&full_rastertocamera, make_float3(1, 0, 0));
full_dy = transform_perspective_direction(&full_rastertocamera, make_float3(0, 1, 0));
}
- else if (type == CAMERA_PERSPECTIVE) {
+ else if (camera_type == CAMERA_PERSPECTIVE) {
dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) -
transform_perspective(&rastertocamera, make_float3(0, 0, 0));
dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) -
@@ -310,7 +319,7 @@ void Camera::update(Scene *scene)
full_dx = transform_direction(&cameratoworld, full_dx);
full_dy = transform_direction(&cameratoworld, full_dy);
- if (type == CAMERA_PERSPECTIVE) {
+ if (camera_type == CAMERA_PERSPECTIVE) {
float3 v = transform_perspective(&full_rastertocamera,
make_float3(full_width, full_height, 1.0f));
frustum_right_normal = normalize(make_float3(v.z, 0.0f, -v.x));
@@ -348,7 +357,7 @@ void Camera::update(Scene *scene)
if (need_motion == Scene::MOTION_PASS) {
/* TODO(sergey): Support perspective (zoom, fov) motion. */
- if (type == CAMERA_PANORAMA) {
+ if (camera_type == CAMERA_PANORAMA) {
if (have_motion) {
kcam->motion_pass_pre = transform_inverse(motion[0]);
kcam->motion_pass_post = transform_inverse(motion[motion.size() - 1]);
@@ -377,7 +386,7 @@ void Camera::update(Scene *scene)
}
/* TODO(sergey): Support other types of camera. */
- if (use_perspective_motion && type == CAMERA_PERSPECTIVE) {
+ if (use_perspective_motion && camera_type == CAMERA_PERSPECTIVE) {
/* TODO(sergey): Move to an utility function and de-duplicate with
* calculation above.
*/
@@ -402,7 +411,7 @@ void Camera::update(Scene *scene)
kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime : -1.0f;
/* type */
- kcam->type = type;
+ kcam->type = camera_type;
/* anamorphic lens bokeh */
kcam->inv_aperture_ratio = 1.0f / aperture_ratio;
@@ -464,7 +473,7 @@ void Camera::update(Scene *scene)
kcam->rolling_shutter_duration = rolling_shutter_duration;
/* Set further update flags */
- need_update = false;
+ clear_modified();
need_device_update = true;
need_flags_update = true;
previous_need_motion = need_motion;
@@ -527,7 +536,7 @@ void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scen
[&](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 &&
+ if (object->get_geometry()->has_volume &&
viewplane_boundbox.intersects(object->bounds)) {
/* TODO(sergey): Consider adding more grained check. */
VLOG(1) << "Detected camera inside volume.";
@@ -553,25 +562,10 @@ void Camera::device_free(Device * /*device*/, DeviceScene *dscene, Scene *scene)
dscene->camera_motion.free();
}
-bool Camera::modified(const Camera &cam)
-{
- return !Node::equals(cam);
-}
-
-bool Camera::motion_modified(const Camera &cam)
-{
- return !((motion == cam.motion) && (use_perspective_motion == cam.use_perspective_motion));
-}
-
-void Camera::tag_update()
-{
- need_update = true;
-}
-
float3 Camera::transform_raster_to_world(float raster_x, float raster_y)
{
float3 D, P;
- if (type == CAMERA_PERSPECTIVE) {
+ if (camera_type == CAMERA_PERSPECTIVE) {
D = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
float3 Pclip = normalize(D);
P = make_float3(0.0f, 0.0f, 0.0f);
@@ -584,7 +578,7 @@ float3 Camera::transform_raster_to_world(float raster_x, float raster_y)
*/
P += nearclip * D / Pclip.z;
}
- else if (type == CAMERA_ORTHOGRAPHIC) {
+ else if (camera_type == CAMERA_ORTHOGRAPHIC) {
D = make_float3(0.0f, 0.0f, 1.0f);
/* TODO(sergey): Aperture support? */
P = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
@@ -603,7 +597,7 @@ BoundBox Camera::viewplane_bounds_get()
* checks we need in a more clear and smart fashion? */
BoundBox bounds = BoundBox::empty;
- if (type == CAMERA_PANORAMA) {
+ if (camera_type == CAMERA_PANORAMA) {
if (use_spherical_stereo == false) {
bounds.grow(make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w));
}
@@ -628,7 +622,7 @@ BoundBox Camera::viewplane_bounds_get()
bounds.grow(transform_raster_to_world(0.0f, (float)height));
bounds.grow(transform_raster_to_world((float)width, (float)height));
bounds.grow(transform_raster_to_world((float)width, 0.0f));
- if (type == CAMERA_PERSPECTIVE) {
+ if (camera_type == CAMERA_PERSPECTIVE) {
/* Center point has the most distance in local Z axis,
* use it to construct bounding box/
*/
@@ -642,7 +636,7 @@ float Camera::world_to_raster_size(float3 P)
{
float res = 1.0f;
- if (type == CAMERA_ORTHOGRAPHIC) {
+ if (camera_type == CAMERA_ORTHOGRAPHIC) {
res = min(len(full_dx), len(full_dy));
if (offscreen_dicing_scale > 1.0f) {
@@ -668,7 +662,7 @@ float Camera::world_to_raster_size(float3 P)
}
}
}
- else if (type == CAMERA_PERSPECTIVE) {
+ else if (camera_type == CAMERA_PERSPECTIVE) {
/* Calculate as if point is directly ahead of the camera. */
float3 raster = make_float3(0.5f * full_width, 0.5f * full_height, 0.0f);
float3 Pcamera = transform_perspective(&full_rastertocamera, raster);
@@ -743,7 +737,7 @@ float Camera::world_to_raster_size(float3 P)
}
}
}
- else if (type == CAMERA_PANORAMA) {
+ else if (camera_type == CAMERA_PANORAMA) {
float3 D = transform_point(&worldtocamera, P);
float dist = len(D);
@@ -794,6 +788,16 @@ bool Camera::use_motion() const
return motion.size() > 1;
}
+void Camera::set_screen_size_and_resolution(int width_, int height_, int resolution_)
+{
+ if (width_ != width || height_ != height || resolution_ != resolution) {
+ width = width_;
+ height = height_;
+ resolution = resolution_;
+ tag_modified();
+ }
+}
+
float Camera::motion_time(int step) const
{
return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 21dad5eea3b..7970381f338 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -73,78 +73,92 @@ class Camera : public Node {
};
/* motion blur */
- float shuttertime;
- MotionPosition motion_position;
- array<float> shutter_curve;
+ NODE_SOCKET_API(float, shuttertime)
+ NODE_SOCKET_API(MotionPosition, motion_position)
+ NODE_SOCKET_API_ARRAY(array<float>, shutter_curve)
size_t shutter_table_offset;
/* ** Rolling shutter effect. ** */
/* Defines rolling shutter effect type. */
- RollingShutterType rolling_shutter_type;
+ NODE_SOCKET_API(RollingShutterType, rolling_shutter_type)
/* Specifies exposure time of scanlines when using
* rolling shutter effect.
*/
- float rolling_shutter_duration;
+ NODE_SOCKET_API(float, rolling_shutter_duration)
/* depth of field */
- float focaldistance;
- float aperturesize;
- uint blades;
- float bladesrotation;
+ NODE_SOCKET_API(float, focaldistance)
+ NODE_SOCKET_API(float, aperturesize)
+ NODE_SOCKET_API(uint, blades)
+ NODE_SOCKET_API(float, bladesrotation)
/* type */
- CameraType type;
- float fov;
+ NODE_SOCKET_API(CameraType, camera_type)
+ NODE_SOCKET_API(float, fov)
/* panorama */
- PanoramaType panorama_type;
- float fisheye_fov;
- float fisheye_lens;
- float latitude_min;
- float latitude_max;
- float longitude_min;
- float longitude_max;
+ NODE_SOCKET_API(PanoramaType, panorama_type)
+ NODE_SOCKET_API(float, fisheye_fov)
+ NODE_SOCKET_API(float, fisheye_lens)
+ NODE_SOCKET_API(float, latitude_min)
+ NODE_SOCKET_API(float, latitude_max)
+ NODE_SOCKET_API(float, longitude_min)
+ NODE_SOCKET_API(float, longitude_max)
/* panorama stereo */
- StereoEye stereo_eye;
- bool use_spherical_stereo;
- float interocular_distance;
- float convergence_distance;
- bool use_pole_merge;
- float pole_merge_angle_from;
- float pole_merge_angle_to;
+ NODE_SOCKET_API(StereoEye, stereo_eye)
+ NODE_SOCKET_API(bool, use_spherical_stereo)
+ NODE_SOCKET_API(float, interocular_distance)
+ NODE_SOCKET_API(float, convergence_distance)
+ NODE_SOCKET_API(bool, use_pole_merge)
+ NODE_SOCKET_API(float, pole_merge_angle_from)
+ NODE_SOCKET_API(float, pole_merge_angle_to)
/* anamorphic lens bokeh */
- float aperture_ratio;
+ NODE_SOCKET_API(float, aperture_ratio)
/* sensor */
- float sensorwidth;
- float sensorheight;
+ NODE_SOCKET_API(float, sensorwidth)
+ NODE_SOCKET_API(float, sensorheight)
/* clipping */
- float nearclip;
- float farclip;
+ NODE_SOCKET_API(float, nearclip)
+ NODE_SOCKET_API(float, farclip)
/* screen */
- int width, height;
- int resolution;
BoundBox2D viewplane;
+ NODE_SOCKET_API_STRUCT_MEMBER(float, viewplane, left)
+ NODE_SOCKET_API_STRUCT_MEMBER(float, viewplane, right)
+ NODE_SOCKET_API_STRUCT_MEMBER(float, viewplane, bottom)
+ NODE_SOCKET_API_STRUCT_MEMBER(float, viewplane, top)
+
/* width and height change during preview, so we need these for calculating dice rates. */
- int full_width, full_height;
+ NODE_SOCKET_API(int, full_width)
+ NODE_SOCKET_API(int, full_height)
/* controls how fast the dicing rate falls off for geometry out side of view */
- float offscreen_dicing_scale;
+ NODE_SOCKET_API(float, offscreen_dicing_scale)
/* border */
BoundBox2D border;
+ NODE_SOCKET_API_STRUCT_MEMBER(float, border, left)
+ NODE_SOCKET_API_STRUCT_MEMBER(float, border, right)
+ NODE_SOCKET_API_STRUCT_MEMBER(float, border, bottom)
+ NODE_SOCKET_API_STRUCT_MEMBER(float, border, top)
+
BoundBox2D viewport_camera_border;
+ NODE_SOCKET_API_STRUCT_MEMBER(float, viewport_camera_border, left)
+ NODE_SOCKET_API_STRUCT_MEMBER(float, viewport_camera_border, right)
+ NODE_SOCKET_API_STRUCT_MEMBER(float, viewport_camera_border, bottom)
+ NODE_SOCKET_API_STRUCT_MEMBER(float, viewport_camera_border, top)
/* transformation */
- Transform matrix;
+ NODE_SOCKET_API(Transform, matrix)
/* motion */
- array<Transform> motion;
- bool use_perspective_motion;
- float fov_pre, fov_post;
+ NODE_SOCKET_API_ARRAY(array<Transform>, motion)
+ NODE_SOCKET_API(bool, use_perspective_motion)
+ NODE_SOCKET_API(float, fov_pre)
+ NODE_SOCKET_API(float, fov_post)
/* computed camera parameters */
ProjectionTransform screentoworld;
@@ -174,7 +188,6 @@ class Camera : public Node {
float3 frustum_bottom_normal;
/* update */
- bool need_update;
bool need_device_update;
bool need_flags_update;
int previous_need_motion;
@@ -183,6 +196,12 @@ class Camera : public Node {
KernelCamera kernel_camera;
array<DecomposedTransform> kernel_camera_motion;
+ private:
+ int width;
+ int height;
+ int resolution;
+
+ public:
/* functions */
Camera();
~Camera();
@@ -195,10 +214,6 @@ class Camera : public Node {
void device_update_volume(Device *device, DeviceScene *dscene, Scene *scene);
void device_free(Device *device, DeviceScene *dscene, Scene *scene);
- bool modified(const Camera &cam);
- bool motion_modified(const Camera &cam);
- void tag_update();
-
/* Public utility functions. */
BoundBox viewplane_bounds_get();
@@ -210,6 +225,8 @@ class Camera : public Node {
int motion_step(float time) const;
bool use_motion() const;
+ void set_screen_size_and_resolution(int width_, int height_, int resolution_);
+
private:
/* Private utility functions. */
float3 transform_raster_to_world(float raster_x, float raster_y);
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index e4c1e452bd5..5c3778f6ae5 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -40,10 +40,8 @@ static bool compare_pass_order(const Pass &a, const Pass &b)
return (a.components > b.components);
}
-NODE_DEFINE(Pass)
+static NodeEnum *get_pass_type_enum()
{
- NodeType *type = NodeType::add("pass", create);
-
static NodeEnum pass_type_enum;
pass_type_enum.insert("combined", PASS_COMBINED);
pass_type_enum.insert("depth", PASS_DEPTH);
@@ -84,7 +82,15 @@ NODE_DEFINE(Pass)
pass_type_enum.insert("bake_primitive", PASS_BAKE_PRIMITIVE);
pass_type_enum.insert("bake_differential", PASS_BAKE_DIFFERENTIAL);
- SOCKET_ENUM(type, "Type", pass_type_enum, PASS_COMBINED);
+ return &pass_type_enum;
+}
+
+NODE_DEFINE(Pass)
+{
+ NodeType *type = NodeType::add("pass", create);
+
+ NodeEnum *pass_type_enum = get_pass_type_enum();
+ SOCKET_ENUM(type, "Type", *pass_type_enum, PASS_COMBINED);
SOCKET_STRING(name, "Name", ustring());
return type;
@@ -383,6 +389,21 @@ NODE_DEFINE(Film)
SOCKET_INT(denoising_flags, "Denoising Flags", 0);
SOCKET_BOOLEAN(use_adaptive_sampling, "Use Adaptive Sampling", false);
+ SOCKET_BOOLEAN(use_light_visibility, "Use Light Visibility", false);
+
+ NodeEnum *pass_type_enum = get_pass_type_enum();
+ SOCKET_ENUM(display_pass, "Display Pass", *pass_type_enum, PASS_COMBINED);
+
+ static NodeEnum cryptomatte_passes_enum;
+ cryptomatte_passes_enum.insert("none", CRYPT_NONE);
+ cryptomatte_passes_enum.insert("object", CRYPT_OBJECT);
+ cryptomatte_passes_enum.insert("material", CRYPT_MATERIAL);
+ cryptomatte_passes_enum.insert("asset", CRYPT_ASSET);
+ cryptomatte_passes_enum.insert("accurate", CRYPT_ACCURATE);
+ SOCKET_ENUM(cryptomatte_passes, "Cryptomatte Passes", cryptomatte_passes_enum, CRYPT_NONE);
+
+ SOCKET_INT(cryptomatte_depth, "Cryptomatte Depth", 0);
+
return type;
}
@@ -392,8 +413,6 @@ Film::Film() : Node(node_type)
filter_table_offset = TABLE_OFFSET_INVALID;
cryptomatte_passes = CRYPT_NONE;
display_pass = PASS_COMBINED;
-
- need_update = true;
}
Film::~Film()
@@ -407,7 +426,7 @@ void Film::add_default(Scene *scene)
void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
- if (!need_update)
+ if (!is_modified())
return;
scoped_callback_timer timer([scene](double time) {
@@ -658,7 +677,7 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
denoising_data_offset = kfilm->pass_denoising_data;
denoising_clean_offset = kfilm->pass_denoising_clean;
- need_update = false;
+ clear_modified();
}
void Film::device_free(Device * /*device*/, DeviceScene * /*dscene*/, Scene *scene)
@@ -666,11 +685,6 @@ void Film::device_free(Device * /*device*/, DeviceScene * /*dscene*/, Scene *sce
scene->lookup_tables->remove_table(&filter_table_offset);
}
-bool Film::modified(const Film &film)
-{
- return !Node::equals(film);
-}
-
void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool update_passes)
{
if (Pass::contains(scene->passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) {
@@ -691,11 +705,6 @@ void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool upd
}
}
-void Film::tag_update(Scene * /*scene*/)
-{
- need_update = true;
-}
-
int Film::get_aov_offset(Scene *scene, string name, bool &is_color)
{
int num_color = 0, num_value = 0;
@@ -719,4 +728,24 @@ int Film::get_aov_offset(Scene *scene, string name, bool &is_color)
return -1;
}
+int Film::get_pass_stride() const
+{
+ return pass_stride;
+}
+
+int Film::get_denoising_data_offset() const
+{
+ return denoising_data_offset;
+}
+
+int Film::get_denoising_clean_offset() const
+{
+ return denoising_clean_offset;
+}
+
+size_t Film::get_filter_table_offset() const
+{
+ return filter_table_offset;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h
index 961058c008e..462a7275491 100644
--- a/intern/cycles/render/film.h
+++ b/intern/cycles/render/film.h
@@ -60,34 +60,35 @@ class Film : public Node {
public:
NODE_DECLARE
- float exposure;
- bool denoising_data_pass;
- bool denoising_clean_pass;
- bool denoising_prefiltered_pass;
- int denoising_flags;
- float pass_alpha_threshold;
-
- PassType display_pass;
- int pass_stride;
- int denoising_data_offset;
- int denoising_clean_offset;
+ NODE_SOCKET_API(float, exposure)
+ NODE_SOCKET_API(bool, denoising_data_pass)
+ NODE_SOCKET_API(bool, denoising_clean_pass)
+ NODE_SOCKET_API(bool, denoising_prefiltered_pass)
+ NODE_SOCKET_API(int, denoising_flags)
+ NODE_SOCKET_API(float, pass_alpha_threshold)
- FilterType filter_type;
- float filter_width;
- size_t filter_table_offset;
+ NODE_SOCKET_API(PassType, display_pass)
- float mist_start;
- float mist_depth;
- float mist_falloff;
+ NODE_SOCKET_API(FilterType, filter_type)
+ NODE_SOCKET_API(float, filter_width)
- bool use_light_visibility;
- CryptomatteType cryptomatte_passes;
- int cryptomatte_depth;
+ NODE_SOCKET_API(float, mist_start)
+ NODE_SOCKET_API(float, mist_depth)
+ NODE_SOCKET_API(float, mist_falloff)
- bool use_adaptive_sampling;
+ NODE_SOCKET_API(bool, use_light_visibility)
+ NODE_SOCKET_API(CryptomatteType, cryptomatte_passes)
+ NODE_SOCKET_API(int, cryptomatte_depth)
- bool need_update;
+ NODE_SOCKET_API(bool, use_adaptive_sampling)
+ private:
+ int pass_stride;
+ int denoising_data_offset;
+ int denoising_clean_offset;
+ size_t filter_table_offset;
+
+ public:
Film();
~Film();
@@ -97,11 +98,14 @@ class Film : public Node {
void device_update(Device *device, DeviceScene *dscene, Scene *scene);
void device_free(Device *device, DeviceScene *dscene, Scene *scene);
- bool modified(const Film &film);
void tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool update_passes = true);
- void tag_update(Scene *scene);
int get_aov_offset(Scene *scene, string name, bool &is_color);
+
+ int get_pass_stride() const;
+ int get_denoising_data_offset() const;
+ int get_denoising_clean_offset() const;
+ size_t get_filter_table_offset() const;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp
index fdfce63bbeb..a63fc620c69 100644
--- a/intern/cycles/render/geometry.cpp
+++ b/intern/cycles/render/geometry.cpp
@@ -52,14 +52,14 @@ NODE_ABSTRACT_DEFINE(Geometry)
SOCKET_UINT(motion_steps, "Motion Steps", 3);
SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false);
+ SOCKET_NODE_ARRAY(used_shaders, "Shaders", &Shader::node_type);
return type;
}
Geometry::Geometry(const NodeType *node_type, const Type type)
- : Node(node_type), type(type), attributes(this, ATTR_PRIM_GEOMETRY)
+ : Node(node_type), geometry_type(type), attributes(this, ATTR_PRIM_GEOMETRY)
{
- need_update = true;
need_update_rebuild = false;
transform_applied = false;
@@ -81,9 +81,11 @@ Geometry::~Geometry()
delete bvh;
}
-void Geometry::clear()
+void Geometry::clear(bool preserve_shaders)
{
- used_shaders.clear();
+ if (!preserve_shaders)
+ used_shaders.clear();
+
transform_applied = false;
transform_negative_scaled = false;
transform_normal = transform_identity();
@@ -97,9 +99,11 @@ bool Geometry::need_attribute(Scene *scene, AttributeStandard std)
if (scene->need_global_attribute(std))
return true;
- foreach (Shader *shader, used_shaders)
+ foreach (Node *node, used_shaders) {
+ Shader *shader = static_cast<Shader *>(node);
if (shader->attributes.find(std))
return true;
+ }
return false;
}
@@ -109,13 +113,27 @@ bool Geometry::need_attribute(Scene * /*scene*/, ustring name)
if (name == ustring())
return false;
- foreach (Shader *shader, used_shaders)
+ foreach (Node *node, used_shaders) {
+ Shader *shader = static_cast<Shader *>(node);
if (shader->attributes.find(name))
return true;
+ }
return false;
}
+AttributeRequestSet Geometry::needed_attributes()
+{
+ AttributeRequestSet result;
+
+ foreach (Node *node, used_shaders) {
+ Shader *shader = static_cast<Shader *>(node);
+ result.add(shader->attributes);
+ }
+
+ return result;
+}
+
float Geometry::motion_time(int step) const
{
return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f;
@@ -159,8 +177,9 @@ bool Geometry::is_instanced() const
bool Geometry::has_true_displacement() const
{
- foreach (Shader *shader, used_shaders) {
- if (shader->has_displacement && shader->displacement_method != DISPLACE_BUMP) {
+ foreach (Node *node, used_shaders) {
+ Shader *shader = static_cast<Shader *>(node);
+ if (shader->has_displacement && shader->get_displacement_method() != DISPLACE_BUMP) {
return true;
}
}
@@ -186,7 +205,7 @@ void Geometry::compute_bvh(
msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total);
Object object;
- object.geometry = this;
+ object.set_geometry(this);
vector<Geometry *> geometry;
geometry.push_back(this);
@@ -220,7 +239,7 @@ void Geometry::compute_bvh(
}
}
- need_update = false;
+ clear_modified();
need_update_rebuild = false;
}
@@ -242,16 +261,18 @@ bool Geometry::has_voxel_attributes() const
void Geometry::tag_update(Scene *scene, bool rebuild)
{
- need_update = true;
+ tag_modified();
if (rebuild) {
need_update_rebuild = true;
scene->light_manager->need_update = true;
}
else {
- foreach (Shader *shader, used_shaders)
+ foreach (Node *node, used_shaders) {
+ Shader *shader = static_cast<Shader *>(node);
if (shader->has_surface_emission)
scene->light_manager->need_update = true;
+ }
}
scene->geometry_manager->need_update = true;
@@ -305,15 +326,12 @@ void GeometryManager::update_osl_attributes(Device *device,
}
/* find geometry attributes */
- size_t j;
-
- for (j = 0; j < scene->geometry.size(); j++)
- if (scene->geometry[j] == object->geometry)
- break;
+ size_t j = object->geometry->index;
+ assert(j < scene->geometry.size() && scene->geometry[j] == object->geometry);
AttributeRequestSet &attributes = geom_attributes[j];
- /* set object attributes */
+ /* set mesh attributes */
foreach (AttributeRequest &req, attributes.requests) {
OSLGlobals::Attribute osl_attr;
@@ -375,10 +393,68 @@ void GeometryManager::update_osl_attributes(Device *device,
#endif
}
+/* Generate a normal attribute map entry from an attribute descriptor. */
+static void emit_attribute_map_entry(
+ uint4 *attr_map, int index, uint id, TypeDesc type, const AttributeDescriptor &desc)
+{
+ attr_map[index].x = id;
+ attr_map[index].y = desc.element;
+ attr_map[index].z = as_uint(desc.offset);
+
+ if (type == TypeDesc::TypeFloat)
+ attr_map[index].w = NODE_ATTR_FLOAT;
+ else if (type == TypeDesc::TypeMatrix)
+ attr_map[index].w = NODE_ATTR_MATRIX;
+ else if (type == TypeFloat2)
+ attr_map[index].w = NODE_ATTR_FLOAT2;
+ else if (type == TypeFloat4)
+ attr_map[index].w = NODE_ATTR_FLOAT4;
+ else if (type == TypeRGBA)
+ attr_map[index].w = NODE_ATTR_RGBA;
+ else
+ attr_map[index].w = NODE_ATTR_FLOAT3;
+
+ attr_map[index].w |= desc.flags << 8;
+}
+
+/* Generate an attribute map end marker, optionally including a link to another map.
+ * Links are used to connect object attribute maps to mesh attribute maps. */
+static void emit_attribute_map_terminator(uint4 *attr_map, int index, bool chain, uint chain_link)
+{
+ for (int j = 0; j < ATTR_PRIM_TYPES; j++) {
+ attr_map[index + j].x = ATTR_STD_NONE;
+ attr_map[index + j].y = chain; /* link is valid flag */
+ attr_map[index + j].z = chain ? chain_link + j : 0; /* link to the correct sub-entry */
+ attr_map[index + j].w = 0;
+ }
+}
+
+/* Generate all necessary attribute map entries from the attribute request. */
+static void emit_attribute_mapping(
+ uint4 *attr_map, int index, Scene *scene, AttributeRequest &req, Geometry *geom)
+{
+ uint id;
+
+ if (req.std == ATTR_STD_NONE)
+ id = scene->shader_manager->get_attribute_id(req.name);
+ else
+ id = scene->shader_manager->get_attribute_id(req.std);
+
+ emit_attribute_map_entry(attr_map, index, id, req.type, req.desc);
+
+ if (geom->is_mesh()) {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ if (mesh->get_num_subd_faces()) {
+ emit_attribute_map_entry(attr_map, index + 1, id, req.subd_type, req.subd_desc);
+ }
+ }
+}
+
void GeometryManager::update_svm_attributes(Device *,
DeviceScene *dscene,
Scene *scene,
- vector<AttributeRequestSet> &geom_attributes)
+ vector<AttributeRequestSet> &geom_attributes,
+ vector<AttributeRequestSet> &object_attributes)
{
/* for SVM, the attributes_map table is used to lookup the offset of an
* attribute, based on a unique shader attribute id. */
@@ -392,6 +468,19 @@ void GeometryManager::update_svm_attributes(Device *,
attr_map_size += (geom_attributes[i].size() + 1) * ATTR_PRIM_TYPES;
}
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ Object *object = scene->objects[i];
+
+ /* only allocate a table for the object if it actually has attributes */
+ if (object_attributes[i].size() == 0) {
+ object->attr_map_offset = 0;
+ }
+ else {
+ object->attr_map_offset = attr_map_size;
+ attr_map_size += (object_attributes[i].size() + 1) * ATTR_PRIM_TYPES;
+ }
+ }
+
if (attr_map_size == 0)
return;
@@ -403,69 +492,31 @@ void GeometryManager::update_svm_attributes(Device *,
Geometry *geom = scene->geometry[i];
AttributeRequestSet &attributes = geom_attributes[i];
- /* set object attributes */
+ /* set geometry attributes */
int index = geom->attr_map_offset;
foreach (AttributeRequest &req, attributes.requests) {
- uint id;
-
- if (req.std == ATTR_STD_NONE)
- id = scene->shader_manager->get_attribute_id(req.name);
- else
- id = scene->shader_manager->get_attribute_id(req.std);
-
- attr_map[index].x = id;
- attr_map[index].y = req.desc.element;
- attr_map[index].z = as_uint(req.desc.offset);
+ emit_attribute_mapping(attr_map, index, scene, req, geom);
+ index += ATTR_PRIM_TYPES;
+ }
- if (req.type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else if (req.type == TypeDesc::TypeMatrix)
- attr_map[index].w = NODE_ATTR_MATRIX;
- else if (req.type == TypeFloat2)
- attr_map[index].w = NODE_ATTR_FLOAT2;
- else if (req.type == TypeRGBA)
- attr_map[index].w = NODE_ATTR_RGBA;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
+ emit_attribute_map_terminator(attr_map, index, false, 0);
+ }
- attr_map[index].w |= req.desc.flags << 8;
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ Object *object = scene->objects[i];
+ AttributeRequestSet &attributes = object_attributes[i];
- index++;
+ /* set object attributes */
+ if (attributes.size() > 0) {
+ int index = object->attr_map_offset;
- if (geom->type == Geometry::MESH) {
- Mesh *mesh = static_cast<Mesh *>(geom);
- if (mesh->subd_faces.size()) {
- attr_map[index].x = id;
- attr_map[index].y = req.subd_desc.element;
- attr_map[index].z = as_uint(req.subd_desc.offset);
-
- if (req.subd_type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else if (req.subd_type == TypeDesc::TypeMatrix)
- attr_map[index].w = NODE_ATTR_MATRIX;
- else if (req.subd_type == TypeFloat2)
- attr_map[index].w = NODE_ATTR_FLOAT2;
- else if (req.subd_type == TypeRGBA)
- attr_map[index].w = NODE_ATTR_RGBA;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
-
- attr_map[index].w |= req.subd_desc.flags << 8;
- }
+ foreach (AttributeRequest &req, attributes.requests) {
+ emit_attribute_mapping(attr_map, index, scene, req, object->geometry);
+ index += ATTR_PRIM_TYPES;
}
- index++;
- }
-
- /* terminator */
- for (int j = 0; j < ATTR_PRIM_TYPES; j++) {
- attr_map[index].x = ATTR_STD_NONE;
- attr_map[index].y = 0;
- attr_map[index].z = 0;
- attr_map[index].w = 0;
-
- index++;
+ emit_attribute_map_terminator(attr_map, index, true, object->geometry->attr_map_offset);
}
}
@@ -505,19 +556,19 @@ static void update_attribute_element_size(Geometry *geom,
}
}
-static void update_attribute_element_offset(Geometry *geom,
- device_vector<float> &attr_float,
- size_t &attr_float_offset,
- device_vector<float2> &attr_float2,
- size_t &attr_float2_offset,
- device_vector<float4> &attr_float3,
- size_t &attr_float3_offset,
- device_vector<uchar4> &attr_uchar4,
- size_t &attr_uchar4_offset,
- Attribute *mattr,
- AttributePrimitive prim,
- TypeDesc &type,
- AttributeDescriptor &desc)
+void GeometryManager::update_attribute_element_offset(Geometry *geom,
+ device_vector<float> &attr_float,
+ size_t &attr_float_offset,
+ device_vector<float2> &attr_float2,
+ size_t &attr_float2_offset,
+ device_vector<float4> &attr_float3,
+ size_t &attr_float3_offset,
+ device_vector<uchar4> &attr_uchar4,
+ size_t &attr_uchar4_offset,
+ Attribute *mattr,
+ AttributePrimitive prim,
+ TypeDesc &type,
+ AttributeDescriptor &desc)
{
if (mattr) {
/* store element and type */
@@ -589,7 +640,7 @@ static void update_attribute_element_offset(Geometry *geom,
/* mesh vertex/curve index is global, not per object, so we sneak
* a correction for that in here */
- if (geom->type == Geometry::MESH) {
+ if (geom->is_mesh()) {
Mesh *mesh = static_cast<Mesh *>(geom);
if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK &&
desc.flags & ATTR_SUBDIVIDED) {
@@ -613,7 +664,7 @@ static void update_attribute_element_offset(Geometry *geom,
offset -= mesh->corner_offset;
}
}
- else if (geom->type == Geometry::HAIR) {
+ else if (geom->is_hair()) {
Hair *hair = static_cast<Hair *>(geom);
if (element == ATTR_ELEMENT_CURVE)
offset -= hair->prim_offset;
@@ -645,13 +696,48 @@ void GeometryManager::device_update_attributes(Device *device,
for (size_t i = 0; i < scene->geometry.size(); i++) {
Geometry *geom = scene->geometry[i];
+ geom->index = i;
scene->need_global_attributes(geom_attributes[i]);
- foreach (Shader *shader, geom->used_shaders) {
+ foreach (Node *node, geom->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
geom_attributes[i].add(shader->attributes);
}
}
+ /* convert object attributes to use the same data structures as geometry ones */
+ vector<AttributeRequestSet> object_attributes(scene->objects.size());
+ vector<AttributeSet> object_attribute_values;
+
+ object_attribute_values.reserve(scene->objects.size());
+
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ Object *object = scene->objects[i];
+ Geometry *geom = object->geometry;
+ size_t geom_idx = geom->index;
+
+ assert(geom_idx < scene->geometry.size() && scene->geometry[geom_idx] == geom);
+
+ object_attribute_values.push_back(AttributeSet(geom, ATTR_PRIM_GEOMETRY));
+
+ AttributeRequestSet &geom_requests = geom_attributes[geom_idx];
+ AttributeRequestSet &attributes = object_attributes[i];
+ AttributeSet &values = object_attribute_values[i];
+
+ for (size_t j = 0; j < object->attributes.size(); j++) {
+ ParamValue &param = object->attributes[j];
+
+ /* add attributes that are requested and not already handled by the mesh */
+ if (geom_requests.find(param.name()) && !geom->attributes.find(param.name())) {
+ attributes.add(param.name());
+
+ Attribute *attr = values.add(param.name(), param.type(), ATTR_ELEMENT_OBJECT);
+ assert(param.datasize() == attr->buffer.size());
+ memcpy(attr->buffer.data(), param.data(), param.datasize());
+ }
+ }
+ }
+
/* mesh attribute are stored in a single array per data type. here we fill
* those arrays, and set the offset and element type to create attribute
* maps next */
@@ -663,6 +749,7 @@ void GeometryManager::device_update_attributes(Device *device,
size_t attr_float2_size = 0;
size_t attr_float3_size = 0;
size_t attr_uchar4_size = 0;
+
for (size_t i = 0; i < scene->geometry.size(); i++) {
Geometry *geom = scene->geometry[i];
AttributeRequestSet &attributes = geom_attributes[i];
@@ -677,7 +764,7 @@ void GeometryManager::device_update_attributes(Device *device,
&attr_float3_size,
&attr_uchar4_size);
- if (geom->type == Geometry::MESH) {
+ if (geom->is_mesh()) {
Mesh *mesh = static_cast<Mesh *>(geom);
Attribute *subd_attr = mesh->subd_attributes.find(req);
@@ -692,6 +779,20 @@ void GeometryManager::device_update_attributes(Device *device,
}
}
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ Object *object = scene->objects[i];
+
+ foreach (Attribute &attr, object_attribute_values[i].attributes) {
+ update_attribute_element_size(object->geometry,
+ &attr,
+ ATTR_PRIM_GEOMETRY,
+ &attr_float_size,
+ &attr_float2_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ }
+ }
+
dscene->attributes_float.alloc(attr_float_size);
dscene->attributes_float2.alloc(attr_float2_size);
dscene->attributes_float3.alloc(attr_float3_size);
@@ -725,7 +826,7 @@ void GeometryManager::device_update_attributes(Device *device,
req.type,
req.desc);
- if (geom->type == Geometry::MESH) {
+ if (geom->is_mesh()) {
Mesh *mesh = static_cast<Mesh *>(geom);
Attribute *subd_attr = mesh->subd_attributes.find(req);
@@ -749,11 +850,42 @@ void GeometryManager::device_update_attributes(Device *device,
}
}
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ Object *object = scene->objects[i];
+ AttributeRequestSet &attributes = object_attributes[i];
+ AttributeSet &values = object_attribute_values[i];
+
+ foreach (AttributeRequest &req, attributes.requests) {
+ Attribute *attr = values.find(req);
+
+ update_attribute_element_offset(object->geometry,
+ dscene->attributes_float,
+ attr_float_offset,
+ dscene->attributes_float2,
+ attr_float2_offset,
+ dscene->attributes_float3,
+ attr_float3_offset,
+ dscene->attributes_uchar4,
+ attr_uchar4_offset,
+ attr,
+ ATTR_PRIM_GEOMETRY,
+ req.type,
+ req.desc);
+
+ /* object attributes don't care about subdivision */
+ req.subd_type = req.type;
+ req.subd_desc = req.desc;
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
/* create attribute lookup maps */
if (scene->shader_manager->use_osl())
update_osl_attributes(device, scene, geom_attributes);
- update_svm_attributes(device, dscene, scene, geom_attributes);
+ update_svm_attributes(device, dscene, scene, geom_attributes, object_attributes);
if (progress.get_cancel())
return;
@@ -797,7 +929,7 @@ void GeometryManager::mesh_calc_offset(Scene *scene)
size_t optix_prim_size = 0;
foreach (Geometry *geom, scene->geometry) {
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
mesh->vert_offset = vert_size;
@@ -810,8 +942,8 @@ void GeometryManager::mesh_calc_offset(Scene *scene)
vert_size += mesh->verts.size();
tri_size += mesh->num_triangles();
- if (mesh->subd_faces.size()) {
- Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1];
+ if (mesh->get_num_subd_faces()) {
+ Mesh::SubdFace last = mesh->get_subd_face(mesh->get_num_subd_faces() - 1);
patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
/* patch tables are stored in same array so include them in patch_size */
@@ -821,19 +953,19 @@ void GeometryManager::mesh_calc_offset(Scene *scene)
}
}
- face_size += mesh->subd_faces.size();
+ face_size += mesh->get_num_subd_faces();
corner_size += mesh->subd_face_corners.size();
mesh->optix_prim_offset = optix_prim_size;
optix_prim_size += mesh->num_triangles();
}
- else if (geom->type == Geometry::HAIR) {
+ else if (geom->is_hair()) {
Hair *hair = static_cast<Hair *>(geom);
hair->curvekey_offset = curve_key_size;
hair->prim_offset = curve_size;
- curve_key_size += hair->curve_keys.size();
+ curve_key_size += hair->get_curve_keys().size();
curve_size += hair->num_curves();
hair->optix_prim_offset = optix_prim_size;
@@ -855,14 +987,14 @@ void GeometryManager::device_update_mesh(
size_t patch_size = 0;
foreach (Geometry *geom, scene->geometry) {
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
vert_size += mesh->verts.size();
tri_size += mesh->num_triangles();
- if (mesh->subd_faces.size()) {
- Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1];
+ if (mesh->get_num_subd_faces()) {
+ Mesh::SubdFace last = mesh->get_subd_face(mesh->get_num_subd_faces() - 1);
patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
/* patch tables are stored in same array so include them in patch_size */
@@ -872,10 +1004,10 @@ void GeometryManager::device_update_mesh(
}
}
}
- else if (geom->type == Geometry::HAIR) {
+ else if (geom->is_hair()) {
Hair *hair = static_cast<Hair *>(geom);
- curve_key_size += hair->curve_keys.size();
+ curve_key_size += hair->get_curve_keys().size();
curve_size += hair->num_curves();
}
}
@@ -889,7 +1021,7 @@ void GeometryManager::device_update_mesh(
* really use same semantic of arrays.
*/
foreach (Geometry *geom, scene->geometry) {
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
for (size_t i = 0; i < mesh->num_triangles(); ++i) {
tri_prim_index[i + mesh->prim_offset] = 3 * (i + mesh->prim_offset);
@@ -917,7 +1049,7 @@ void GeometryManager::device_update_mesh(
float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size);
foreach (Geometry *geom, scene->geometry) {
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]);
mesh->pack_normals(&vnormal[mesh->vert_offset]);
@@ -949,7 +1081,7 @@ void GeometryManager::device_update_mesh(
float4 *curves = dscene->curves.alloc(curve_size);
foreach (Geometry *geom, scene->geometry) {
- if (geom->type == Geometry::HAIR) {
+ if (geom->is_hair()) {
Hair *hair = static_cast<Hair *>(geom);
hair->pack_curves(scene,
&curve_keys[hair->curvekey_offset],
@@ -970,7 +1102,7 @@ void GeometryManager::device_update_mesh(
uint *patch_data = dscene->patches.alloc(patch_size);
foreach (Geometry *geom, scene->geometry) {
- if (geom->type == Geometry::MESH) {
+ if (geom->is_mesh()) {
Mesh *mesh = static_cast<Mesh *>(geom);
mesh->pack_patches(&patch_data[mesh->patch_offset],
mesh->vert_offset,
@@ -993,7 +1125,7 @@ void GeometryManager::device_update_mesh(
if (for_displacement) {
float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3);
foreach (Geometry *geom, scene->geometry) {
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
Mesh *mesh = static_cast<Mesh *>(geom);
for (size_t i = 0; i < mesh->num_triangles(); ++i) {
Mesh::Triangle t = mesh->get_triangle(i);
@@ -1120,7 +1252,8 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
foreach (Geometry *geom, scene->geometry) {
geom->has_volume = false;
- foreach (const Shader *shader, geom->used_shaders) {
+ foreach (Node *node, geom->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
if (shader->has_volume) {
geom->has_volume = true;
}
@@ -1132,7 +1265,7 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
/* Re-create volume mesh if we will rebuild or refit the BVH. Note we
* should only do it in that case, otherwise the BVH and mesh can go
* out of sync. */
- if (geom->need_update && geom->type == Geometry::VOLUME) {
+ if (geom->is_modified() && geom->geometry_type == Geometry::VOLUME) {
/* Create volume meshes if there is voxel data. */
if (!volume_images_updated) {
progress.set_status("Updating Meshes Volume Bounds");
@@ -1144,7 +1277,7 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
create_volume_mesh(volume, progress);
}
- if (geom->type == Geometry::HAIR) {
+ if (geom->is_hair()) {
/* Set curve shape, still a global scene setting for now. */
Hair *hair = static_cast<Hair *>(geom);
hair->curve_shape = scene->params.hair_shape;
@@ -1163,9 +1296,10 @@ void GeometryManager::device_update_displacement_images(Device *device,
ImageManager *image_manager = scene->image_manager;
set<int> bump_images;
foreach (Geometry *geom, scene->geometry) {
- if (geom->need_update) {
- foreach (Shader *shader, geom->used_shaders) {
- if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ if (geom->is_modified()) {
+ foreach (Node *node, geom->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
+ if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) {
continue;
}
foreach (ShaderNode *node, shader->graph->nodes) {
@@ -1199,7 +1333,7 @@ void GeometryManager::device_update_volume_images(Device *device, Scene *scene,
set<int> volume_images;
foreach (Geometry *geom, scene->geometry) {
- if (!geom->need_update) {
+ if (!geom->is_modified()) {
continue;
}
@@ -1248,12 +1382,14 @@ void GeometryManager::device_update(Device *device,
});
foreach (Geometry *geom, scene->geometry) {
- foreach (Shader *shader, geom->used_shaders) {
+ foreach (Node *node, geom->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
if (shader->need_update_geometry)
- geom->need_update = true;
+ geom->tag_modified();
}
- if (geom->need_update && (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME)) {
+ if (geom->is_modified() &&
+ (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME)) {
Mesh *mesh = static_cast<Mesh *>(geom);
/* Update normals. */
@@ -1265,8 +1401,7 @@ void GeometryManager::device_update(Device *device,
}
/* Test if we need tessellation. */
- if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 &&
- mesh->subd_params) {
+ if (mesh->need_tesselation()) {
total_tess_needed++;
}
@@ -1291,17 +1426,18 @@ void GeometryManager::device_update(Device *device,
});
Camera *dicing_camera = scene->dicing_camera;
+ dicing_camera->set_screen_size_and_resolution(
+ dicing_camera->get_full_width(), dicing_camera->get_full_height(), 1);
dicing_camera->update(scene);
size_t i = 0;
foreach (Geometry *geom, scene->geometry) {
- if (!(geom->need_update && geom->type == Geometry::MESH)) {
+ if (!(geom->is_modified() && geom->is_mesh())) {
continue;
}
Mesh *mesh = static_cast<Mesh *>(geom);
- if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 &&
- mesh->subd_params) {
+ if (mesh->need_tesselation()) {
string msg = "Tessellating ";
if (mesh->name == "")
msg += string_printf("%u/%u", (uint)(i + 1), (uint)total_tess_needed);
@@ -1378,8 +1514,8 @@ void GeometryManager::device_update(Device *device,
});
foreach (Geometry *geom, scene->geometry) {
- if (geom->need_update) {
- if (geom->type == Geometry::MESH) {
+ if (geom->is_modified()) {
+ if (geom->is_mesh()) {
Mesh *mesh = static_cast<Mesh *>(geom);
if (displace(device, dscene, scene, mesh, progress)) {
displacement_done = true;
@@ -1421,7 +1557,7 @@ void GeometryManager::device_update(Device *device,
size_t i = 0;
foreach (Geometry *geom, scene->geometry) {
- if (geom->need_update) {
+ if (geom->is_modified()) {
pool.push(function_bind(
&Geometry::compute_bvh, geom, device, dscene, &scene->params, &progress, i, num_bvh));
if (geom->need_build_bvh(bvh_layout)) {
diff --git a/intern/cycles/render/geometry.h b/intern/cycles/render/geometry.h
index bcadb3a8051..1c101540464 100644
--- a/intern/cycles/render/geometry.h
+++ b/intern/cycles/render/geometry.h
@@ -56,13 +56,13 @@ class Geometry : public Node {
VOLUME,
};
- Type type;
+ Type geometry_type;
/* Attributes */
AttributeSet attributes;
/* Shaders */
- vector<Shader *> used_shaders;
+ NODE_SOCKET_API_ARRAY(array<Node *>, used_shaders)
/* Transform */
BoundBox bounds;
@@ -71,8 +71,8 @@ class Geometry : public Node {
Transform transform_normal;
/* Motion Blur */
- uint motion_steps;
- bool use_motion_blur;
+ NODE_SOCKET_API(uint, motion_steps)
+ NODE_SOCKET_API(bool, use_motion_blur)
/* Maximum number of motion steps supported (due to Embree). */
static const uint MAX_MOTION_STEPS = 129;
@@ -88,15 +88,17 @@ class Geometry : public Node {
bool has_surface_bssrdf; /* Set in the device_update_flags(). */
/* Update Flags */
- bool need_update;
bool need_update_rebuild;
+ /* Index into scene->geometry (only valid during update) */
+ size_t index;
+
/* Constructor/Destructor */
explicit Geometry(const NodeType *node_type, const Type type);
virtual ~Geometry();
/* Geometry */
- virtual void clear();
+ virtual void clear(bool preserve_shaders = false);
virtual void compute_bounds() = 0;
virtual void apply_transform(const Transform &tfm, const bool apply_to_motion) = 0;
@@ -104,6 +106,8 @@ class Geometry : public Node {
bool need_attribute(Scene *scene, AttributeStandard std);
bool need_attribute(Scene *scene, ustring name);
+ AttributeRequestSet needed_attributes();
+
/* UDIM */
virtual void get_uv_tiles(ustring map, unordered_set<int> &tiles) = 0;
@@ -138,6 +142,16 @@ class Geometry : public Node {
bool has_motion_blur() const;
bool has_voxel_attributes() const;
+ bool is_mesh() const
+ {
+ return geometry_type == MESH;
+ }
+
+ bool is_hair() const
+ {
+ return geometry_type == HAIR;
+ }
+
/* Updates */
void tag_update(Scene *scene, bool rebuild);
};
@@ -177,7 +191,8 @@ class GeometryManager {
void update_svm_attributes(Device *device,
DeviceScene *dscene,
Scene *scene,
- vector<AttributeRequestSet> &geom_attributes);
+ vector<AttributeRequestSet> &geom_attributes,
+ vector<AttributeRequestSet> &object_attributes);
/* Compute verts/triangles/curves offsets in global arrays. */
void mesh_calc_offset(Scene *scene);
@@ -200,6 +215,21 @@ class GeometryManager {
void device_update_displacement_images(Device *device, Scene *scene, Progress &progress);
void device_update_volume_images(Device *device, Scene *scene, Progress &progress);
+
+ private:
+ static void update_attribute_element_offset(Geometry *geom,
+ device_vector<float> &attr_float,
+ size_t &attr_float_offset,
+ device_vector<float2> &attr_float2,
+ size_t &attr_float2_offset,
+ device_vector<float4> &attr_float3,
+ size_t &attr_float3_offset,
+ device_vector<uchar4> &attr_uchar4,
+ size_t &attr_uchar4_offset,
+ Attribute *mattr,
+ AttributePrimitive prim,
+ TypeDesc &type,
+ AttributeDescriptor &desc);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 088fda00abb..4adfebf80ae 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -273,8 +273,8 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
if (to->type() == SocketType::CLOSURE) {
EmissionNode *emission = create_node<EmissionNode>();
- emission->color = make_float3(1.0f, 1.0f, 1.0f);
- emission->strength = 1.0f;
+ emission->set_color(make_float3(1.0f, 1.0f, 1.0f));
+ emission->set_strength(1.0f);
convert = add(emission);
/* Connect float inputs to Strength to save an additional Falue->Color conversion. */
if (from->type() == SocketType::FLOAT) {
@@ -586,7 +586,7 @@ void ShaderGraph::constant_fold(Scene *scene)
*/
if (has_displacement && !output()->input("Displacement")->link) {
ColorNode *value = (ColorNode *)add(create_node<ColorNode>());
- value->value = output()->displacement;
+ value->set_value(output()->get_displacement());
connect(value->output("Color"), output()->input("Displacement"));
}
@@ -1004,8 +1004,8 @@ void ShaderGraph::bump_from_displacement(bool use_object_space)
/* add bump node and connect copied graphs to it */
BumpNode *bump = (BumpNode *)add(create_node<BumpNode>());
- bump->use_object_space = use_object_space;
- bump->distance = 1.0f;
+ bump->set_use_object_space(use_object_space);
+ bump->set_distance(1.0f);
ShaderOutput *out = displacement_in->link;
ShaderOutput *out_center = nodes_center[out->parent]->output(out->name());
@@ -1017,9 +1017,9 @@ void ShaderGraph::bump_from_displacement(bool use_object_space)
VectorMathNode *dot_dx = (VectorMathNode *)add(create_node<VectorMathNode>());
VectorMathNode *dot_dy = (VectorMathNode *)add(create_node<VectorMathNode>());
- dot_center->type = NODE_VECTOR_MATH_DOT_PRODUCT;
- dot_dx->type = NODE_VECTOR_MATH_DOT_PRODUCT;
- dot_dy->type = NODE_VECTOR_MATH_DOT_PRODUCT;
+ dot_center->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT);
+ dot_dx->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT);
+ dot_dy->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT);
GeometryNode *geom = (GeometryNode *)add(create_node<GeometryNode>());
connect(geom->output("Normal"), dot_center->input("Vector2"));
@@ -1073,7 +1073,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
if (fin->link)
connect(fin->link, fac_in);
else
- mix_node->fac = node->get_float(fin->socket_type);
+ mix_node->set_fac(node->get_float(fin->socket_type));
if (weight_out)
connect(weight_out, weight_in);
@@ -1108,12 +1108,12 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
if (weight_in->link)
connect(weight_in->link, math_node->input("Value1"));
else
- math_node->value1 = weight_value;
+ math_node->set_value1(weight_value);
if (weight_out)
connect(weight_out, math_node->input("Value2"));
else
- math_node->value2 = 1.0f;
+ math_node->set_value2(1.0f);
weight_out = math_node->output("Value");
if (weight_in->link)
diff --git a/intern/cycles/render/hair.cpp b/intern/cycles/render/hair.cpp
index 816c15cf4ef..d67bd209142 100644
--- a/intern/cycles/render/hair.cpp
+++ b/intern/cycles/render/hair.cpp
@@ -321,9 +321,9 @@ void Hair::reserve_curves(int numcurves, int numkeys)
attributes.resize(true);
}
-void Hair::clear()
+void Hair::clear(bool preserve_shaders)
{
- Geometry::clear();
+ Geometry::clear(preserve_shaders);
curve_keys.clear();
curve_radius.clear();
@@ -337,12 +337,18 @@ void Hair::add_curve_key(float3 co, float radius)
{
curve_keys.push_back_reserved(co);
curve_radius.push_back_reserved(radius);
+
+ tag_curve_keys_modified();
+ tag_curve_radius_modified();
}
void Hair::add_curve(int first_key, int shader)
{
curve_first_key.push_back_reserved(first_key);
curve_shader.push_back_reserved(shader);
+
+ tag_curve_first_key_modified();
+ tag_curve_shader_modified();
}
void Hair::copy_center_to_motion_step(const int motion_step)
@@ -474,8 +480,9 @@ void Hair::pack_curves(Scene *scene,
for (size_t i = 0; i < curve_num; i++) {
Curve curve = get_curve(i);
int shader_id = curve_shader[i];
- Shader *shader = (shader_id < used_shaders.size()) ? used_shaders[shader_id] :
- scene->default_surface;
+ Shader *shader = (shader_id < used_shaders.size()) ?
+ static_cast<Shader *>(used_shaders[shader_id]) :
+ scene->default_surface;
shader_id = scene->shader_manager->get_shader_id(shader, false);
curve_data[i] = make_float4(__int_as_float(curve.first_key + curvekey_offset),
diff --git a/intern/cycles/render/hair.h b/intern/cycles/render/hair.h
index 39d6a34d799..32c5b00e879 100644
--- a/intern/cycles/render/hair.h
+++ b/intern/cycles/render/hair.h
@@ -89,10 +89,10 @@ class Hair : public Geometry {
float4 r_keys[4]) const;
};
- array<float3> curve_keys;
- array<float> curve_radius;
- array<int> curve_first_key;
- array<int> curve_shader;
+ NODE_SOCKET_API(array<float3>, curve_keys)
+ NODE_SOCKET_API(array<float>, curve_radius)
+ NODE_SOCKET_API(array<int>, curve_first_key)
+ NODE_SOCKET_API(array<int>, curve_shader)
/* BVH */
size_t curvekey_offset;
@@ -103,7 +103,7 @@ class Hair : public Geometry {
~Hair();
/* Geometry */
- void clear() override;
+ void clear(bool preserve_shaders = false) override;
void resize_curves(int numcurves, int numkeys);
void reserve_curves(int numcurves, int numkeys);
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index e50e70c8591..3e6ff289c85 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -381,7 +381,7 @@ ImageHandle ImageManager::add_image(const string &filename, const ImageParams &p
ImageHandle ImageManager::add_image(const string &filename,
const ImageParams &params,
- const vector<int> &tiles)
+ const array<int> &tiles)
{
ImageHandle handle;
handle.manager = this;
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index c9eccb3468a..6ac1db9ed63 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -174,7 +174,7 @@ class ImageManager {
ImageHandle add_image(const string &filename, const ImageParams &params);
ImageHandle add_image(const string &filename,
const ImageParams &params,
- const vector<int> &tiles);
+ const array<int> &tiles);
ImageHandle add_image(ImageLoader *loader, const ImageParams &params, const bool builtin = true);
void device_update(Device *device, Scene *scene, Progress &progress);
diff --git a/intern/cycles/render/image_vdb.cpp b/intern/cycles/render/image_vdb.cpp
index fc2cfe9874e..5d0999d5623 100644
--- a/intern/cycles/render/image_vdb.cpp
+++ b/intern/cycles/render/image_vdb.cpp
@@ -144,8 +144,12 @@ bool VDBImageLoader::load_metadata(ImageMetaData &metadata)
}
}
+# ifdef WITH_NANOVDB
+ Transform texture_to_index = transform_identity();
+# else
Transform texture_to_index = transform_translate(min.x(), min.y(), min.z()) *
transform_scale(dim.x(), dim.y(), dim.z());
+# endif
metadata.transform_3d = transform_inverse(index_to_object * texture_to_index);
metadata.use_transform_3d = true;
@@ -159,10 +163,10 @@ bool VDBImageLoader::load_metadata(ImageMetaData &metadata)
bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size_t, const bool)
{
-#if defined(WITH_NANOVDB)
+#ifdef WITH_OPENVDB
+# ifdef WITH_NANOVDB
memcpy(pixels, nanogrid.data(), nanogrid.size());
- return true;
-#elif defined(WITH_OPENVDB)
+# else
if (grid->isType<openvdb::FloatGrid>()) {
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense);
@@ -202,7 +206,7 @@ bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense);
}
-
+# endif
return true;
#else
(void)pixels;
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index cc085af20a0..3dc4b2fd4c5 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -96,7 +96,6 @@ NODE_DEFINE(Integrator)
Integrator::Integrator() : Node(node_type)
{
- need_update = true;
}
Integrator::~Integrator()
@@ -105,7 +104,7 @@ Integrator::~Integrator()
void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
- if (!need_update)
+ if (!is_modified())
return;
scoped_callback_timer timer([scene](double time) {
@@ -144,7 +143,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->transparent_shadows = false;
foreach (Shader *shader, scene->shaders) {
/* keep this in sync with SD_HAS_TRANSPARENT_SHADOW in shader.cpp */
- if ((shader->has_surface_transparent && shader->use_transparent_shadow) ||
+ if ((shader->has_surface_transparent && shader->get_use_transparent_shadow()) ||
shader->has_volume) {
kintegrator->transparent_shadows = true;
break;
@@ -227,7 +226,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
if (method == BRANCHED_PATH) {
foreach (Light *light, scene->lights)
- max_samples = max(max_samples, light->samples);
+ max_samples = max(max_samples, light->get_samples());
max_samples = max(max_samples,
max(diffuse_samples, max(glossy_samples, transmission_samples)));
@@ -265,7 +264,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
dscene->sample_pattern_lut.copy_to_device();
}
- need_update = false;
+ clear_modified();
}
void Integrator::device_free(Device *, DeviceScene *dscene)
@@ -273,11 +272,6 @@ void Integrator::device_free(Device *, DeviceScene *dscene)
dscene->sample_pattern_lut.free();
}
-bool Integrator::modified(const Integrator &integrator)
-{
- return !Node::equals(integrator);
-}
-
void Integrator::tag_update(Scene *scene)
{
foreach (Shader *shader, scene->shaders) {
@@ -286,7 +280,7 @@ void Integrator::tag_update(Scene *scene)
break;
}
}
- need_update = true;
+ tag_modified();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index 9804caebe6e..9fe46ad591c 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -31,52 +31,52 @@ class Integrator : public Node {
public:
NODE_DECLARE
- int min_bounce;
- int max_bounce;
+ NODE_SOCKET_API(int, min_bounce)
+ NODE_SOCKET_API(int, max_bounce)
- int max_diffuse_bounce;
- int max_glossy_bounce;
- int max_transmission_bounce;
- int max_volume_bounce;
+ NODE_SOCKET_API(int, max_diffuse_bounce)
+ NODE_SOCKET_API(int, max_glossy_bounce)
+ NODE_SOCKET_API(int, max_transmission_bounce)
+ NODE_SOCKET_API(int, max_volume_bounce)
- int transparent_min_bounce;
- int transparent_max_bounce;
+ NODE_SOCKET_API(int, transparent_min_bounce)
+ NODE_SOCKET_API(int, transparent_max_bounce)
- int ao_bounces;
+ NODE_SOCKET_API(int, ao_bounces)
- int volume_max_steps;
- float volume_step_rate;
+ NODE_SOCKET_API(int, volume_max_steps)
+ NODE_SOCKET_API(float, volume_step_rate)
- bool caustics_reflective;
- bool caustics_refractive;
- float filter_glossy;
+ NODE_SOCKET_API(bool, caustics_reflective)
+ NODE_SOCKET_API(bool, caustics_refractive)
+ NODE_SOCKET_API(float, filter_glossy)
- int seed;
+ NODE_SOCKET_API(int, seed)
- float sample_clamp_direct;
- float sample_clamp_indirect;
- bool motion_blur;
+ NODE_SOCKET_API(float, sample_clamp_direct)
+ NODE_SOCKET_API(float, sample_clamp_indirect)
+ NODE_SOCKET_API(bool, motion_blur)
/* Maximum number of samples, beyond which we are likely to run into
* precision issues for sampling patterns. */
static const int MAX_SAMPLES = (1 << 24);
- int aa_samples;
- int diffuse_samples;
- int glossy_samples;
- int transmission_samples;
- int ao_samples;
- int mesh_light_samples;
- int subsurface_samples;
- int volume_samples;
- int start_sample;
+ NODE_SOCKET_API(int, aa_samples)
+ NODE_SOCKET_API(int, diffuse_samples)
+ NODE_SOCKET_API(int, glossy_samples)
+ NODE_SOCKET_API(int, transmission_samples)
+ NODE_SOCKET_API(int, ao_samples)
+ NODE_SOCKET_API(int, mesh_light_samples)
+ NODE_SOCKET_API(int, subsurface_samples)
+ NODE_SOCKET_API(int, volume_samples)
+ NODE_SOCKET_API(int, start_sample)
- bool sample_all_lights_direct;
- bool sample_all_lights_indirect;
- float light_sampling_threshold;
+ NODE_SOCKET_API(bool, sample_all_lights_direct)
+ NODE_SOCKET_API(bool, sample_all_lights_indirect)
+ NODE_SOCKET_API(float, light_sampling_threshold)
- int adaptive_min_samples;
- float adaptive_threshold;
+ NODE_SOCKET_API(int, adaptive_min_samples)
+ NODE_SOCKET_API(float, adaptive_threshold)
enum Method {
BRANCHED_PATH = 0,
@@ -85,11 +85,9 @@ class Integrator : public Node {
NUM_METHODS,
};
- Method method;
+ NODE_SOCKET_API(Method, method)
- SamplingPattern sampling_pattern;
-
- bool need_update;
+ NODE_SOCKET_API(SamplingPattern, sampling_pattern)
Integrator();
~Integrator();
@@ -97,7 +95,6 @@ class Integrator : public Node {
void device_update(Device *device, DeviceScene *dscene, Scene *scene);
void device_free(Device *device, DeviceScene *dscene);
- bool modified(const Integrator &integrator);
void tag_update(Scene *scene);
};
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 100530ffba6..80190dcbf82 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -114,7 +114,7 @@ NODE_DEFINE(Light)
type_enum.insert("background", LIGHT_BACKGROUND);
type_enum.insert("area", LIGHT_AREA);
type_enum.insert("spot", LIGHT_SPOT);
- SOCKET_ENUM(type, "Type", type_enum, LIGHT_POINT);
+ SOCKET_ENUM(light_type, "Type", type_enum, LIGHT_POINT);
SOCKET_COLOR(strength, "Strength", make_float3(1.0f, 1.0f, 1.0f));
@@ -162,7 +162,7 @@ Light::Light() : Node(node_type)
void Light::tag_update(Scene *scene)
{
- scene->light_manager->need_update = true;
+ scene->light_manager->need_update = is_modified();
}
bool Light::has_contribution(Scene *scene)
@@ -173,7 +173,7 @@ bool Light::has_contribution(Scene *scene)
if (is_portal) {
return false;
}
- if (type == LIGHT_BACKGROUND) {
+ if (light_type == LIGHT_BACKGROUND) {
return true;
}
return (shader) ? shader->has_surface_emission : scene->default_light->has_surface_emission;
@@ -200,7 +200,7 @@ LightManager::~LightManager()
bool LightManager::has_background_light(Scene *scene)
{
foreach (Light *light, scene->lights) {
- if (light->type == LIGHT_BACKGROUND && light->is_enabled) {
+ if (light->light_type == LIGHT_BACKGROUND && light->is_enabled) {
return true;
}
}
@@ -217,7 +217,7 @@ void LightManager::test_enabled_lights(Scene *scene)
foreach (Light *light, scene->lights) {
light->is_enabled = light->has_contribution(scene);
has_portal |= light->is_portal;
- has_background |= light->type == LIGHT_BACKGROUND;
+ has_background |= light->light_type == LIGHT_BACKGROUND;
}
bool background_enabled = false;
@@ -232,7 +232,7 @@ void LightManager::test_enabled_lights(Scene *scene)
const bool disable_mis = !(has_portal || shader->has_surface_spatial_varying);
VLOG_IF(1, disable_mis) << "Background MIS has been disabled.\n";
foreach (Light *light, scene->lights) {
- if (light->type == LIGHT_BACKGROUND) {
+ if (light->light_type == LIGHT_BACKGROUND) {
light->is_enabled = !disable_mis;
background_enabled = !disable_mis;
background_resolution = light->map_resolution;
@@ -250,8 +250,8 @@ void LightManager::test_enabled_lights(Scene *scene)
bool LightManager::object_usable_as_light(Object *object)
{
- Geometry *geom = object->geometry;
- if (geom->type != Geometry::MESH && geom->type != Geometry::VOLUME) {
+ Geometry *geom = object->get_geometry();
+ if (geom->geometry_type != Geometry::MESH && geom->geometry_type != Geometry::VOLUME) {
return false;
}
/* Skip objects with NaNs */
@@ -259,7 +259,7 @@ bool LightManager::object_usable_as_light(Object *object)
return false;
}
/* Skip if we are not visible for BSDFs. */
- if (!(object->visibility & (PATH_RAY_DIFFUSE | PATH_RAY_GLOSSY | PATH_RAY_TRANSMIT))) {
+ if (!(object->get_visibility() & (PATH_RAY_DIFFUSE | PATH_RAY_GLOSSY | PATH_RAY_TRANSMIT))) {
return false;
}
/* Skip if we have no emission shaders. */
@@ -267,8 +267,9 @@ bool LightManager::object_usable_as_light(Object *object)
* iterate all geometry shaders twice (when counting and when calculating
* triangle area.
*/
- foreach (const Shader *shader, geom->used_shaders) {
- if (shader->use_mis && shader->has_surface_emission) {
+ foreach (Node *node, geom->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
+ if (shader->get_use_mis() && shader->has_surface_emission) {
return true;
}
}
@@ -308,15 +309,15 @@ void LightManager::device_update_distribution(Device *,
}
/* Count triangles. */
- Mesh *mesh = static_cast<Mesh *>(object->geometry);
+ Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
size_t mesh_num_triangles = mesh->num_triangles();
for (size_t i = 0; i < mesh_num_triangles; i++) {
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] :
+ int shader_index = mesh->get_shader()[i];
+ Shader *shader = (shader_index < mesh->get_used_shaders().size()) ?
+ static_cast<Shader *>(mesh->get_used_shaders()[shader_index]) :
scene->default_surface;
- if (shader->use_mis && shader->has_surface_emission) {
+ if (shader->get_use_mis() && shader->has_surface_emission) {
num_triangles++;
}
}
@@ -342,37 +343,37 @@ void LightManager::device_update_distribution(Device *,
continue;
}
/* Sum area. */
- Mesh *mesh = static_cast<Mesh *>(object->geometry);
+ Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
bool transform_applied = mesh->transform_applied;
- Transform tfm = object->tfm;
+ Transform tfm = object->get_tfm();
int object_id = j;
int shader_flag = 0;
- if (!(object->visibility & PATH_RAY_DIFFUSE)) {
+ if (!(object->get_visibility() & PATH_RAY_DIFFUSE)) {
shader_flag |= SHADER_EXCLUDE_DIFFUSE;
use_light_visibility = true;
}
- if (!(object->visibility & PATH_RAY_GLOSSY)) {
+ if (!(object->get_visibility() & PATH_RAY_GLOSSY)) {
shader_flag |= SHADER_EXCLUDE_GLOSSY;
use_light_visibility = true;
}
- if (!(object->visibility & PATH_RAY_TRANSMIT)) {
+ if (!(object->get_visibility() & PATH_RAY_TRANSMIT)) {
shader_flag |= SHADER_EXCLUDE_TRANSMIT;
use_light_visibility = true;
}
- if (!(object->visibility & PATH_RAY_VOLUME_SCATTER)) {
+ if (!(object->get_visibility() & PATH_RAY_VOLUME_SCATTER)) {
shader_flag |= SHADER_EXCLUDE_SCATTER;
use_light_visibility = true;
}
size_t mesh_num_triangles = mesh->num_triangles();
for (size_t i = 0; i < mesh_num_triangles; i++) {
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] :
+ int shader_index = mesh->get_shader()[i];
+ Shader *shader = (shader_index < mesh->get_used_shaders().size()) ?
+ static_cast<Shader *>(mesh->get_used_shaders()[shader_index]) :
scene->default_surface;
- if (shader->use_mis && shader->has_surface_emission) {
+ if (shader->get_use_mis() && shader->has_surface_emission) {
distribution[offset].totarea = totarea;
distribution[offset].prim = i + mesh->prim_offset;
distribution[offset].mesh_light.shader_flag = shader_flag;
@@ -380,12 +381,12 @@ void LightManager::device_update_distribution(Device *,
offset++;
Mesh::Triangle t = mesh->get_triangle(i);
- if (!t.valid(&mesh->verts[0])) {
+ if (!t.valid(&mesh->get_verts()[0])) {
continue;
}
- float3 p1 = mesh->verts[t.v[0]];
- float3 p2 = mesh->verts[t.v[1]];
- float3 p3 = mesh->verts[t.v[2]];
+ float3 p1 = mesh->get_verts()[t.v[0]];
+ float3 p2 = mesh->get_verts()[t.v[1]];
+ float3 p3 = mesh->get_verts()[t.v[2]];
if (!transform_applied) {
p1 = transform_point(&tfm, p1);
@@ -417,16 +418,16 @@ void LightManager::device_update_distribution(Device *,
distribution[offset].lamp.size = light->size;
totarea += lightarea;
- if (light->type == LIGHT_DISTANT) {
+ if (light->light_type == LIGHT_DISTANT) {
use_lamp_mis |= (light->angle > 0.0f && light->use_mis);
}
- else if (light->type == LIGHT_POINT || light->type == LIGHT_SPOT) {
+ else if (light->light_type == LIGHT_POINT || light->light_type == LIGHT_SPOT) {
use_lamp_mis |= (light->size > 0.0f && light->use_mis);
}
- else if (light->type == LIGHT_AREA) {
+ else if (light->light_type == LIGHT_AREA) {
use_lamp_mis |= light->use_mis;
}
- else if (light->type == LIGHT_BACKGROUND) {
+ else if (light->light_type == LIGHT_BACKGROUND) {
num_background_lights++;
background_mis |= light->use_mis;
}
@@ -576,7 +577,7 @@ void LightManager::device_update_background(Device *device,
/* find background light */
foreach (Light *light, scene->lights) {
- if (light->type == LIGHT_BACKGROUND) {
+ if (light->light_type == LIGHT_BACKGROUND) {
background_light = light;
break;
}
@@ -611,7 +612,7 @@ void LightManager::device_update_background(Device *device,
}
if (node->type == SkyTextureNode::node_type) {
SkyTextureNode *sky = (SkyTextureNode *)node;
- if (sky->type == NODE_SKY_NISHITA && sky->sun_disc) {
+ if (sky->get_sky_type() == NODE_SKY_NISHITA && sky->get_sun_disc()) {
/* Ensure that the input coordinates aren't transformed before they reach the node.
* If that is the case, the logic used for sampling the sun's location does not work
* and we have to fall back to map-based sampling. */
@@ -627,8 +628,8 @@ 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;
+ float latitude = sky->get_sun_elevation();
+ float longitude = M_2PI_F - sky->get_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());
@@ -771,13 +772,13 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
use_light_visibility = true;
}
- klights[light_index].type = light->type;
+ klights[light_index].type = light->light_type;
klights[light_index].samples = light->samples;
klights[light_index].strength[0] = light->strength.x;
klights[light_index].strength[1] = light->strength.y;
klights[light_index].strength[2] = light->strength.z;
- if (light->type == LIGHT_POINT) {
+ if (light->light_type == LIGHT_POINT) {
shader_id &= ~SHADER_AREA_LIGHT;
float radius = light->size;
@@ -793,7 +794,7 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
klights[light_index].spot.radius = radius;
klights[light_index].spot.invarea = invarea;
}
- else if (light->type == LIGHT_DISTANT) {
+ else if (light->light_type == LIGHT_DISTANT) {
shader_id &= ~SHADER_AREA_LIGHT;
float angle = light->angle / 2.0f;
@@ -816,8 +817,8 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
klights[light_index].distant.radius = radius;
klights[light_index].distant.cosangle = cosangle;
}
- else if (light->type == LIGHT_BACKGROUND) {
- uint visibility = scene->background->visibility;
+ else if (light->light_type == LIGHT_BACKGROUND) {
+ uint visibility = scene->background->get_visibility();
shader_id &= ~SHADER_AREA_LIGHT;
shader_id |= SHADER_USE_MIS;
@@ -839,7 +840,7 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
use_light_visibility = true;
}
}
- else if (light->type == LIGHT_AREA) {
+ else if (light->light_type == LIGHT_AREA) {
float3 axisu = light->axisu * (light->sizeu * light->size);
float3 axisv = light->axisv * (light->sizev * light->size);
float area = len(axisu) * len(axisv);
@@ -869,7 +870,7 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
klights[light_index].area.dir[1] = dir.y;
klights[light_index].area.dir[2] = dir.z;
}
- else if (light->type == LIGHT_SPOT) {
+ else if (light->light_type == LIGHT_SPOT) {
shader_id &= ~SHADER_AREA_LIGHT;
float radius = light->size;
@@ -913,7 +914,7 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
foreach (Light *light, scene->lights) {
if (!light->is_portal)
continue;
- assert(light->type == LIGHT_AREA);
+ assert(light->light_type == LIGHT_AREA);
float3 co = light->co;
float3 axisu = light->axisu * (light->sizeu * light->size);
@@ -995,10 +996,7 @@ void LightManager::device_update(Device *device,
if (progress.get_cancel())
return;
- if (use_light_visibility != scene->film->use_light_visibility) {
- scene->film->use_light_visibility = use_light_visibility;
- scene->film->tag_update(scene);
- }
+ scene->film->set_use_light_visibility(use_light_visibility);
need_update = false;
need_update_background = false;
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index d136e8f1a08..e590e13b489 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -21,6 +21,10 @@
#include "graph/node.h"
+/* included as Light::set_shader defined through NODE_SOCKET_API does not select
+ * the right Node::set overload as it does not know that Shader is a Node */
+#include "render/shader.h"
+
#include "util/util_ies.h"
#include "util/util_thread.h"
#include "util/util_types.h"
@@ -41,46 +45,48 @@ class Light : public Node {
Light();
- LightType type;
- float3 strength;
- float3 co;
+ NODE_SOCKET_API(LightType, light_type)
+ NODE_SOCKET_API(float3, strength)
+ NODE_SOCKET_API(float3, co)
- float3 dir;
- float size;
- float angle;
+ NODE_SOCKET_API(float3, dir)
+ NODE_SOCKET_API(float, size)
+ NODE_SOCKET_API(float, angle)
- float3 axisu;
- float sizeu;
- float3 axisv;
- float sizev;
- bool round;
+ NODE_SOCKET_API(float3, axisu)
+ NODE_SOCKET_API(float, sizeu)
+ NODE_SOCKET_API(float3, axisv)
+ NODE_SOCKET_API(float, sizev)
+ NODE_SOCKET_API(bool, round)
- Transform tfm;
+ NODE_SOCKET_API(Transform, tfm)
- int map_resolution;
+ NODE_SOCKET_API(int, map_resolution)
- float spot_angle;
- float spot_smooth;
+ NODE_SOCKET_API(float, spot_angle)
+ NODE_SOCKET_API(float, spot_smooth)
- bool cast_shadow;
- bool use_mis;
- bool use_diffuse;
- bool use_glossy;
- bool use_transmission;
- bool use_scatter;
+ NODE_SOCKET_API(bool, cast_shadow)
+ NODE_SOCKET_API(bool, use_mis)
+ NODE_SOCKET_API(bool, use_diffuse)
+ NODE_SOCKET_API(bool, use_glossy)
+ NODE_SOCKET_API(bool, use_transmission)
+ NODE_SOCKET_API(bool, use_scatter)
- bool is_portal;
- bool is_enabled;
+ NODE_SOCKET_API(bool, is_portal)
+ NODE_SOCKET_API(bool, is_enabled)
- Shader *shader;
- int samples;
- int max_bounces;
- uint random_id;
+ NODE_SOCKET_API(Shader *, shader)
+ NODE_SOCKET_API(int, samples)
+ NODE_SOCKET_API(int, max_bounces)
+ NODE_SOCKET_API(uint, random_id)
void tag_update(Scene *scene);
/* Check whether the light has contribution the scene. */
bool has_contribution(Scene *scene);
+
+ friend class LightManager;
};
class LightManager {
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 3015ac5e569..11c8e240afd 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -132,11 +132,58 @@ NODE_DEFINE(Mesh)
SOCKET_INT_ARRAY(shader, "Shader", array<int>());
SOCKET_BOOLEAN_ARRAY(smooth, "Smooth", array<bool>());
+ SOCKET_INT_ARRAY(triangle_patch, "Triangle Patch", array<int>());
+ SOCKET_POINT2_ARRAY(vert_patch_uv, "Patch UVs", array<float2>());
+
+ static NodeEnum subdivision_type_enum;
+ subdivision_type_enum.insert("none", SUBDIVISION_NONE);
+ subdivision_type_enum.insert("linear", SUBDIVISION_LINEAR);
+ subdivision_type_enum.insert("catmull_clark", SUBDIVISION_CATMULL_CLARK);
+ SOCKET_ENUM(subdivision_type, "Subdivision Type", subdivision_type_enum, SUBDIVISION_NONE);
+
+ SOCKET_INT_ARRAY(subd_creases_edge, "Subdivision Crease Edges", array<int>());
+ SOCKET_FLOAT_ARRAY(subd_creases_weight, "Subdivision Crease Weights", array<float>());
+ SOCKET_INT_ARRAY(subd_face_corners, "Subdivision Face Corners", array<int>());
+ SOCKET_INT_ARRAY(subd_start_corner, "Subdivision Face Start Corner", array<int>());
+ SOCKET_INT_ARRAY(subd_num_corners, "Subdivision Face Corner Count", array<int>());
+ SOCKET_INT_ARRAY(subd_shader, "Subdivision Face Shader", array<int>());
+ SOCKET_BOOLEAN_ARRAY(subd_smooth, "Subdivision Face Smooth", array<bool>());
+ SOCKET_INT_ARRAY(subd_ptex_offset, "Subdivision Face PTex Offset", array<int>());
+ SOCKET_INT(num_ngons, "NGons Number", 0);
+
+ /* Subdivisions parameters */
+ SOCKET_FLOAT(subd_dicing_rate, "Subdivision Dicing Rate", 0.0f)
+ SOCKET_INT(subd_max_level, "Subdivision Dicing Rate", 0);
+ SOCKET_TRANSFORM(subd_objecttoworld, "Subdivision Object Transform", transform_identity());
+
return type;
}
-Mesh::Mesh(const NodeType *node_type_, Type geom_type_)
- : Geometry(node_type_, geom_type_), subd_attributes(this, ATTR_PRIM_SUBD)
+SubdParams *Mesh::get_subd_params()
+{
+ if (subdivision_type == SubdivisionType::SUBDIVISION_NONE) {
+ return nullptr;
+ }
+
+ if (!subd_params) {
+ subd_params = new SubdParams(this);
+ }
+
+ subd_params->dicing_rate = subd_dicing_rate;
+ subd_params->max_level = subd_max_level;
+ subd_params->objecttoworld = subd_objecttoworld;
+
+ return subd_params;
+}
+
+bool Mesh::need_tesselation()
+{
+ return get_subd_params() && (verts_is_modified() || subd_dicing_rate_is_modified() ||
+ subd_objecttoworld_is_modified() || subd_max_level_is_modified());
+}
+
+Mesh::Mesh(const NodeType *node_type, Type geom_type_)
+ : Geometry(node_type, geom_type_), subd_attributes(this, ATTR_PRIM_SUBD)
{
vert_offset = 0;
@@ -145,6 +192,7 @@ Mesh::Mesh(const NodeType *node_type_, Type geom_type_)
corner_offset = 0;
num_subd_verts = 0;
+ num_subd_faces = 0;
num_ngons = 0;
@@ -171,7 +219,7 @@ void Mesh::resize_mesh(int numverts, int numtris)
shader.resize(numtris);
smooth.resize(numtris);
- if (subd_faces.size()) {
+ if (get_num_subd_faces()) {
triangle_patch.resize(numtris);
vert_patch_uv.resize(numverts);
}
@@ -187,7 +235,7 @@ void Mesh::reserve_mesh(int numverts, int numtris)
shader.reserve(numtris);
smooth.reserve(numtris);
- if (subd_faces.size()) {
+ if (get_num_subd_faces()) {
triangle_patch.reserve(numtris);
vert_patch_uv.reserve(numverts);
}
@@ -197,25 +245,41 @@ void Mesh::reserve_mesh(int numverts, int numtris)
void Mesh::resize_subd_faces(int numfaces, int num_ngons_, int numcorners)
{
- subd_faces.resize(numfaces);
+ subd_start_corner.resize(numfaces);
+ subd_num_corners.resize(numfaces);
+ subd_shader.resize(numfaces);
+ subd_smooth.resize(numfaces);
+ subd_ptex_offset.resize(numfaces);
subd_face_corners.resize(numcorners);
num_ngons = num_ngons_;
+ num_subd_faces = numfaces;
subd_attributes.resize();
}
void Mesh::reserve_subd_faces(int numfaces, int num_ngons_, int numcorners)
{
- subd_faces.reserve(numfaces);
+ subd_start_corner.reserve(numfaces);
+ subd_num_corners.reserve(numfaces);
+ subd_shader.reserve(numfaces);
+ subd_smooth.reserve(numfaces);
+ subd_ptex_offset.reserve(numfaces);
subd_face_corners.reserve(numcorners);
num_ngons = num_ngons_;
+ num_subd_faces = numfaces;
subd_attributes.resize(true);
}
-void Mesh::clear(bool preserve_voxel_data)
+void Mesh::reserve_subd_creases(size_t num_creases)
{
- Geometry::clear();
+ subd_creases_edge.reserve(num_creases * 2);
+ subd_creases_weight.reserve(num_creases);
+}
+
+void Mesh::clear(bool preserve_shaders, bool preserve_voxel_data)
+{
+ Geometry::clear(preserve_shaders);
/* clear all verts and triangles */
verts.clear();
@@ -226,12 +290,18 @@ void Mesh::clear(bool preserve_voxel_data)
triangle_patch.clear();
vert_patch_uv.clear();
- subd_faces.clear();
+ subd_start_corner.clear();
+ subd_num_corners.clear();
+ subd_shader.clear();
+ subd_smooth.clear();
+ subd_ptex_offset.clear();
subd_face_corners.clear();
num_subd_verts = 0;
+ num_subd_faces = 0;
- subd_creases.clear();
+ subd_creases_edge.clear();
+ subd_creases_weight.clear();
subd_attributes.clear();
attributes.clear(preserve_voxel_data);
@@ -239,30 +309,36 @@ void Mesh::clear(bool preserve_voxel_data)
vert_to_stitching_key_map.clear();
vert_stitching_map.clear();
+ subdivision_type = SubdivisionType::SUBDIVISION_NONE;
+
delete patch_table;
patch_table = NULL;
}
-void Mesh::clear()
+void Mesh::clear(bool preserve_shaders)
{
- clear(false);
+ clear(preserve_shaders, false);
}
void Mesh::add_vertex(float3 P)
{
verts.push_back_reserved(P);
+ tag_verts_modified();
- if (subd_faces.size()) {
+ if (get_num_subd_faces()) {
vert_patch_uv.push_back_reserved(make_float2(0.0f, 0.0f));
+ tag_vert_patch_uv_modified();
}
}
void Mesh::add_vertex_slow(float3 P)
{
verts.push_back_slow(P);
+ tag_verts_modified();
- if (subd_faces.size()) {
+ if (get_num_subd_faces()) {
vert_patch_uv.push_back_slow(make_float2(0.0f, 0.0f));
+ tag_vert_patch_uv_modified();
}
}
@@ -274,8 +350,13 @@ void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
shader.push_back_reserved(shader_);
smooth.push_back_reserved(smooth_);
- if (subd_faces.size()) {
+ tag_triangles_modified();
+ tag_shader_modified();
+ tag_smooth_modified();
+
+ if (get_num_subd_faces()) {
triangle_patch.push_back_reserved(-1);
+ tag_triangle_patch_modified();
}
}
@@ -288,14 +369,47 @@ void Mesh::add_subd_face(int *corners, int num_corners, int shader_, bool smooth
}
int ptex_offset = 0;
-
- if (subd_faces.size()) {
- SubdFace &s = subd_faces[subd_faces.size() - 1];
+ // cannot use get_num_subd_faces here as it holds the total number of subd_faces, but we do not
+ // have the total amount of data yet
+ if (subd_shader.size()) {
+ SubdFace s = get_subd_face(subd_shader.size() - 1);
ptex_offset = s.ptex_offset + s.num_ptex_faces();
}
- SubdFace face = {start_corner, num_corners, shader_, smooth_, ptex_offset};
- subd_faces.push_back_reserved(face);
+ subd_start_corner.push_back_reserved(start_corner);
+ subd_num_corners.push_back_reserved(num_corners);
+ subd_shader.push_back_reserved(shader_);
+ subd_smooth.push_back_reserved(smooth_);
+ subd_ptex_offset.push_back_reserved(ptex_offset);
+
+ tag_subd_face_corners_modified();
+ tag_subd_start_corner_modified();
+ tag_subd_num_corners_modified();
+ tag_subd_shader_modified();
+ tag_subd_smooth_modified();
+ tag_subd_ptex_offset_modified();
+}
+
+Mesh::SubdFace Mesh::get_subd_face(size_t index) const
+{
+ Mesh::SubdFace s;
+ s.shader = subd_shader[index];
+ s.num_corners = subd_num_corners[index];
+ s.smooth = subd_smooth[index];
+ s.ptex_offset = subd_ptex_offset[index];
+ s.start_corner = subd_start_corner[index];
+ return s;
+}
+
+void Mesh::add_crease(int v0, int v1, float weight)
+{
+ subd_creases_edge.push_back_slow(v0);
+ subd_creases_edge.push_back_slow(v1);
+ subd_creases_weight.push_back_slow(weight);
+
+ tag_subd_creases_edge_modified();
+ tag_subd_creases_edge_modified();
+ tag_subd_creases_weight_modified();
}
void Mesh::copy_center_to_motion_step(const int motion_step)
@@ -505,7 +619,7 @@ void Mesh::add_vertex_normals()
}
/* subd vertex normals */
- if (!subd_attributes.find(ATTR_STD_VERTEX_NORMAL) && subd_faces.size()) {
+ if (!subd_attributes.find(ATTR_STD_VERTEX_NORMAL) && get_num_subd_faces()) {
/* get attributes */
Attribute *attr_vN = subd_attributes.add(ATTR_STD_VERTEX_NORMAL);
float3 *vN = attr_vN->data_float3();
@@ -513,8 +627,8 @@ void Mesh::add_vertex_normals()
/* compute vertex normals */
memset(vN, 0, verts.size() * sizeof(float3));
- for (size_t i = 0; i < subd_faces.size(); i++) {
- SubdFace &face = subd_faces[i];
+ for (size_t i = 0; i < get_num_subd_faces(); i++) {
+ SubdFace face = get_subd_face(i);
float3 fN = face.normal(this);
for (size_t j = 0; j < face.num_corners; j++) {
@@ -574,8 +688,9 @@ void Mesh::pack_shaders(Scene *scene, uint *tri_shader)
if (shader_ptr[i] != last_shader || last_smooth != smooth[i]) {
last_shader = shader_ptr[i];
last_smooth = smooth[i];
- Shader *shader = (last_shader < used_shaders.size()) ? used_shaders[last_shader] :
- scene->default_surface;
+ Shader *shader = (last_shader < used_shaders.size()) ?
+ static_cast<Shader *>(used_shaders[last_shader]) :
+ scene->default_surface;
shader_id = scene->shader_manager->get_shader_id(shader, last_smooth);
}
@@ -616,7 +731,7 @@ void Mesh::pack_verts(const vector<uint> &tri_prim_index,
{
size_t verts_size = verts.size();
- if (verts_size && subd_faces.size()) {
+ if (verts_size && get_num_subd_faces()) {
float2 *vert_patch_uv_ptr = vert_patch_uv.data();
for (size_t i = 0; i < verts_size; i++) {
@@ -633,17 +748,17 @@ void Mesh::pack_verts(const vector<uint> &tri_prim_index,
t.v[2] + vert_offset,
tri_prim_index[i + tri_offset]);
- tri_patch[i] = (!subd_faces.size()) ? -1 : (triangle_patch[i] * 8 + patch_offset);
+ tri_patch[i] = (!get_num_subd_faces()) ? -1 : (triangle_patch[i] * 8 + patch_offset);
}
}
void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset)
{
- size_t num_faces = subd_faces.size();
+ size_t num_faces = get_num_subd_faces();
int ngons = 0;
for (size_t f = 0; f < num_faces; f++) {
- SubdFace face = subd_faces[f];
+ SubdFace face = get_subd_face(f);
if (face.is_quad()) {
int c[4];
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index c8286a01e2c..6630dcd8a35 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -118,36 +118,57 @@ class Mesh : public Geometry {
float crease;
};
+ SubdEdgeCrease get_subd_crease(size_t i) const
+ {
+ SubdEdgeCrease s;
+ s.v[0] = subd_creases_edge[i * 2];
+ s.v[1] = subd_creases_edge[i * 2 + 1];
+ s.crease = subd_creases_weight[i];
+ return s;
+ }
+
+ bool need_tesselation();
+
enum SubdivisionType {
SUBDIVISION_NONE,
SUBDIVISION_LINEAR,
SUBDIVISION_CATMULL_CLARK,
};
- SubdivisionType subdivision_type;
+ NODE_SOCKET_API(SubdivisionType, subdivision_type)
/* Mesh Data */
- array<int> triangles;
- array<float3> verts;
- array<int> shader;
- array<bool> smooth;
+ NODE_SOCKET_API_ARRAY(array<int>, triangles)
+ NODE_SOCKET_API_ARRAY(array<float3>, verts)
+ NODE_SOCKET_API_ARRAY(array<int>, shader)
+ NODE_SOCKET_API_ARRAY(array<bool>, smooth)
/* used for storing patch info for subd triangles, only allocated if there are patches */
- array<int> triangle_patch; /* must be < 0 for non subd triangles */
- array<float2> vert_patch_uv;
+ NODE_SOCKET_API_ARRAY(array<int>, triangle_patch) /* must be < 0 for non subd triangles */
+ NODE_SOCKET_API_ARRAY(array<float2>, vert_patch_uv)
+
+ /* SubdFaces */
+ NODE_SOCKET_API_ARRAY(array<int>, subd_start_corner)
+ NODE_SOCKET_API_ARRAY(array<int>, subd_num_corners)
+ NODE_SOCKET_API_ARRAY(array<int>, subd_shader)
+ NODE_SOCKET_API_ARRAY(array<bool>, subd_smooth)
+ NODE_SOCKET_API_ARRAY(array<int>, subd_ptex_offset)
- array<SubdFace> subd_faces;
- array<int> subd_face_corners;
- int num_ngons;
+ NODE_SOCKET_API_ARRAY(array<int>, subd_face_corners)
+ NODE_SOCKET_API(int, num_ngons)
- array<SubdEdgeCrease> subd_creases;
+ NODE_SOCKET_API_ARRAY(array<int>, subd_creases_edge)
+ NODE_SOCKET_API_ARRAY(array<float>, subd_creases_weight)
- SubdParams *subd_params;
+ /* Subdivisions parameters */
+ NODE_SOCKET_API(float, subd_dicing_rate)
+ NODE_SOCKET_API(int, subd_max_level)
+ NODE_SOCKET_API(Transform, subd_objecttoworld)
AttributeSet subd_attributes;
+ private:
PackedPatchTable *patch_table;
-
/* BVH */
size_t vert_offset;
@@ -157,13 +178,22 @@ class Mesh : public Geometry {
size_t corner_offset;
size_t num_subd_verts;
+ size_t num_subd_faces;
- private:
unordered_map<int, int> vert_to_stitching_key_map; /* real vert index -> stitching index */
unordered_multimap<int, int>
vert_stitching_map; /* stitching index -> multiple real vert indices */
+
+ friend class BVH;
+ friend class BVHBuild;
+ friend class BVHEmbree;
+ friend class BVHSpatialSplit;
friend class DiagSplit;
+ friend class EdgeDice;
friend class GeometryManager;
+ friend class ObjectManager;
+
+ SubdParams *subd_params = nullptr;
public:
/* Functions */
@@ -174,12 +204,13 @@ class Mesh : public Geometry {
void reserve_mesh(int numverts, int numfaces);
void resize_subd_faces(int numfaces, int num_ngons, int numcorners);
void reserve_subd_faces(int numfaces, int num_ngons, int numcorners);
- void clear(bool preserve_voxel_data);
- void clear() override;
+ void reserve_subd_creases(size_t num_creases);
+ void clear(bool preserve_shaders = false) override;
void add_vertex(float3 P);
void add_vertex_slow(float3 P);
void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
void add_subd_face(int *corners, int num_corners, int shader_, bool smooth_);
+ void add_crease(int v0, int v1, float weight);
void copy_center_to_motion_step(const int motion_step);
@@ -202,6 +233,28 @@ class Mesh : public Geometry {
void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset);
void tessellate(DiagSplit *split);
+
+ SubdFace get_subd_face(size_t index) const;
+
+ SubdParams *get_subd_params();
+
+ size_t get_num_subd_faces() const
+ {
+ return num_subd_faces;
+ }
+
+ void set_num_subd_faces(size_t num_subd_faces_)
+ {
+ num_subd_faces = num_subd_faces_;
+ }
+
+ size_t get_num_subd_verts()
+ {
+ return num_subd_verts;
+ }
+
+ protected:
+ void clear(bool preserve_shaders, bool preserve_voxel_data);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index 467810f9273..b4fb5dcdea2 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -58,7 +58,7 @@ bool GeometryManager::displace(
size_t object_index = OBJECT_NONE;
for (size_t i = 0; i < scene->objects.size(); i++) {
- if (scene->objects[i]->geometry == mesh) {
+ if (scene->objects[i]->get_geometry() == mesh) {
object_index = i;
break;
}
@@ -76,10 +76,10 @@ bool GeometryManager::displace(
Mesh::Triangle t = mesh->get_triangle(i);
int shader_index = mesh->shader[i];
Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] :
+ static_cast<Shader *>(mesh->used_shaders[shader_index]) :
scene->default_surface;
- if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) {
continue;
}
@@ -160,10 +160,10 @@ bool GeometryManager::displace(
Mesh::Triangle t = mesh->get_triangle(i);
int shader_index = mesh->shader[i];
Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] :
+ static_cast<Shader *>(mesh->used_shaders[shader_index]) :
scene->default_surface;
- if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) {
continue;
}
@@ -227,8 +227,9 @@ bool GeometryManager::displace(
bool need_recompute_vertex_normals = false;
- foreach (Shader *shader, mesh->used_shaders) {
- if (shader->has_displacement && shader->displacement_method == DISPLACE_TRUE) {
+ foreach (Node *node, mesh->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
+ if (shader->has_displacement && shader->get_displacement_method() == DISPLACE_TRUE) {
need_recompute_vertex_normals = true;
break;
}
@@ -241,11 +242,11 @@ bool GeometryManager::displace(
for (size_t i = 0; i < num_triangles; i++) {
int shader_index = mesh->shader[i];
Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] :
+ static_cast<Shader *>(mesh->used_shaders[shader_index]) :
scene->default_surface;
tri_has_true_disp[i] = shader->has_displacement &&
- shader->displacement_method == DISPLACE_TRUE;
+ shader->get_displacement_method() == DISPLACE_TRUE;
}
/* static vertex normals */
diff --git a/intern/cycles/render/mesh_subdivision.cpp b/intern/cycles/render/mesh_subdivision.cpp
index 3d72b2fab91..7408ee2dbdf 100644
--- a/intern/cycles/render/mesh_subdivision.cpp
+++ b/intern/cycles/render/mesh_subdivision.cpp
@@ -46,13 +46,11 @@ template<>
bool TopologyRefinerFactory<ccl::Mesh>::resizeComponentTopology(TopologyRefiner &refiner,
ccl::Mesh const &mesh)
{
- setNumBaseVertices(refiner, mesh.verts.size());
- setNumBaseFaces(refiner, mesh.subd_faces.size());
+ setNumBaseVertices(refiner, mesh.get_verts().size());
+ setNumBaseFaces(refiner, mesh.get_num_subd_faces());
- const ccl::Mesh::SubdFace *face = mesh.subd_faces.data();
-
- for (int i = 0; i < mesh.subd_faces.size(); i++, face++) {
- setNumBaseFaceVertices(refiner, i, face->num_corners);
+ for (int i = 0; i < mesh.get_num_subd_faces(); i++) {
+ setNumBaseFaceVertices(refiner, i, mesh.get_subd_num_corners()[i]);
}
return true;
@@ -62,14 +60,17 @@ template<>
bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTopology(TopologyRefiner &refiner,
ccl::Mesh const &mesh)
{
- const ccl::Mesh::SubdFace *face = mesh.subd_faces.data();
+ const ccl::array<int> &subd_face_corners = mesh.get_subd_face_corners();
+ const ccl::array<int> &subd_start_corner = mesh.get_subd_start_corner();
+ const ccl::array<int> &subd_num_corners = mesh.get_subd_num_corners();
- for (int i = 0; i < mesh.subd_faces.size(); i++, face++) {
+ for (int i = 0; i < mesh.get_num_subd_faces(); i++) {
IndexArray face_verts = getBaseFaceVertices(refiner, i);
- int *corner = &mesh.subd_face_corners[face->start_corner];
+ int start_corner = subd_start_corner[i];
+ int *corner = &subd_face_corners[start_corner];
- for (int j = 0; j < face->num_corners; j++, corner++) {
+ for (int j = 0; j < subd_num_corners[i]; j++, corner++) {
face_verts[j] = *corner;
}
}
@@ -81,17 +82,18 @@ template<>
bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTags(TopologyRefiner &refiner,
ccl::Mesh const &mesh)
{
- const ccl::Mesh::SubdEdgeCrease *crease = mesh.subd_creases.data();
+ size_t num_creases = mesh.get_subd_creases_weight().size();
- for (int i = 0; i < mesh.subd_creases.size(); i++, crease++) {
- Index edge = findBaseEdge(refiner, crease->v[0], crease->v[1]);
+ for (int i = 0; i < num_creases; i++) {
+ ccl::Mesh::SubdEdgeCrease crease = mesh.get_subd_crease(i);
+ Index edge = findBaseEdge(refiner, crease.v[0], crease.v[1]);
if (edge != INDEX_INVALID) {
- setBaseEdgeSharpness(refiner, edge, crease->crease * 10.0f);
+ setBaseEdgeSharpness(refiner, edge, crease.crease * 10.0f);
}
}
- for (int i = 0; i < mesh.verts.size(); i++) {
+ for (int i = 0; i < mesh.get_verts().size(); i++) {
ConstIndexArray vert_edges = getBaseVertexEdges(refiner, i);
if (vert_edges.size() == 2) {
@@ -203,8 +205,8 @@ class OsdData {
int num_local_points = patch_table->GetNumLocalPoints();
verts.resize(num_refiner_verts + num_local_points);
- for (int i = 0; i < mesh->verts.size(); i++) {
- verts[i].value = mesh->verts[i];
+ for (int i = 0; i < mesh->get_verts().size(); i++) {
+ verts[i].value = mesh->get_verts()[i];
}
OsdValue<float3> *src = verts.data();
@@ -278,16 +280,17 @@ class OsdData {
{
/* loop over all edges to find longest in screen space */
const Far::TopologyLevel &level = refiner->GetLevel(0);
- Transform objecttoworld = mesh->subd_params->objecttoworld;
- Camera *cam = mesh->subd_params->camera;
+ const SubdParams *subd_params = mesh->get_subd_params();
+ Transform objecttoworld = subd_params->objecttoworld;
+ Camera *cam = subd_params->camera;
float longest_edge = 0.0f;
for (size_t i = 0; i < level.GetNumEdges(); i++) {
Far::ConstIndexArray verts = level.GetEdgeVertices(i);
- float3 a = mesh->verts[verts[0]];
- float3 b = mesh->verts[verts[1]];
+ float3 a = mesh->get_verts()[verts[0]];
+ float3 b = mesh->get_verts()[verts[1]];
float edge_len;
@@ -305,7 +308,7 @@ class OsdData {
}
/* calculate isolation level */
- int isolation = (int)(log2f(max(longest_edge / mesh->subd_params->dicing_rate, 1.0f)) + 1.0f);
+ int isolation = (int)(log2f(max(longest_edge / subd_params->dicing_rate, 1.0f)) + 1.0f);
return min(isolation, 10);
}
@@ -368,12 +371,16 @@ struct OsdPatch : Patch {
void Mesh::tessellate(DiagSplit *split)
{
+ /* reset the number of subdivision vertices, in case the Mesh was not cleared
+ * between calls or data updates */
+ num_subd_verts = 0;
+
#ifdef WITH_OPENSUBDIV
OsdData osd_data;
bool need_packed_patch_table = false;
if (subdivision_type == SUBDIVISION_CATMULL_CLARK) {
- if (subd_faces.size()) {
+ if (get_num_subd_faces()) {
osd_data.build_from_mesh(this);
}
}
@@ -391,7 +398,7 @@ void Mesh::tessellate(DiagSplit *split)
}
}
- int num_faces = subd_faces.size();
+ int num_faces = get_num_subd_faces();
Attribute *attr_vN = subd_attributes.find(ATTR_STD_VERTEX_NORMAL);
float3 *vN = (attr_vN) ? attr_vN->data_float3() : NULL;
@@ -399,7 +406,7 @@ void Mesh::tessellate(DiagSplit *split)
/* count patches */
int num_patches = 0;
for (int f = 0; f < num_faces; f++) {
- SubdFace &face = subd_faces[f];
+ SubdFace face = get_subd_face(f);
if (face.is_quad()) {
num_patches++;
@@ -416,7 +423,7 @@ void Mesh::tessellate(DiagSplit *split)
OsdPatch *patch = osd_patches.data();
for (int f = 0; f < num_faces; f++) {
- SubdFace &face = subd_faces[f];
+ SubdFace face = get_subd_face(f);
if (face.is_quad()) {
patch->patch_index = face.ptex_offset;
@@ -444,7 +451,7 @@ void Mesh::tessellate(DiagSplit *split)
LinearQuadPatch *patch = linear_patches.data();
for (int f = 0; f < num_faces; f++) {
- SubdFace &face = subd_faces[f];
+ SubdFace face = get_subd_face(f);
if (face.is_quad()) {
float3 *hull = patch->hull;
@@ -542,7 +549,7 @@ void Mesh::tessellate(DiagSplit *split)
/* keep subdivision for corner attributes disabled for now */
attr.flags &= ~ATTR_SUBDIVIDED;
}
- else if (subd_faces.size()) {
+ else if (get_num_subd_faces()) {
osd_data.subdivide_attribute(attr);
need_packed_patch_table = true;
@@ -558,7 +565,7 @@ void Mesh::tessellate(DiagSplit *split)
switch (attr.element) {
case ATTR_ELEMENT_VERTEX: {
for (int f = 0; f < num_faces; f++) {
- SubdFace &face = subd_faces[f];
+ SubdFace face = get_subd_face(f);
if (!face.is_quad()) {
char *center = data + (verts.size() - num_subd_verts + ngons) * stride;
@@ -581,7 +588,7 @@ void Mesh::tessellate(DiagSplit *split)
} break;
case ATTR_ELEMENT_CORNER: {
for (int f = 0; f < num_faces; f++) {
- SubdFace &face = subd_faces[f];
+ SubdFace face = get_subd_face(f);
if (!face.is_quad()) {
char *center = data + (subd_face_corners.size() + ngons) * stride;
@@ -600,7 +607,7 @@ void Mesh::tessellate(DiagSplit *split)
} break;
case ATTR_ELEMENT_CORNER_BYTE: {
for (int f = 0; f < num_faces; f++) {
- SubdFace &face = subd_faces[f];
+ SubdFace face = get_subd_face(f);
if (!face.is_quad()) {
uchar *center = (uchar *)data + (subd_face_corners.size() + ngons) * stride;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index fa6096ff39b..43dff896db7 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -247,6 +247,9 @@ NODE_DEFINE(ImageTextureNode)
SOCKET_FLOAT(projection_blend, "Projection Blend", 0.0f);
+ SOCKET_INT_ARRAY(tiles, "Tiles", array<int>());
+ SOCKET_BOOLEAN(animated, "Animated", false);
+
SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_UV);
SOCKET_OUT_COLOR(color, "Color");
@@ -259,7 +262,7 @@ ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(node_type)
{
colorspace = u_colorspace_raw;
animated = false;
- tiles.push_back(1001);
+ tiles.push_back_slow(1001);
}
ShaderNode *ImageTextureNode::clone(ShaderGraph *graph) const
@@ -286,7 +289,7 @@ void ImageTextureNode::cull_tiles(Scene *scene, ShaderGraph *graph)
* 1001 tile, so there's no point in loading any others. */
if (projection == NODE_IMAGE_PROJ_BOX) {
tiles.clear();
- tiles.push_back(1001);
+ tiles.push_back_slow(1001);
return;
}
@@ -308,7 +311,7 @@ void ImageTextureNode::cull_tiles(Scene *scene, ShaderGraph *graph)
ShaderNode *node = vector_in->link->parent;
if (node->type == UVMapNode::node_type) {
UVMapNode *uvmap = (UVMapNode *)node;
- attribute = uvmap->attribute;
+ attribute = uvmap->get_attribute();
}
else if (node->type == TextureCoordinateNode::node_type) {
if (vector_in->link != node->output("UV")) {
@@ -325,20 +328,21 @@ void ImageTextureNode::cull_tiles(Scene *scene, ShaderGraph *graph)
* be to have a cache in each mesh that is indexed by attribute.
* Additionally, building a graph-to-meshes list once could help. */
foreach (Geometry *geom, scene->geometry) {
- foreach (Shader *shader, geom->used_shaders) {
+ foreach (Node *node, geom->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
if (shader->graph == graph) {
geom->get_uv_tiles(attribute, used_tiles);
}
}
}
- ccl::vector<int> new_tiles;
+ array<int> new_tiles;
foreach (int tile, tiles) {
if (used_tiles.count(tile)) {
- new_tiles.push_back(tile);
+ new_tiles.push_back_slow(tile);
}
}
- tiles.swap(new_tiles);
+ tiles.steal_data(new_tiles);
}
void ImageTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -511,6 +515,8 @@ NODE_DEFINE(EnvironmentTextureNode)
projection_enum.insert("mirror_ball", NODE_ENVIRONMENT_MIRROR_BALL);
SOCKET_ENUM(projection, "Projection", projection_enum, NODE_ENVIRONMENT_EQUIRECTANGULAR);
+ SOCKET_BOOLEAN(animated, "Animated", false);
+
SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
SOCKET_OUT_COLOR(color, "Color");
@@ -790,7 +796,7 @@ NODE_DEFINE(SkyTextureNode)
type_enum.insert("preetham", NODE_SKY_PREETHAM);
type_enum.insert("hosek_wilkie", NODE_SKY_HOSEK);
type_enum.insert("nishita_improved", NODE_SKY_NISHITA);
- SOCKET_ENUM(type, "Type", type_enum, NODE_SKY_NISHITA);
+ SOCKET_ENUM(sky_type, "Type", type_enum, NODE_SKY_NISHITA);
SOCKET_VECTOR(sun_direction, "Sun Direction", make_float3(0.0f, 0.0f, 1.0f));
SOCKET_FLOAT(turbidity, "Turbidity", 2.2f);
@@ -823,11 +829,11 @@ void SkyTextureNode::compile(SVMCompiler &compiler)
ShaderOutput *color_out = output("Color");
SunSky sunsky;
- if (type == NODE_SKY_PREETHAM)
+ if (sky_type == NODE_SKY_PREETHAM)
sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity);
- else if (type == NODE_SKY_HOSEK)
+ else if (sky_type == NODE_SKY_HOSEK)
sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo);
- else if (type == NODE_SKY_NISHITA) {
+ else if (sky_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);
@@ -860,9 +866,9 @@ void SkyTextureNode::compile(SVMCompiler &compiler)
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
compiler.stack_assign(color_out);
- compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), type);
+ compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), sky_type);
/* nishita doesn't need this data */
- if (type != NODE_SKY_NISHITA) {
+ if (sky_type != NODE_SKY_NISHITA) {
compiler.add_node(__float_as_uint(sunsky.phi),
__float_as_uint(sunsky.theta),
__float_as_uint(sunsky.radiance_x),
@@ -919,11 +925,11 @@ void SkyTextureNode::compile(OSLCompiler &compiler)
tex_mapping.compile(compiler);
SunSky sunsky;
- if (type == NODE_SKY_PREETHAM)
+ if (sky_type == NODE_SKY_PREETHAM)
sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity);
- else if (type == NODE_SKY_HOSEK)
+ else if (sky_type == NODE_SKY_HOSEK)
sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo);
- else if (type == NODE_SKY_NISHITA) {
+ else if (sky_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);
@@ -963,7 +969,7 @@ void SkyTextureNode::compile(OSLCompiler &compiler)
compiler.parameter_array("config_z", sunsky.config_z, 9);
compiler.parameter_array("nishita_data", sunsky.nishita_data, 10);
/* nishita texture */
- if (type == NODE_SKY_NISHITA) {
+ if (sky_type == NODE_SKY_NISHITA) {
compiler.parameter_texture("filename", handle.svm_slot());
}
compiler.add(this, "node_sky_texture");
@@ -985,7 +991,7 @@ NODE_DEFINE(GradientTextureNode)
type_enum.insert("radial", NODE_BLEND_RADIAL);
type_enum.insert("quadratic_sphere", NODE_BLEND_QUADRATIC_SPHERE);
type_enum.insert("spherical", NODE_BLEND_SPHERICAL);
- SOCKET_ENUM(type, "Type", type_enum, NODE_BLEND_LINEAR);
+ SOCKET_ENUM(gradient_type, "Type", type_enum, NODE_BLEND_LINEAR);
SOCKET_IN_POINT(
vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
@@ -1009,7 +1015,7 @@ void GradientTextureNode::compile(SVMCompiler &compiler)
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
compiler.add_node(NODE_TEX_GRADIENT,
- compiler.encode_uchar4(type,
+ compiler.encode_uchar4(gradient_type,
vector_offset,
compiler.stack_assign_if_linked(fac_out),
compiler.stack_assign_if_linked(color_out)));
@@ -1369,7 +1375,7 @@ NODE_DEFINE(MusgraveTextureNode)
type_enum.insert("hybrid_multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL);
type_enum.insert("ridged_multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL);
type_enum.insert("hetero_terrain", NODE_MUSGRAVE_HETERO_TERRAIN);
- SOCKET_ENUM(type, "Type", type_enum, NODE_MUSGRAVE_FBM);
+ SOCKET_ENUM(musgrave_type, "Type", type_enum, NODE_MUSGRAVE_FBM);
SOCKET_IN_POINT(
vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
@@ -1414,7 +1420,7 @@ void MusgraveTextureNode::compile(SVMCompiler &compiler)
compiler.add_node(
NODE_TEX_MUSGRAVE,
- compiler.encode_uchar4(type, dimensions, vector_stack_offset, w_stack_offset),
+ compiler.encode_uchar4(musgrave_type, dimensions, vector_stack_offset, w_stack_offset),
compiler.encode_uchar4(scale_stack_offset,
detail_stack_offset,
dimension_stack_offset,
@@ -1447,7 +1453,7 @@ NODE_DEFINE(WaveTextureNode)
static NodeEnum type_enum;
type_enum.insert("bands", NODE_WAVE_BANDS);
type_enum.insert("rings", NODE_WAVE_RINGS);
- SOCKET_ENUM(type, "Type", type_enum, NODE_WAVE_BANDS);
+ SOCKET_ENUM(wave_type, "Type", type_enum, NODE_WAVE_BANDS);
static NodeEnum bands_direction_enum;
bands_direction_enum.insert("x", NODE_WAVE_BANDS_DIRECTION_X);
@@ -1504,7 +1510,7 @@ void WaveTextureNode::compile(SVMCompiler &compiler)
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
compiler.add_node(NODE_TEX_WAVE,
- compiler.encode_uchar4(type, bands_direction, rings_direction, profile),
+ compiler.encode_uchar4(wave_type, bands_direction, rings_direction, profile),
compiler.encode_uchar4(vector_offset,
compiler.stack_assign_if_linked(scale_in),
compiler.stack_assign_if_linked(distortion_in)),
@@ -1926,7 +1932,7 @@ NODE_DEFINE(MappingNode)
type_enum.insert("texture", NODE_MAPPING_TYPE_TEXTURE);
type_enum.insert("vector", NODE_MAPPING_TYPE_VECTOR);
type_enum.insert("normal", NODE_MAPPING_TYPE_NORMAL);
- SOCKET_ENUM(type, "Type", type_enum, NODE_MAPPING_TYPE_POINT);
+ SOCKET_ENUM(mapping_type, "Type", type_enum, NODE_MAPPING_TYPE_POINT);
SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_IN_POINT(location, "Location", make_float3(0.0f, 0.0f, 0.0f));
@@ -1945,11 +1951,11 @@ MappingNode::MappingNode() : ShaderNode(node_type)
void MappingNode::constant_fold(const ConstantFolder &folder)
{
if (folder.all_inputs_constant()) {
- float3 result = svm_mapping((NodeMappingType)type, vector, location, rotation, scale);
+ float3 result = svm_mapping((NodeMappingType)mapping_type, vector, location, rotation, scale);
folder.make_constant(result);
}
else {
- folder.fold_mapping((NodeMappingType)type);
+ folder.fold_mapping((NodeMappingType)mapping_type);
}
}
@@ -1969,7 +1975,7 @@ void MappingNode::compile(SVMCompiler &compiler)
compiler.add_node(
NODE_MAPPING,
- type,
+ mapping_type,
compiler.encode_uchar4(
vector_stack_offset, location_stack_offset, rotation_stack_offset, scale_stack_offset),
result_stack_offset);
@@ -2385,7 +2391,7 @@ void GlossyBsdfNode::simplify_settings(Scene *scene)
}
Integrator *integrator = scene->integrator;
ShaderInput *roughness_input = input("Roughness");
- if (integrator->filter_glossy == 0.0f) {
+ if (integrator->get_filter_glossy() == 0.0f) {
/* Fallback to Sharp closure for Roughness close to 0.
* Note: Keep the epsilon in sync with kernel!
*/
@@ -2478,7 +2484,7 @@ void GlassBsdfNode::simplify_settings(Scene *scene)
}
Integrator *integrator = scene->integrator;
ShaderInput *roughness_input = input("Roughness");
- if (integrator->filter_glossy == 0.0f) {
+ if (integrator->get_filter_glossy() == 0.0f) {
/* Fallback to Sharp closure for Roughness close to 0.
* Note: Keep the epsilon in sync with kernel!
*/
@@ -2571,7 +2577,7 @@ void RefractionBsdfNode::simplify_settings(Scene *scene)
}
Integrator *integrator = scene->integrator;
ShaderInput *roughness_input = input("Roughness");
- if (integrator->filter_glossy == 0.0f) {
+ if (integrator->get_filter_glossy() == 0.0f) {
/* Fallback to Sharp closure for Roughness close to 0.
* Note: Keep the epsilon in sync with kernel!
*/
@@ -3743,7 +3749,7 @@ void GeometryNode::compile(SVMCompiler &compiler)
if (!out->links.empty()) {
if (compiler.output_type() != SHADER_TYPE_VOLUME) {
compiler.add_node(
- attr_node, ATTR_STD_POINTINESS, compiler.stack_assign(out), NODE_ATTR_FLOAT);
+ attr_node, ATTR_STD_POINTINESS, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT);
}
else {
compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
@@ -3753,8 +3759,10 @@ void GeometryNode::compile(SVMCompiler &compiler)
out = output("Random Per Island");
if (!out->links.empty()) {
if (compiler.output_type() != SHADER_TYPE_VOLUME) {
- compiler.add_node(
- attr_node, ATTR_STD_RANDOM_PER_ISLAND, compiler.stack_assign(out), NODE_ATTR_FLOAT);
+ compiler.add_node(attr_node,
+ ATTR_STD_RANDOM_PER_ISLAND,
+ compiler.stack_assign(out),
+ NODE_ATTR_OUTPUT_FLOAT);
}
else {
compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
@@ -3872,7 +3880,7 @@ void TextureCoordinateNode::compile(SVMCompiler &compiler)
}
else {
int attr = compiler.attribute(ATTR_STD_GENERATED);
- compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
+ compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3);
}
}
}
@@ -3889,7 +3897,7 @@ void TextureCoordinateNode::compile(SVMCompiler &compiler)
}
else {
int attr = compiler.attribute(ATTR_STD_UV);
- compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
+ compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3);
}
}
@@ -4007,7 +4015,7 @@ void UVMapNode::compile(SVMCompiler &compiler)
else
attr = compiler.attribute(ATTR_STD_UV);
- compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
+ compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3);
}
}
}
@@ -4403,7 +4411,7 @@ void HairInfoNode::compile(SVMCompiler &compiler)
out = output("Intercept");
if (!out->links.empty()) {
int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
- compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
+ compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT);
}
out = output("Thickness");
@@ -4424,7 +4432,7 @@ void HairInfoNode::compile(SVMCompiler &compiler)
out = output("Random");
if (!out->links.empty()) {
int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
- compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
+ compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT);
}
}
@@ -4479,7 +4487,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
ShaderOutput *color_out = output("Color");
if (!color_out->links.empty()) {
AttributeNode *attr = graph->create_node<AttributeNode>();
- attr->attribute = "color";
+ attr->set_attribute(ustring("color"));
graph->add(attr);
graph->relink(color_out, attr->output("Color"));
}
@@ -4487,7 +4495,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
ShaderOutput *density_out = output("Density");
if (!density_out->links.empty()) {
AttributeNode *attr = graph->create_node<AttributeNode>();
- attr->attribute = "density";
+ attr->set_attribute(ustring("density"));
graph->add(attr);
graph->relink(density_out, attr->output("Fac"));
}
@@ -4495,7 +4503,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
ShaderOutput *flame_out = output("Flame");
if (!flame_out->links.empty()) {
AttributeNode *attr = graph->create_node<AttributeNode>();
- attr->attribute = "flame";
+ attr->set_attribute(ustring("flame"));
graph->add(attr);
graph->relink(flame_out, attr->output("Fac"));
}
@@ -4503,7 +4511,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
ShaderOutput *temperature_out = output("Temperature");
if (!temperature_out->links.empty()) {
AttributeNode *attr = graph->create_node<AttributeNode>();
- attr->attribute = "temperature";
+ attr->set_attribute(ustring("temperature"));
graph->add(attr);
graph->relink(temperature_out, attr->output("Fac"));
}
@@ -4880,7 +4888,7 @@ NODE_DEFINE(MixNode)
type_enum.insert("color", NODE_MIX_COLOR);
type_enum.insert("soft_light", NODE_MIX_SOFT);
type_enum.insert("linear_light", NODE_MIX_LINEAR);
- SOCKET_ENUM(type, "Type", type_enum, NODE_MIX_BLEND);
+ SOCKET_ENUM(mix_type, "Type", type_enum, NODE_MIX_BLEND);
SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
@@ -4908,7 +4916,7 @@ void MixNode::compile(SVMCompiler &compiler)
compiler.stack_assign(fac_in),
compiler.stack_assign(color1_in),
compiler.stack_assign(color2_in));
- compiler.add_node(NODE_MIX, type, compiler.stack_assign(color_out));
+ compiler.add_node(NODE_MIX, mix_type, compiler.stack_assign(color_out));
if (use_clamp) {
compiler.add_node(NODE_MIX, 0, compiler.stack_assign(color_out));
@@ -4926,10 +4934,10 @@ void MixNode::compile(OSLCompiler &compiler)
void MixNode::constant_fold(const ConstantFolder &folder)
{
if (folder.all_inputs_constant()) {
- folder.make_constant_clamp(svm_mix(type, fac, color1, color2), use_clamp);
+ folder.make_constant_clamp(svm_mix(mix_type, fac, color1, color2), use_clamp);
}
else {
- folder.fold_mix(type, use_clamp);
+ folder.fold_mix(mix_type, use_clamp);
}
}
@@ -5386,6 +5394,7 @@ NODE_DEFINE(AttributeNode)
SOCKET_OUT_COLOR(color, "Color");
SOCKET_OUT_VECTOR(vector, "Vector");
SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_FLOAT(alpha, "Alpha");
return type;
}
@@ -5399,8 +5408,10 @@ void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
ShaderOutput *color_out = output("Color");
ShaderOutput *vector_out = output("Vector");
ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *alpha_out = output("Alpha");
- if (!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty()) {
+ if (!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty() ||
+ !alpha_out->links.empty()) {
attributes->add_standard(attribute);
}
@@ -5416,6 +5427,7 @@ void AttributeNode::compile(SVMCompiler &compiler)
ShaderOutput *color_out = output("Color");
ShaderOutput *vector_out = output("Vector");
ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *alpha_out = output("Alpha");
ShaderNodeType attr_node = NODE_ATTR;
int attr = compiler.attribute_standard(attribute);
@@ -5426,15 +5438,22 @@ void AttributeNode::compile(SVMCompiler &compiler)
if (!color_out->links.empty() || !vector_out->links.empty()) {
if (!color_out->links.empty()) {
- compiler.add_node(attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_FLOAT3);
+ compiler.add_node(
+ attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_OUTPUT_FLOAT3);
}
if (!vector_out->links.empty()) {
- compiler.add_node(attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_FLOAT3);
+ compiler.add_node(
+ attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_OUTPUT_FLOAT3);
}
}
if (!fac_out->links.empty()) {
- compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_FLOAT);
+ compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_OUTPUT_FLOAT);
+ }
+
+ if (!alpha_out->links.empty()) {
+ compiler.add_node(
+ attr_node, attr, compiler.stack_assign(alpha_out), NODE_ATTR_OUTPUT_FLOAT_ALPHA);
}
}
@@ -5748,7 +5767,7 @@ NODE_DEFINE(MapRangeNode)
type_enum.insert("stepped", NODE_MAP_RANGE_STEPPED);
type_enum.insert("smoothstep", NODE_MAP_RANGE_SMOOTHSTEP);
type_enum.insert("smootherstep", NODE_MAP_RANGE_SMOOTHERSTEP);
- SOCKET_ENUM(type, "Type", type_enum, NODE_MAP_RANGE_LINEAR);
+ SOCKET_ENUM(range_type, "Type", type_enum, NODE_MAP_RANGE_LINEAR);
SOCKET_IN_FLOAT(value, "Value", 1.0f);
SOCKET_IN_FLOAT(from_min, "From Min", 0.0f);
@@ -5773,7 +5792,7 @@ void MapRangeNode::expand(ShaderGraph *graph)
ShaderOutput *result_out = output("Result");
if (!result_out->links.empty()) {
ClampNode *clamp_node = graph->create_node<ClampNode>();
- clamp_node->type = NODE_CLAMP_RANGE;
+ clamp_node->set_clamp_type(NODE_CLAMP_RANGE);
graph->add(clamp_node);
graph->relink(result_out, clamp_node->output("Result"));
graph->connect(result_out, clamp_node->input("Value"));
@@ -5781,13 +5800,13 @@ void MapRangeNode::expand(ShaderGraph *graph)
graph->connect(input("To Min")->link, clamp_node->input("Min"));
}
else {
- clamp_node->min = to_min;
+ clamp_node->set_min(to_min);
}
if (input("To Max")->link) {
graph->connect(input("To Max")->link, clamp_node->input("Max"));
}
else {
- clamp_node->max = to_max;
+ clamp_node->set_max(to_max);
}
}
}
@@ -5816,7 +5835,7 @@ void MapRangeNode::compile(SVMCompiler &compiler)
value_stack_offset,
compiler.encode_uchar4(
from_min_stack_offset, from_max_stack_offset, to_min_stack_offset, to_max_stack_offset),
- compiler.encode_uchar4(type, steps_stack_offset, result_stack_offset));
+ compiler.encode_uchar4(range_type, steps_stack_offset, result_stack_offset));
compiler.add_node(__float_as_int(from_min),
__float_as_int(from_max),
@@ -5840,7 +5859,7 @@ NODE_DEFINE(ClampNode)
static NodeEnum type_enum;
type_enum.insert("minmax", NODE_CLAMP_MINMAX);
type_enum.insert("range", NODE_CLAMP_RANGE);
- SOCKET_ENUM(type, "Type", type_enum, NODE_CLAMP_MINMAX);
+ SOCKET_ENUM(clamp_type, "Type", type_enum, NODE_CLAMP_MINMAX);
SOCKET_IN_FLOAT(value, "Value", 1.0f);
SOCKET_IN_FLOAT(min, "Min", 0.0f);
@@ -5858,7 +5877,7 @@ ClampNode::ClampNode() : ShaderNode(node_type)
void ClampNode::constant_fold(const ConstantFolder &folder)
{
if (folder.all_inputs_constant()) {
- if (type == NODE_CLAMP_RANGE && (min > max)) {
+ if (clamp_type == NODE_CLAMP_RANGE && (min > max)) {
folder.make_constant(clamp(value, max, min));
}
else {
@@ -5881,7 +5900,7 @@ void ClampNode::compile(SVMCompiler &compiler)
compiler.add_node(NODE_CLAMP,
value_stack_offset,
- compiler.encode_uchar4(min_stack_offset, max_stack_offset, type),
+ compiler.encode_uchar4(min_stack_offset, max_stack_offset, clamp_type),
result_stack_offset);
compiler.add_node(__float_as_int(min), __float_as_int(max));
}
@@ -5991,7 +6010,7 @@ NODE_DEFINE(MathNode)
type_enum.insert("smoothmin", NODE_MATH_SMOOTH_MIN);
type_enum.insert("smoothmax", NODE_MATH_SMOOTH_MAX);
type_enum.insert("compare", NODE_MATH_COMPARE);
- SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD);
+ SOCKET_ENUM(math_type, "Type", type_enum, NODE_MATH_ADD);
SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
@@ -6014,9 +6033,9 @@ void MathNode::expand(ShaderGraph *graph)
ShaderOutput *result_out = output("Value");
if (!result_out->links.empty()) {
ClampNode *clamp_node = graph->create_node<ClampNode>();
- clamp_node->type = NODE_CLAMP_MINMAX;
- clamp_node->min = 0.0f;
- clamp_node->max = 1.0f;
+ clamp_node->set_clamp_type(NODE_CLAMP_MINMAX);
+ clamp_node->set_min(0.0f);
+ clamp_node->set_max(1.0f);
graph->add(clamp_node);
graph->relink(result_out, clamp_node->output("Result"));
graph->connect(result_out, clamp_node->input("Value"));
@@ -6027,10 +6046,10 @@ void MathNode::expand(ShaderGraph *graph)
void MathNode::constant_fold(const ConstantFolder &folder)
{
if (folder.all_inputs_constant()) {
- folder.make_constant(svm_math(type, value1, value2, value3));
+ folder.make_constant(svm_math(math_type, value1, value2, value3));
}
else {
- folder.fold_math(type);
+ folder.fold_math(math_type);
}
}
@@ -6048,7 +6067,7 @@ void MathNode::compile(SVMCompiler &compiler)
compiler.add_node(
NODE_MATH,
- type,
+ math_type,
compiler.encode_uchar4(value1_stack_offset, value2_stack_offset, value3_stack_offset),
value_stack_offset);
}
@@ -6094,7 +6113,7 @@ NODE_DEFINE(VectorMathNode)
type_enum.insert("sine", NODE_VECTOR_MATH_SINE);
type_enum.insert("cosine", NODE_VECTOR_MATH_COSINE);
type_enum.insert("tangent", NODE_VECTOR_MATH_TANGENT);
- SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_MATH_ADD);
+ SOCKET_ENUM(math_type, "Type", type_enum, NODE_VECTOR_MATH_ADD);
SOCKET_IN_VECTOR(vector1, "Vector1", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_IN_VECTOR(vector2, "Vector2", make_float3(0.0f, 0.0f, 0.0f));
@@ -6117,7 +6136,7 @@ void VectorMathNode::constant_fold(const ConstantFolder &folder)
float3 vector = make_float3(0.0f, 0.0f, 0.0f);
if (folder.all_inputs_constant()) {
- svm_vector_math(&value, &vector, type, vector1, vector2, vector3, scale);
+ svm_vector_math(&value, &vector, math_type, vector1, vector2, vector3, scale);
if (folder.output == output("Value")) {
folder.make_constant(value);
}
@@ -6126,7 +6145,7 @@ void VectorMathNode::constant_fold(const ConstantFolder &folder)
}
}
else {
- folder.fold_vector_math(type);
+ folder.fold_vector_math(math_type);
}
}
@@ -6145,12 +6164,12 @@ void VectorMathNode::compile(SVMCompiler &compiler)
int vector_stack_offset = compiler.stack_assign_if_linked(vector_out);
/* 3 Vector Operators */
- if (type == NODE_VECTOR_MATH_WRAP) {
+ if (math_type == NODE_VECTOR_MATH_WRAP) {
ShaderInput *vector3_in = input("Vector3");
int vector3_stack_offset = compiler.stack_assign(vector3_in);
compiler.add_node(
NODE_VECTOR_MATH,
- type,
+ math_type,
compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, scale_stack_offset),
compiler.encode_uchar4(value_stack_offset, vector_stack_offset));
compiler.add_node(vector3_stack_offset);
@@ -6158,7 +6177,7 @@ void VectorMathNode::compile(SVMCompiler &compiler)
else {
compiler.add_node(
NODE_VECTOR_MATH,
- type,
+ math_type,
compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, scale_stack_offset),
compiler.encode_uchar4(value_stack_offset, vector_stack_offset));
}
@@ -6182,7 +6201,7 @@ NODE_DEFINE(VectorRotateNode)
type_enum.insert("y_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Y);
type_enum.insert("z_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Z);
type_enum.insert("euler_xyz", NODE_VECTOR_ROTATE_TYPE_EULER_XYZ);
- SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_ROTATE_TYPE_AXIS);
+ SOCKET_ENUM(rotate_type, "Type", type_enum, NODE_VECTOR_ROTATE_TYPE_AXIS);
SOCKET_BOOLEAN(invert, "Invert", false);
@@ -6209,14 +6228,15 @@ void VectorRotateNode::compile(SVMCompiler &compiler)
ShaderInput *angle_in = input("Angle");
ShaderOutput *vector_out = output("Vector");
- compiler.add_node(
- NODE_VECTOR_ROTATE,
- compiler.encode_uchar4(
- type, compiler.stack_assign(vector_in), compiler.stack_assign(rotation_in), invert),
- compiler.encode_uchar4(compiler.stack_assign(center_in),
- compiler.stack_assign(axis_in),
- compiler.stack_assign(angle_in)),
- compiler.stack_assign(vector_out));
+ compiler.add_node(NODE_VECTOR_ROTATE,
+ compiler.encode_uchar4(rotate_type,
+ compiler.stack_assign(vector_in),
+ compiler.stack_assign(rotation_in),
+ invert),
+ compiler.encode_uchar4(compiler.stack_assign(center_in),
+ compiler.stack_assign(axis_in),
+ compiler.stack_assign(angle_in)),
+ compiler.stack_assign(vector_out));
}
void VectorRotateNode::compile(OSLCompiler &compiler)
@@ -6236,7 +6256,7 @@ NODE_DEFINE(VectorTransformNode)
type_enum.insert("vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
type_enum.insert("point", NODE_VECTOR_TRANSFORM_TYPE_POINT);
type_enum.insert("normal", NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
- SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
+ SOCKET_ENUM(transform_type, "Type", type_enum, NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
static NodeEnum space_enum;
space_enum.insert("world", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
@@ -6262,7 +6282,7 @@ void VectorTransformNode::compile(SVMCompiler &compiler)
compiler.add_node(
NODE_VECTOR_TRANSFORM,
- compiler.encode_uchar4(type, convert_from, convert_to),
+ compiler.encode_uchar4(transform_type, convert_from, convert_to),
compiler.encode_uchar4(compiler.stack_assign(vector_in), compiler.stack_assign(vector_out)));
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 62dd9d843a8..4d51b4fccaf 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -70,6 +70,17 @@ class TextureNode : public ShaderNode {
{
}
TextureMapping tex_mapping;
+ NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, translation)
+ NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, rotation)
+ NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, scale)
+ NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, min)
+ NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, max)
+ NODE_SOCKET_API_STRUCT_MEMBER(bool, tex_mapping, use_minmax)
+ NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Type, tex_mapping, type)
+ NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Mapping, tex_mapping, x_mapping)
+ NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Mapping, tex_mapping, y_mapping)
+ NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Mapping, tex_mapping, z_mapping)
+ NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Projection, tex_mapping, projection)
};
/* Any node which uses image manager's slot should be a subclass of this one. */
@@ -108,16 +119,16 @@ class ImageTextureNode : public ImageSlotTextureNode {
ImageParams image_params() const;
/* Parameters. */
- ustring filename;
- ustring colorspace;
- ImageAlphaType alpha_type;
- NodeImageProjection projection;
- InterpolationType interpolation;
- ExtensionType extension;
- float projection_blend;
- bool animated;
- float3 vector;
- ccl::vector<int> tiles;
+ NODE_SOCKET_API(ustring, filename)
+ NODE_SOCKET_API(ustring, colorspace)
+ NODE_SOCKET_API(ImageAlphaType, alpha_type)
+ NODE_SOCKET_API(NodeImageProjection, projection)
+ NODE_SOCKET_API(InterpolationType, interpolation)
+ NODE_SOCKET_API(ExtensionType, extension)
+ NODE_SOCKET_API(float, projection_blend)
+ NODE_SOCKET_API(bool, animated)
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(array<int>, tiles)
protected:
void cull_tiles(Scene *scene, ShaderGraph *graph);
@@ -146,13 +157,13 @@ class EnvironmentTextureNode : public ImageSlotTextureNode {
ImageParams image_params() const;
/* Parameters. */
- ustring filename;
- ustring colorspace;
- ImageAlphaType alpha_type;
- NodeEnvironmentProjection projection;
- InterpolationType interpolation;
- bool animated;
- float3 vector;
+ NODE_SOCKET_API(ustring, filename)
+ NODE_SOCKET_API(ustring, colorspace)
+ NODE_SOCKET_API(ImageAlphaType, alpha_type)
+ NODE_SOCKET_API(NodeEnvironmentProjection, projection)
+ NODE_SOCKET_API(InterpolationType, interpolation)
+ NODE_SOCKET_API(bool, animated)
+ NODE_SOCKET_API(float3, vector)
};
class SkyTextureNode : public TextureNode {
@@ -164,20 +175,20 @@ class SkyTextureNode : public TextureNode {
return NODE_GROUP_LEVEL_2;
}
- NodeSkyType type;
- float3 sun_direction;
- float turbidity;
- float ground_albedo;
- bool sun_disc;
- float sun_size;
- float sun_intensity;
- float sun_elevation;
- float sun_rotation;
- float altitude;
- float air_density;
- float dust_density;
- float ozone_density;
- float3 vector;
+ NODE_SOCKET_API(NodeSkyType, sky_type)
+ NODE_SOCKET_API(float3, sun_direction)
+ NODE_SOCKET_API(float, turbidity)
+ NODE_SOCKET_API(float, ground_albedo)
+ NODE_SOCKET_API(bool, sun_disc)
+ NODE_SOCKET_API(float, sun_size)
+ NODE_SOCKET_API(float, sun_intensity)
+ NODE_SOCKET_API(float, sun_elevation)
+ NODE_SOCKET_API(float, sun_rotation)
+ NODE_SOCKET_API(float, altitude)
+ NODE_SOCKET_API(float, air_density)
+ NODE_SOCKET_API(float, dust_density)
+ NODE_SOCKET_API(float, ozone_density)
+ NODE_SOCKET_API(float3, vector)
ImageHandle handle;
float get_sun_size()
@@ -191,10 +202,10 @@ class OutputNode : public ShaderNode {
public:
SHADER_NODE_CLASS(OutputNode)
- void *surface;
- void *volume;
- float3 displacement;
- float3 normal;
+ NODE_SOCKET_API(Node *, surface)
+ NODE_SOCKET_API(Node *, volume)
+ NODE_SOCKET_API(float3, displacement)
+ NODE_SOCKET_API(float3, normal)
/* Don't allow output node de-duplication. */
virtual bool equals(const ShaderNode & /*other*/)
@@ -208,10 +219,10 @@ class OutputAOVNode : public ShaderNode {
SHADER_NODE_CLASS(OutputAOVNode)
virtual void simplify_settings(Scene *scene);
- float value;
- float3 color;
+ NODE_SOCKET_API(float, value)
+ NODE_SOCKET_API(float3, color)
- ustring name;
+ NODE_SOCKET_API(ustring, name)
virtual int get_group()
{
@@ -237,17 +248,21 @@ class GradientTextureNode : public TextureNode {
return NODE_GROUP_LEVEL_2;
}
- NodeGradientType type;
- float3 vector;
+ NODE_SOCKET_API(NodeGradientType, gradient_type)
+ NODE_SOCKET_API(float3, vector)
};
class NoiseTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(NoiseTextureNode)
- int dimensions;
- float w, scale, detail, roughness, distortion;
- float3 vector;
+ NODE_SOCKET_API(int, dimensions)
+ NODE_SOCKET_API(float, w)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, detail)
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(float, distortion)
+ NODE_SOCKET_API(float3, vector)
};
class VoronoiTextureNode : public TextureNode {
@@ -271,11 +286,15 @@ class VoronoiTextureNode : public TextureNode {
return result;
}
- int dimensions;
- NodeVoronoiDistanceMetric metric;
- NodeVoronoiFeature feature;
- float w, scale, exponent, smoothness, randomness;
- float3 vector;
+ NODE_SOCKET_API(int, dimensions)
+ NODE_SOCKET_API(NodeVoronoiDistanceMetric, metric)
+ NODE_SOCKET_API(NodeVoronoiFeature, feature)
+ NODE_SOCKET_API(float, w)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, exponent)
+ NODE_SOCKET_API(float, smoothness)
+ NODE_SOCKET_API(float, randomness)
+ NODE_SOCKET_API(float3, vector)
};
class MusgraveTextureNode : public TextureNode {
@@ -287,10 +306,16 @@ class MusgraveTextureNode : public TextureNode {
return NODE_GROUP_LEVEL_2;
}
- int dimensions;
- NodeMusgraveType type;
- float w, scale, detail, dimension, lacunarity, offset, gain;
- float3 vector;
+ NODE_SOCKET_API(int, dimensions)
+ NODE_SOCKET_API(NodeMusgraveType, musgrave_type)
+ NODE_SOCKET_API(float, w)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, detail)
+ NODE_SOCKET_API(float, dimension)
+ NODE_SOCKET_API(float, lacunarity)
+ NODE_SOCKET_API(float, offset)
+ NODE_SOCKET_API(float, gain)
+ NODE_SOCKET_API(float3, vector)
};
class WaveTextureNode : public TextureNode {
@@ -302,13 +327,18 @@ class WaveTextureNode : public TextureNode {
return NODE_GROUP_LEVEL_2;
}
- NodeWaveType type;
- NodeWaveBandsDirection bands_direction;
- NodeWaveRingsDirection rings_direction;
- NodeWaveProfile profile;
+ NODE_SOCKET_API(NodeWaveType, wave_type)
+ NODE_SOCKET_API(NodeWaveBandsDirection, bands_direction)
+ NODE_SOCKET_API(NodeWaveRingsDirection, rings_direction)
+ NODE_SOCKET_API(NodeWaveProfile, profile)
- float scale, distortion, detail, detail_scale, detail_roughness, phase;
- float3 vector;
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, distortion)
+ NODE_SOCKET_API(float, detail)
+ NODE_SOCKET_API(float, detail_scale)
+ NODE_SOCKET_API(float, detail_roughness)
+ NODE_SOCKET_API(float, phase)
+ NODE_SOCKET_API(float3, vector)
};
class MagicTextureNode : public TextureNode {
@@ -320,17 +350,20 @@ class MagicTextureNode : public TextureNode {
return NODE_GROUP_LEVEL_2;
}
- int depth;
- float3 vector;
- float scale, distortion;
+ NODE_SOCKET_API(int, depth)
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, distortion)
};
class CheckerTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(CheckerTextureNode)
- float3 vector, color1, color2;
- float scale;
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float3, color1)
+ NODE_SOCKET_API(float3, color2)
+ NODE_SOCKET_API(float, scale)
virtual int get_group()
{
@@ -342,12 +375,21 @@ class BrickTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(BrickTextureNode)
- float offset, squash;
- int offset_frequency, squash_frequency;
-
- float3 color1, color2, mortar;
- float scale, mortar_size, mortar_smooth, bias, brick_width, row_height;
- float3 vector;
+ NODE_SOCKET_API(float, offset)
+ NODE_SOCKET_API(float, squash)
+ NODE_SOCKET_API(int, offset_frequency)
+ NODE_SOCKET_API(int, squash_frequency)
+
+ NODE_SOCKET_API(float3, color1)
+ NODE_SOCKET_API(float3, color2)
+ NODE_SOCKET_API(float3, mortar)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, mortar_size)
+ NODE_SOCKET_API(float, mortar_smooth)
+ NODE_SOCKET_API(float, bias)
+ NODE_SOCKET_API(float, brick_width)
+ NODE_SOCKET_API(float, row_height)
+ NODE_SOCKET_API(float3, vector)
virtual int get_group()
{
@@ -377,11 +419,11 @@ class PointDensityTextureNode : public ShaderNode {
}
/* Parameters. */
- ustring filename;
- NodeTexVoxelSpace space;
- InterpolationType interpolation;
- Transform tfm;
- float3 vector;
+ NODE_SOCKET_API(ustring, filename)
+ NODE_SOCKET_API(NodeTexVoxelSpace, space)
+ NODE_SOCKET_API(InterpolationType, interpolation)
+ NODE_SOCKET_API(Transform, tfm)
+ NODE_SOCKET_API(float3, vector)
/* Runtime. */
ImageHandle handle;
@@ -406,11 +448,11 @@ class IESLightNode : public TextureNode {
return NODE_GROUP_LEVEL_2;
}
- ustring filename;
- ustring ies;
+ NODE_SOCKET_API(ustring, filename)
+ NODE_SOCKET_API(ustring, ies)
- float strength;
- float3 vector;
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float3, vector)
private:
LightManager *light_manager;
@@ -427,9 +469,9 @@ class WhiteNoiseTextureNode : public ShaderNode {
return NODE_GROUP_LEVEL_2;
}
- int dimensions;
- float3 vector;
- float w;
+ NODE_SOCKET_API(int, dimensions)
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float, w)
};
class MappingNode : public ShaderNode {
@@ -441,8 +483,11 @@ class MappingNode : public ShaderNode {
}
void constant_fold(const ConstantFolder &folder);
- float3 vector, location, rotation, scale;
- NodeMappingType type;
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float3, location)
+ NODE_SOCKET_API(float3, rotation)
+ NODE_SOCKET_API(float3, scale)
+ NODE_SOCKET_API(NodeMappingType, mapping_type)
};
class RGBToBWNode : public ShaderNode {
@@ -450,7 +495,7 @@ class RGBToBWNode : public ShaderNode {
SHADER_NODE_CLASS(RGBToBWNode)
void constant_fold(const ConstantFolder &folder);
- float3 color;
+ NODE_SOCKET_API(float3, color)
};
class ConvertNode : public ShaderNode {
@@ -460,6 +505,7 @@ class ConvertNode : public ShaderNode {
void constant_fold(const ConstantFolder &folder);
+ private:
SocketType::Type from, to;
union {
@@ -472,7 +518,6 @@ class ConvertNode : public ShaderNode {
};
ustring value_string;
- private:
static const int MAX_TYPE = 12;
static bool register_types();
static Node *create(const NodeType *type);
@@ -500,6 +545,7 @@ class BsdfBaseNode : public ShaderNode {
return false;
}
+ protected:
ClosureType closure;
};
@@ -514,18 +560,20 @@ class BsdfNode : public BsdfBaseNode {
ShaderInput *param3 = NULL,
ShaderInput *param4 = NULL);
- float3 color;
- float3 normal;
- float surface_mix_weight;
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float, surface_mix_weight)
};
class AnisotropicBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(AnisotropicBsdfNode)
- float3 tangent;
- float roughness, anisotropy, rotation;
- ClosureType distribution;
+ NODE_SOCKET_API(float3, tangent)
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(float, anisotropy)
+ NODE_SOCKET_API(float, rotation)
+ NODE_SOCKET_API(ClosureType, distribution)
ClosureType get_closure_type()
{
@@ -542,7 +590,7 @@ class DiffuseBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(DiffuseBsdfNode)
- float roughness;
+ NODE_SOCKET_API(float, roughness)
};
/* Disney principled BRDF */
@@ -570,19 +618,37 @@ class PrincipledBsdfNode : public BsdfBaseNode {
ShaderInput *anisotropic_rotation,
ShaderInput *transmission_roughness);
- float3 base_color;
- float3 subsurface_color, subsurface_radius;
- float metallic, subsurface, specular, roughness, specular_tint, anisotropic, sheen, sheen_tint,
- clearcoat, clearcoat_roughness, ior, transmission, anisotropic_rotation,
- transmission_roughness;
- float3 normal, clearcoat_normal, tangent;
- float surface_mix_weight;
- ClosureType distribution, distribution_orig;
- ClosureType subsurface_method;
- float3 emission;
- float emission_strength;
- float alpha;
+ NODE_SOCKET_API(float3, base_color)
+ NODE_SOCKET_API(float3, subsurface_color)
+ NODE_SOCKET_API(float3, subsurface_radius)
+ NODE_SOCKET_API(float, metallic)
+ NODE_SOCKET_API(float, subsurface)
+ NODE_SOCKET_API(float, specular)
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(float, specular_tint)
+ NODE_SOCKET_API(float, anisotropic)
+ NODE_SOCKET_API(float, sheen)
+ NODE_SOCKET_API(float, sheen_tint)
+ NODE_SOCKET_API(float, clearcoat)
+ NODE_SOCKET_API(float, clearcoat_roughness)
+ NODE_SOCKET_API(float, ior)
+ NODE_SOCKET_API(float, transmission)
+ NODE_SOCKET_API(float, anisotropic_rotation)
+ NODE_SOCKET_API(float, transmission_roughness)
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float3, clearcoat_normal)
+ NODE_SOCKET_API(float3, tangent)
+ NODE_SOCKET_API(float, surface_mix_weight)
+ NODE_SOCKET_API(ClosureType, distribution)
+ NODE_SOCKET_API(ClosureType, subsurface_method)
+ NODE_SOCKET_API(float3, emission)
+ NODE_SOCKET_API(float, emission_strength)
+ NODE_SOCKET_API(float, alpha)
+ private:
+ ClosureType distribution_orig;
+
+ public:
bool has_integrator_dependency();
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_attribute_dependency()
@@ -610,7 +676,7 @@ class VelvetBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(VelvetBsdfNode)
- float sigma;
+ NODE_SOCKET_API(float, sigma)
};
class GlossyBsdfNode : public BsdfNode {
@@ -624,8 +690,12 @@ class GlossyBsdfNode : public BsdfNode {
return distribution;
}
- float roughness, roughness_orig;
- ClosureType distribution, distribution_orig;
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(ClosureType, distribution)
+
+ private:
+ float roughness_orig;
+ ClosureType distribution_orig;
};
class GlassBsdfNode : public BsdfNode {
@@ -639,8 +709,13 @@ class GlassBsdfNode : public BsdfNode {
return distribution;
}
- float roughness, roughness_orig, IOR;
- ClosureType distribution, distribution_orig;
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(float, IOR)
+ NODE_SOCKET_API(ClosureType, distribution)
+
+ private:
+ float roughness_orig;
+ ClosureType distribution_orig;
};
class RefractionBsdfNode : public BsdfNode {
@@ -654,16 +729,22 @@ class RefractionBsdfNode : public BsdfNode {
return distribution;
}
- float roughness, roughness_orig, IOR;
- ClosureType distribution, distribution_orig;
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(float, IOR)
+ NODE_SOCKET_API(ClosureType, distribution)
+
+ private:
+ float roughness_orig;
+ ClosureType distribution_orig;
};
class ToonBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(ToonBsdfNode)
- float smooth, size;
- ClosureType component;
+ NODE_SOCKET_API(float, smooth)
+ NODE_SOCKET_API(float, size)
+ NODE_SOCKET_API(ClosureType, component)
};
class SubsurfaceScatteringNode : public BsdfNode {
@@ -679,11 +760,11 @@ class SubsurfaceScatteringNode : public BsdfNode {
return falloff;
}
- float scale;
- float3 radius;
- float sharpness;
- float texture_blur;
- ClosureType falloff;
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float3, radius)
+ NODE_SOCKET_API(float, sharpness)
+ NODE_SOCKET_API(float, texture_blur)
+ NODE_SOCKET_API(ClosureType, falloff)
};
class EmissionNode : public ShaderNode {
@@ -700,9 +781,9 @@ class EmissionNode : public ShaderNode {
return true;
}
- float3 color;
- float strength;
- float surface_mix_weight;
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float, surface_mix_weight)
};
class BackgroundNode : public ShaderNode {
@@ -710,9 +791,9 @@ class BackgroundNode : public ShaderNode {
SHADER_NODE_CLASS(BackgroundNode)
void constant_fold(const ConstantFolder &folder);
- float3 color;
- float strength;
- float surface_mix_weight;
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float, surface_mix_weight)
};
class HoldoutNode : public ShaderNode {
@@ -727,8 +808,8 @@ class HoldoutNode : public ShaderNode {
return CLOSURE_HOLDOUT_ID;
}
- float surface_mix_weight;
- float volume_mix_weight;
+ NODE_SOCKET_API(float, surface_mix_weight)
+ NODE_SOCKET_API(float, volume_mix_weight)
};
class AmbientOcclusionNode : public ShaderNode {
@@ -748,13 +829,13 @@ class AmbientOcclusionNode : public ShaderNode {
return true;
}
- float3 color;
- float distance;
- float3 normal;
- int samples;
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, distance)
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(int, samples)
- bool only_local;
- bool inside;
+ NODE_SOCKET_API(bool, only_local)
+ NODE_SOCKET_API(bool, inside)
};
class VolumeNode : public ShaderNode {
@@ -780,11 +861,14 @@ class VolumeNode : public ShaderNode {
return true;
}
- float3 color;
- float density;
- float volume_mix_weight;
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, density)
+ NODE_SOCKET_API(float, volume_mix_weight)
+
+ protected:
ClosureType closure;
+ public:
virtual bool equals(const ShaderNode & /*other*/)
{
/* TODO(sergey): With some care Volume nodes can be de-duplicated. */
@@ -801,7 +885,7 @@ class ScatterVolumeNode : public VolumeNode {
public:
SHADER_NODE_CLASS(ScatterVolumeNode)
- float anisotropy;
+ NODE_SOCKET_API(float, anisotropy)
};
class PrincipledVolumeNode : public VolumeNode {
@@ -813,17 +897,17 @@ class PrincipledVolumeNode : public VolumeNode {
return true;
}
- ustring density_attribute;
- ustring color_attribute;
- ustring temperature_attribute;
+ NODE_SOCKET_API(ustring, density_attribute)
+ NODE_SOCKET_API(ustring, color_attribute)
+ NODE_SOCKET_API(ustring, temperature_attribute)
- float anisotropy;
- float3 absorption_color;
- float emission_strength;
- float3 emission_color;
- float blackbody_intensity;
- float3 blackbody_tint;
- float temperature;
+ NODE_SOCKET_API(float, anisotropy)
+ NODE_SOCKET_API(float3, absorption_color)
+ NODE_SOCKET_API(float, emission_strength)
+ NODE_SOCKET_API(float3, emission_color)
+ NODE_SOCKET_API(float, blackbody_intensity)
+ NODE_SOCKET_API(float3, blackbody_tint)
+ NODE_SOCKET_API(float, temperature)
};
/* Interface between the I/O sockets and the SVM/OSL backend. */
@@ -833,36 +917,36 @@ class PrincipledHairBsdfNode : public BsdfBaseNode {
void attributes(Shader *shader, AttributeRequestSet *attributes);
/* Longitudinal roughness. */
- float roughness;
+ NODE_SOCKET_API(float, roughness)
/* Azimuthal roughness. */
- float radial_roughness;
+ NODE_SOCKET_API(float, radial_roughness)
/* Randomization factor for roughnesses. */
- float random_roughness;
+ NODE_SOCKET_API(float, random_roughness)
/* Longitudinal roughness factor for only the diffuse bounce (shiny undercoat). */
- float coat;
+ NODE_SOCKET_API(float, coat)
/* Index of reflection. */
- float ior;
+ NODE_SOCKET_API(float, ior)
/* Cuticle tilt angle. */
- float offset;
+ NODE_SOCKET_API(float, offset)
/* Direct coloring's color. */
- float3 color;
+ NODE_SOCKET_API(float3, color)
/* Melanin concentration. */
- float melanin;
+ NODE_SOCKET_API(float, melanin)
/* Melanin redness ratio. */
- float melanin_redness;
+ NODE_SOCKET_API(float, melanin_redness)
/* Dye color. */
- float3 tint;
+ NODE_SOCKET_API(float3, tint)
/* Randomization factor for melanin quantities. */
- float random_color;
+ NODE_SOCKET_API(float, random_color)
/* Absorption coefficient (unfiltered). */
- float3 absorption_coefficient;
+ NODE_SOCKET_API(float3, absorption_coefficient)
- float3 normal;
- float surface_mix_weight;
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float, surface_mix_weight)
/* If linked, here will be the given random number. */
- float random;
+ NODE_SOCKET_API(float, random)
/* Selected coloring parametrization. */
- NodePrincipledHairParametrization parametrization;
+ NODE_SOCKET_API(NodePrincipledHairParametrization, parametrization)
};
class HairBsdfNode : public BsdfNode {
@@ -873,11 +957,11 @@ class HairBsdfNode : public BsdfNode {
return component;
}
- ClosureType component;
- float offset;
- float roughness_u;
- float roughness_v;
- float3 tangent;
+ NODE_SOCKET_API(ClosureType, component)
+ NODE_SOCKET_API(float, offset)
+ NODE_SOCKET_API(float, roughness_u)
+ NODE_SOCKET_API(float, roughness_v)
+ NODE_SOCKET_API(float3, tangent)
};
class GeometryNode : public ShaderNode {
@@ -894,7 +978,7 @@ class GeometryNode : public ShaderNode {
}
int get_group();
- float3 normal_osl;
+ NODE_SOCKET_API(float3, normal_osl)
};
class TextureCoordinateNode : public ShaderNode {
@@ -910,10 +994,10 @@ class TextureCoordinateNode : public ShaderNode {
return true;
}
- float3 normal_osl;
- bool from_dupli;
- bool use_transform;
- Transform ob_tfm;
+ NODE_SOCKET_API(float3, normal_osl)
+ NODE_SOCKET_API(bool, from_dupli)
+ NODE_SOCKET_API(bool, use_transform)
+ NODE_SOCKET_API(Transform, ob_tfm)
};
class UVMapNode : public ShaderNode {
@@ -933,8 +1017,8 @@ class UVMapNode : public ShaderNode {
return NODE_GROUP_LEVEL_1;
}
- ustring attribute;
- bool from_dupli;
+ NODE_SOCKET_API(ustring, attribute)
+ NODE_SOCKET_API(bool, from_dupli)
};
class LightPathNode : public ShaderNode {
@@ -958,8 +1042,8 @@ class LightFalloffNode : public ShaderNode {
return NODE_GROUP_LEVEL_2;
}
- float strength;
- float smooth;
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float, smooth)
};
class ObjectInfoNode : public ShaderNode {
@@ -1036,7 +1120,7 @@ class VertexColorNode : public ShaderNode {
return true;
}
- ustring layer_name;
+ NODE_SOCKET_API(ustring, layer_name)
};
class ValueNode : public ShaderNode {
@@ -1045,7 +1129,7 @@ class ValueNode : public ShaderNode {
void constant_fold(const ConstantFolder &folder);
- float value;
+ NODE_SOCKET_API(float, value)
};
class ColorNode : public ShaderNode {
@@ -1054,7 +1138,7 @@ class ColorNode : public ShaderNode {
void constant_fold(const ConstantFolder &folder);
- float3 value;
+ NODE_SOCKET_API(float3, value)
};
class AddClosureNode : public ShaderNode {
@@ -1068,15 +1152,15 @@ class MixClosureNode : public ShaderNode {
SHADER_NODE_CLASS(MixClosureNode)
void constant_fold(const ConstantFolder &folder);
- float fac;
+ NODE_SOCKET_API(float, fac)
};
class MixClosureWeightNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixClosureWeightNode)
- float weight;
- float fac;
+ NODE_SOCKET_API(float, weight)
+ NODE_SOCKET_API(float, fac)
};
class InvertNode : public ShaderNode {
@@ -1088,8 +1172,8 @@ class InvertNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- float fac;
- float3 color;
+ NODE_SOCKET_API(float, fac)
+ NODE_SOCKET_API(float3, color)
};
class MixNode : public ShaderNode {
@@ -1102,11 +1186,11 @@ class MixNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- NodeMix type;
- bool use_clamp;
- float3 color1;
- float3 color2;
- float fac;
+ NODE_SOCKET_API(NodeMix, mix_type)
+ NODE_SOCKET_API(bool, use_clamp)
+ NODE_SOCKET_API(float3, color1)
+ NODE_SOCKET_API(float3, color2)
+ NODE_SOCKET_API(float, fac)
};
class CombineRGBNode : public ShaderNode {
@@ -1118,7 +1202,9 @@ class CombineRGBNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- float r, g, b;
+ NODE_SOCKET_API(float, r)
+ NODE_SOCKET_API(float, g)
+ NODE_SOCKET_API(float, b)
};
class CombineHSVNode : public ShaderNode {
@@ -1130,7 +1216,9 @@ class CombineHSVNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- float h, s, v;
+ NODE_SOCKET_API(float, h)
+ NODE_SOCKET_API(float, s)
+ NODE_SOCKET_API(float, v)
};
class CombineXYZNode : public ShaderNode {
@@ -1142,7 +1230,9 @@ class CombineXYZNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- float x, y, z;
+ NODE_SOCKET_API(float, x)
+ NODE_SOCKET_API(float, y)
+ NODE_SOCKET_API(float, z)
};
class GammaNode : public ShaderNode {
@@ -1154,8 +1244,8 @@ class GammaNode : public ShaderNode {
return NODE_GROUP_LEVEL_1;
}
- float3 color;
- float gamma;
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, gamma)
};
class BrightContrastNode : public ShaderNode {
@@ -1167,9 +1257,9 @@ class BrightContrastNode : public ShaderNode {
return NODE_GROUP_LEVEL_1;
}
- float3 color;
- float bright;
- float contrast;
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, bright)
+ NODE_SOCKET_API(float, contrast)
};
class SeparateRGBNode : public ShaderNode {
@@ -1181,7 +1271,7 @@ class SeparateRGBNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- float3 color;
+ NODE_SOCKET_API(float3, color)
};
class SeparateHSVNode : public ShaderNode {
@@ -1193,7 +1283,7 @@ class SeparateHSVNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- float3 color;
+ NODE_SOCKET_API(float3, color)
};
class SeparateXYZNode : public ShaderNode {
@@ -1205,18 +1295,18 @@ class SeparateXYZNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- float3 vector;
+ NODE_SOCKET_API(float3, vector)
};
class HSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(HSVNode)
- float hue;
- float saturation;
- float value;
- float fac;
- float3 color;
+ NODE_SOCKET_API(float, hue)
+ NODE_SOCKET_API(float, saturation)
+ NODE_SOCKET_API(float, value)
+ NODE_SOCKET_API(float, fac)
+ NODE_SOCKET_API(float3, color)
};
class AttributeNode : public ShaderNode {
@@ -1232,7 +1322,7 @@ class AttributeNode : public ShaderNode {
return true;
}
- ustring attribute;
+ NODE_SOCKET_API(ustring, attribute)
};
class CameraNode : public ShaderNode {
@@ -1260,8 +1350,8 @@ class FresnelNode : public ShaderNode {
return NODE_GROUP_LEVEL_1;
}
- float3 normal;
- float IOR;
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float, IOR)
};
class LayerWeightNode : public ShaderNode {
@@ -1276,8 +1366,8 @@ class LayerWeightNode : public ShaderNode {
return NODE_GROUP_LEVEL_1;
}
- float3 normal;
- float blend;
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float, blend)
};
class WireframeNode : public ShaderNode {
@@ -1292,8 +1382,8 @@ class WireframeNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- float size;
- bool use_pixel_size;
+ NODE_SOCKET_API(float, size)
+ NODE_SOCKET_API(bool, use_pixel_size)
};
class WavelengthNode : public ShaderNode {
@@ -1304,7 +1394,7 @@ class WavelengthNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- float wavelength;
+ NODE_SOCKET_API(float, wavelength)
};
class BlackbodyNode : public ShaderNode {
@@ -1316,7 +1406,7 @@ class BlackbodyNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- float temperature;
+ NODE_SOCKET_API(float, temperature)
};
class MapRangeNode : public ShaderNode {
@@ -1328,9 +1418,14 @@ class MapRangeNode : public ShaderNode {
}
void expand(ShaderGraph *graph);
- float value, from_min, from_max, to_min, to_max, steps;
- NodeMapRangeType type;
- bool clamp;
+ NODE_SOCKET_API(float, value)
+ NODE_SOCKET_API(float, from_min)
+ NODE_SOCKET_API(float, from_max)
+ NODE_SOCKET_API(float, to_min)
+ NODE_SOCKET_API(float, to_max)
+ NODE_SOCKET_API(float, steps)
+ NODE_SOCKET_API(NodeMapRangeType, range_type)
+ NODE_SOCKET_API(bool, clamp)
};
class ClampNode : public ShaderNode {
@@ -1341,8 +1436,10 @@ class ClampNode : public ShaderNode {
{
return NODE_GROUP_LEVEL_3;
}
- float value, min, max;
- NodeClampType type;
+ NODE_SOCKET_API(float, value)
+ NODE_SOCKET_API(float, min)
+ NODE_SOCKET_API(float, max)
+ NODE_SOCKET_API(NodeClampType, clamp_type)
};
class MathNode : public ShaderNode {
@@ -1355,11 +1452,11 @@ class MathNode : public ShaderNode {
void expand(ShaderGraph *graph);
void constant_fold(const ConstantFolder &folder);
- float value1;
- float value2;
- float value3;
- NodeMathType type;
- bool use_clamp;
+ NODE_SOCKET_API(float, value1)
+ NODE_SOCKET_API(float, value2)
+ NODE_SOCKET_API(float, value3)
+ NODE_SOCKET_API(NodeMathType, math_type)
+ NODE_SOCKET_API(bool, use_clamp)
};
class NormalNode : public ShaderNode {
@@ -1370,8 +1467,8 @@ class NormalNode : public ShaderNode {
return NODE_GROUP_LEVEL_2;
}
- float3 direction;
- float3 normal;
+ NODE_SOCKET_API(float3, direction)
+ NODE_SOCKET_API(float3, normal)
};
class VectorMathNode : public ShaderNode {
@@ -1383,11 +1480,11 @@ class VectorMathNode : public ShaderNode {
}
void constant_fold(const ConstantFolder &folder);
- float3 vector1;
- float3 vector2;
- float3 vector3;
- float scale;
- NodeVectorMathType type;
+ NODE_SOCKET_API(float3, vector1)
+ NODE_SOCKET_API(float3, vector2)
+ NODE_SOCKET_API(float3, vector3)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(NodeVectorMathType, math_type)
};
class VectorRotateNode : public ShaderNode {
@@ -1398,13 +1495,13 @@ class VectorRotateNode : public ShaderNode {
{
return NODE_GROUP_LEVEL_3;
}
- NodeVectorRotateType type;
- bool invert;
- float3 vector;
- float3 center;
- float3 axis;
- float angle;
- float3 rotation;
+ NODE_SOCKET_API(NodeVectorRotateType, rotate_type)
+ NODE_SOCKET_API(bool, invert)
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float3, center)
+ NODE_SOCKET_API(float3, axis)
+ NODE_SOCKET_API(float, angle)
+ NODE_SOCKET_API(float3, rotation)
};
class VectorTransformNode : public ShaderNode {
@@ -1416,10 +1513,10 @@ class VectorTransformNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- NodeVectorTransformType type;
- NodeVectorTransformConvertSpace convert_from;
- NodeVectorTransformConvertSpace convert_to;
- float3 vector;
+ NODE_SOCKET_API(NodeVectorTransformType, transform_type)
+ NODE_SOCKET_API(NodeVectorTransformConvertSpace, convert_from)
+ NODE_SOCKET_API(NodeVectorTransformConvertSpace, convert_to)
+ NODE_SOCKET_API(float3, vector)
};
class BumpNode : public ShaderNode {
@@ -1435,15 +1532,15 @@ class BumpNode : public ShaderNode {
return NODE_FEATURE_BUMP;
}
- bool invert;
- bool use_object_space;
- float height;
- float sample_center;
- float sample_x;
- float sample_y;
- float3 normal;
- float strength;
- float distance;
+ NODE_SOCKET_API(bool, invert)
+ NODE_SOCKET_API(bool, use_object_space)
+ NODE_SOCKET_API(float, height)
+ NODE_SOCKET_API(float, sample_center)
+ NODE_SOCKET_API(float, sample_x)
+ NODE_SOCKET_API(float, sample_y)
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float, distance)
};
class CurvesNode : public ShaderNode {
@@ -1456,9 +1553,11 @@ class CurvesNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- array<float3> curves;
- float min_x, max_x, fac;
- float3 value;
+ NODE_SOCKET_API(array<float3>, curves)
+ NODE_SOCKET_API(float, min_x)
+ NODE_SOCKET_API(float, max_x)
+ NODE_SOCKET_API(float, fac)
+ NODE_SOCKET_API(float3, value)
protected:
using ShaderNode::constant_fold;
@@ -1488,16 +1587,16 @@ class RGBRampNode : public ShaderNode {
return NODE_GROUP_LEVEL_1;
}
- array<float3> ramp;
- array<float> ramp_alpha;
- float fac;
- bool interpolate;
+ NODE_SOCKET_API(array<float3>, ramp)
+ NODE_SOCKET_API(array<float>, ramp_alpha)
+ NODE_SOCKET_API(float, fac)
+ NODE_SOCKET_API(bool, interpolate)
};
class SetNormalNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SetNormalNode)
- float3 direction;
+ NODE_SOCKET_API(float3, direction)
};
class OSLNode : public ShaderNode {
@@ -1549,11 +1648,11 @@ class NormalMapNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- NodeNormalMapSpace space;
- ustring attribute;
- float strength;
- float3 color;
- float3 normal_osl;
+ NODE_SOCKET_API(NodeNormalMapSpace, space)
+ NODE_SOCKET_API(ustring, attribute)
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float3, normal_osl)
};
class TangentNode : public ShaderNode {
@@ -1573,10 +1672,10 @@ class TangentNode : public ShaderNode {
return NODE_GROUP_LEVEL_3;
}
- NodeTangentDirectionType direction_type;
- NodeTangentAxis axis;
- ustring attribute;
- float3 normal_osl;
+ NODE_SOCKET_API(NodeTangentDirectionType, direction_type)
+ NODE_SOCKET_API(NodeTangentAxis, axis)
+ NODE_SOCKET_API(ustring, attribute)
+ NODE_SOCKET_API(float3, normal_osl)
};
class BevelNode : public ShaderNode {
@@ -1595,9 +1694,9 @@ class BevelNode : public ShaderNode {
return true;
}
- float radius;
- float3 normal;
- int samples;
+ NODE_SOCKET_API(float, radius)
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(int, samples)
};
class DisplacementNode : public ShaderNode {
@@ -1609,11 +1708,11 @@ class DisplacementNode : public ShaderNode {
return NODE_FEATURE_BUMP;
}
- NodeNormalMapSpace space;
- float height;
- float midlevel;
- float scale;
- float3 normal;
+ NODE_SOCKET_API(NodeNormalMapSpace, space)
+ NODE_SOCKET_API(float, height)
+ NODE_SOCKET_API(float, midlevel)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float3, normal)
};
class VectorDisplacementNode : public ShaderNode {
@@ -1630,11 +1729,11 @@ class VectorDisplacementNode : public ShaderNode {
return NODE_FEATURE_BUMP;
}
- NodeNormalMapSpace space;
- ustring attribute;
- float3 vector;
- float midlevel;
- float scale;
+ NODE_SOCKET_API(NodeNormalMapSpace, space)
+ NODE_SOCKET_API(ustring, attribute)
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float, midlevel)
+ NODE_SOCKET_API(float, scale)
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index bce2e08b390..70ce60252f0 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -104,9 +104,13 @@ NODE_DEFINE(Object)
SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f));
SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
SOCKET_FLOAT(shadow_terminator_offset, "Terminator Offset", 0.0f);
+ SOCKET_STRING(asset_name, "Asset Name", ustring());
SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false);
+ SOCKET_NODE(particle_system, "Particle System", &ParticleSystem::node_type);
+ SOCKET_INT(particle_index, "Particle Index", 0);
+
return type;
}
@@ -114,6 +118,7 @@ Object::Object() : Node(node_type)
{
particle_system = NULL;
particle_index = 0;
+ attr_map_offset = 0;
bounds = BoundBox::empty;
}
@@ -212,10 +217,11 @@ void Object::tag_update(Scene *scene)
{
if (geometry) {
if (geometry->transform_applied)
- geometry->need_update = true;
+ geometry->tag_modified();
- foreach (Shader *shader, geometry->used_shaders) {
- if (shader->use_mis && shader->has_surface_emission)
+ foreach (Node *node, geometry->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
+ if (shader->get_use_mis() && shader->has_surface_emission)
scene->light_manager->need_update = true;
}
}
@@ -272,7 +278,7 @@ uint Object::visibility_for_tracing() const
float Object::compute_volume_step_size() const
{
- if (geometry->type != Geometry::MESH && geometry->type != Geometry::VOLUME) {
+ if (geometry->geometry_type != Geometry::MESH && geometry->geometry_type != Geometry::VOLUME) {
return FLT_MAX;
}
@@ -285,11 +291,12 @@ float Object::compute_volume_step_size() const
/* Compute step rate from shaders. */
float step_rate = FLT_MAX;
- foreach (Shader *shader, mesh->used_shaders) {
+ foreach (Node *node, mesh->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
if (shader->has_volume) {
- if ((shader->heterogeneous_volume && shader->has_volume_spatial_varying) ||
+ if ((shader->get_heterogeneous_volume() && shader->has_volume_spatial_varying) ||
(shader->has_volume_attribute_dependency)) {
- step_rate = fminf(shader->volume_step_rate, step_rate);
+ step_rate = fminf(shader->get_volume_step_rate(), step_rate);
}
}
}
@@ -301,7 +308,7 @@ float Object::compute_volume_step_size() const
/* Compute step size from voxel grids. */
float step_size = FLT_MAX;
- if (geometry->type == Geometry::VOLUME) {
+ if (geometry->geometry_type == Geometry::VOLUME) {
Volume *volume = static_cast<Volume *>(geometry);
foreach (Attribute &attr, volume->attributes.attributes) {
@@ -313,12 +320,17 @@ float Object::compute_volume_step_size() const
}
/* User specified step size. */
- float voxel_step_size = volume->step_size;
+ float voxel_step_size = volume->get_step_size();
if (voxel_step_size == 0.0f) {
/* Auto detect step size. */
- float3 size = make_float3(
- 1.0f / metadata.width, 1.0f / metadata.height, 1.0f / metadata.depth);
+ float3 size = make_float3(1.0f, 1.0f, 1.0f);
+#ifdef WITH_NANOVDB
+ /* Dimensions were not applied to image transform with NanOVDB (see image_vdb.cpp) */
+ if (metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
+ metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3)
+#endif
+ size /= make_float3(metadata.width, metadata.height, metadata.depth);
/* Step size is transformed from voxel to world space. */
Transform voxel_tfm = tfm;
@@ -327,7 +339,7 @@ float Object::compute_volume_step_size() const
}
voxel_step_size = min3(fabs(transform_direction(&voxel_tfm, size)));
}
- else if (volume->object_space) {
+ else if (volume->get_object_space()) {
/* User specified step size in object space. */
float3 size = make_float3(voxel_step_size, voxel_step_size, voxel_step_size);
voxel_step_size = min3(fabs(transform_direction(&tfm, size)));
@@ -371,14 +383,15 @@ static float object_surface_area(UpdateObjectTransformState *state,
const Transform &tfm,
Geometry *geom)
{
- if (geom->type != Geometry::MESH && geom->type != Geometry::VOLUME) {
+ if (geom->geometry_type != Geometry::MESH && geom->geometry_type != Geometry::VOLUME) {
return 0.0f;
}
Mesh *mesh = static_cast<Mesh *>(geom);
- if (mesh->has_volume || geom->type == Geometry::VOLUME) {
+ if (mesh->has_volume || geom->geometry_type == Geometry::VOLUME) {
/* Volume density automatically adjust to object scale. */
- if (geom->type == Geometry::VOLUME && static_cast<Volume *>(geom)->object_space) {
+ if (geom->geometry_type == Geometry::VOLUME &&
+ static_cast<Volume *>(geom)->get_object_space()) {
const float3 unit = normalize(make_float3(1.0f, 1.0f, 1.0f));
return 1.0f / len(transform_direction(&tfm, unit));
}
@@ -410,9 +423,9 @@ static float object_surface_area(UpdateObjectTransformState *state,
size_t num_triangles = mesh->num_triangles();
for (size_t j = 0; j < num_triangles; j++) {
Mesh::Triangle t = mesh->get_triangle(j);
- float3 p1 = mesh->verts[t.v[0]];
- float3 p2 = mesh->verts[t.v[1]];
- float3 p3 = mesh->verts[t.v[2]];
+ float3 p1 = mesh->get_verts()[t.v[0]];
+ float3 p2 = mesh->get_verts()[t.v[1]];
+ float3 p3 = mesh->get_verts()[t.v[2]];
surface_area += triangle_area(p1, p2, p3);
}
@@ -431,9 +444,9 @@ static float object_surface_area(UpdateObjectTransformState *state,
size_t num_triangles = mesh->num_triangles();
for (size_t j = 0; j < num_triangles; j++) {
Mesh::Triangle t = mesh->get_triangle(j);
- float3 p1 = transform_point(&tfm, mesh->verts[t.v[0]]);
- float3 p2 = transform_point(&tfm, mesh->verts[t.v[1]]);
- float3 p3 = transform_point(&tfm, mesh->verts[t.v[2]]);
+ float3 p1 = transform_point(&tfm, mesh->get_verts()[t.v[0]]);
+ float3 p2 = transform_point(&tfm, mesh->get_verts()[t.v[1]]);
+ float3 p3 = transform_point(&tfm, mesh->get_verts()[t.v[2]]);
surface_area += triangle_area(p1, p2, p3);
}
@@ -472,11 +485,11 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
kobject.particle_index = particle_index;
kobject.motion_offset = 0;
- if (geom->use_motion_blur) {
+ if (geom->get_use_motion_blur()) {
state->have_motion = true;
}
- if (geom->type == Geometry::MESH) {
+ if (geom->geometry_type == Geometry::MESH) {
/* TODO: why only mesh? */
Mesh *mesh = static_cast<Mesh *>(geom);
if (mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
@@ -527,14 +540,16 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
kobject.dupli_generated[0] = ob->dupli_generated[0];
kobject.dupli_generated[1] = ob->dupli_generated[1];
kobject.dupli_generated[2] = ob->dupli_generated[2];
- kobject.numkeys = (geom->type == Geometry::HAIR) ? static_cast<Hair *>(geom)->curve_keys.size() :
- 0;
+ kobject.numkeys = (geom->geometry_type == Geometry::HAIR) ?
+ static_cast<Hair *>(geom)->get_curve_keys().size() :
+ 0;
kobject.dupli_uv[0] = ob->dupli_uv[0];
kobject.dupli_uv[1] = ob->dupli_uv[1];
- int totalsteps = geom->motion_steps;
+ int totalsteps = geom->get_motion_steps();
kobject.numsteps = (totalsteps - 1) / 2;
- kobject.numverts = (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) ?
- static_cast<Mesh *>(geom)->verts.size() :
+ kobject.numverts = (geom->geometry_type == Geometry::MESH ||
+ geom->geometry_type == Geometry::VOLUME) ?
+ static_cast<Mesh *>(geom)->get_verts().size() :
0;
kobject.patch_map_offset = 0;
kobject.attribute_map_offset = 0;
@@ -552,7 +567,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
state->object_volume_step[ob->index] = FLT_MAX;
/* Have curves. */
- if (geom->type == Geometry::HAIR) {
+ if (geom->geometry_type == Geometry::HAIR) {
state->have_curves = true;
}
}
@@ -687,6 +702,10 @@ void ObjectManager::device_update(Device *device,
progress.set_status("Updating Objects", "Applying Static Transformations");
apply_static_transforms(dscene, scene, progress);
}
+
+ foreach (Object *object, scene->objects) {
+ object->clear_modified();
+ }
}
void ObjectManager::device_update_flags(
@@ -786,7 +805,7 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc
foreach (Object *object, scene->objects) {
Geometry *geom = object->geometry;
- if (geom->type == Geometry::MESH) {
+ if (geom->geometry_type == Geometry::MESH) {
Mesh *mesh = static_cast<Mesh *>(geom);
if (mesh->patch_table) {
uint patch_map_offset = 2 * (mesh->patch_table_offset + mesh->patch_table->total_size() -
@@ -800,8 +819,15 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc
}
}
- if (kobjects[object->index].attribute_map_offset != geom->attr_map_offset) {
- kobjects[object->index].attribute_map_offset = geom->attr_map_offset;
+ size_t attr_map_offset = object->attr_map_offset;
+
+ /* An object attribute map cannot have a zero offset because mesh maps come first. */
+ if (attr_map_offset == 0) {
+ attr_map_offset = geom->attr_map_offset;
+ }
+
+ if (kobjects[object->index].attribute_map_offset != attr_map_offset) {
+ kobjects[object->index].attribute_map_offset = attr_map_offset;
update = true;
}
}
@@ -857,11 +883,11 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P
bool apply = (geometry_users[geom] == 1) && !geom->has_surface_bssrdf &&
!geom->has_true_displacement();
- if (geom->type == Geometry::MESH || geom->type == Geometry::VOLUME) {
+ if (geom->geometry_type == Geometry::MESH) {
Mesh *mesh = static_cast<Mesh *>(geom);
- apply = apply && mesh->subdivision_type == Mesh::SUBDIVISION_NONE;
+ apply = apply && mesh->get_subdivision_type() == Mesh::SUBDIVISION_NONE;
}
- else if (geom->type == Geometry::HAIR) {
+ else if (geom->geometry_type == Geometry::HAIR) {
/* Can't apply non-uniform scale to curves, this can't be represented by
* control points and radius alone. */
float scale;
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index ac9b4c331f5..76c9c30abb0 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -18,6 +18,11 @@
#define __OBJECT_H__
#include "graph/node.h"
+
+/* included as Object::set_particle_system defined through NODE_SOCKET_API does
+ * not select the right Node::set overload as it does not know that ParticleSystem
+ * is a Node */
+#include "render/particles.h"
#include "render/scene.h"
#include "util/util_array.h"
@@ -46,26 +51,26 @@ class Object : public Node {
public:
NODE_DECLARE
- Geometry *geometry;
- Transform tfm;
+ NODE_SOCKET_API(Geometry *, geometry)
+ NODE_SOCKET_API(Transform, tfm)
BoundBox bounds;
- uint random_id;
- int pass_id;
- float3 color;
- ustring asset_name;
+ NODE_SOCKET_API(uint, random_id)
+ NODE_SOCKET_API(int, pass_id)
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(ustring, asset_name)
vector<ParamValue> attributes;
- uint visibility;
- array<Transform> motion;
- bool hide_on_missing_motion;
- bool use_holdout;
- bool is_shadow_catcher;
- float shadow_terminator_offset;
+ NODE_SOCKET_API(uint, visibility)
+ NODE_SOCKET_API_ARRAY(array<Transform>, motion)
+ NODE_SOCKET_API(bool, hide_on_missing_motion)
+ NODE_SOCKET_API(bool, use_holdout)
+ NODE_SOCKET_API(bool, is_shadow_catcher)
+ NODE_SOCKET_API(float, shadow_terminator_offset)
- float3 dupli_generated;
- float2 dupli_uv;
+ NODE_SOCKET_API(float3, dupli_generated)
+ NODE_SOCKET_API(float2, dupli_uv)
- ParticleSystem *particle_system;
- int particle_index;
+ NODE_SOCKET_API(ParticleSystem *, particle_system);
+ NODE_SOCKET_API(int, particle_index);
Object();
~Object();
@@ -106,7 +111,12 @@ class Object : public Node {
* in the device vectors. Gets set in device_update. */
int index;
+ /* Reference to the attribute map with object attributes,
+ * or 0 if none. Set in update_svm_attributes. */
+ size_t attr_map_offset;
+
friend class ObjectManager;
+ friend class GeometryManager;
};
/* Object Manager */
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 0c2b2cf27e9..bea2c534bd1 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -131,7 +131,7 @@ void OSLShaderManager::device_update(Device *device,
compiler.background = (shader == background_shader);
compiler.compile(og, shader);
- if (shader->use_mis && shader->has_surface_emission)
+ if (shader->get_use_mis() && shader->has_surface_emission)
scene->light_manager->need_update = true;
}
@@ -145,7 +145,7 @@ void OSLShaderManager::device_update(Device *device,
og->use = true;
foreach (Shader *shader, scene->shaders)
- shader->need_update = false;
+ shader->clear_modified();
need_update = false;
@@ -1120,18 +1120,18 @@ OSL::ShaderGroupRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph
void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
{
- if (shader->need_update) {
+ if (shader->is_modified()) {
ShaderGraph *graph = shader->graph;
ShaderNode *output = (graph) ? graph->output() : NULL;
- bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
+ bool has_bump = (shader->get_displacement_method() != DISPLACE_TRUE) &&
output->input("Surface")->link && output->input("Displacement")->link;
/* finalize */
shader->graph->finalize(scene,
has_bump,
shader->has_integrator_dependency,
- shader->displacement_method == DISPLACE_BOTH);
+ shader->get_displacement_method() == DISPLACE_BOTH);
current_shader = shader;
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 3fb6c9620e6..98c256a43b5 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -339,7 +339,7 @@ void Scene::device_update(Device *device_, Progress &progress)
Scene::MotionType Scene::need_motion()
{
- if (integrator->motion_blur)
+ if (integrator->get_motion_blur())
return MOTION_BLUR;
else if (Pass::contains(passes, PASS_MOTION))
return MOTION_PASS;
@@ -352,7 +352,7 @@ float Scene::motion_shutter_time()
if (need_motion() == Scene::MOTION_PASS)
return 2.0f;
else
- return camera->shuttertime;
+ return camera->get_shuttertime();
}
bool Scene::need_global_attribute(AttributeStandard std)
@@ -376,20 +376,21 @@ void Scene::need_global_attributes(AttributeRequestSet &attributes)
bool Scene::need_update()
{
- return (need_reset() || film->need_update);
+ return (need_reset() || film->is_modified());
}
bool Scene::need_data_update()
{
- return (background->need_update || image_manager->need_update || object_manager->need_update ||
+ return (background->is_modified() || image_manager->need_update || object_manager->need_update ||
geometry_manager->need_update || light_manager->need_update ||
- lookup_tables->need_update || integrator->need_update || shader_manager->need_update ||
- particle_system_manager->need_update || bake_manager->need_update || film->need_update);
+ lookup_tables->need_update || integrator->is_modified() || shader_manager->need_update ||
+ particle_system_manager->need_update || bake_manager->need_update ||
+ film->is_modified());
}
bool Scene::need_reset()
{
- return need_data_update() || camera->need_update;
+ return need_data_update() || camera->is_modified();
}
void Scene::reset()
@@ -398,9 +399,9 @@ void Scene::reset()
shader_manager->add_default(this);
/* ensure all objects are updated */
- camera->tag_update();
- dicing_camera->tag_update();
- film->tag_update(this);
+ camera->tag_modified();
+ dicing_camera->tag_modified();
+ film->tag_modified();
background->tag_update(this);
integrator->tag_update(this);
object_manager->tag_update(this);
@@ -442,24 +443,24 @@ DeviceRequestedFeatures Scene::get_requested_device_features()
requested_features.use_object_motion = false;
requested_features.use_camera_motion = use_motion && camera->use_motion();
foreach (Object *object, objects) {
- Geometry *geom = object->geometry;
+ Geometry *geom = object->get_geometry();
if (use_motion) {
- requested_features.use_object_motion |= object->use_motion() | geom->use_motion_blur;
- requested_features.use_camera_motion |= geom->use_motion_blur;
+ requested_features.use_object_motion |= object->use_motion() | geom->get_use_motion_blur();
+ requested_features.use_camera_motion |= geom->get_use_motion_blur();
}
- if (object->is_shadow_catcher) {
+ if (object->get_is_shadow_catcher()) {
requested_features.use_shadow_tricks = true;
}
- if (geom->type == Geometry::MESH) {
+ if (geom->is_mesh()) {
Mesh *mesh = static_cast<Mesh *>(geom);
#ifdef WITH_OPENSUBDIV
- if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
+ if (mesh->get_subdivision_type() != Mesh::SUBDIVISION_NONE) {
requested_features.use_patch_evaluation = true;
}
#endif
requested_features.use_true_displacement |= mesh->has_true_displacement();
}
- else if (geom->type == Geometry::HAIR) {
+ else if (geom->is_hair()) {
requested_features.use_hair = true;
}
}
@@ -467,8 +468,9 @@ DeviceRequestedFeatures Scene::get_requested_device_features()
requested_features.use_background_light = light_manager->has_background_light(this);
requested_features.use_baking = bake_manager->get_baking();
- requested_features.use_integrator_branched = (integrator->method == Integrator::BRANCHED_PATH);
- if (film->denoising_data_pass) {
+ requested_features.use_integrator_branched = (integrator->get_method() ==
+ Integrator::BRANCHED_PATH);
+ if (film->get_denoising_data_pass()) {
requested_features.use_denoising = true;
requested_features.use_shadow_tricks = true;
}
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index c22e29043d3..a60542259f6 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -61,22 +61,6 @@ Session::Session(const SessionParams &params_)
TaskScheduler::init(params.threads);
- /* Create CPU/GPU devices. */
- device = Device::create(params.device, stats, profiler, params.background);
-
- /* Create buffers for interactive rendering. */
- if (params.background && !params.write_render_cb) {
- buffers = NULL;
- display = NULL;
- }
- else {
- buffers = new RenderBuffers(device);
- display = new DisplayBuffer(device, params.display_buffer_linear);
- }
-
- /* Validate denoising parameters. */
- set_denoising(params.denoising);
-
session_thread = NULL;
scene = NULL;
@@ -90,6 +74,26 @@ Session::Session(const SessionParams &params_)
gpu_draw_ready = false;
gpu_need_display_buffer_update = false;
pause = false;
+
+ buffers = NULL;
+ display = NULL;
+
+ /* Validate denoising parameters. */
+ set_denoising(params.denoising);
+
+ /* Create CPU/GPU devices. */
+ device = Device::create(params.device, stats, profiler, params.background);
+
+ if (!device->error_message().empty()) {
+ progress.set_error(device->error_message());
+ return;
+ }
+
+ /* Create buffers for interactive rendering. */
+ if (!(params.background && !params.write_render_cb)) {
+ buffers = new RenderBuffers(device);
+ display = new DisplayBuffer(device, params.display_buffer_linear);
+ }
}
Session::~Session()
@@ -110,7 +114,7 @@ Session::~Session()
wait();
}
- if (params.write_render_cb) {
+ if (buffers && params.write_render_cb) {
/* Copy to display buffer and write out image if requested */
delete display;
@@ -378,6 +382,62 @@ bool Session::draw_cpu(BufferParams &buffer_params, DeviceDrawParams &draw_param
return false;
}
+bool Session::steal_tile(RenderTile &rtile, Device *tile_device, thread_scoped_lock &tile_lock)
+{
+ /* Devices that can get their tiles stolen don't steal tiles themselves.
+ * Additionally, if there are no stealable tiles in flight, give up here. */
+ if (tile_device->info.type == DEVICE_CPU || stealable_tiles == 0) {
+ return false;
+ }
+
+ /* Wait until no other thread is trying to steal a tile. */
+ while (tile_stealing_state != NOT_STEALING && stealable_tiles > 0) {
+ /* Someone else is currently trying to get a tile.
+ * Wait on the condition variable and try later. */
+ tile_steal_cond.wait(tile_lock);
+ }
+ /* If another thread stole the last stealable tile in the meantime, give up. */
+ if (stealable_tiles == 0) {
+ return false;
+ }
+
+ /* There are stealable tiles in flight, so signal that one should be released. */
+ tile_stealing_state = WAITING_FOR_TILE;
+
+ /* Wait until a device notices the signal and releases its tile. */
+ while (tile_stealing_state != GOT_TILE && stealable_tiles > 0) {
+ tile_steal_cond.wait(tile_lock);
+ }
+ /* If the last stealable tile finished on its own, give up. */
+ if (tile_stealing_state != GOT_TILE) {
+ tile_stealing_state = NOT_STEALING;
+ return false;
+ }
+
+ /* Successfully stole a tile, now move it to the new device. */
+ rtile = stolen_tile;
+ rtile.buffers->buffer.move_device(tile_device);
+ rtile.buffer = rtile.buffers->buffer.device_pointer;
+ rtile.stealing_state = RenderTile::NO_STEALING;
+ rtile.num_samples -= (rtile.sample - rtile.start_sample);
+ rtile.start_sample = rtile.sample;
+
+ tile_stealing_state = NOT_STEALING;
+
+ /* Poke any threads which might be waiting for NOT_STEALING above. */
+ tile_steal_cond.notify_one();
+
+ return true;
+}
+
+bool Session::get_tile_stolen()
+{
+ /* If tile_stealing_state is WAITING_FOR_TILE, atomically set it to RELEASING_TILE
+ * and return true. */
+ TileStealingState expected = WAITING_FOR_TILE;
+ return tile_stealing_state.compare_exchange_weak(expected, RELEASING_TILE);
+}
+
bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_types)
{
if (progress.get_cancel()) {
@@ -399,7 +459,8 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ
denoising_cond.wait(tile_lock);
continue;
}
- return false;
+
+ return steal_tile(rtile, tile_device, tile_lock);
}
/* fill render tile */
@@ -415,11 +476,18 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ
if (tile->state == Tile::DENOISE) {
rtile.task = RenderTile::DENOISE;
}
- else if (read_bake_tile_cb) {
- rtile.task = RenderTile::BAKE;
- }
else {
- rtile.task = RenderTile::PATH_TRACE;
+ if (tile_device->info.type == DEVICE_CPU) {
+ stealable_tiles++;
+ rtile.stealing_state = RenderTile::CAN_BE_STOLEN;
+ }
+
+ if (read_bake_tile_cb) {
+ rtile.task = RenderTile::BAKE;
+ }
+ else {
+ rtile.task = RenderTile::PATH_TRACE;
+ }
}
tile_lock.unlock();
@@ -504,6 +572,26 @@ void Session::release_tile(RenderTile &rtile, const bool need_denoise)
{
thread_scoped_lock tile_lock(tile_mutex);
+ if (rtile.stealing_state != RenderTile::NO_STEALING) {
+ stealable_tiles--;
+ if (rtile.stealing_state == RenderTile::WAS_STOLEN) {
+ /* If the tile is being stolen, don't release it here - the new device will pick up where
+ * the old one left off. */
+
+ assert(tile_stealing_state == RELEASING_TILE);
+ assert(rtile.sample < rtile.start_sample + rtile.num_samples);
+
+ tile_stealing_state = GOT_TILE;
+ stolen_tile = rtile;
+ tile_steal_cond.notify_all();
+ return;
+ }
+ else if (stealable_tiles == 0) {
+ /* If this was the last stealable tile, wake up any threads still waiting for one. */
+ tile_steal_cond.notify_all();
+ }
+ }
+
progress.add_finished_tile(rtile.task == RenderTile::DENOISE);
bool delete_tile;
@@ -811,6 +899,8 @@ void Session::reset_(BufferParams &buffer_params, int samples)
}
tile_manager.reset(buffer_params, samples);
+ stealable_tiles = 0;
+ tile_stealing_state = NOT_STEALING;
progress.reset_sample();
bool show_progress = params.background || tile_manager.get_num_effective_samples() != INT_MAX;
@@ -918,23 +1008,19 @@ 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 || resolution != cam->resolution) {
- cam->width = width;
- cam->height = height;
- cam->resolution = resolution;
- cam->tag_update();
- }
+ cam->set_screen_size_and_resolution(width, height, resolution);
/* number of samples is needed by multi jittered
* sampling pattern and by baking */
Integrator *integrator = scene->integrator;
BakeManager *bake_manager = scene->bake_manager;
- if (integrator->sampling_pattern != SAMPLING_PATTERN_SOBOL || bake_manager->get_baking()) {
+ if (integrator->get_sampling_pattern() != SAMPLING_PATTERN_SOBOL || bake_manager->get_baking()) {
int aa_samples = tile_manager.num_samples;
- if (aa_samples != integrator->aa_samples) {
- integrator->aa_samples = aa_samples;
+ integrator->set_aa_samples(aa_samples);
+
+ if (integrator->is_modified()) {
integrator->tag_update(scene);
}
}
@@ -1028,7 +1114,7 @@ bool Session::render_need_denoise(bool &delayed)
/* Viewport render. */
/* It can happen that denoising was already enabled, but the scene still needs an update. */
- if (scene->film->need_update || !scene->film->denoising_data_offset) {
+ if (scene->film->is_modified() || !scene->film->get_denoising_data_offset()) {
return false;
}
@@ -1071,10 +1157,12 @@ void Session::render(bool need_denoise)
task.get_cancel = function_bind(&Progress::get_cancel, &this->progress);
task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1);
task.update_progress_sample = function_bind(&Progress::add_samples, &this->progress, _1, _2);
+ task.get_tile_stolen = function_bind(&Session::get_tile_stolen, this);
task.need_finish_queue = params.progressive_refine;
- task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH;
+ task.integrator_branched = scene->integrator->get_method() == Integrator::BRANCHED_PATH;
- task.adaptive_sampling.use = (scene->integrator->sampling_pattern == SAMPLING_PATTERN_PMJ) &&
+ task.adaptive_sampling.use = (scene->integrator->get_sampling_pattern() ==
+ SAMPLING_PATTERN_PMJ) &&
scene->dscene.data.film.pass_adaptive_aux_buffer;
task.adaptive_sampling.min_samples = scene->dscene.data.integrator.adaptive_min_samples;
task.adaptive_sampling.adaptive_step = scene->dscene.data.integrator.adaptive_step;
@@ -1085,10 +1173,10 @@ void Session::render(bool need_denoise)
if (need_denoise) {
task.denoising = params.denoising;
- task.pass_stride = scene->film->pass_stride;
+ task.pass_stride = scene->film->get_pass_stride();
task.target_pass_stride = task.pass_stride;
- task.pass_denoising_data = scene->film->denoising_data_offset;
- task.pass_denoising_clean = scene->film->denoising_clean_offset;
+ task.pass_denoising_data = scene->film->get_denoising_data_offset();
+ task.pass_denoising_clean = scene->film->get_denoising_clean_offset();
task.denoising_from_render = true;
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index a22bf7731ae..770d3124db7 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -193,6 +193,8 @@ class Session {
bool render_need_denoise(bool &delayed);
+ bool steal_tile(RenderTile &tile, Device *tile_device, thread_scoped_lock &tile_lock);
+ bool get_tile_stolen();
bool acquire_tile(RenderTile &tile, Device *tile_device, uint tile_types);
void update_tile_sample(RenderTile &tile);
void release_tile(RenderTile &tile, const bool need_denoise);
@@ -217,11 +219,22 @@ class Session {
thread_mutex buffers_mutex;
thread_mutex display_mutex;
thread_condition_variable denoising_cond;
+ thread_condition_variable tile_steal_cond;
double reset_time;
double last_update_time;
double last_display_time;
+ RenderTile stolen_tile;
+ typedef enum {
+ NOT_STEALING, /* There currently is no tile stealing in progress. */
+ WAITING_FOR_TILE, /* A device is waiting for another device to release a tile. */
+ RELEASING_TILE, /* A device has releasing a stealable tile. */
+ GOT_TILE /* A device has released a stealable tile, which is now stored in stolen_tile. */
+ } TileStealingState;
+ std::atomic<TileStealingState> tile_stealing_state;
+ int stealable_tiles;
+
/* progressive refine */
bool update_progressive_refine(bool cancel);
};
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 135d0dc962b..cf49dedc426 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -187,6 +187,8 @@ NODE_DEFINE(Shader)
displacement_method_enum.insert("both", DISPLACE_BOTH);
SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
+ SOCKET_INT(pass_id, "Pass ID", 0);
+
return type;
}
@@ -216,7 +218,6 @@ Shader::Shader() : Node(node_type)
id = -1;
used = false;
- need_update = true;
need_update_geometry = true;
}
@@ -250,7 +251,7 @@ bool Shader::is_constant_emission(float3 *emission)
return false;
}
- *emission = node->color * node->strength;
+ *emission = node->get_color() * node->get_strength();
}
else if (surf->link->parent->type == BackgroundNode::node_type) {
BackgroundNode *node = (BackgroundNode *)surf->link->parent;
@@ -262,7 +263,7 @@ bool Shader::is_constant_emission(float3 *emission)
return false;
}
- *emission = node->color * node->strength;
+ *emission = node->get_color() * node->get_strength();
}
else {
return false;
@@ -306,7 +307,7 @@ void Shader::set_graph(ShaderGraph *graph_)
void Shader::tag_update(Scene *scene)
{
/* update tag */
- need_update = true;
+ tag_modified();
scene->shader_manager->need_update = true;
/* if the shader previously was emissive, update light distribution,
@@ -369,7 +370,7 @@ void Shader::tag_used(Scene *scene)
/* if an unused shader suddenly gets used somewhere, it needs to be
* recompiled because it was skipped for compilation before */
if (!used) {
- need_update = true;
+ tag_modified();
scene->shader_manager->need_update = true;
}
}
@@ -493,16 +494,18 @@ void ShaderManager::update_shaders_used(Scene *scene)
scene->default_background->used = true;
scene->default_empty->used = true;
- if (scene->background->shader)
- scene->background->shader->used = true;
+ if (scene->background->get_shader())
+ scene->background->get_shader()->used = true;
foreach (Geometry *geom, scene->geometry)
- foreach (Shader *shader, geom->used_shaders)
+ foreach (Node *node, geom->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
shader->used = true;
+ }
foreach (Light *light, scene->lights)
- if (light->shader)
- light->shader->used = true;
+ if (light->get_shader())
+ const_cast<Shader *>(light->get_shader())->used = true;
}
void ShaderManager::device_update_common(Device *device,
@@ -522,9 +525,9 @@ void ShaderManager::device_update_common(Device *device,
foreach (Shader *shader, scene->shaders) {
uint flag = 0;
- if (shader->use_mis)
+ if (shader->get_use_mis())
flag |= SD_USE_MIS;
- if (shader->has_surface_transparent && shader->use_transparent_shadow)
+ if (shader->has_surface_transparent && shader->get_use_transparent_shadow())
flag |= SD_HAS_TRANSPARENT_SHADOW;
if (shader->has_volume) {
flag |= SD_HAS_VOLUME;
@@ -539,7 +542,7 @@ void ShaderManager::device_update_common(Device *device,
if (shader->has_volume_connected && !shader->has_surface)
flag |= SD_HAS_ONLY_VOLUME;
if (shader->has_volume) {
- if (shader->heterogeneous_volume && shader->has_volume_spatial_varying)
+ if (shader->get_heterogeneous_volume() && shader->has_volume_spatial_varying)
flag |= SD_HETEROGENEOUS_VOLUME;
}
if (shader->has_volume_attribute_dependency)
@@ -547,16 +550,16 @@ void ShaderManager::device_update_common(Device *device,
if (shader->has_bssrdf_bump)
flag |= SD_HAS_BSSRDF_BUMP;
if (device->info.has_volume_decoupled) {
- if (shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR)
+ if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_EQUIANGULAR)
flag |= SD_VOLUME_EQUIANGULAR;
- if (shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
+ if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
flag |= SD_VOLUME_MIS;
}
- if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
+ if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_CUBIC)
flag |= SD_VOLUME_CUBIC;
if (shader->has_bump)
flag |= SD_HAS_BUMP;
- if (shader->displacement_method != DISPLACE_BUMP)
+ if (shader->get_displacement_method() != DISPLACE_BUMP)
flag |= SD_HAS_DISPLACEMENT;
/* constant emission check */
@@ -568,7 +571,7 @@ void ShaderManager::device_update_common(Device *device,
/* regular shader */
kshader->flags = flag;
- kshader->pass_id = shader->pass_id;
+ kshader->pass_id = shader->get_pass_id();
kshader->constant_emission[0] = constant_emission.x;
kshader->constant_emission[1] = constant_emission.y;
kshader->constant_emission[2] = constant_emission.z;
@@ -625,7 +628,7 @@ void ShaderManager::add_default(Scene *scene)
ShaderGraph *graph = new ShaderGraph();
DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>();
- diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
+ diffuse->set_color(make_float3(0.8f, 0.8f, 0.8f));
graph->add(diffuse);
graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
@@ -658,8 +661,8 @@ void ShaderManager::add_default(Scene *scene)
ShaderGraph *graph = new ShaderGraph();
EmissionNode *emission = graph->create_node<EmissionNode>();
- emission->color = make_float3(0.8f, 0.8f, 0.8f);
- emission->strength = 0.0f;
+ emission->set_color(make_float3(0.8f, 0.8f, 0.8f));
+ emission->set_strength(0.0f);
graph->add(emission);
graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
@@ -703,10 +706,10 @@ void ShaderManager::get_requested_graph_features(ShaderGraph *graph,
requested_features->nodes_features |= node->get_feature();
if (node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode *>(node);
- if (CLOSURE_IS_VOLUME(bsdf_node->closure)) {
+ if (CLOSURE_IS_VOLUME(bsdf_node->get_closure_type())) {
requested_features->nodes_features |= NODE_FEATURE_VOLUME;
}
- else if (CLOSURE_IS_PRINCIPLED(bsdf_node->closure)) {
+ else if (CLOSURE_IS_PRINCIPLED(bsdf_node->get_closure_type())) {
requested_features->use_principled = true;
}
}
@@ -738,7 +741,7 @@ void ShaderManager::get_requested_features(Scene *scene,
ShaderNode *output_node = shader->graph->output();
if (output_node->input("Displacement")->link != NULL) {
requested_features->nodes_features |= NODE_FEATURE_BUMP;
- if (shader->displacement_method == DISPLACE_BOTH) {
+ if (shader->get_displacement_method() == DISPLACE_BOTH) {
requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE;
requested_features->max_nodes_group = max(requested_features->max_nodes_group,
NODE_GROUP_LEVEL_1);
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index 897b0984a7e..de19048d8e1 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -81,22 +81,25 @@ class Shader : public Node {
public:
NODE_DECLARE
- int pass_id;
-
/* shader graph */
ShaderGraph *graph;
+ NODE_SOCKET_API(int, pass_id)
+
/* sampling */
- bool use_mis;
- bool use_transparent_shadow;
- bool heterogeneous_volume;
- VolumeSampling volume_sampling_method;
- int volume_interpolation_method;
- float volume_step_rate;
+ NODE_SOCKET_API(bool, use_mis)
+ NODE_SOCKET_API(bool, use_transparent_shadow)
+ NODE_SOCKET_API(bool, heterogeneous_volume)
+ NODE_SOCKET_API(VolumeSampling, volume_sampling_method)
+ NODE_SOCKET_API(int, volume_interpolation_method)
+ NODE_SOCKET_API(float, volume_step_rate)
+
+ /* displacement */
+ NODE_SOCKET_API(DisplacementMethod, displacement_method)
+
float prev_volume_step_rate;
/* synchronization */
- bool need_update;
bool need_update_geometry;
/* If the shader has only volume components, the surface is assumed to
@@ -122,9 +125,6 @@ class Shader : public Node {
bool has_volume_attribute_dependency;
bool has_integrator_dependency;
- /* displacement */
- DisplacementMethod displacement_method;
-
/* requested mesh attributes */
AttributeRequestSet attributes;
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index d66744d06be..b2bc17aec19 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -123,8 +123,8 @@ void SVMShaderManager::device_update(Device *device,
for (int i = 0; i < num_shaders; i++) {
Shader *shader = scene->shaders[i];
- shader->need_update = false;
- if (shader->use_mis && shader->has_surface_emission) {
+ shader->clear_modified();
+ if (shader->get_use_mis() && shader->has_surface_emission) {
scene->light_manager->need_update = true;
}
@@ -749,7 +749,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
/* for the bump shader we need add a node to store the shader state */
bool need_bump_state = (type == SHADER_TYPE_BUMP) &&
- (shader->displacement_method == DISPLACE_BOTH);
+ (shader->get_displacement_method() == DISPLACE_BOTH);
int bump_state_offset = SVM_STACK_INVALID;
if (need_bump_state) {
bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE);
@@ -840,7 +840,7 @@ void SVMCompiler::compile(Shader *shader, array<int4> &svm_nodes, int index, Sum
const double time_start = time_dt();
- bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
+ bool has_bump = (shader->get_displacement_method() != DISPLACE_TRUE) &&
output->input("Surface")->link && output->input("Displacement")->link;
/* finalize */
@@ -849,7 +849,7 @@ void SVMCompiler::compile(Shader *shader, array<int4> &svm_nodes, int index, Sum
shader->graph->finalize(scene,
has_bump,
shader->has_integrator_dependency,
- shader->displacement_method == DISPLACE_BOTH);
+ shader->get_displacement_method() == DISPLACE_BOTH);
}
current_shader = shader;
diff --git a/intern/cycles/render/volume.cpp b/intern/cycles/render/volume.cpp
index fcf33a5e50a..63261d6a247 100644
--- a/intern/cycles/render/volume.cpp
+++ b/intern/cycles/render/volume.cpp
@@ -36,11 +36,7 @@ CCL_NAMESPACE_BEGIN
NODE_DEFINE(Volume)
{
- NodeType *type = NodeType::add("volume", create, NodeType::NONE, Geometry::node_base_type);
-
- SOCKET_INT_ARRAY(triangles, "Triangles", array<int>());
- SOCKET_POINT_ARRAY(verts, "Vertices", array<float3>());
- SOCKET_INT_ARRAY(shader, "Shader", array<int>());
+ NodeType *type = NodeType::add("volume", create, NodeType::NONE, Mesh::node_type);
SOCKET_FLOAT(clipping, "Clipping", 0.001f);
SOCKET_FLOAT(step_size, "Step Size", 0.0f);
@@ -56,9 +52,9 @@ Volume::Volume() : Mesh(node_type, Geometry::VOLUME)
object_space = false;
}
-void Volume::clear()
+void Volume::clear(bool preserve_shaders)
{
- Mesh::clear(true);
+ Mesh::clear(preserve_shaders, true);
}
struct QuadData {
@@ -523,20 +519,20 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress)
if (image_memory->data_elements == 1) {
grid = openvdb_grid_from_device_texture<openvdb::FloatGrid>(
- image_memory, volume->clipping, handle.metadata().transform_3d);
+ image_memory, volume->get_clipping(), handle.metadata().transform_3d);
}
else if (image_memory->data_elements == 3) {
grid = openvdb_grid_from_device_texture<openvdb::Vec3fGrid>(
- image_memory, volume->clipping, handle.metadata().transform_3d);
+ image_memory, volume->get_clipping(), handle.metadata().transform_3d);
}
else if (image_memory->data_elements == 4) {
grid = openvdb_grid_from_device_texture<openvdb::Vec4fGrid>(
- image_memory, volume->clipping, handle.metadata().transform_3d);
+ image_memory, volume->get_clipping(), handle.metadata().transform_3d);
}
}
if (grid) {
- builder.add_grid(grid, do_clipping, volume->clipping);
+ builder.add_grid(grid, do_clipping, volume->get_clipping());
}
}
#endif
@@ -549,17 +545,19 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress)
Shader *volume_shader = NULL;
int pad_size = 0;
- foreach (Shader *shader, volume->used_shaders) {
+ foreach (Node *node, volume->get_used_shaders()) {
+ Shader *shader = static_cast<Shader *>(node);
+
if (!shader->has_volume) {
continue;
}
volume_shader = shader;
- if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_LINEAR) {
+ if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_LINEAR) {
pad_size = max(1, pad_size);
}
- else if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC) {
+ else if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_CUBIC) {
pad_size = max(2, pad_size);
}
@@ -587,8 +585,8 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress)
volume->clear();
volume->reserve_mesh(vertices.size(), indices.size() / 3);
- volume->used_shaders.push_back(volume_shader);
- volume->need_update = true;
+ volume->used_shaders.push_back_slow(volume_shader);
+ volume->tag_modified();
volume->need_update_rebuild = true;
for (size_t i = 0; i < vertices.size(); ++i) {
diff --git a/intern/cycles/render/volume.h b/intern/cycles/render/volume.h
index 05157eb948f..2e9703bf7ed 100644
--- a/intern/cycles/render/volume.h
+++ b/intern/cycles/render/volume.h
@@ -28,11 +28,11 @@ class Volume : public Mesh {
Volume();
- float clipping;
- float step_size;
- bool object_space;
+ NODE_SOCKET_API(float, clipping)
+ NODE_SOCKET_API(float, step_size)
+ NODE_SOCKET_API(bool, object_space)
- virtual void clear() override;
+ virtual void clear(bool preserve_shaders = false) override;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index 91c7f4bea05..4efdb98aa0f 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -42,11 +42,11 @@ void EdgeDice::reserve(int num_verts, int num_triangles)
{
Mesh *mesh = params.mesh;
- vert_offset = mesh->verts.size();
+ vert_offset = mesh->get_verts().size();
tri_offset = mesh->num_triangles();
- mesh->resize_mesh(mesh->verts.size() + num_verts, mesh->num_triangles());
- mesh->reserve_mesh(mesh->verts.size() + num_verts, mesh->num_triangles() + num_triangles);
+ mesh->resize_mesh(mesh->get_verts().size() + num_verts, mesh->num_triangles());
+ mesh->reserve_mesh(mesh->get_verts().size() + num_verts, mesh->num_triangles() + num_triangles);
Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index 1a8c182510c..928f5bf2ed7 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -341,8 +341,8 @@ void DiagSplit::split_patches(Patch *patches, size_t patches_byte_stride)
{
int patch_index = 0;
- for (int f = 0; f < params.mesh->subd_faces.size(); f++) {
- Mesh::SubdFace &face = params.mesh->subd_faces[f];
+ for (int f = 0; f < params.mesh->get_num_subd_faces(); f++) {
+ Mesh::SubdFace face = params.mesh->get_subd_face(f);
Patch *patch = (Patch *)(((char *)patches) + patch_index * patches_byte_stride);
@@ -372,8 +372,8 @@ static Edge *create_edge_from_corner(DiagSplit *split,
int v0,
int v1)
{
- int a = mesh->subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)];
- int b = mesh->subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)];
+ int a = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 0, face.num_corners)];
+ int b = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 1, face.num_corners)];
reversed = !(b < a);
@@ -443,8 +443,8 @@ static Edge *create_split_edge_from_corner(DiagSplit *split,
{
Edge *edge = split->alloc_edge();
- int a = mesh->subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)];
- int b = mesh->subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)];
+ int a = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 0, face.num_corners)];
+ int b = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 1, face.num_corners)];
if (b < a) {
edge->stitch_edge_key = {b, a};
diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp
index 4639fc6d0dd..3eaec982d09 100644
--- a/intern/cycles/test/render_graph_finalize_test.cpp
+++ b/intern/cycles/test/render_graph_finalize_test.cpp
@@ -64,9 +64,11 @@ template<typename T> class ShaderNodeBuilder {
return *this;
}
- template<typename T2, typename V> ShaderNodeBuilder &set(V T2::*pfield, V value)
+ template<typename V> ShaderNodeBuilder &set_param(const string &input_name, V value)
{
- static_cast<T *>(node_)->*pfield = value;
+ const SocketType *input_socket = node_->type->find_input(ustring(input_name.c_str()));
+ EXPECT_NE((void *)NULL, input_socket);
+ node_->set(*input_socket, value);
return *this;
}
@@ -121,8 +123,8 @@ class ShaderGraphBuilder {
/* Common input/output boilerplate. */
ShaderGraphBuilder &add_attribute(const string &name)
{
- return (*this).add_node(ShaderNodeBuilder<AttributeNode>(*graph_, name)
- .set(&AttributeNode::attribute, ustring(name)));
+ return (*this).add_node(
+ ShaderNodeBuilder<AttributeNode>(*graph_, name).set_param("attribute", ustring(name)));
}
ShaderGraphBuilder &output_closure(const string &from)
@@ -210,12 +212,12 @@ TEST_F(RenderGraph, deduplicate_deep)
builder.add_node(ShaderNodeBuilder<GeometryNode>(graph, "Geometry1"))
.add_node(ShaderNodeBuilder<GeometryNode>(graph, "Geometry2"))
- .add_node(ShaderNodeBuilder<ValueNode>(graph, "Value1").set(&ValueNode::value, 0.8f))
- .add_node(ShaderNodeBuilder<ValueNode>(graph, "Value2").set(&ValueNode::value, 0.8f))
+ .add_node(ShaderNodeBuilder<ValueNode>(graph, "Value1").set_param("value", 0.8f))
+ .add_node(ShaderNodeBuilder<ValueNode>(graph, "Value2").set_param("value", 0.8f))
.add_node(ShaderNodeBuilder<NoiseTextureNode>(graph, "Noise1"))
.add_node(ShaderNodeBuilder<NoiseTextureNode>(graph, "Noise2"))
.add_node(ShaderNodeBuilder<MixNode>(graph, "Mix")
- .set(&MixNode::type, NODE_MIX_BLEND)
+ .set_param("mix_type", NODE_MIX_BLEND)
.set("Fac", 0.5f))
.add_connection("Geometry1::Parametric", "Noise1::Vector")
.add_connection("Value1::Value", "Noise1::Scale")
@@ -422,8 +424,8 @@ TEST_F(RenderGraph, constant_fold_mix_add)
builder
.add_node(ShaderNodeBuilder<MixNode>(graph, "MixAdd")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, false)
+ .set_param("mix_type", NODE_MIX_ADD)
+ .set_param("use_clamp", false)
.set("Fac", 0.8f)
.set("Color1", make_float3(0.3f, 0.5f, 0.7f))
.set("Color2", make_float3(0.4f, 0.8f, 0.9f)))
@@ -443,8 +445,8 @@ TEST_F(RenderGraph, constant_fold_mix_add_clamp)
builder
.add_node(ShaderNodeBuilder<MixNode>(graph, "MixAdd")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
+ .set_param("mix_type", NODE_MIX_ADD)
+ .set_param("use_clamp", true)
.set("Fac", 0.8f)
.set("Color1", make_float3(0.3f, 0.5f, 0.7f))
.set("Color2", make_float3(0.4f, 0.8f, 0.9f)))
@@ -465,8 +467,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_dodge_no_fac_0)
builder.add_attribute("Attribute1")
.add_attribute("Attribute2")
.add_node(ShaderNodeBuilder<MixNode>(graph, "Mix")
- .set(&MixNode::type, NODE_MIX_DODGE)
- .set(&MixNode::use_clamp, false)
+ .set_param("mix_type", NODE_MIX_DODGE)
+ .set_param("use_clamp", false)
.set("Fac", 0.0f))
.add_connection("Attribute1::Color", "Mix::Color1")
.add_connection("Attribute2::Color", "Mix::Color2")
@@ -487,8 +489,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_light_no_fac_0)
builder.add_attribute("Attribute1")
.add_attribute("Attribute2")
.add_node(ShaderNodeBuilder<MixNode>(graph, "Mix")
- .set(&MixNode::type, NODE_MIX_LIGHT)
- .set(&MixNode::use_clamp, false)
+ .set_param("mix_type", NODE_MIX_LIGHT)
+ .set_param("use_clamp", false)
.set("Fac", 0.0f))
.add_connection("Attribute1::Color", "Mix::Color1")
.add_connection("Attribute2::Color", "Mix::Color2")
@@ -509,8 +511,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_burn_no_fac_0)
builder.add_attribute("Attribute1")
.add_attribute("Attribute2")
.add_node(ShaderNodeBuilder<MixNode>(graph, "Mix")
- .set(&MixNode::type, NODE_MIX_BURN)
- .set(&MixNode::use_clamp, false)
+ .set_param("mix_type", NODE_MIX_BURN)
+ .set_param("use_clamp", false)
.set("Fac", 0.0f))
.add_connection("Attribute1::Color", "Mix::Color1")
.add_connection("Attribute2::Color", "Mix::Color2")
@@ -531,8 +533,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_blend_clamped_no_fac_0)
builder.add_attribute("Attribute1")
.add_attribute("Attribute2")
.add_node(ShaderNodeBuilder<MixNode>(graph, "Mix")
- .set(&MixNode::type, NODE_MIX_BLEND)
- .set(&MixNode::use_clamp, true)
+ .set_param("mix_type", NODE_MIX_BLEND)
+ .set_param("use_clamp", true)
.set("Fac", 0.0f))
.add_connection("Attribute1::Color", "Mix::Color1")
.add_connection("Attribute2::Color", "Mix::Color2")
@@ -557,22 +559,22 @@ TEST_F(RenderGraph, constant_fold_part_mix_blend)
.add_attribute("Attribute2")
/* choose left */
.add_node(ShaderNodeBuilder<MixNode>(graph, "MixBlend1")
- .set(&MixNode::type, NODE_MIX_BLEND)
- .set(&MixNode::use_clamp, false)
+ .set_param("mix_type", NODE_MIX_BLEND)
+ .set_param("use_clamp", false)
.set("Fac", 0.0f))
.add_connection("Attribute1::Color", "MixBlend1::Color1")
.add_connection("Attribute2::Color", "MixBlend1::Color2")
/* choose right */
.add_node(ShaderNodeBuilder<MixNode>(graph, "MixBlend2")
- .set(&MixNode::type, NODE_MIX_BLEND)
- .set(&MixNode::use_clamp, false)
+ .set_param("mix_type", NODE_MIX_BLEND)
+ .set_param("use_clamp", false)
.set("Fac", 1.0f))
.add_connection("Attribute1::Color", "MixBlend2::Color2")
.add_connection("Attribute2::Color", "MixBlend2::Color1")
/* both inputs folded to Attribute1 */
.add_node(ShaderNodeBuilder<MixNode>(graph, "MixBlend3")
- .set(&MixNode::type, NODE_MIX_BLEND)
- .set(&MixNode::use_clamp, false))
+ .set_param("mix_type", NODE_MIX_BLEND)
+ .set_param("use_clamp", false))
.add_connection("Attribute1::Fac", "MixBlend3::Fac")
.add_connection("MixBlend1::Color", "MixBlend3::Color1")
.add_connection("MixBlend2::Color", "MixBlend3::Color2")
@@ -592,8 +594,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_sub_same_fac_bad)
builder.add_attribute("Attribute")
.add_node(ShaderNodeBuilder<MixNode>(graph, "Mix")
- .set(&MixNode::type, NODE_MIX_SUB)
- .set(&MixNode::use_clamp, true)
+ .set_param("mix_type", NODE_MIX_SUB)
+ .set_param("use_clamp", true)
.set("Fac", 0.5f))
.add_connection("Attribute::Color", "Mix::Color1")
.add_connection("Attribute::Color", "Mix::Color2")
@@ -613,8 +615,8 @@ TEST_F(RenderGraph, constant_fold_part_mix_sub_same_fac_1)
builder.add_attribute("Attribute")
.add_node(ShaderNodeBuilder<MixNode>(graph, "Mix")
- .set(&MixNode::type, NODE_MIX_SUB)
- .set(&MixNode::use_clamp, true)
+ .set_param("mix_type", NODE_MIX_SUB)
+ .set_param("use_clamp", true)
.set("Fac", 1.0f))
.add_connection("Attribute::Color", "Mix::Color1")
.add_connection("Attribute::Color", "Mix::Color2")
@@ -635,12 +637,12 @@ static void build_mix_partial_test_graph(ShaderGraphBuilder &builder,
.add_attribute("Attribute")
/* constant on the left */
.add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Mix_Cx_Fx")
- .set(&MixNode::type, type)
- .set(&MixNode::use_clamp, false)
+ .set_param("mix_type", type)
+ .set_param("use_clamp", false)
.set("Color1", constval))
.add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Mix_Cx_F1")
- .set(&MixNode::type, type)
- .set(&MixNode::use_clamp, false)
+ .set_param("mix_type", type)
+ .set_param("use_clamp", false)
.set("Color1", constval)
.set("Fac", 1.0f))
.add_connection("Attribute::Fac", "Mix_Cx_Fx::Fac")
@@ -648,12 +650,12 @@ static void build_mix_partial_test_graph(ShaderGraphBuilder &builder,
.add_connection("Attribute::Color", "Mix_Cx_F1::Color2")
/* constant on the right */
.add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Mix_xC_Fx")
- .set(&MixNode::type, type)
- .set(&MixNode::use_clamp, false)
+ .set_param("mix_type", type)
+ .set_param("use_clamp", false)
.set("Color2", constval))
.add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Mix_xC_F1")
- .set(&MixNode::type, type)
- .set(&MixNode::use_clamp, false)
+ .set_param("mix_type", type)
+ .set_param("use_clamp", false)
.set("Color2", constval)
.set("Fac", 1.0f))
.add_connection("Attribute::Fac", "Mix_xC_Fx::Fac")
@@ -661,16 +663,16 @@ static void build_mix_partial_test_graph(ShaderGraphBuilder &builder,
.add_connection("Attribute::Color", "Mix_xC_F1::Color1")
/* results of actual tests simply added up to connect to output */
.add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Out12")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
+ .set_param("mix_type", NODE_MIX_ADD)
+ .set_param("use_clamp", true)
.set("Fac", 1.0f))
.add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Out34")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
+ .set_param("mix_type", NODE_MIX_ADD)
+ .set_param("use_clamp", true)
.set("Fac", 1.0f))
.add_node(ShaderNodeBuilder<MixNode>(builder.graph(), "Out1234")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
+ .set_param("mix_type", NODE_MIX_ADD)
+ .set_param("use_clamp", true)
.set("Fac", 1.0f))
.add_connection("Mix_Cx_Fx::Color", "Out12::Color1")
.add_connection("Mix_Cx_F1::Color", "Out12::Color2")
@@ -898,8 +900,8 @@ TEST_F(RenderGraph, constant_fold_gamma_part_0)
.add_connection("Attribute::Color", "Gamma_xC::Color")
/* output sum */
.add_node(ShaderNodeBuilder<MixNode>(graph, "Out")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
+ .set_param("mix_type", NODE_MIX_ADD)
+ .set_param("use_clamp", true)
.set("Fac", 1.0f))
.add_connection("Gamma_Cx::Color", "Out::Color1")
.add_connection("Gamma_xC::Color", "Out::Color2")
@@ -928,8 +930,8 @@ TEST_F(RenderGraph, constant_fold_gamma_part_1)
.add_connection("Attribute::Color", "Gamma_xC::Color")
/* output sum */
.add_node(ShaderNodeBuilder<MixNode>(graph, "Out")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
+ .set_param("mix_type", NODE_MIX_ADD)
+ .set_param("use_clamp", true)
.set("Fac", 1.0f))
.add_connection("Gamma_Cx::Color", "Out::Color1")
.add_connection("Gamma_xC::Color", "Out::Color2")
@@ -988,8 +990,8 @@ TEST_F(RenderGraph, constant_fold_math)
builder
.add_node(ShaderNodeBuilder<MathNode>(graph, "Math")
- .set(&MathNode::type, NODE_MATH_ADD)
- .set(&MathNode::use_clamp, false)
+ .set_param("math_type", NODE_MATH_ADD)
+ .set_param("use_clamp", false)
.set("Value1", 0.7f)
.set("Value2", 0.9f))
.output_value("Math::Value");
@@ -1007,8 +1009,8 @@ TEST_F(RenderGraph, constant_fold_math_clamp)
builder
.add_node(ShaderNodeBuilder<MathNode>(graph, "Math")
- .set(&MathNode::type, NODE_MATH_ADD)
- .set(&MathNode::use_clamp, true)
+ .set_param("math_type", NODE_MATH_ADD)
+ .set_param("use_clamp", true)
.set("Value1", 0.7f)
.set("Value2", 0.9f))
.output_value("Math::Value");
@@ -1028,20 +1030,20 @@ static void build_math_partial_test_graph(ShaderGraphBuilder &builder,
.add_attribute("Attribute")
/* constant on the left */
.add_node(ShaderNodeBuilder<MathNode>(builder.graph(), "Math_Cx")
- .set(&MathNode::type, type)
- .set(&MathNode::use_clamp, false)
+ .set_param("math_type", type)
+ .set_param("use_clamp", false)
.set("Value1", constval))
.add_connection("Attribute::Fac", "Math_Cx::Value2")
/* constant on the right */
.add_node(ShaderNodeBuilder<MathNode>(builder.graph(), "Math_xC")
- .set(&MathNode::type, type)
- .set(&MathNode::use_clamp, false)
+ .set_param("math_type", type)
+ .set_param("use_clamp", false)
.set("Value2", constval))
.add_connection("Attribute::Fac", "Math_xC::Value1")
/* output sum */
.add_node(ShaderNodeBuilder<MathNode>(builder.graph(), "Out")
- .set(&MathNode::type, NODE_MATH_ADD)
- .set(&MathNode::use_clamp, true))
+ .set_param("math_type", NODE_MATH_ADD)
+ .set_param("use_clamp", true))
.add_connection("Math_Cx::Value", "Out::Value1")
.add_connection("Math_xC::Value", "Out::Value2")
.output_value("Out::Value");
@@ -1178,7 +1180,7 @@ TEST_F(RenderGraph, constant_fold_vector_math)
builder
.add_node(ShaderNodeBuilder<VectorMathNode>(graph, "VectorMath")
- .set(&VectorMathNode::type, NODE_VECTOR_MATH_SUBTRACT)
+ .set_param("math_type", NODE_VECTOR_MATH_SUBTRACT)
.set("Vector1", make_float3(1.3f, 0.5f, 0.7f))
.set("Vector2", make_float3(-1.7f, 0.5f, 0.7f)))
.output_color("VectorMath::Vector");
@@ -1198,17 +1200,17 @@ static void build_vecmath_partial_test_graph(ShaderGraphBuilder &builder,
.add_attribute("Attribute")
/* constant on the left */
.add_node(ShaderNodeBuilder<VectorMathNode>(builder.graph(), "Math_Cx")
- .set(&VectorMathNode::type, type)
+ .set_param("math_type", type)
.set("Vector1", constval))
.add_connection("Attribute::Vector", "Math_Cx::Vector2")
/* constant on the right */
.add_node(ShaderNodeBuilder<VectorMathNode>(builder.graph(), "Math_xC")
- .set(&VectorMathNode::type, type)
+ .set_param("math_type", type)
.set("Vector2", constval))
.add_connection("Attribute::Vector", "Math_xC::Vector1")
/* output sum */
.add_node(ShaderNodeBuilder<VectorMathNode>(builder.graph(), "Out")
- .set(&VectorMathNode::type, NODE_VECTOR_MATH_ADD))
+ .set_param("math_type", NODE_VECTOR_MATH_ADD))
.add_connection("Math_Cx::Vector", "Out::Vector1")
.add_connection("Math_xC::Vector", "Out::Vector2")
.output_color("Out::Vector");
@@ -1312,9 +1314,9 @@ TEST_F(RenderGraph, constant_fold_rgb_curves)
builder
.add_node(ShaderNodeBuilder<RGBCurvesNode>(graph, "Curves")
- .set(&CurvesNode::curves, curve)
- .set(&CurvesNode::min_x, 0.1f)
- .set(&CurvesNode::max_x, 0.9f)
+ .set_param("curves", curve)
+ .set_param("min_x", 0.1f)
+ .set_param("max_x", 0.9f)
.set("Fac", 0.5f)
.set("Color", make_float3(0.3f, 0.5f, 0.7f)))
.output_color("Curves::Color");
@@ -1336,9 +1338,9 @@ TEST_F(RenderGraph, constant_fold_rgb_curves_fac_0)
builder.add_attribute("Attribute")
.add_node(ShaderNodeBuilder<RGBCurvesNode>(graph, "Curves")
- .set(&CurvesNode::curves, curve)
- .set(&CurvesNode::min_x, 0.1f)
- .set(&CurvesNode::max_x, 0.9f)
+ .set_param("curves", curve)
+ .set_param("min_x", 0.1f)
+ .set_param("max_x", 0.9f)
.set("Fac", 0.0f))
.add_connection("Attribute::Color", "Curves::Color")
.output_color("Curves::Color");
@@ -1360,9 +1362,9 @@ TEST_F(RenderGraph, constant_fold_rgb_curves_fac_0_const)
builder
.add_node(ShaderNodeBuilder<RGBCurvesNode>(graph, "Curves")
- .set(&CurvesNode::curves, curve)
- .set(&CurvesNode::min_x, 0.1f)
- .set(&CurvesNode::max_x, 0.9f)
+ .set_param("curves", curve)
+ .set_param("min_x", 0.1f)
+ .set_param("max_x", 0.9f)
.set("Fac", 0.0f)
.set("Color", make_float3(0.3f, 0.5f, 0.7f)))
.output_color("Curves::Color");
@@ -1384,9 +1386,9 @@ TEST_F(RenderGraph, constant_fold_vector_curves)
builder
.add_node(ShaderNodeBuilder<VectorCurvesNode>(graph, "Curves")
- .set(&CurvesNode::curves, curve)
- .set(&CurvesNode::min_x, 0.1f)
- .set(&CurvesNode::max_x, 0.9f)
+ .set_param("curves", curve)
+ .set_param("min_x", 0.1f)
+ .set_param("max_x", 0.9f)
.set("Fac", 0.5f)
.set("Vector", make_float3(0.3f, 0.5f, 0.7f)))
.output_color("Curves::Vector");
@@ -1408,9 +1410,9 @@ TEST_F(RenderGraph, constant_fold_vector_curves_fac_0)
builder.add_attribute("Attribute")
.add_node(ShaderNodeBuilder<VectorCurvesNode>(graph, "Curves")
- .set(&CurvesNode::curves, curve)
- .set(&CurvesNode::min_x, 0.1f)
- .set(&CurvesNode::max_x, 0.9f)
+ .set_param("curves", curve)
+ .set_param("min_x", 0.1f)
+ .set_param("max_x", 0.9f)
.set("Fac", 0.0f))
.add_connection("Attribute::Vector", "Curves::Vector")
.output_color("Curves::Vector");
@@ -1435,11 +1437,11 @@ TEST_F(RenderGraph, constant_fold_rgb_ramp)
builder
.add_node(ShaderNodeBuilder<RGBRampNode>(graph, "Ramp")
- .set(&RGBRampNode::ramp, curve)
- .set(&RGBRampNode::ramp_alpha, alpha)
- .set(&RGBRampNode::interpolate, true)
+ .set_param("ramp", curve)
+ .set_param("ramp_alpha", alpha)
+ .set_param("interpolate", true)
.set("Fac", 0.56f))
- .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix").set(&MixNode::type, NODE_MIX_ADD))
+ .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix").set_param("mix_type", NODE_MIX_ADD))
.add_connection("Ramp::Color", "Mix::Color1")
.add_connection("Ramp::Alpha", "Mix::Color2")
.output_color("Mix::Color");
@@ -1464,11 +1466,11 @@ TEST_F(RenderGraph, constant_fold_rgb_ramp_flat)
builder
.add_node(ShaderNodeBuilder<RGBRampNode>(graph, "Ramp")
- .set(&RGBRampNode::ramp, curve)
- .set(&RGBRampNode::ramp_alpha, alpha)
- .set(&RGBRampNode::interpolate, false)
+ .set_param("ramp", curve)
+ .set_param("ramp_alpha", alpha)
+ .set_param("interpolate", false)
.set("Fac", 0.56f))
- .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix").set(&MixNode::type, NODE_MIX_ADD))
+ .add_node(ShaderNodeBuilder<MixNode>(graph, "Mix").set_param("mix_type", NODE_MIX_ADD))
.add_connection("Ramp::Color", "Mix::Color1")
.add_connection("Ramp::Alpha", "Mix::Color2")
.output_color("Mix::Color");
@@ -1510,7 +1512,7 @@ TEST_F(RenderGraph, constant_fold_convert_color_vector_color)
builder.add_attribute("Attribute")
.add_node(ShaderNodeBuilder<VectorMathNode>(graph, "VecAdd")
- .set(&VectorMathNode::type, NODE_VECTOR_MATH_ADD)
+ .set_param("math_type", NODE_VECTOR_MATH_ADD)
.set("Vector2", make_float3(0, 0, 0)))
.add_connection("Attribute::Color", "VecAdd::Vector1")
.output_color("VecAdd::Vector");
@@ -1531,7 +1533,7 @@ TEST_F(RenderGraph, constant_fold_convert_color_float_color)
builder.add_attribute("Attribute")
.add_node(ShaderNodeBuilder<MathNode>(graph, "MathAdd")
- .set(&MathNode::type, NODE_MATH_ADD)
+ .set_param("math_type", NODE_MATH_ADD)
.set("Value2", 0.0f))
.add_connection("Attribute::Color", "MathAdd::Value1")
.output_color("MathAdd::Value");
diff --git a/intern/cycles/util/util_array.h b/intern/cycles/util/util_array.h
index db80ab474e0..ea481787018 100644
--- a/intern/cycles/util/util_array.h
+++ b/intern/cycles/util/util_array.h
@@ -213,6 +213,26 @@ template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class arra
return data_[i];
}
+ T *begin()
+ {
+ return data_;
+ }
+
+ const T *begin() const
+ {
+ return data_;
+ }
+
+ T *end()
+ {
+ return data_ + datasize_;
+ }
+
+ const T *end() const
+ {
+ return data_ + datasize_;
+ }
+
void reserve(size_t newcapacity)
{
if (newcapacity > capacity_) {
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index a721595667d..fc80fa9696c 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -53,7 +53,7 @@ typedef unsigned short ushort;
/* Fixed Bits Types */
#ifdef __KERNEL_OPENCL__
-typedef ulong uint64_t;
+typedef unsigned long uint64_t;
#endif
#ifndef __KERNEL_GPU__
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 77e777db872..4a2a12932fe 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -332,7 +332,7 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
elseif(WIN32)
# # Warnings as errors, this is too strict!
# if(MSVC)
- # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX")
+ # string(APPEND CMAKE_CXX_FLAGS " /WX")
# endif()
list(APPEND INC_SYS
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 2046b55c97f..64740b68c0c 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -31,8 +31,8 @@ extern "C" {
/**
* Definition of a callback routine that receives events.
- * \param event The event received.
- * \param userdata The callback's user data, supplied to GHOST_CreateSystem.
+ * \param event: The event received.
+ * \param userdata: The callback's user data, supplied to #GHOST_CreateSystem.
*/
typedef int (*GHOST_EventCallbackProcPtr)(GHOST_EventHandle event, GHOST_TUserDataPtr userdata);
@@ -49,21 +49,20 @@ extern void GHOST_SystemInitDebug(GHOST_SystemHandle systemhandle, int is_debug_
/**
* Disposes the one and only system.
- * \param systemhandle The handle to the system
+ * \param systemhandle: The handle to the system.
* \return An indication of success.
*/
extern GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle);
/**
* Show a system message box to the user
- * \param systemhandle The handle to the system
- * \param title Title of the message box
- * \param message Message of the message box
- * \param help_label Text to show on the help button that opens a link
- * \param continue_label Text to show on the ok button that continues
- * \param link Optional (hyper)link to a webpage to show when pressing help
- * \param dialog_options Options to configure the message box.
- * \return void.
+ * \param systemhandle: The handle to the system.
+ * \param title: Title of the message box.
+ * \param message: Message of the message box.
+ * \param help_label: Text to show on the help button that opens a link.
+ * \param continue_label: Text to show on the ok button that continues.
+ * \param link: Optional (hyper)link to a webpage to show when pressing help.
+ * \param dialog_options: Options to configure the message box.
*/
extern void GHOST_ShowMessageBox(GHOST_SystemHandle systemhandle,
const char *title,
@@ -75,15 +74,15 @@ extern void GHOST_ShowMessageBox(GHOST_SystemHandle systemhandle,
/**
* Creates an event consumer object
- * \param eventCallback The event callback routine.
- * \param userdata Pointer to user data returned to the callback routine.
+ * \param eventCallback: The event callback routine.
+ * \param userdata: Pointer to user data returned to the callback routine.
*/
extern GHOST_EventConsumerHandle GHOST_CreateEventConsumer(
GHOST_EventCallbackProcPtr eventCallback, GHOST_TUserDataPtr userdata);
/**
* Disposes an event consumer object
- * \param consumerhandle Handle to the event consumer.
+ * \param consumerhandle: Handle to the event consumer.
* \return An indication of success.
*/
extern GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consumerhandle);
@@ -92,7 +91,7 @@ extern GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consu
* Returns the system time.
* Returns the number of milliseconds since the start of the system process.
* Based on ANSI clock() routine.
- * \param systemhandle The handle to the system
+ * \param systemhandle: The handle to the system.
* \return The number of milliseconds.
*/
extern GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle);
@@ -101,11 +100,11 @@ extern GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle);
* Installs a timer.
* Note that, on most operating systems, messages need to be processed in order
* for the timer callbacks to be invoked.
- * \param systemhandle The handle to the system
- * \param delay The time to wait for the first call to the timerProc (in milliseconds)
- * \param interval The interval between calls to the timerProc (in milliseconds)
- * \param timerProc The callback invoked when the interval expires,
- * \param userData Placeholder for user data.
+ * \param systemhandle: The handle to the system.
+ * \param delay: The time to wait for the first call to the timerProc (in milliseconds).
+ * \param interval: The interval between calls to the timerProc (in milliseconds).
+ * \param timerProc: The callback invoked when the interval expires.
+ * \param userData: Placeholder for user data.
* \return A timer task (0 if timer task installation failed).
*/
extern GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle,
@@ -116,8 +115,8 @@ extern GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle,
/**
* Removes a timer.
- * \param systemhandle The handle to the system
- * \param timertaskhandle Timer task to be removed.
+ * \param systemhandle: The handle to the system.
+ * \param timertaskhandle: Timer task to be removed.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle,
@@ -129,17 +128,16 @@ extern GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle,
/**
* Returns the number of displays on this system.
- * \param systemhandle The handle to the system
+ * \param systemhandle: The handle to the system.
* \return The number of displays.
*/
extern GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle);
/**
* Returns the dimensions of the main display on this system.
- * \param systemhandle The handle to the system
- * \param width A pointer the width gets put in
- * \param height A pointer the height gets put in
- * \return void.
+ * \param systemhandle: The handle to the system.
+ * \param width: A pointer the width gets put in.
+ * \param height: A pointer the height gets put in.
*/
extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
GHOST_TUns32 *width,
@@ -149,10 +147,9 @@ extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
* Returns the dimensions of all displays combine
* (the current workspace).
* No need to worry about overlapping monitors.
- * \param systemhandle The handle to the system
- * \param width A pointer the width gets put in
- * \param height A pointer the height gets put in
- * \return void.
+ * \param systemhandle: The handle to the system.
+ * \param width: A pointer the width gets put in.
+ * \param height: A pointer the height gets put in.
*/
extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
GHOST_TUns32 *width,
@@ -162,15 +159,15 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
* Create a new window.
* The new window is added to the list of windows managed.
* Never explicitly delete the window, use disposeWindow() instead.
- * \param systemhandle The handle to the system
- * \param title The name of the window
+ * \param systemhandle: The handle to the system.
+ * \param title: The name of the window.
* (displayed in the title bar of the window if the OS supports it).
- * \param left The coordinate of the left edge of the window.
- * \param top The coordinate of the top edge of the window.
- * \param width The width the window.
- * \param height The height the window.
- * \param state The state of the window when opened.
- * \param type The type of drawing context installed in this window.
+ * \param left: The coordinate of the left edge of the window.
+ * \param top: The coordinate of the top edge of the window.
+ * \param width: The width the window.
+ * \param height: The height the window.
+ * \param state: The state of the window when opened.
+ * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL options.
* \return A handle to the new window ( == NULL if creation failed).
*/
@@ -198,8 +195,8 @@ extern GHOST_WindowHandle GHOST_CreateDialogWindow(GHOST_SystemHandle systemhand
/**
* Create a new offscreen context.
* Never explicitly delete the context, use disposeContext() instead.
- * \param systemhandle The handle to the system
- * \param platform_support_callback An optional callback to check platform support
+ * \param systemhandle: The handle to the system.
+ * \param platform_support_callback: An optional callback to check platform support.
* \return A handle to the new context ( == NULL if creation failed).
*/
extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
@@ -207,8 +204,8 @@ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemha
/**
* Dispose of a context.
- * \param systemhandle The handle to the system
- * \param contexthandle Handle to the context to be disposed.
+ * \param systemhandle: The handle to the system.
+ * \param contexthandle: Handle to the context to be disposed.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
@@ -216,15 +213,15 @@ extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle
/**
* Returns the window user data.
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return The window user data.
*/
extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle);
/**
* Changes the window user data.
- * \param windowhandle The handle to the window
- * \param userdata The window user data.
+ * \param windowhandle: The handle to the window.
+ * \param userdata: The window user data.
*/
extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata);
@@ -232,8 +229,8 @@ extern int GHOST_IsDialogWindow(GHOST_WindowHandle windowhandle);
/**
* Dispose a window.
- * \param systemhandle The handle to the system
- * \param windowhandle Handle to the window to be disposed.
+ * \param systemhandle: The handle to the system.
+ * \param windowhandle: Handle to the window to be disposed.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle,
@@ -241,17 +238,17 @@ extern GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle,
/**
* Returns whether a window is valid.
- * \param systemhandle The handle to the system
- * \param windowhandle Handle to the window to be checked.
+ * \param systemhandle: The handle to the system.
+ * \param windowhandle: Handle to the window to be checked.
* \return Indication of validity.
*/
extern int GHOST_ValidWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle);
/**
* Begins full screen mode.
- * \param systemhandle The handle to the system
- * \param setting The new setting of the display.
- * \param stereoVisual Option for stereo display.
+ * \param systemhandle: The handle to the system.
+ * \param setting: The new setting of the display.
+ * \param stereoVisual: Option for stereo display.
* \return A handle to the window displayed in full screen.
* This window is invalid after full screen has been ended.
*/
@@ -261,14 +258,14 @@ extern GHOST_WindowHandle GHOST_BeginFullScreen(GHOST_SystemHandle systemhandle,
/**
* Ends full screen mode.
- * \param systemhandle The handle to the system
+ * \param systemhandle: The handle to the system.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_EndFullScreen(GHOST_SystemHandle systemhandle);
/**
* Returns current full screen mode status.
- * \param systemhandle The handle to the system
+ * \param systemhandle: The handle to the system.
* \return The current status.
*/
extern int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle);
@@ -279,8 +276,8 @@ extern int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle);
/**
* Retrieves events from the system and stores them in the queue.
- * \param systemhandle The handle to the system
- * \param waitForEvent Boolean to indicate that ProcessEvents should
+ * \param systemhandle: The handle to the system.
+ * \param waitForEvent: Boolean to indicate that #ProcessEvents should.
* wait (block) until the next event before returning.
* \return Indication of the presence of events.
*/
@@ -288,14 +285,14 @@ extern int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent
/**
* Retrieves events from the queue and send them to the event consumers.
- * \param systemhandle The handle to the system
+ * \param systemhandle: The handle to the system.
*/
extern void GHOST_DispatchEvents(GHOST_SystemHandle systemhandle);
/**
* Adds the given event consumer to our list.
- * \param systemhandle The handle to the system
- * \param consumerhandle The event consumer to add.
+ * \param systemhandle: The handle to the system.
+ * \param consumerhandle: The event consumer to add.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle,
@@ -303,8 +300,8 @@ extern GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle,
/**
* Remove the given event consumer to our list.
- * \param systemhandle The handle to the system
- * \param consumerhandle The event consumer to remove.
+ * \param systemhandle: The handle to the system.
+ * \param consumerhandle: The event consumer to remove.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_RemoveEventConsumer(GHOST_SystemHandle systemhandle,
@@ -316,14 +313,14 @@ extern GHOST_TSuccess GHOST_RemoveEventConsumer(GHOST_SystemHandle systemhandle,
/**
* Sets the progress bar value displayed in the window/application icon
- * \param windowhandle The handle to the window
- * \param progress The progress % (0.0 to 1.0)
+ * \param windowhandle: The handle to the window.
+ * \param progress: The progress percentage (0.0 to 1.0).
*/
extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, float progress);
/**
* Hides the progress bar in the icon
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
*/
extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle);
@@ -333,7 +330,7 @@ extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle);
/**
* Returns the current cursor shape.
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return The current cursor shape.
*/
extern GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle);
@@ -341,8 +338,8 @@ extern GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandl
/**
* Set the shape of the cursor. If the shape is not supported by the platform,
* it will use the default cursor instead.
- * \param windowhandle The handle to the window
- * \param cursorshape The new cursor shape type id.
+ * \param windowhandle: The handle to the window.
+ * \param cursorshape: The new cursor shape type id.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetCursorShape(GHOST_WindowHandle windowhandle,
@@ -357,14 +354,14 @@ extern GHOST_TSuccess GHOST_HasCursorShape(GHOST_WindowHandle windowhandle,
/**
* Set the shape of the cursor to a custom cursor of specified size.
- * \param windowhandle The handle to the window
- * \param bitmap The bitmap data for the cursor.
- * \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 hot-spot.
- * \param hotY The Y coordinate of the cursor hot-spot.
- * \param canInvertColor Let macOS invert cursor color to match platform convention.
+ * \param windowhandle: The handle to the window.
+ * \param bitmap: The bitmap data for the cursor.
+ * \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 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.
*/
extern GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle,
@@ -378,24 +375,24 @@ extern GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle
/**
* Returns the visibility state of the cursor.
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return The visibility state of the cursor.
*/
extern int GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle);
/**
* Shows or hides the cursor.
- * \param windowhandle The handle to the window
- * \param visible The new visibility state of the cursor.
+ * \param windowhandle: The handle to the window.
+ * \param visible: The new visibility state of the cursor.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle, int visible);
/**
* Returns the current location of the cursor (location in screen coordinates)
- * \param systemhandle The handle to the system
- * \param x The x-coordinate of the cursor.
- * \param y The y-coordinate of the cursor.
+ * \param systemhandle: The handle to the system.
+ * \param x: The x-coordinate of the cursor.
+ * \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle,
@@ -405,9 +402,9 @@ extern GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle,
/**
* Updates the location of the cursor (location in screen coordinates).
* Not all operating systems allow the cursor to be moved (without the input device being moved).
- * \param systemhandle The handle to the system
- * \param x The x-coordinate of the cursor.
- * \param y The y-coordinate of the cursor.
+ * \param systemhandle: The handle to the system.
+ * \param x: The x-coordinate of the cursor.
+ * \param y: The y-coordinate of the cursor.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
@@ -418,10 +415,10 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
* Grabs the cursor for a modal operation, to keep receiving
* events when the mouse is outside the window. X11 only, others
* do this automatically.
- * \param windowhandle The handle to the window
- * \param mode The new grab state of the cursor.
- * \param bounds The grab region (optional) - left,top,right,bottom
- * \param mouse_ungrab_xy XY for new mouse location (optional) - x,y
+ * \param windowhandle: The handle to the window.
+ * \param mode: The new grab state of the cursor.
+ * \param bounds: The grab region (optional) - left,top,right,bottom.
+ * \param mouse_ungrab_xy: XY for new mouse location (optional).
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
@@ -436,9 +433,9 @@ extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
/**
* Returns the state of a modifier key (outside the message queue).
- * \param systemhandle The handle to the system
- * \param mask The modifier key state to retrieve.
- * \param isDown Pointer to return modifier state in.
+ * \param systemhandle: The handle to the system.
+ * \param mask: The modifier key state to retrieve.
+ * \param isDown: Pointer to return modifier state in.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle,
@@ -447,9 +444,9 @@ extern GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle,
/**
* Returns the state of a mouse button (outside the message queue).
- * \param systemhandle The handle to the system
- * \param mask The button state to retrieve.
- * \param isDown Pointer to return button state in.
+ * \param systemhandle: The handle to the system.
+ * \param mask: The button state to retrieve.
+ * \param isDown: Pointer to return button state in.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle,
@@ -479,14 +476,14 @@ extern void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, GHOST_
/**
* Returns the event type.
- * \param eventhandle The handle to the event
+ * \param eventhandle: The handle to the event.
* \return The event type.
*/
extern GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle);
/**
* Returns the time this event was generated.
- * \param eventhandle The handle to the event
+ * \param eventhandle: The handle to the event.
* \return The event generation time.
*/
extern GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle);
@@ -494,66 +491,66 @@ extern GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle);
/**
* Returns the window this event was generated on,
* or NULL if it is a 'system' event.
- * \param eventhandle The handle to the event
+ * \param eventhandle: The handle to the event.
* \return The generating window.
*/
extern GHOST_WindowHandle GHOST_GetEventWindow(GHOST_EventHandle eventhandle);
/**
* Returns the event data.
- * \param eventhandle The handle to the event
+ * \param eventhandle: The handle to the event.
* \return The event data.
*/
extern GHOST_TEventDataPtr GHOST_GetEventData(GHOST_EventHandle eventhandle);
/**
* Returns the timer callback.
- * \param timertaskhandle The handle to the timer-task.
+ * \param timertaskhandle: The handle to the timer-task.
* \return The timer callback.
*/
extern GHOST_TimerProcPtr GHOST_GetTimerProc(GHOST_TimerTaskHandle timertaskhandle);
/**
* Changes the timer callback.
- * \param timertaskhandle The handle to the timertask
- * \param timerProc The timer callback.
+ * \param timertaskhandle: The handle to the timertask.
+ * \param timerProc: The timer callback.
*/
extern void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle,
GHOST_TimerProcPtr timerProc);
/**
* Returns the timer user data.
- * \param timertaskhandle The handle to the timertask
+ * \param timertaskhandle: The handle to the timertask.
* \return The timer user data.
*/
extern GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle);
/**
* Changes the time user data.
- * \param timertaskhandle The handle to the timertask
- * \param userdata The timer user data.
+ * \param timertaskhandle: The handle to the timertask.
+ * \param userdata: The timer user data.
*/
extern void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle,
GHOST_TUserDataPtr userdata);
/**
* Returns indication as to whether the window is valid.
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return The validity of the window.
*/
extern int GHOST_GetValid(GHOST_WindowHandle windowhandle);
/**
* Returns the type of drawing context used in this window.
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return The current type of drawing context.
*/
extern GHOST_TDrawingContextType GHOST_GetDrawingContextType(GHOST_WindowHandle windowhandle);
/**
* Tries to install a rendering context in this window.
- * \param windowhandle The handle to the window
- * \param type The type of rendering context installed.
+ * \param windowhandle: The handle to the window.
+ * \param type: The type of rendering context installed.
* \return Indication as to whether installation has succeeded.
*/
extern GHOST_TSuccess GHOST_SetDrawingContextType(GHOST_WindowHandle windowhandle,
@@ -561,8 +558,8 @@ extern GHOST_TSuccess GHOST_SetDrawingContextType(GHOST_WindowHandle windowhandl
/**
* Sets the title displayed in the title bar.
- * \param windowhandle The handle to the window
- * \param title The title to display in the title bar.
+ * \param windowhandle: The handle to the window.
+ * \param title: The title to display in the title bar.
*/
extern void GHOST_SetTitle(GHOST_WindowHandle windowhandle, const char *title);
@@ -570,7 +567,7 @@ extern void GHOST_SetTitle(GHOST_WindowHandle windowhandle, const char *title);
* Returns the title displayed in the title bar. The title
* should be free'd with free().
*
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return The title, free with free().
*/
extern char *GHOST_GetTitle(GHOST_WindowHandle windowhandle);
@@ -578,7 +575,7 @@ extern char *GHOST_GetTitle(GHOST_WindowHandle windowhandle);
/**
* Returns the window rectangle dimensions.
* These are screen coordinates.
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return A handle to the bounding rectangle of the window.
*/
extern GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle);
@@ -586,38 +583,38 @@ extern GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhand
/**
* Returns the client rectangle dimensions.
* The left and top members of the rectangle are always zero.
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return A handle to the bounding rectangle of the window.
*/
extern GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle);
/**
- * Disposes a rectangle object
- * \param rectanglehandle Handle to the rectangle.
+ * Disposes a rectangle object.
+ * \param rectanglehandle: Handle to the rectangle.
*/
void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle);
/**
* Resizes client rectangle width.
- * \param windowhandle The handle to the window
- * \param width The new width of the client area of the window.
+ * \param windowhandle: The handle to the window.
+ * \param width: The new width of the client area of the window.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle, GHOST_TUns32 width);
/**
* Resizes client rectangle height.
- * \param windowhandle The handle to the window
- * \param height The new height of the client area of the window.
+ * \param windowhandle: The handle to the window.
+ * \param height: The new height of the client area of the window.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle, GHOST_TUns32 height);
/**
* Resizes client rectangle.
- * \param windowhandle The handle to the window
- * \param width The new width of the client area of the window.
- * \param height The new height of the client area of the window.
+ * \param windowhandle: The handle to the window.
+ * \param width: The new width of the client area of the window.
+ * \param height: The new height of the client area of the window.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle,
@@ -626,11 +623,11 @@ extern GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle,
/**
* Converts a point in screen coordinates to client rectangle coordinates
- * \param windowhandle The handle to the window
- * \param inX The x-coordinate on the screen.
- * \param inY The y-coordinate on the screen.
- * \param outX The x-coordinate in the client rectangle.
- * \param outY The y-coordinate in the client rectangle.
+ * \param windowhandle: The handle to the window.
+ * \param inX: The x-coordinate on the screen.
+ * \param inY: The y-coordinate on the screen.
+ * \param outX: The x-coordinate in the client rectangle.
+ * \param outY: The y-coordinate in the client rectangle.
*/
extern void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle,
GHOST_TInt32 inX,
@@ -640,11 +637,11 @@ extern void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle,
/**
* Converts a point in screen coordinates to client rectangle coordinates
- * \param windowhandle The handle to the window
- * \param inX The x-coordinate in the client rectangle.
- * \param inY The y-coordinate in the client rectangle.
- * \param outX The x-coordinate on the screen.
- * \param outY The y-coordinate on the screen.
+ * \param windowhandle: The handle to the window.
+ * \param inX: The x-coordinate in the client rectangle.
+ * \param inY: The y-coordinate in the client rectangle.
+ * \param outX: The x-coordinate on the screen.
+ * \param outY: The y-coordinate on the screen.
*/
extern void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle,
GHOST_TInt32 inX,
@@ -654,24 +651,24 @@ extern void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle,
/**
* Returns the state of the window (normal, minimized, maximized).
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return The state of the window.
*/
extern GHOST_TWindowState GHOST_GetWindowState(GHOST_WindowHandle windowhandle);
/**
* Sets the state of the window (normal, minimized, maximized).
- * \param windowhandle The handle to the window
- * \param state The state of the window.
+ * \param windowhandle: The handle to the window.
+ * \param state: The state of the window.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle,
GHOST_TWindowState state);
/**
- * Sets the window "modified" status, indicating unsaved changes
- * \param windowhandle The handle to the window
- * \param isUnsavedChanges Unsaved changes or not
+ * Sets the window "modified" status, indicating unsaved changes.
+ * \param windowhandle: The handle to the window.
+ * \param isUnsavedChanges: Unsaved changes or not.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle,
@@ -679,8 +676,8 @@ extern GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhand
/**
* Sets the order of the window (bottom, top).
- * \param windowhandle The handle to the window
- * \param order The order of the window.
+ * \param windowhandle: The handle to the window.
+ * \param order: The order of the window.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle,
@@ -688,20 +685,20 @@ extern GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle,
/**
* Swaps front and back buffers of a window.
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return A success indicator.
*/
extern GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle);
/**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
+ * Sets the swap interval for #swapBuffers.
+ * \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
extern GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int interval);
/**
- * Gets the current swap interval for swapBuffers.
+ * Gets the current swap interval for #swapBuffers.
* \param windowhandle: The handle to the window
* \param intervalOut: pointer to location to return swap interval
* (left untouched if there is an error)
@@ -711,28 +708,28 @@ extern GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int
/**
* Activates the drawing context of this window.
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return A success indicator.
*/
extern GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle);
/**
* Invalidates the contents of this window.
- * \param windowhandle The handle to the window
+ * \param windowhandle: The handle to the window.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle);
/**
* Activates the drawing context of this context.
- * \param contexthandle The handle to the context
+ * \param contexthandle: The handle to the context.
* \return A success indicator.
*/
extern GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle);
/**
* Release the drawing context bound to this thread.
- * \param contexthandle The handle to the context
+ * \param contexthandle: The handle to the context.
* \return A success indicator.
*/
extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle);
@@ -756,32 +753,32 @@ extern unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windwHa
/**
* Set which tablet API to use. Only affects Windows, other platforms have a single API.
- * \param systemhandle The handle to the system
- * \param api Enum indicating which API to use.
+ * \param systemhandle: The handle to the system.
+ * \param api: Enum indicating which API to use.
*/
extern void GHOST_SetTabletAPI(GHOST_SystemHandle systemhandle, GHOST_TTabletAPI api);
/**
* Access to rectangle width.
- * \param rectanglehandle The handle to the rectangle
+ * \param rectanglehandle: The handle to the rectangle.
* \return width of the rectangle
*/
extern GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle);
/**
* Access to rectangle height.
- * \param rectanglehandle The handle to the rectangle
+ * \param rectanglehandle: The handle to the rectangle.
* \return height of the rectangle
*/
extern GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle);
/**
* Gets all members of the rectangle.
- * \param rectanglehandle The handle to the rectangle
- * \param l Pointer to return left coordinate in.
- * \param t Pointer to return top coordinate in.
- * \param r Pointer to return right coordinate in.
- * \param b Pointer to return bottom coordinate in.
+ * \param rectanglehandle: The handle to the rectangle.
+ * \param l: Pointer to return left coordinate in.
+ * \param t: Pointer to return top coordinate in.
+ * \param r: Pointer to return right coordinate in.
+ * \param b: Pointer to return bottom coordinate in.
*/
extern void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle,
GHOST_TInt32 *l,
@@ -791,11 +788,11 @@ extern void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle,
/**
* Sets all members of the rectangle.
- * \param rectanglehandle The handle to the rectangle
- * \param l requested left coordinate of the rectangle
- * \param t requested top coordinate of the rectangle
- * \param r requested right coordinate of the rectangle
- * \param b requested bottom coordinate of the rectangle
+ * \param rectanglehandle: The handle to the rectangle.
+ * \param l: requested left coordinate of the rectangle.
+ * \param t: requested top coordinate of the rectangle.
+ * \param r: requested right coordinate of the rectangle.
+ * \param b: requested bottom coordinate of the rectangle.
*/
extern void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle,
GHOST_TInt32 l,
@@ -806,7 +803,7 @@ extern void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle,
/**
* Returns whether this rectangle is empty.
* Empty rectangles are rectangles that have width==0 and/or height==0.
- * \param rectanglehandle The handle to the rectangle
+ * \param rectanglehandle: The handle to the rectangle.
* \return Success value (true == empty rectangle)
*/
extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehandle);
@@ -815,7 +812,7 @@ extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehand
* Returns whether this rectangle is valid.
* Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b.
* Thus, empty rectangles are valid.
- * \param rectanglehandle The handle to the rectangle
+ * \param rectanglehandle: The handle to the rectangle.
* \return Success value (true == valid rectangle)
*/
extern GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle);
@@ -823,25 +820,25 @@ extern GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehand
/**
* Grows (or shrinks the rectangle).
* The method avoids negative insets making the rectangle invalid
- * \param rectanglehandle The handle to the rectangle
- * \param i The amount of offset given to each extreme (negative values shrink the rectangle).
+ * \param rectanglehandle: The handle to the rectangle.
+ * \param i: The amount of offset given to each extreme (negative values shrink the rectangle).
*/
extern void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle, GHOST_TInt32 i);
/**
* Does a union of the rectangle given and this rectangle.
* The result is stored in this rectangle.
- * \param rectanglehandle The handle to the rectangle
- * \param anotherrectanglehandle The rectangle that is input for the union operation.
+ * \param rectanglehandle: The handle to the rectangle.
+ * \param anotherrectanglehandle: The rectangle that is input for the union operation.
*/
extern void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle,
GHOST_RectangleHandle anotherrectanglehandle);
/**
* Grows the rectangle to included a point.
- * \param rectanglehandle The handle to the rectangle
- * \param x The x-coordinate of the point.
- * \param y The y-coordinate of the point.
+ * \param rectanglehandle: The handle to the rectangle.
+ * \param x: The x-coordinate of the point.
+ * \param y: The y-coordinate of the point.
*/
extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle,
GHOST_TInt32 x,
@@ -850,9 +847,9 @@ extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle,
/**
* Returns whether the point is inside this rectangle.
* Point on the boundary is considered inside.
- * \param rectanglehandle The handle to the rectangle
- * \param x x-coordinate of point to test.
- * \param y y-coordinate of point to test.
+ * \param rectanglehandle: The handle to the rectangle.
+ * \param x: x-coordinate of point to test.
+ * \param y: y-coordinate of point to test.
* \return Success value (true if point is inside).
*/
extern GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle,
@@ -861,8 +858,8 @@ extern GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehan
/**
* Returns whether the rectangle is inside this rectangle.
- * \param rectanglehandle The handle to the rectangle
- * \param anotherrectanglehandle The rectangle to test.
+ * \param rectanglehandle: The handle to the rectangle.
+ * \param anotherrectanglehandle: The rectangle to test.
* \return visibility (not, partially or fully visible).
*/
extern GHOST_TVisibility GHOST_GetRectangleVisibility(
@@ -871,9 +868,9 @@ extern GHOST_TVisibility GHOST_GetRectangleVisibility(
/**
* Sets rectangle members.
* Sets rectangle members such that it is centered at the given location.
- * \param rectanglehandle The handle to the rectangle
- * \param cx Requested center x-coordinate of the rectangle
- * \param cy Requested center y-coordinate of the rectangle
+ * \param rectanglehandle: The handle to the rectangle.
+ * \param cx: Requested center x-coordinate of the rectangle.
+ * \param cy: Requested center y-coordinate of the rectangle.
*/
extern void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle,
GHOST_TInt32 cx,
@@ -883,11 +880,11 @@ extern void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle,
* Sets rectangle members.
* Sets rectangle members such that it is centered at the given location,
* with the width requested.
- * \param rectanglehandle The handle to the rectangle
- * \param cx requested center x-coordinate of the rectangle
- * \param cy requested center y-coordinate of the rectangle
- * \param w requested width of the rectangle
- * \param h requested height of the rectangle
+ * \param rectanglehandle: The handle to the rectangle.
+ * \param cx: requested center x-coordinate of the rectangle.
+ * \param cy: requested center y-coordinate of the rectangle.
+ * \param w: requested width of the rectangle.
+ * \param h: requested height of the rectangle.
*/
extern void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle,
GHOST_TInt32 cx,
@@ -899,8 +896,8 @@ extern void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle,
* Clips a rectangle.
* Updates the rectangle given such that it will fit within this one.
* This can result in an empty rectangle.
- * \param rectanglehandle The handle to the rectangle
- * \param anotherrectanglehandle The rectangle to clip
+ * \param rectanglehandle: The handle to the rectangle.
+ * \param anotherrectanglehandle: The rectangle to clip.
* \return Whether clipping has occurred
*/
extern GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle,
@@ -908,21 +905,21 @@ extern GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle,
/**
* Return the data from the clipboard
- * \param selection Boolean to return the selection instead, X11 only feature.
+ * \param selection: Boolean to return the selection instead, X11 only feature.
* \return clipboard data
*/
extern GHOST_TUns8 *GHOST_getClipboard(int selection);
/**
* Put data to the Clipboard
- * \param buffer the string buffer to set.
- * \param selection Set the selection instead, X11 only feature.
+ * \param buffer: the string buffer to set.
+ * \param selection: Set the selection instead, X11 only feature.
*/
extern void GHOST_putClipboard(GHOST_TInt8 *buffer, int selection);
/**
* Toggles console
- * \param action
+ * \param action:
* - 0: Hides
* - 1: Shows
* - 2: Toggles
@@ -955,14 +952,14 @@ extern GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle);
/**
* Enable IME attached to the given window, i.e. allows user-input
* events to be dispatched to the IME.
- * \param windowhandle Window handle of the caller
- * \param x Requested x-coordinate of the rectangle
- * \param y Requested y-coordinate of the rectangle
- * \param w Requested width of the rectangle
- * \param h Requested height of the rectangle
- * \param complete Whether or not to complete the ongoing composition
- * true: Start a new composition
- * false: Move the IME windows to the given position without finishing it.
+ * \param windowhandle: Window handle of the caller.
+ * \param x: Requested x-coordinate of the rectangle.
+ * \param y: Requested y-coordinate of the rectangle.
+ * \param w: Requested width of the rectangle.
+ * \param h: Requested height of the rectangle.
+ * \param complete: Whether or not to complete the ongoing composition.
+ * - true: Start a new composition.
+ * - false: Move the IME windows to the given position without finishing it.
*/
extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
GHOST_TInt32 x,
@@ -973,7 +970,7 @@ extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
/**
* Disable the IME attached to the given window, i.e. prohibits any user-input
* events from being dispatched to the IME.
- * \param windowhandle The window handle of the caller
+ * \param windowhandle: The window handle of the caller.
*/
extern void GHOST_EndIME(GHOST_WindowHandle windowhandle);
@@ -1071,4 +1068,5 @@ GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_context);
#ifdef __cplusplus
}
+
#endif
diff --git a/intern/ghost/GHOST_IContext.h b/intern/ghost/GHOST_IContext.h
index c6316e90ce4..278a9a40bd1 100644
--- a/intern/ghost/GHOST_IContext.h
+++ b/intern/ghost/GHOST_IContext.h
@@ -44,13 +44,13 @@ class GHOST_IContext {
/**
* Activates the drawing context.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
virtual GHOST_TSuccess activateDrawingContext() = 0;
/**
* Release the drawing context of the calling thread.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
virtual GHOST_TSuccess releaseDrawingContext() = 0;
diff --git a/intern/ghost/GHOST_IEventConsumer.h b/intern/ghost/GHOST_IEventConsumer.h
index b5975068da0..9096c70904b 100644
--- a/intern/ghost/GHOST_IEventConsumer.h
+++ b/intern/ghost/GHOST_IEventConsumer.h
@@ -46,8 +46,8 @@ class GHOST_IEventConsumer {
/**
* This method is called by the system when it has events to dispatch.
* \see GHOST_ISystem#dispatchEvents
- * \param event The event that can be handled or ignored.
- * \return Indication as to whether the event was handled.
+ * \param event: The event that can be handled or ignored.
+ * \return Indication as to whether the event was handled.
*/
virtual bool processEvent(GHOST_IEvent *event) = 0;
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 61ddae47292..81b54cf5a0d 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -183,10 +183,10 @@ class GHOST_ISystem {
* Installs a timer.
* Note that, on most operating systems, messages need to be processed in order
* for the timer callbacks to be invoked.
- * \param delay The time to wait for the first call to the timerProc (in milliseconds)
- * \param interval The interval between calls to the timerProc (in milliseconds)
- * \param timerProc The callback invoked when the interval expires,
- * \param userData Placeholder for user data.
+ * \param delay: The time to wait for the first call to the timerProc (in milliseconds).
+ * \param interval: The interval between calls to the timerProc (in milliseconds).
+ * \param timerProc: The callback invoked when the interval expires.
+ * \param userData: Placeholder for user data.
* \return A timer task (0 if timer task installation failed).
*/
virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay,
@@ -196,7 +196,7 @@ class GHOST_ISystem {
/**
* Removes a timer.
- * \param timerTask Timer task to be removed.
+ * \param timerTask: Timer task to be removed.
* \return Indication of success.
*/
virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask) = 0;
@@ -255,38 +255,38 @@ class GHOST_ISystem {
/**
* Dispose a window.
- * \param window Pointer to the window to be disposed.
- * \return Indication of success.
+ * \param window: Pointer to the window to be disposed.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess disposeWindow(GHOST_IWindow *window) = 0;
/**
* Create a new offscreen context.
* Never explicitly delete the context, use disposeContext() instead.
- * \return The new context (or 0 if creation failed).
+ * \return The new context (or 0 if creation failed).
*/
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
/**
* Dispose of a context.
- * \param context Pointer to the context to be disposed.
- * \return Indication of success.
+ * \param context: Pointer to the context to be disposed.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess disposeContext(GHOST_IContext *context) = 0;
/**
* Returns whether a window is valid.
- * \param window Pointer to the window to be checked.
- * \return Indication of validity.
+ * \param window: Pointer to the window to be checked.
+ * \return Indication of validity.
*/
virtual bool validWindow(GHOST_IWindow *window) = 0;
/**
* Begins full screen mode.
- * \param setting The new setting of the display.
- * \param window Window displayed in full screen.
+ * \param setting: The new setting of the display.
+ * \param window: Window displayed in full screen.
* This window is invalid after full screen has been ended.
- * \return Indication of success.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting &setting,
GHOST_IWindow **window,
@@ -295,17 +295,17 @@ class GHOST_ISystem {
/**
* Updates the resolution while in fullscreen mode.
- * \param setting The new setting of the display.
- * \param window Window displayed in full screen.
+ * \param setting: The new setting of the display.
+ * \param window: Window displayed in full screen.
*
- * \return Indication of success.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting &setting,
GHOST_IWindow **window) = 0;
/**
* Ends full screen mode.
- * \return Indication of success.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess endFullScreen(void) = 0;
@@ -331,7 +331,7 @@ class GHOST_ISystem {
/**
* Retrieves events from the system and stores them in the queue.
- * \param waitForEvent Flag to wait for an event (or return immediately).
+ * \param waitForEvent: Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
*/
virtual bool processEvents(bool waitForEvent) = 0;
@@ -343,14 +343,14 @@ class GHOST_ISystem {
/**
* Adds the given event consumer to our list.
- * \param consumer The event consumer to add.
+ * \param consumer: The event consumer to add.
* \return Indication of success.
*/
virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer) = 0;
/**
* Removes the given event consumer to our list.
- * \param consumer The event consumer to remove.
+ * \param consumer: The event consumer to remove.
* \return Indication of success.
*/
virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer) = 0;
@@ -361,18 +361,18 @@ class GHOST_ISystem {
/**
* Returns the current location of the cursor (location in screen coordinates)
- * \param x The x-coordinate of the cursor.
- * \param y The y-coordinate of the cursor.
- * \return Indication of success.
+ * \param x: The x-coordinate of the cursor.
+ * \param y: The y-coordinate of the cursor.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const = 0;
/**
* Updates the location of the cursor (location in screen coordinates).
* Not all operating systems allow the cursor to be moved (without the input device being moved).
- * \param x The x-coordinate of the cursor.
- * \param y The y-coordinate of the cursor.
- * \return Indication of success.
+ * \param x: The x-coordinate of the cursor.
+ * \param y: The y-coordinate of the cursor.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) = 0;
@@ -382,23 +382,23 @@ class GHOST_ISystem {
/**
* Returns the state of a modifier key (outside the message queue).
- * \param mask The modifier key state to retrieve.
- * \param isDown The state of a modifier key (true == pressed).
- * \return Indication of success.
+ * \param mask: The modifier key state to retrieve.
+ * \param isDown: The state of a modifier key (true == pressed).
+ * \return Indication of success.
*/
virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool &isDown) const = 0;
/**
* Returns the state of a mouse button (outside the message queue).
- * \param mask The button state to retrieve.
- * \param isDown Button state.
- * \return Indication of success.
+ * \param mask: The button state to retrieve.
+ * \param isDown: Button state.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool &isDown) const = 0;
/**
* Set which tablet API to use. Only affects Windows, other platforms have a single API.
- * \param api Enum indicating which API to use.
+ * \param api: Enum indicating which API to use.
*/
virtual void setTabletAPI(GHOST_TTabletAPI api) = 0;
@@ -412,8 +412,8 @@ class GHOST_ISystem {
/**
* Toggles console
- * \param action
- * - 0: Hides
+ * \param action:
+ * - 0: Hides.
* - 1: Shows
* - 2: Toggles
* - 3: Hides if it runs not from command line
@@ -445,12 +445,12 @@ class GHOST_ISystem {
/**
* Show a system message box
*
- * \param title The title of the message box
- * \param message The message to display
- * \param help_label Help button label
- * \param continue_label Continue button label
- * \param link An optional hyperlink
- * \param dialog_options Options how to display the message
+ * \param title: The title of the message box.
+ * \param message: The message to display.
+ * \param help_label: Help button label.
+ * \param continue_label: Continue button label.
+ * \param link: An optional hyperlink.
+ * \param dialog_options: Options how to display the message.
*/
virtual GHOST_TSuccess showMessageBox(const char * /*title*/,
const char * /*message*/,
diff --git a/intern/ghost/GHOST_ITimerTask.h b/intern/ghost/GHOST_ITimerTask.h
index 0f4ac74c466..5d3013ac348 100644
--- a/intern/ghost/GHOST_ITimerTask.h
+++ b/intern/ghost/GHOST_ITimerTask.h
@@ -55,7 +55,7 @@ class GHOST_ITimerTask {
/**
* Changes the timer callback.
- * \param timerProc The timer callback.
+ * \param timerProc: The timer callback.
*/
virtual void setTimerProc(const GHOST_TimerProcPtr timerProc) = 0;
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 6e8b61ae5a1..1650b230812 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -73,62 +73,62 @@ class GHOST_IWindow {
/**
* Tries to install a rendering context in this window.
- * \param type The type of rendering context installed.
+ * \param type: The type of rendering context installed.
* \return Indication as to whether installation has succeeded.
*/
virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) = 0;
/**
* Sets the title displayed in the title bar.
- * \param title The title to display in the title bar.
+ * \param title: The title to display in the title bar.
*/
virtual void setTitle(const char *title) = 0;
/**
* Returns the title displayed in the title bar.
- * \param title The title displayed in the title bar.
+ * \param title: The title displayed in the title bar.
*/
virtual std::string getTitle() const = 0;
/**
* Returns the window rectangle dimensions.
* These are screen coordinates.
- * \param bounds The bounding rectangle of the window.
+ * \param bounds: The bounding rectangle of the window.
*/
virtual void getWindowBounds(GHOST_Rect &bounds) const = 0;
/**
* Returns the client rectangle dimensions.
* The left and top members of the rectangle are always zero.
- * \param bounds The bounding rectangle of the client area of the window.
+ * \param bounds: The bounding rectangle of the client area of the window.
*/
virtual void getClientBounds(GHOST_Rect &bounds) const = 0;
/**
* Resizes client rectangle width.
- * \param width The new width of the client area of the window.
+ * \param width: The new width of the client area of the window.
*/
virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
/**
* Resizes client rectangle height.
- * \param height The new height of the client area of the window.
+ * \param height: The new height of the client area of the window.
*/
virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0;
/**
* Resizes client rectangle.
- * \param width The new width of the client area of the window.
- * \param height The new height of the client area of the window.
+ * \param width: The new width of the client area of the window.
+ * \param height: The new height of the client area of the window.
*/
virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0;
/**
* Converts a point in screen coordinates to client rectangle coordinates
- * \param inX The x-coordinate on the screen.
- * \param inY The y-coordinate on the screen.
- * \param outX The x-coordinate in the client rectangle.
- * \param outY The y-coordinate in the client rectangle.
+ * \param inX: The x-coordinate on the screen.
+ * \param inY: The y-coordinate on the screen.
+ * \param outX: The x-coordinate in the client rectangle.
+ * \param outY: The y-coordinate in the client rectangle.
*/
virtual void screenToClient(GHOST_TInt32 inX,
GHOST_TInt32 inY,
@@ -137,10 +137,10 @@ class GHOST_IWindow {
/**
* Converts a point in screen coordinates to client rectangle coordinates
- * \param inX The x-coordinate in the client rectangle.
- * \param inY The y-coordinate in the client rectangle.
- * \param outX The x-coordinate on the screen.
- * \param outY The y-coordinate on the screen.
+ * \param inX: The x-coordinate in the client rectangle.
+ * \param inY: The y-coordinate in the client rectangle.
+ * \param outX: The x-coordinate on the screen.
+ * \param outY: The y-coordinate on the screen.
*/
virtual void clientToScreen(GHOST_TInt32 inX,
GHOST_TInt32 inY,
@@ -166,14 +166,14 @@ class GHOST_IWindow {
/**
* Sets the state of the window (normal, minimized, maximized).
- * \param state The state of the window.
+ * \param state: The state of the window.
* \return Indication of success.
*/
virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0;
/**
* Sets the window "modified" status, indicating unsaved changes
- * \param isUnsavedChanges Unsaved changes or not
+ * \param isUnsavedChanges: Unsaved changes or not.
* \return Indication of success.
*/
virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges) = 0;
@@ -186,27 +186,27 @@ class GHOST_IWindow {
/**
* Sets the order of the window (bottom, top).
- * \param order The order of the window.
+ * \param order: The order of the window.
* \return Indication of success.
*/
virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0;
/**
* Swaps front and back buffers of a window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
virtual GHOST_TSuccess swapBuffers() = 0;
/**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
+ * Sets the swap interval for #swapBuffers.
+ * \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
virtual GHOST_TSuccess setSwapInterval(int interval) = 0;
/**
- * Gets the current swap interval for swapBuffers.
- * \param intervalOut pointer to location to return swap interval
+ * Gets the current swap interval for #swapBuffers.
+ * \param intervalOut: pointer to location to return swap interval.
* (left untouched if there is an error)
* \return A boolean success indicator of if swap interval was successfully read.
*/
@@ -214,13 +214,13 @@ class GHOST_IWindow {
/**
* Activates the drawing context of this window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
virtual GHOST_TSuccess activateDrawingContext() = 0;
/**
- * Gets the OpenGL framebuffer associated with the window's contents.
- * \return The name of an OpenGL framebuffer object.
+ * Gets the OpenGL frame-buffer associated with the window's contents.
+ * \return The name of an OpenGL frame-buffer object.
*/
virtual unsigned int getDefaultFramebuffer() = 0;
@@ -238,7 +238,7 @@ class GHOST_IWindow {
/**
* Changes the window user data.
- * \param userData The window user data.
+ * \param userData: The window user data.
*/
virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
@@ -250,7 +250,7 @@ class GHOST_IWindow {
/**
* Sets the progress bar value displayed in the window/application icon
- * \param progress The progress %
+ * \param progress: The progress percentage (0.0 to 1.0).
*/
virtual GHOST_TSuccess setProgressBar(float progress) = 0;
@@ -265,13 +265,13 @@ class GHOST_IWindow {
/**
* Returns the current cursor shape.
- * \return The current cursor shape.
+ * \return The current cursor shape.
*/
virtual GHOST_TStandardCursor getCursorShape() const = 0;
/**
* Set the shape of the cursor.
- * \param cursorShape: The new cursor shape type id.
+ * \param cursorShape: The new cursor shape type id.
* \return Indication of success.
*/
virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0;
@@ -284,11 +284,11 @@ 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 hot-spot.
- * \param hotY The Y coordinate of the cursor hot-spot.
- * \return Indication of success.
+ * \param bitmap: The bitmap data for the cursor.
+ * \param mask: The mask data for the cursor.
+ * \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,
GHOST_TUns8 *mask,
@@ -300,21 +300,21 @@ class GHOST_IWindow {
/**
* Returns the visibility state of the cursor.
- * \return The visibility state of the cursor.
+ * \return The visibility state of the cursor.
*/
virtual bool getCursorVisibility() const = 0;
/**
* Shows or hides the cursor.
- * \param visible The new visibility state of the cursor.
- * \return Indication of success.
+ * \param visible: The new visibility state of the cursor.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess setCursorVisibility(bool visible) = 0;
/**
* Grabs the cursor for a modal operation.
- * \param grab The new grab state of the cursor.
- * \return Indication of success.
+ * \param grab: The new grab state of the cursor.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode /*mode*/,
GHOST_TAxisFlag /*wrap_axis*/,
@@ -340,13 +340,13 @@ class GHOST_IWindow {
/**
* Enable IME attached to the given window, i.e. allows user-input
* events to be dispatched to the IME.
- * \param x Requested x-coordinate of the rectangle
- * \param y Requested y-coordinate of the rectangle
- * \param w Requested width of the rectangle
- * \param h Requested height of the rectangle
- * \param complete Whether or not to complete the ongoing composition
- * true: Start a new composition
- * false: Move the IME windows to the given position without finishing it.
+ * \param x: Requested x-coordinate of the rectangle.
+ * \param y: Requested y-coordinate of the rectangle.
+ * \param w: Requested width of the rectangle.
+ * \param h: Requested height of the rectangle.
+ * \param complete: Whether or not to complete the ongoing composition.
+ * - true: Start a new composition
+ * - false: Move the IME windows to the given position without finishing it.
*/
virtual void beginIME(
GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed) = 0;
diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h
index fcc9da20197..dae2a2a8cbb 100644
--- a/intern/ghost/GHOST_Rect.h
+++ b/intern/ghost/GHOST_Rect.h
@@ -37,10 +37,10 @@ class GHOST_Rect {
public:
/**
* Constructs a rectangle with the given values.
- * \param l requested left coordinate of the rectangle
- * \param t requested top coordinate of the rectangle
- * \param r requested right coordinate of the rectangle
- * \param b requested bottom coordinate of the rectangle
+ * \param l: requested left coordinate of the rectangle.
+ * \param t: requested top coordinate of the rectangle.
+ * \param r: requested right coordinate of the rectangle.
+ * \param b: requested bottom coordinate of the rectangle.
*/
GHOST_Rect(GHOST_TInt32 l = 0, GHOST_TInt32 t = 0, GHOST_TInt32 r = 0, GHOST_TInt32 b = 0)
: m_l(l), m_t(t), m_r(r), m_b(b)
@@ -56,13 +56,13 @@ class GHOST_Rect {
/**
* Access to rectangle width.
- * \return width of the rectangle
+ * \return width of the rectangle.
*/
virtual inline GHOST_TInt32 getWidth() const;
/**
* Access to rectangle height.
- * \return height of the rectangle
+ * \return height of the rectangle.
*/
virtual inline GHOST_TInt32 getHeight() const;
@@ -86,7 +86,7 @@ class GHOST_Rect {
* Returns whether this rectangle is valid.
* Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b.
* Thus, empty rectangles are valid.
- * \return boolean value (true==valid rectangle)
+ * \return boolean value (true==valid rectangle)
*/
virtual inline bool isValid() const;
@@ -113,8 +113,8 @@ class GHOST_Rect {
/**
* Grows the rectangle to included a point.
- * \param x The x-coordinate of the point.
- * \param y The y-coordinate of the point.
+ * \param x: The x-coordinate of the point.
+ * \param y: The y-coordinate of the point.
*/
virtual inline void wrapPoint(GHOST_TInt32 &x,
GHOST_TInt32 &y,
@@ -124,24 +124,24 @@ class GHOST_Rect {
/**
* Returns whether the point is inside this rectangle.
* Point on the boundary is considered inside.
- * \param x x-coordinate of point to test.
- * \param y y-coordinate of point to test.
+ * \param x: x-coordinate of point to test.
+ * \param y: y-coordinate of point to test.
* \return boolean value (true if point is inside).
*/
virtual inline bool isInside(GHOST_TInt32 x, GHOST_TInt32 y) const;
/**
* Returns whether the rectangle is inside this rectangle.
- * \param r rectangle to test.
- * \return visibility (not, partially or fully visible).
+ * \param r: rectangle to test.
+ * \return visibility (not, partially or fully visible).
*/
virtual GHOST_TVisibility getVisibility(GHOST_Rect &r) const;
/**
* Sets rectangle members.
* Sets rectangle members such that it is centered at the given location.
- * \param cx requested center x-coordinate of the rectangle
- * \param cy requested center y-coordinate of the rectangle
+ * \param cx: requested center x-coordinate of the rectangle.
+ * \param cy: requested center y-coordinate of the rectangle.
*/
virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy);
@@ -149,10 +149,10 @@ class GHOST_Rect {
* Sets rectangle members.
* Sets rectangle members such that it is centered at the given location,
* with the width requested.
- * \param cx requested center x-coordinate of the rectangle
- * \param cy requested center y-coordinate of the rectangle
- * \param w requested width of the rectangle
- * \param h requested height of the rectangle
+ * \param cx: requested center x-coordinate of the rectangle.
+ * \param cy: requested center y-coordinate of the rectangle.
+ * \param w: requested width of the rectangle.
+ * \param h: requested height of the rectangle.
*/
virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h);
@@ -160,8 +160,8 @@ class GHOST_Rect {
* Clips a rectangle.
* Updates the rectangle given such that it will fit within this one.
* This can result in an empty rectangle.
- * \param r the rectangle to clip
- * \return whether clipping has occurred
+ * \param r: the rectangle to clip.
+ * \return whether clipping has occurred
*/
virtual bool clip(GHOST_Rect &r) const;
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 5f0516ae121..547be04ac86 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -162,7 +162,8 @@ typedef enum {
} GHOST_TDrawingContextType;
typedef enum {
- GHOST_kButtonMaskLeft = 0,
+ GHOST_kButtonMaskNone,
+ GHOST_kButtonMaskLeft,
GHOST_kButtonMaskMiddle,
GHOST_kButtonMaskRight,
GHOST_kButtonMaskButton4,
@@ -584,8 +585,8 @@ typedef int GHOST_TEmbedderWindowID;
/**
* A timer task callback routine.
- * \param task The timer task object.
- * \param time The current time.
+ * \param task: The timer task object.
+ * \param time: The current time.
*/
#ifdef __cplusplus
class GHOST_ITimerTask;
diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h
index e28fae8870c..e77bab4f2ec 100644
--- a/intern/ghost/intern/GHOST_Buttons.h
+++ b/intern/ghost/intern/GHOST_Buttons.h
@@ -40,15 +40,15 @@ struct GHOST_Buttons {
/**
* Returns the state of a single button.
- * \param mask Key button to return.
+ * \param mask: Key button to return.
* \return The state of the button (pressed == true).
*/
bool get(GHOST_TButtonMask mask) const;
/**
* Updates the state of a single button.
- * \param mask Button state to update.
- * \param down The new state of the button.
+ * \param mask: Button state to update.
+ * \param down: The new state of the button.
*/
void set(GHOST_TButtonMask mask, bool down);
diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.h b/intern/ghost/intern/GHOST_CallbackEventConsumer.h
index 9a76f4b031f..0d4941907c7 100644
--- a/intern/ghost/intern/GHOST_CallbackEventConsumer.h
+++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.h
@@ -35,8 +35,8 @@ class GHOST_CallbackEventConsumer : public GHOST_IEventConsumer {
public:
/**
* Constructor.
- * \param eventCallback The call-back routine invoked.
- * \param userData The data passed back through the call-back routine.
+ * \param eventCallback: The call-back routine invoked.
+ * \param userData: The data passed back through the call-back routine.
*/
GHOST_CallbackEventConsumer(GHOST_EventCallbackProcPtr eventCallback,
GHOST_TUserDataPtr userData);
@@ -50,7 +50,7 @@ class GHOST_CallbackEventConsumer : public GHOST_IEventConsumer {
/**
* This method is called by an event producer when an event is available.
- * \param event The event that can be handled or ignored.
+ * \param event: The event that can be handled or ignored.
* \return Indication as to whether the event was handled.
*/
bool processEvent(GHOST_IEvent *event);
diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h
index 33eeacbb203..d07913b28c4 100644
--- a/intern/ghost/intern/GHOST_Context.h
+++ b/intern/ghost/intern/GHOST_Context.h
@@ -35,7 +35,7 @@ class GHOST_Context : public GHOST_IContext {
public:
/**
* Constructor.
- * \param stereoVisual Stereo visual for quad buffered stereo.
+ * \param stereoVisual: Stereo visual for quad buffered stereo.
*/
GHOST_Context(bool stereoVisual) : m_stereoVisual(stereoVisual)
{
@@ -50,19 +50,19 @@ class GHOST_Context : public GHOST_IContext {
/**
* Swaps front and back buffers of a window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
virtual GHOST_TSuccess swapBuffers() = 0;
/**
* Activates the drawing context of this window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
virtual GHOST_TSuccess activateDrawingContext() = 0;
/**
* Release the drawing context of the calling thread.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
virtual GHOST_TSuccess releaseDrawingContext() = 0;
@@ -89,8 +89,8 @@ class GHOST_Context : public GHOST_IContext {
virtual GHOST_TSuccess releaseNativeHandles() = 0;
/**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
+ * Sets the swap interval for #swapBuffers.
+ * \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
virtual GHOST_TSuccess setSwapInterval(int /*interval*/)
@@ -99,8 +99,8 @@ class GHOST_Context : public GHOST_IContext {
}
/**
- * Gets the current swap interval for swapBuffers.
- * \param intervalOut Variable to store the swap interval if it can be read.
+ * Gets the current swap interval for #swapBuffers.
+ * \param intervalOut: Variable to store the swap interval if it can be read.
* \return Whether the swap interval can be read.
*/
virtual GHOST_TSuccess getSwapInterval(int &)
diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h
index 7b1e186dede..d499ec987b0 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.h
+++ b/intern/ghost/intern/GHOST_ContextCGL.h
@@ -50,19 +50,19 @@ class GHOST_ContextCGL : public GHOST_Context {
/**
* Swaps front and back buffers of a window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess swapBuffers();
/**
* Activates the drawing context of this window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess activateDrawingContext();
/**
* Release the drawing context of the calling thread.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess releaseDrawingContext();
@@ -82,15 +82,15 @@ class GHOST_ContextCGL : public GHOST_Context {
GHOST_TSuccess releaseNativeHandles();
/**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
+ * Sets the swap interval for #swapBuffers.
+ * \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
GHOST_TSuccess setSwapInterval(int interval);
/**
- * Gets the current swap interval for swapBuffers.
- * \param intervalOut Variable to store the swap interval if it can be read.
+ * Gets the current swap interval for #swapBuffers.
+ * \param intervalOut: Variable to store the swap interval if it can be read.
* \return Whether the swap interval can be read.
*/
GHOST_TSuccess getSwapInterval(int &);
diff --git a/intern/ghost/intern/GHOST_ContextD3D.h b/intern/ghost/intern/GHOST_ContextD3D.h
index e85516838fc..18b4a5d1286 100644
--- a/intern/ghost/intern/GHOST_ContextD3D.h
+++ b/intern/ghost/intern/GHOST_ContextD3D.h
@@ -38,19 +38,19 @@ class GHOST_ContextD3D : public GHOST_Context {
/**
* Swaps front and back buffers of a window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess swapBuffers();
/**
* Activates the drawing context of this window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess activateDrawingContext();
/**
* Release the drawing context of the calling thread.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess releaseDrawingContext();
@@ -77,8 +77,8 @@ class GHOST_ContextD3D : public GHOST_Context {
GHOST_TSuccess releaseNativeHandles();
/**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
+ * Sets the swap interval for #swapBuffers.
+ * \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
GHOST_TSuccess setSwapInterval(int /*interval*/)
@@ -87,8 +87,8 @@ class GHOST_ContextD3D : public GHOST_Context {
}
/**
- * Gets the current swap interval for swapBuffers.
- * \param intervalOut Variable to store the swap interval if it can be read.
+ * Gets the current swap interval for #swapBuffers.
+ * \param intervalOut: Variable to store the swap interval if it can be read.
* \return Whether the swap interval can be read.
*/
GHOST_TSuccess getSwapInterval(int &)
diff --git a/intern/ghost/intern/GHOST_ContextEGL.h b/intern/ghost/intern/GHOST_ContextEGL.h
index e5dae0d22a8..f828271d88d 100644
--- a/intern/ghost/intern/GHOST_ContextEGL.h
+++ b/intern/ghost/intern/GHOST_ContextEGL.h
@@ -57,19 +57,19 @@ class GHOST_ContextEGL : public GHOST_Context {
/**
* Swaps front and back buffers of a window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess swapBuffers();
/**
* Activates the drawing context of this window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess activateDrawingContext();
/**
* Release the drawing context of the calling thread.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess releaseDrawingContext();
@@ -87,15 +87,15 @@ class GHOST_ContextEGL : public GHOST_Context {
GHOST_TSuccess releaseNativeHandles();
/**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
+ * Sets the swap interval for #swapBuffers.
+ * \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
GHOST_TSuccess setSwapInterval(int interval);
/**
- * Gets the current swap interval for swapBuffers.
- * \param intervalOut Variable to store the swap interval if it can be read.
+ * Gets the current swap interval for #swapBuffers.
+ * \param intervalOut: Variable to store the swap interval if it can be read.
* \return Whether the swap interval can be read.
*/
GHOST_TSuccess getSwapInterval(int &intervalOut);
diff --git a/intern/ghost/intern/GHOST_ContextGLX.h b/intern/ghost/intern/GHOST_ContextGLX.h
index e5654b1aed7..178c750ea99 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.h
+++ b/intern/ghost/intern/GHOST_ContextGLX.h
@@ -61,19 +61,19 @@ class GHOST_ContextGLX : public GHOST_Context {
/**
* Swaps front and back buffers of a window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess swapBuffers();
/**
* Activates the drawing context of this window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess activateDrawingContext();
/**
* Release the drawing context of the calling thread.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess releaseDrawingContext();
@@ -91,15 +91,15 @@ class GHOST_ContextGLX : public GHOST_Context {
GHOST_TSuccess releaseNativeHandles();
/**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
+ * Sets the swap interval for #swapBuffers.
+ * \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
GHOST_TSuccess setSwapInterval(int interval);
/**
- * Gets the current swap interval for swapBuffers.
- * \param intervalOut Variable to store the swap interval if it can be read.
+ * Gets the current swap interval for #swapBuffers.
+ * \param intervalOut: Variable to store the swap interval if it can be read.
* \return Whether the swap interval can be read.
*/
GHOST_TSuccess getSwapInterval(int &intervalOut);
diff --git a/intern/ghost/intern/GHOST_ContextNone.h b/intern/ghost/intern/GHOST_ContextNone.h
index b1ac349e4a7..46dde89794a 100644
--- a/intern/ghost/intern/GHOST_ContextNone.h
+++ b/intern/ghost/intern/GHOST_ContextNone.h
@@ -35,50 +35,50 @@ class GHOST_ContextNone : public GHOST_Context {
/**
* Dummy function
- * \return Always succeeds
+ * \return Always succeeds
*/
GHOST_TSuccess swapBuffers();
/**
* Dummy function
- * \return Always succeeds
+ * \return Always succeeds.
*/
GHOST_TSuccess activateDrawingContext();
/**
* Dummy function
- * \return Always succeeds
+ * \return Always succeeds.
*/
GHOST_TSuccess releaseDrawingContext();
/**
* Dummy function
- * \return Always succeeds
+ * \return Always succeeds.
*/
GHOST_TSuccess updateDrawingContext();
/**
* Dummy function
- * \return Always succeeds
+ * \return Always succeeds.
*/
GHOST_TSuccess initializeDrawingContext();
/**
* Dummy function
- * \return Always succeeds
+ * \return Always succeeds.
*/
GHOST_TSuccess releaseNativeHandles();
/**
* Dummy function
- * \return Always succeeds
+ * \return Always succeeds.
*/
GHOST_TSuccess setSwapInterval(int interval);
/**
* Dummy function
- * \param intervalOut Gets whatever was set by setSwapInterval
- * \return Always succeeds
+ * \param intervalOut: Gets whatever was set by #setSwapInterval.
+ * \return Always succeeds.
*/
GHOST_TSuccess getSwapInterval(int &intervalOut);
diff --git a/intern/ghost/intern/GHOST_ContextSDL.h b/intern/ghost/intern/GHOST_ContextSDL.h
index ead2e91181c..8e8c91b86a3 100644
--- a/intern/ghost/intern/GHOST_ContextSDL.h
+++ b/intern/ghost/intern/GHOST_ContextSDL.h
@@ -61,19 +61,19 @@ class GHOST_ContextSDL : public GHOST_Context {
/**
* Swaps front and back buffers of a window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess swapBuffers();
/**
* Activates the drawing context of this window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess activateDrawingContext();
/**
* Release the drawing context of the calling thread.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess releaseDrawingContext();
@@ -91,15 +91,15 @@ class GHOST_ContextSDL : public GHOST_Context {
GHOST_TSuccess releaseNativeHandles();
/**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
+ * Sets the swap interval for #swapBuffers.
+ * \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
GHOST_TSuccess setSwapInterval(int interval);
/**
- * Gets the current swap interval for swapBuffers.
- * \param intervalOut Variable to store the swap interval if it can be read.
+ * Gets the current swap interval for #swapBuffers.
+ * \param intervalOut: Variable to store the swap interval if it can be read.
* \return Whether the swap interval can be read.
*/
GHOST_TSuccess getSwapInterval(int &intervalOut);
diff --git a/intern/ghost/intern/GHOST_ContextWGL.h b/intern/ghost/intern/GHOST_ContextWGL.h
index 087fca100e4..7367bc3baed 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.h
+++ b/intern/ghost/intern/GHOST_ContextWGL.h
@@ -58,19 +58,19 @@ class GHOST_ContextWGL : public GHOST_Context {
/**
* Swaps front and back buffers of a window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess swapBuffers();
/**
* Activates the drawing context of this window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess activateDrawingContext();
/**
* Release the drawing context of the calling thread.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
GHOST_TSuccess releaseDrawingContext();
@@ -88,15 +88,15 @@ class GHOST_ContextWGL : public GHOST_Context {
GHOST_TSuccess releaseNativeHandles();
/**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
+ * Sets the swap interval for #swapBuffers.
+ * \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
GHOST_TSuccess setSwapInterval(int interval);
/**
- * Gets the current swap interval for swapBuffers.
- * \param intervalOut Variable to store the swap interval if it can be read.
+ * Gets the current swap interval for #swapBuffers.
+ * \param intervalOut: Variable to store the swap interval if it can be read.
* \return Whether the swap interval can be read.
*/
GHOST_TSuccess getSwapInterval(int &intervalOut);
diff --git a/intern/ghost/intern/GHOST_DisplayManager.h b/intern/ghost/intern/GHOST_DisplayManager.h
index 67b9aada55f..26bc687a179 100644
--- a/intern/ghost/intern/GHOST_DisplayManager.h
+++ b/intern/ghost/intern/GHOST_DisplayManager.h
@@ -52,15 +52,15 @@ class GHOST_DisplayManager {
/**
* Returns the number of display devices on this system.
- * \param numDisplays The number of displays on this system.
+ * \param numDisplays: The number of displays on this system.
* \return Indication of success.
*/
virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const;
/**
* Returns the number of display settings for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param numSettings The number of settings of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param numSettings: The number of settings of the display device with this index.
* \return Indication of success.
*/
virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display,
@@ -68,9 +68,9 @@ class GHOST_DisplayManager {
/**
* Returns the current setting for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param index The setting index to be returned.
- * \param setting The setting of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param index: The setting index to be returned.
+ * \param setting: The setting of the display device with this index.
* \return Indication of success.
*/
virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display,
@@ -79,8 +79,8 @@ class GHOST_DisplayManager {
/**
* Returns the current setting for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The current setting of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display,
@@ -90,8 +90,8 @@ class GHOST_DisplayManager {
* Changes the current setting for this display device.
* The setting given to this method is matched against the available display settings.
* The best match is activated (@see findMatch()).
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The setting of the display device to be matched and activated.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param setting: The setting of the display device to be matched and activated.
* \return Indication of success.
*/
virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display,
@@ -102,9 +102,9 @@ class GHOST_DisplayManager {
/**
* Finds the best display settings match.
- * \param display The index of the display device.
- * \param setting The setting to match.
- * \param match The optimal display setting.
+ * \param display: The index of the display device.
+ * \param setting: The setting to match.
+ * \param match: The optimal display setting.
* \return Indication of success.
*/
GHOST_TSuccess findMatch(GHOST_TUns8 display,
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
index 5edd555a78b..745ad457796 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
@@ -43,14 +43,14 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager {
/**
* Returns the number of display devices on this system.
- * \param numDisplays The number of displays on this system.
+ * \param numDisplays: The number of displays on this system.
* \return Indication of success.
*/
GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const;
/**
* Returns the number of display settings for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
* \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
@@ -58,9 +58,9 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager {
/**
* Returns the current setting for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param index The setting index to be returned.
- * \param setting The setting of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param index: The setting index to be returned.
+ * \param setting: The setting of the display device with this index.
* \return Indication of success.
*/
GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display,
@@ -69,8 +69,8 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager {
/**
* Returns the current setting for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The current setting of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display,
@@ -78,8 +78,8 @@ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager {
/**
* Changes the current setting for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The current setting of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display,
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
index 3392d515c16..2de866b04ec 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerWin32.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
@@ -42,14 +42,14 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager {
/**
* Returns the number of display devices on this system.
- * \param numDisplays The number of displays on this system.
+ * \param numDisplays: The number of displays on this system.
* \return Indication of success.
*/
GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const;
/**
* Returns the number of display settings for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
* \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
@@ -57,9 +57,9 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager {
/**
* Returns the current setting for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param index The setting index to be returned.
- * \param setting The setting of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param index: The setting index to be returned.
+ * \param setting: The setting of the display device with this index.
* \return Indication of success.
*/
GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display,
@@ -68,8 +68,8 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager {
/**
* Returns the current setting for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The current setting of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display,
@@ -77,8 +77,8 @@ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager {
/**
* Changes the current setting for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The current setting of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display,
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h
index a36ff8d49f1..e0fc1cc1210 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerX11.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h
@@ -40,14 +40,14 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager {
/**
* Returns the number of display devices on this system.
- * \param numDisplays The number of displays on this system.
+ * \param numDisplays: The number of displays on this system.
* \return Indication of success.
*/
GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const;
/**
* Returns the number of display settings for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
* \param numSetting: The number of settings of the display device with this index.
* \return Indication of success.
*/
@@ -55,9 +55,9 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager {
/**
* Returns the current setting for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param index The setting index to be returned.
- * \param setting The setting of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param index: The setting index to be returned.
+ * \param setting: The setting of the display device with this index.
* \return Indication of success.
*/
GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display,
@@ -66,8 +66,8 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager {
/**
* Returns the current setting for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The current setting of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display,
@@ -75,8 +75,8 @@ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager {
/**
* Changes the current setting for this display device.
- * \param display The index of the display to query with 0 <= display < getNumDisplays().
- * \param setting The current setting of the display device with this index.
+ * \param display: The index of the display to query with 0 <= display < getNumDisplays().
+ * \param setting: The current setting of the display device with this index.
* \return Indication of success.
*/
GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display,
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h
index ecce3a68835..08e8ba11b23 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.h
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.h
@@ -73,8 +73,8 @@ class GHOST_DropTargetWin32 : public IDropTarget {
* With the modifier keys, we want to distinguish left and right keys.
* Sometimes this is not possible (Windows ME for instance). Then, we want
* events generated for both keys.
- * \param window The window to register as drop target.
- * \param system The associated system.
+ * \param window: The window to register as drop target.
+ * \param system: The associated system.
*/
GHOST_DropTargetWin32(GHOST_WindowWin32 *window, GHOST_SystemWin32 *system);
@@ -89,14 +89,14 @@ class GHOST_DropTargetWin32 : public IDropTarget {
/**
* Base the effect on those allowed by the drop-source.
- * \param dwAllowed Drop sources allowed drop effect.
+ * \param dwAllowed: Drop sources allowed drop effect.
* \return The allowed drop effect.
*/
DWORD allowedDropEffect(DWORD dwAllowed);
/**
* Query DataObject for the data types it supports.
- * \param pDataObject Pointer to the DataObject.
+ * \param pDataObject: Pointer to the DataObject.
* \return GHOST data type.
*/
GHOST_TDragnDropTypes getGhostType(IDataObject *pDataObject);
@@ -104,21 +104,21 @@ class GHOST_DropTargetWin32 : public IDropTarget {
/**
* Get data to pass in event.
* It checks the type and calls specific functions for each type.
- * \param pDataObject Pointer to the DataObject.
+ * \param pDataObject: Pointer to the DataObject.
* \return Pointer to data.
*/
void *getGhostData(IDataObject *pDataObject);
/**
* Allocate data as file array to pass in event.
- * \param pDataObject Pointer to the DataObject.
+ * \param pDataObject: Pointer to the DataObject.
* \return Pointer to data.
*/
void *getDropDataAsFilenames(IDataObject *pDataObject);
/**
* Allocate data as string to pass in event.
- * \param pDataObject Pointer to the DataObject.
+ * \param pDataObject: Pointer to the DataObject.
* \return Pointer to data.
*/
void *getDropDataAsString(IDataObject *pDataObject);
@@ -127,8 +127,8 @@ class GHOST_DropTargetWin32 : public IDropTarget {
* Convert Unicode to ANSI, replacing uncomfortable chars with '?'.
* The ANSI codepage is the system default codepage,
* and can change from system to system.
- * \param in LPCWSTR.
- * \param out char *. Is set to NULL on failure.
+ * \param in: LPCWSTR.
+ * \param out: char *. Is set to NULL on failure.
* \return 0 on failure. Else the size of the string including '\0'.
*/
int WideCharToANSI(LPCWSTR in, char *&out);
diff --git a/intern/ghost/intern/GHOST_DropTargetX11.h b/intern/ghost/intern/GHOST_DropTargetX11.h
index a96852da7bb..69f6fec7ac1 100644
--- a/intern/ghost/intern/GHOST_DropTargetX11.h
+++ b/intern/ghost/intern/GHOST_DropTargetX11.h
@@ -34,8 +34,8 @@ class GHOST_DropTargetX11 {
/**
* Constructor
*
- * \param window The window to register as drop target.
- * \param system The associated system.
+ * \param window: The window to register as drop target.
+ * \param system: The associated system.
*/
GHOST_DropTargetX11(GHOST_WindowX11 *window, GHOST_SystemX11 *system);
@@ -52,9 +52,9 @@ class GHOST_DropTargetX11 {
/**
* Get data to pass in event.
* It checks the type and calls specific functions for each type.
- * \param dropType - type of dropped entity.
- * \param dropBuffer - buffer returned from source application
- * \param dropBufferSize - size of returned buffer
+ * \param dropType: Type of dropped entity.
+ * \param dropBuffer: Buffer returned from source application.
+ * \param dropBufferSize: Size of returned buffer.
* \return Pointer to data.
*/
void *getGhostData(Atom dropType, unsigned char *dropBuffer, int dropBufferSize);
@@ -73,25 +73,25 @@ class GHOST_DropTargetX11 {
void Uninitialize(void);
/**
- * Get data to be passed to event from text/uri-list mime type
- * \param dropBuffer - buffer returned from source application
- * \param dropBufferSize - size of dropped buffer
- * \return pointer to newly created GHOST data
+ * Get data to be passed to event from text/URI-list mime type
+ * \param dropBuffer: Buffer returned from source application.
+ * \param dropBufferSize: Size of dropped buffer.
+ * \return pointer to newly created GHOST data.
*/
void *getURIListGhostData(unsigned char *dropBuffer, int dropBufferSize);
/**
- * Decode URL (i.e. converts "file:///a%20b/test" to "file:///a b/test")
- * \param decodedOut - buffer for decoded URL
- * \param bufferSize - size of output buffer
- * \param encodedIn - input encoded buffer to be decoded
+ * Decode URL (i.e. converts `file:///a%20b/test` to `file:///a b/test`)
+ * \param decodedOut: - buffer for decoded URL.
+ * \param bufferSize: - size of output buffer.
+ * \param encodedIn: - input encoded buffer to be decoded.
*/
void UrlDecode(char *decodedOut, int bufferSize, const char *encodedIn);
/**
- * Fully decode file URL (i.e. converts "file:///a%20b/test" to "/a b/test")
- * \param fileUrl - file path URL to be fully decoded
- * \return decoded file path (result should be free-d)
+ * Fully decode file URL (i.e. converts `file:///a%20b/test` to `/a b/test`)
+ * \param fileUrl: - file path URL to be fully decoded.
+ * \return decoded file path (result should be free-d).
*/
char *FileUrlDecode(char *fileUrl);
diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h
index 845d62fa810..5016ca0e117 100644
--- a/intern/ghost/intern/GHOST_Event.h
+++ b/intern/ghost/intern/GHOST_Event.h
@@ -33,9 +33,9 @@ class GHOST_Event : public GHOST_IEvent {
public:
/**
* Constructor.
- * \param msec The time this event was generated.
- * \param type The type of this event.
- * \param window The generating window (or NULL if system event).
+ * \param msec: The time this event was generated.
+ * \param type: The type of this event.
+ * \param window: The generating window (or NULL if system event).
*/
GHOST_Event(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window)
: m_type(type), m_time(msec), m_window(window), m_data(NULL)
diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h
index 7072e0c5409..02804efdcba 100644
--- a/intern/ghost/intern/GHOST_EventButton.h
+++ b/intern/ghost/intern/GHOST_EventButton.h
@@ -34,21 +34,19 @@ class GHOST_EventButton : public GHOST_Event {
public:
/**
* Constructor.
- * \param time The time this event was generated.
- * \param type The type of this event.
- * \param window The window of this event.
- * \param button The state of the buttons were at the time of the event.
- * \param tablet The tablet data associated with this event.
+ * \param time: The time this event was generated.
+ * \param type: The type of this event.
+ * \param window: The window of this event.
+ * \param button: The state of the buttons were at the time of the event.
+ * \param tablet: The tablet data associated with this event.
*/
GHOST_EventButton(GHOST_TUns64 time,
GHOST_TEventType type,
GHOST_IWindow *window,
GHOST_TButtonMask button,
const GHOST_TabletData &tablet)
- : GHOST_Event(time, type, window)
+ : GHOST_Event(time, type, window), m_buttonEventData({button, tablet})
{
- m_buttonEventData.button = button;
- m_buttonEventData.tablet = tablet;
m_data = &m_buttonEventData;
}
diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h
index ba85cd74723..d83ff6af6ce 100644
--- a/intern/ghost/intern/GHOST_EventCursor.h
+++ b/intern/ghost/intern/GHOST_EventCursor.h
@@ -33,11 +33,11 @@ class GHOST_EventCursor : public GHOST_Event {
public:
/**
* Constructor.
- * \param msec The time this event was generated.
- * \param type The type of this event.
- * \param x The x-coordinate of the location the cursor was at the time of the event.
- * \param y The y-coordinate of the location the cursor was at the time of the event.
- * \param tablet The tablet data associated with this event.
+ * \param msec: The time this event was generated.
+ * \param type: The type of this event.
+ * \param x: The x-coordinate of the location the cursor was at the time of the event.
+ * \param y: The y-coordinate of the location the cursor was at the time of the event.
+ * \param tablet: The tablet data associated with this event.
*/
GHOST_EventCursor(GHOST_TUns64 msec,
GHOST_TEventType type,
@@ -45,11 +45,8 @@ class GHOST_EventCursor : public GHOST_Event {
GHOST_TInt32 x,
GHOST_TInt32 y,
const GHOST_TabletData &tablet)
- : GHOST_Event(msec, type, window)
+ : GHOST_Event(msec, type, window), m_cursorEventData({x, y, tablet})
{
- m_cursorEventData.x = x;
- m_cursorEventData.y = y;
- m_cursorEventData.tablet = tablet;
m_data = &m_cursorEventData;
}
diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h
index 10975792993..a86b8302bf5 100644
--- a/intern/ghost/intern/GHOST_EventDragnDrop.h
+++ b/intern/ghost/intern/GHOST_EventDragnDrop.h
@@ -64,13 +64,13 @@ class GHOST_EventDragnDrop : public GHOST_Event {
public:
/**
* Constructor.
- * \param time The time this event was generated.
- * \param type The type of this event.
- * \param dataType The type of the drop candidate object
- * \param window The window where the event occurred
- * \param x The x-coordinate of the location the cursor was at the time of the event.
- * \param y The y-coordinate of the location the cursor was at the time of the event.
- * \param data The "content" dropped in the window
+ * \param time: The time this event was generated.
+ * \param type: The type of this event.
+ * \param dataType: The type of the drop candidate object.
+ * \param window: The window where the event occurred.
+ * \param x: The x-coordinate of the location the cursor was at the time of the event.
+ * \param y: The y-coordinate of the location the cursor was at the time of the event.
+ * \param data: The "content" dropped in the window.
*/
GHOST_EventDragnDrop(GHOST_TUns64 time,
GHOST_TEventType type,
diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h
index cb71b452d80..1e6a3284a51 100644
--- a/intern/ghost/intern/GHOST_EventKey.h
+++ b/intern/ghost/intern/GHOST_EventKey.h
@@ -35,9 +35,9 @@ class GHOST_EventKey : public GHOST_Event {
public:
/**
* Constructor.
- * \param msec The time this event was generated.
- * \param type The type of key event.
- * \param key The key code of the key.
+ * \param msec: The time this event was generated.
+ * \param type: The type of key event.
+ * \param key: The key code of the key.
*/
GHOST_EventKey(GHOST_TUns64 msec,
GHOST_TEventType type,
@@ -55,10 +55,10 @@ class GHOST_EventKey : public GHOST_Event {
/**
* Constructor.
- * \param msec The time this event was generated.
- * \param type The type of key event.
- * \param key The key code of the key.
- * \param ascii The ascii code for the key event.
+ * \param msec: The time this event was generated.
+ * \param type: The type of key event.
+ * \param key: The key code of the key.
+ * \param ascii: The ascii code for the key event.
*/
GHOST_EventKey(GHOST_TUns64 msec,
GHOST_TEventType type,
diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h
index befbdc72a5c..a372eb96a99 100644
--- a/intern/ghost/intern/GHOST_EventManager.h
+++ b/intern/ghost/intern/GHOST_EventManager.h
@@ -57,7 +57,7 @@ class GHOST_EventManager {
/**
* Returns the number of events of a certain type currently on the stack.
- * \param type The type of events to be counted.
+ * \param type: The type of events to be counted.
* \return The number of events on the stack of this type.
*/
GHOST_TUns32 getNumEvents(GHOST_TEventType type);
@@ -66,7 +66,7 @@ class GHOST_EventManager {
* Pushes an event on the stack.
* To dispatch it, call dispatchEvent() or dispatchEvents().
* Do not delete the event!
- * \param event The event to push on the stack.
+ * \param event: The event to push on the stack.
*/
GHOST_TSuccess pushEvent(GHOST_IEvent *event);
@@ -89,30 +89,30 @@ class GHOST_EventManager {
/**
* Adds a consumer to the list of event consumers.
- * \param consumer The consumer added to the list.
+ * \param consumer: The consumer added to the list.
* \return Indication as to whether addition has succeeded.
*/
GHOST_TSuccess addConsumer(GHOST_IEventConsumer *consumer);
/**
* Removes a consumer from the list of event consumers.
- * \param consumer The consumer removed from the list.
+ * \param consumer: The consumer removed from the list.
* \return Indication as to whether removal has succeeded.
*/
GHOST_TSuccess removeConsumer(GHOST_IEventConsumer *consumer);
/**
* Removes all events for a window from the stack.
- * \param window The window to remove events for.
+ * \param window: The window to remove events for.
*/
void removeWindowEvents(GHOST_IWindow *window);
/**
* Removes all events of a certain type from the stack.
- * The window parameter is optional. If non-null, the routine will remove
- * events only associated with that window.
- * \param type The type of events to be removed.
- * \param window The window to remove the events for.
+ * The window parameter is optional.
+ * If non-null, the routine will remove events only associated with that window.
+ * \param type: The type of events to be removed.
+ * \param window: The window to remove the events for.
*/
void removeTypeEvents(GHOST_TEventType type, GHOST_IWindow *window = NULL);
diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h
index 42de4da5ee5..96d0b9acf2d 100644
--- a/intern/ghost/intern/GHOST_EventPrinter.h
+++ b/intern/ghost/intern/GHOST_EventPrinter.h
@@ -34,7 +34,7 @@ class GHOST_EventPrinter : public GHOST_IEventConsumer {
public:
/**
* Prints all the events received to std out.
- * \param event The event that can be handled or not.
+ * \param event: The event that can be handled or not.
* \return Indication as to whether the event was handled.
*/
bool processEvent(GHOST_IEvent *event);
@@ -42,8 +42,8 @@ class GHOST_EventPrinter : public GHOST_IEventConsumer {
protected:
/**
* Converts GHOST key code to a readable string.
- * \param key The GHOST key code to convert.
- * \param str The GHOST key code converted to a readable string.
+ * \param key: The GHOST key code to convert.
+ * \param str: The GHOST key code converted to a readable string.
*/
void getKeyString(GHOST_TKey key, char str[32]) const;
};
diff --git a/intern/ghost/intern/GHOST_EventString.h b/intern/ghost/intern/GHOST_EventString.h
index 8cd24a8a78b..6dd2ffb2e86 100644
--- a/intern/ghost/intern/GHOST_EventString.h
+++ b/intern/ghost/intern/GHOST_EventString.h
@@ -33,10 +33,10 @@ class GHOST_EventString : public GHOST_Event {
public:
/**
* Constructor.
- * \param msec The time this event was generated.
- * \param type The type of this event.
- * \param window The generating window (or NULL if system event).
- * \param data_ptr Pointer to the (unformatted) data associated with the event
+ * \param msec: The time this event was generated.
+ * \param type: The type of this event.
+ * \param window: The generating window (or NULL if system event).
+ * \param data_ptr: Pointer to the (un-formatted) data associated with the event.
*/
GHOST_EventString(GHOST_TUns64 msec,
GHOST_TEventType type,
diff --git a/intern/ghost/intern/GHOST_EventTrackpad.h b/intern/ghost/intern/GHOST_EventTrackpad.h
index a22f8a34fad..3bbb29821a1 100644
--- a/intern/ghost/intern/GHOST_EventTrackpad.h
+++ b/intern/ghost/intern/GHOST_EventTrackpad.h
@@ -33,11 +33,11 @@ class GHOST_EventTrackpad : public GHOST_Event {
public:
/**
* Constructor.
- * \param msec The time this event was generated.
+ * \param msec: The time this event was generated.
* \param window: The window of this event.
- * \param subtype The subtype of the event.
- * \param x The x-delta of the pan event.
- * \param y The y-delta of the pan event.
+ * \param subtype: The subtype of the event.
+ * \param x: The x-delta of the pan event.
+ * \param y: The y-delta of the pan event.
*/
GHOST_EventTrackpad(GHOST_TUns64 msec,
GHOST_IWindow *window,
diff --git a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
index 24b42c08e8a..e9e688b76ab 100644
--- a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
+++ b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
@@ -44,8 +44,8 @@ class GHOST_IXrGraphicsBinding {
* Does __not__ require this object is initialized (can be called prior to
* #initFromGhostContext). It's actually meant to be called first.
*
- * \param r_requirement_info Return argument to retrieve an informal string on the requirements
- * to be met. Useful for error/debug messages.
+ * \param r_requirement_info: Return argument to retrieve an informal string on the requirements.
+ * to be met. Useful for error/debug messages.
*/
virtual bool checkVersionRequirements(class GHOST_Context &ghost_ctx,
XrInstance instance,
diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h
index 74698d50659..63ecfd96cb8 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.h
+++ b/intern/ghost/intern/GHOST_ImeWin32.h
@@ -40,9 +40,9 @@ class GHOST_EventIME : public GHOST_Event {
public:
/**
* Constructor.
- * \param msec The time this event was generated.
- * \param type The type of key event.
- * \param key The key code of the key.
+ * \param msec: The time this event was generated.
+ * \param type: The type of key event.
+ * \param key: The key code of the key.
*/
GHOST_EventIME(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window, void *customdata)
: GHOST_Event(msec, type, window)
diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h
index c41ce8b7f39..e94ccef08c0 100644
--- a/intern/ghost/intern/GHOST_ModifierKeys.h
+++ b/intern/ghost/intern/GHOST_ModifierKeys.h
@@ -40,7 +40,7 @@ struct GHOST_ModifierKeys {
/**
* Returns the modifier key's key code from a modifier key mask.
- * \param mask The mask of the modifier key.
+ * \param mask: The mask of the modifier key.
* \return The modifier key's key code.
*/
static GHOST_TKey getModifierKeyCode(GHOST_TModifierKeyMask mask);
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index d5b23d76016..279f90b9641 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -79,12 +79,14 @@ class GHOST_System : public GHOST_ISystem {
/**
* Installs a timer.
- * Note that, on most operating systems, messages need to be processed in order
+ *
+ * \note On most operating systems, messages need to be processed in order
* for the timer callbacks to be invoked.
- * \param delay The time to wait for the first call to the timerProc (in milliseconds)
- * \param interval The interval between calls to the timerProc
- * \param timerProc The callback invoked when the interval expires,
- * \param userData Placeholder for user data.
+ *
+ * \param delay: The time to wait for the first call to the #timerProc (in milliseconds).
+ * \param interval: The interval between calls to the #timerProc.
+ * \param timerProc: The callback invoked when the interval expires.
+ * \param userData: Placeholder for user data.
* \return A timer task (0 if timer task installation failed).
*/
GHOST_ITimerTask *installTimer(GHOST_TUns64 delay,
@@ -94,7 +96,7 @@ class GHOST_System : public GHOST_ISystem {
/**
* Removes a timer.
- * \param timerTask Timer task to be removed.
+ * \param timerTask: Timer task to be removed.
* \return Indication of success.
*/
GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask);
@@ -105,32 +107,32 @@ class GHOST_System : public GHOST_ISystem {
/**
* Dispose a window.
- * \param window Pointer to the window to be disposed.
- * \return Indication of success.
+ * \param window: Pointer to the window to be disposed.
+ * \return Indication of success.
*/
GHOST_TSuccess disposeWindow(GHOST_IWindow *window);
/**
* Create a new offscreen context.
* Never explicitly delete the context, use disposeContext() instead.
- * \return The new context (or 0 if creation failed).
+ * \return The new context (or 0 if creation failed).
*/
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
/**
* Returns whether a window is valid.
- * \param window Pointer to the window to be checked.
- * \return Indication of validity.
+ * \param window: Pointer to the window to be checked.
+ * \return Indication of validity.
*/
bool validWindow(GHOST_IWindow *window);
/**
* Begins full screen mode.
- * \param setting The new setting of the display.
- * \param window Window displayed in full screen.
- * \param stereoVisual Stereo visual for quad buffered stereo.
+ * \param setting: The new setting of the display.
+ * \param window: Window displayed in full screen.
+ * \param stereoVisual: Stereo visual for quad buffered stereo.
* This window is invalid after full screen has been ended.
- * \return Indication of success.
+ * \return Indication of success.
*/
GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting &setting,
GHOST_IWindow **window,
@@ -139,16 +141,16 @@ class GHOST_System : public GHOST_ISystem {
/**
* Updates the resolution while in fullscreen mode.
- * \param setting The new setting of the display.
- * \param window Window displayed in full screen.
+ * \param setting: The new setting of the display.
+ * \param window: Window displayed in full screen.
*
- * \return Indication of success.
+ * \return Indication of success.
*/
GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting &setting, GHOST_IWindow **window);
/**
* Ends full screen mode.
- * \return Indication of success.
+ * \return Indication of success.
*/
GHOST_TSuccess endFullScreen(void);
@@ -189,14 +191,14 @@ class GHOST_System : public GHOST_ISystem {
/**
* Adds the given event consumer to our list.
- * \param consumer The event consumer to add.
+ * \param consumer: The event consumer to add.
* \return Indication of success.
*/
GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer);
/**
* Remove the given event consumer to our list.
- * \param consumer The event consumer to remove.
+ * \param consumer: The event consumer to remove.
* \return Indication of success.
*/
GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer);
@@ -219,25 +221,25 @@ class GHOST_System : public GHOST_ISystem {
/**
* Returns the state of a modifier key (outside the message queue).
- * \param mask The modifier key state to retrieve.
- * \param isDown The state of a modifier key (true == pressed).
- * \return Indication of success.
+ * \param mask: The modifier key state to retrieve.
+ * \param isDown: The state of a modifier key (true == pressed).
+ * \return Indication of success.
*/
GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool &isDown) const;
/**
* Returns the state of a mouse button (outside the message queue).
- * \param mask The button state to retrieve.
- * \param isDown Button state.
- * \return Indication of success.
+ * \param mask: The button state to retrieve.
+ * \param isDown: Button state.
+ * \return Indication of success.
*/
GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool &isDown) const;
/**
* Set which tablet API to use. Only affects Windows, other platforms have a single API.
- * \param api Enum indicating which API to use.
+ * \param api: Enum indicating which API to use.
*/
- void setTabletAPI(GHOST_TTabletAPI api);
+ virtual void setTabletAPI(GHOST_TTabletAPI api);
GHOST_TTabletAPI getTabletAPI(void);
#ifdef WITH_INPUT_NDOF
@@ -260,7 +262,7 @@ class GHOST_System : public GHOST_ISystem {
* Pushes an event on the stack.
* To dispatch it, call dispatchEvent() or dispatchEvents().
* Do not delete the event!
- * \param event The event to push on the stack.
+ * \param event: The event to push on the stack.
*/
GHOST_TSuccess pushEvent(GHOST_IEvent *event);
@@ -288,41 +290,41 @@ class GHOST_System : public GHOST_ISystem {
/**
* Returns the state of all modifier keys.
- * \param keys The state of all modifier keys (true == pressed).
- * \return Indication of success.
+ * \param keys: The state of all modifier keys (true == pressed).
+ * \return Indication of success.
*/
virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const = 0;
/**
* Returns the state of the mouse buttons (outside the message queue).
- * \param buttons The state of the buttons.
- * \return Indication of success.
+ * \param buttons: The state of the buttons.
+ * \return Indication of success.
*/
virtual GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const = 0;
/**
* Returns the selection buffer
- * \param selection Only used on X11
- * \return Returns the clipboard data
+ * \param selection: Only used on X11.
+ * \return Returns the clipboard data
*
*/
virtual GHOST_TUns8 *getClipboard(bool selection) const = 0;
/**
* Put data to the Clipboard
- * \param buffer The buffer to copy to the clipboard
- * \param selection The clipboard to copy too only used on X11
+ * \param buffer: The buffer to copy to the clipboard.
+ * \param selection: The clipboard to copy too only used on X11.
*/
virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0;
/**
* Show a system message box
- * \param title The title of the message box
- * \param message The message to display
- * \param help_label Help button label
- * \param continue_label Continue button label
- * \param link An optional hyperlink
- * \param dialog_options Options how to display the message
+ * \param title: The title of the message box.
+ * \param message: The message to display.
+ * \param help_label: Help button label.
+ * \param continue_label: Continue button label.
+ * \param link: An optional hyperlink.
+ * \param dialog_options: Options how to display the message.
*/
virtual GHOST_TSuccess showMessageBox(const char * /*title*/,
const char * /*message*/,
@@ -363,7 +365,7 @@ class GHOST_System : public GHOST_ISystem {
/**
* Creates a fullscreen window.
- * \param window The window created.
+ * \param window: The window created.
* \return Indication of success.
*/
GHOST_TSuccess createFullScreenWindow(GHOST_Window **window,
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 22f3c58d297..5637dfb0565 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -85,19 +85,19 @@ class GHOST_SystemCocoa : public GHOST_System {
/**
* Create a new window.
* The new window is added to the list of windows managed.
- * Never explicitly delete the window, use disposeWindow() instead.
- * \param title The name of the window
+ * Never explicitly delete the window, use #disposeWindow() instead.
+ * \param title: The name of the window.
* (displayed in the title bar of the window if the OS supports it).
- * \param left The coordinate of the left edge of the window.
- * \param top The coordinate of the top edge of the window.
- * \param width The width the window.
- * \param height The height the window.
- * \param state The state of the window when opened.
- * \param type The type of drawing context installed in this window.
+ * \param left: The coordinate of the left edge of the window.
+ * \param top: The coordinate of the top edge of the window.
+ * \param width: The width the window.
+ * \param height: The height the window.
+ * \param state: The state of the window when opened.
+ * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
- * \param parentWindow Parent (embedder) window
- * \return The new window (or 0 if creation failed).
+ * \param parentWindow: Parent (embedder) window.
+ * \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *createWindow(const char *title,
GHOST_TInt32 left,
@@ -114,14 +114,14 @@ class GHOST_SystemCocoa : public GHOST_System {
/**
* Create a new offscreen context.
* Never explicitly delete the context, use disposeContext() instead.
- * \return The new context (or 0 if creation failed).
+ * \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
/**
* Dispose of a context.
- * \param context Pointer to the context to be disposed.
- * \return Indication of success.
+ * \param context: Pointer to the context to be disposed.
+ * \return Indication of success.
*/
GHOST_TSuccess disposeContext(GHOST_IContext *context);
@@ -131,7 +131,7 @@ class GHOST_SystemCocoa : public GHOST_System {
/**
* Gets events from the system and stores them in the queue.
- * \param waitForEvent Flag to wait for an event (or return immediately).
+ * \param waitForEvent: Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
*/
bool processEvents(bool waitForEvent);
@@ -150,12 +150,12 @@ class GHOST_SystemCocoa : public GHOST_System {
/**
* Handles a drag'n'drop destination event. Called by GHOST_WindowCocoa window subclass
- * \param eventType The type of drag'n'drop event
- * \param draggedObjectType The type object concerned
- * (currently array of file names, string, TIFF image)
- * \param mouseX x mouse coordinate (in cocoa base window coordinates)
- * \param mouseY y mouse coordinate
- * \param window The window on which the event occurred
+ * \param eventType: The type of drag'n'drop event.
+ * \param draggedObjectType: The type object concerned.
+ * (currently array of file names, string, TIFF image).
+ * \param mouseX: x mouse coordinate (in cocoa base window coordinates).
+ * \param mouseY: y mouse coordinate.
+ * \param window: The window on which the event occurred.
* \return Indication whether the event was handled.
*/
GHOST_TSuccess handleDraggingEvent(GHOST_TEventType eventType,
@@ -171,17 +171,17 @@ class GHOST_SystemCocoa : public GHOST_System {
/**
* Returns the current location of the cursor (location in screen coordinates)
- * \param x The x-coordinate of the cursor.
- * \param y The y-coordinate of the cursor.
- * \return Indication of success.
+ * \param x: The x-coordinate of the cursor.
+ * \param y: The y-coordinate of the cursor.
+ * \return Indication of success.
*/
GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
/**
* Updates the location of the cursor (location in screen coordinates).
- * \param x The x-coordinate of the cursor.
- * \param y The y-coordinate of the cursor.
- * \return Indication of success.
+ * \param x: The x-coordinate of the cursor.
+ * \param y: The y-coordinate of the cursor.
+ * \return Indication of success.
*/
GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
@@ -191,36 +191,36 @@ class GHOST_SystemCocoa : public GHOST_System {
/**
* Returns the state of all modifier keys.
- * \param keys The state of all modifier keys (true == pressed).
- * \return Indication of success.
+ * \param keys: The state of all modifier keys (true == pressed).
+ * \return Indication of success.
*/
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const;
/**
* Returns the state of the mouse buttons (outside the message queue).
- * \param buttons The state of the buttons.
- * \return Indication of success.
+ * \param buttons: The state of the buttons.
+ * \return Indication of success.
*/
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const;
/**
* Returns Clipboard data
- * \param selection Indicate which buffer to return
- * \return Returns the selected buffer
+ * \param selection: Indicate which buffer to return.
+ * \return Returns the selected buffer
*/
GHOST_TUns8 *getClipboard(bool selection) const;
/**
* Puts buffer to system clipboard
- * \param buffer The buffer to be copied
- * \param selection Indicates which buffer to copy too, only used on X11
+ * \param buffer: The buffer to be copied.
+ * \param selection: Indicates which buffer to copy too, only used on X11.
*/
void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
/**
* Handles a window event. Called by GHOST_WindowCocoa window delegate
- * \param eventType The type of window event
- * \param window The window on which the event occurred
+ * \param eventType: The type of window event.
+ * \param window: The window on which the event occurred.
* \return Indication whether the event was handled.
*/
GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa *window);
@@ -284,9 +284,9 @@ class GHOST_SystemCocoa : public GHOST_System {
/**
* Performs the actual cursor position update (location in screen coordinates).
- * \param x The x-coordinate of the cursor.
- * \param y The y-coordinate of the cursor.
- * \return Indication of success.
+ * \param x: The x-coordinate of the cursor.
+ * \param y: The y-coordinate of the cursor.
+ * \return Indication of success.
*/
GHOST_TSuccess setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 152dae48905..19753bca2c7 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -763,7 +763,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
/**
* Create a new offscreen context.
* Never explicitly delete the context, use #disposeContext() instead.
- * \return The new context (or 0 if creation failed).
+ * \return The new context (or 0 if creation failed).
*/
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings)
{
@@ -778,8 +778,8 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSet
/**
* Dispose of a context.
- * \param context Pointer to the context to be disposed.
- * \return Indication of success.
+ * \param context Pointer to the context to be disposed.
+ * \return Indication of success.
*/
GHOST_TSuccess GHOST_SystemCocoa::disposeContext(GHOST_IContext *context)
{
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index b1e2502fa78..8178b9bdf1e 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -234,6 +234,11 @@ GHOST_SystemWin32::~GHOST_SystemWin32()
toggleConsole(1);
}
+GHOST_TUns64 GHOST_SystemWin32::millisSinceStart(__int64 ms) const
+{
+ return (GHOST_TUns64)(ms - m_start * 1000 / m_freq);
+}
+
GHOST_TUns64 GHOST_SystemWin32::performanceCounterToMillis(__int64 perf_ticks) const
{
// Calculate the time passed since system initialization.
@@ -417,8 +422,8 @@ finished:
/**
* Dispose of a context.
- * \param context Pointer to the context to be disposed.
- * \return Indication of success.
+ * \param context Pointer to the context to be disposed.
+ * \return Indication of success.
*/
GHOST_TSuccess GHOST_SystemWin32::disposeContext(GHOST_IContext *context)
{
@@ -941,23 +946,137 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
window->updateMouseCapture(MouseReleased);
}
- if (window->m_tabletInRange) {
- if (window->useTabletAPI(GHOST_kTabletNative)) {
- // Win32 Pointer processing handles input while in-range and in-contact events.
- return NULL;
- }
+ /* Check for active Wintab mouse emulation in addition to a tablet in range because a proximity
+ * leave event might have fired before the Windows mouse up event, thus there are still tablet
+ * events to grab. The described behavior was observed in a Wacom Bamboo CTE-450. */
+ if (window->useTabletAPI(GHOST_kTabletWintab) &&
+ (window->m_tabletInRange || window->wintabSysButPressed()) &&
+ processWintabEvent(type, window, mask, window->getMousePressed())) {
+ /* Wintab processing only handles in-contact events. */
+ return NULL;
}
return new GHOST_EventButton(
- system->getMilliSeconds(), type, window, mask, window->getTabletData());
+ system->getMilliSeconds(), type, window, mask, GHOST_TABLET_DATA_NONE);
+}
+
+GHOST_TSuccess GHOST_SystemWin32::processWintabEvent(GHOST_TEventType type,
+ GHOST_WindowWin32 *window,
+ GHOST_TButtonMask mask,
+ bool mousePressed)
+{
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
+
+ /* Only process Wintab packets if we can correlate them to a Window's mouse button event. When a
+ * button event associated to a mouse button by Wintab occurs outside of WM_*BUTTON events,
+ * there's no way to tell if other simultaneously pressed non-mouse mapped buttons are associated
+ * to a modifier key (shift, alt, ctrl) or a system event (scroll, etc.) and thus it is not
+ * possible to determine if a mouse click event should occur. */
+ if (!mousePressed && !window->wintabSysButPressed()) {
+ return GHOST_kFailure;
+ }
+
+ std::vector<GHOST_WintabInfoWin32> wintabInfo;
+ if (!window->getWintabInfo(wintabInfo)) {
+ return GHOST_kFailure;
+ }
+
+ auto wtiIter = wintabInfo.begin();
+
+ /* We only process events that correlate to a mouse button events, so there may exist Wintab
+ * button down events that were instead mapped to e.g. scroll still in the queue. We need to
+ * skip those and find the last button down mapped to mouse buttons. */
+ if (!window->wintabSysButPressed()) {
+ /* Assume there may be no button down event currently in the queue. */
+ wtiIter = wintabInfo.end();
+
+ for (auto it = wintabInfo.begin(); it != wintabInfo.end(); it++) {
+ if (it->type == GHOST_kEventButtonDown) {
+ wtiIter = it;
+ }
+ }
+ }
+
+ bool unhandledButton = type != GHOST_kEventCursorMove;
+
+ for (; wtiIter != wintabInfo.end(); wtiIter++) {
+ auto info = *wtiIter;
+
+ switch (info.type) {
+ case GHOST_kEventButtonDown: {
+ /* While changing windows with a tablet, Window's mouse button events normally occur before
+ * tablet proximity events, so a button up event can't be differentiated as occurring from
+ * a Wintab tablet or a normal mouse and a Ghost button event will always be generated.
+ *
+ * If we were called during a button down event create a ghost button down event, otherwise
+ * don't duplicate the prior button down as it interrupts drawing immediately after
+ * changing a window. */
+ system->pushEvent(new GHOST_EventCursor(
+ info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
+ if (type == GHOST_kEventButtonDown && mask == info.button) {
+ system->pushEvent(
+ new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
+ unhandledButton = false;
+ }
+ window->updateWintabSysBut(MousePressed);
+ break;
+ }
+ case GHOST_kEventCursorMove:
+ system->pushEvent(new GHOST_EventCursor(
+ info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
+ break;
+ case GHOST_kEventButtonUp:
+ system->pushEvent(
+ new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
+ if (type == GHOST_kEventButtonUp && mask == info.button) {
+ unhandledButton = false;
+ }
+ window->updateWintabSysBut(MouseReleased);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* No Wintab button found correlating to the system button event, handle it too.
+ *
+ * Wintab button up events may be handled during WM_MOUSEMOVE, before their corresponding
+ * WM_*BUTTONUP event has fired, which results in two GHOST Button up events for a single Wintab
+ * associated button event. Alternatively this Windows button up event may have been generated
+ * from a non-stylus device such as a button on the tablet pad and needs to be handled for some
+ * workflows.
+ *
+ * The ambiguity introduced by Windows and Wintab buttons being asynchronous and having no
+ * definitive way to associate each, and that the Wintab API does not provide enough information
+ * to differentiate whether the stylus down is or is not modified by another button to a
+ * non-mouse mapping, means that we must pessimistically generate mouse up events when we are
+ * unsure of an association to prevent the mouse locking into a down state. */
+ if (unhandledButton) {
+ if (!window->wintabSysButPressed()) {
+ GHOST_TInt32 x, y;
+ system->getCursorPosition(x, y);
+ system->pushEvent(new GHOST_EventCursor(system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ window,
+ x,
+ y,
+ GHOST_TABLET_DATA_NONE));
+ }
+ system->pushEvent(new GHOST_EventButton(
+ system->getMilliSeconds(), type, window, mask, GHOST_TABLET_DATA_NONE));
+ }
+
+ return GHOST_kSuccess;
}
-void GHOST_SystemWin32::processPointerEvents(
+void GHOST_SystemWin32::processPointerEvent(
UINT type, GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam, bool &eventHandled)
{
std::vector<GHOST_PointerInfoWin32> pointerInfo;
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
+ /* Pointer events might fire when changing windows for a device which is set to use Wintab, even
+ * when when Wintab is left enabled but set to the bottom of Wintab overlap order. */
if (!window->useTabletAPI(GHOST_kTabletNative)) {
return;
}
@@ -982,7 +1101,7 @@ void GHOST_SystemWin32::processPointerEvents(
pointerInfo[0].tabletData));
break;
case WM_POINTERDOWN:
- // Move cursor to point of contact because GHOST_EventButton does not include position.
+ /* Move cursor to point of contact because GHOST_EventButton does not include position. */
system->pushEvent(new GHOST_EventCursor(pointerInfo[0].time,
GHOST_kEventCursorMove,
window,
@@ -997,8 +1116,8 @@ void GHOST_SystemWin32::processPointerEvents(
window->updateMouseCapture(MousePressed);
break;
case WM_POINTERUPDATE:
- // Coalesced pointer events are reverse chronological order, reorder chronologically.
- // Only contiguous move events are coalesced.
+ /* Coalesced pointer events are reverse chronological order, reorder chronologically.
+ * Only contiguous move events are coalesced. */
for (GHOST_TUns32 i = pointerInfo.size(); i-- > 0;) {
system->pushEvent(new GHOST_EventCursor(pointerInfo[i].time,
GHOST_kEventCursorMove,
@@ -1018,11 +1137,6 @@ void GHOST_SystemWin32::processPointerEvents(
break;
case WM_POINTERLEAVE:
window->m_tabletInRange = false;
- system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
- GHOST_kEventCursorMove,
- window,
- pointerInfo[0].buttonMask,
- pointerInfo[0].tabletData));
break;
default:
break;
@@ -1037,13 +1151,21 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
GHOST_TInt32 x_screen, y_screen;
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
- if (window->m_tabletInRange) {
- if (window->useTabletAPI(GHOST_kTabletNative)) {
- // Tablet input handled in WM_POINTER* events. WM_MOUSEMOVE events in response to tablet
- // input aren't normally generated when using WM_POINTER events, but manually moving the
- // system cursor as we do in WM_POINTER handling does.
+ if (window->m_tabletInRange || window->wintabSysButPressed()) {
+ if (window->useTabletAPI(GHOST_kTabletWintab) &&
+ processWintabEvent(
+ GHOST_kEventCursorMove, window, GHOST_kButtonMaskNone, window->getMousePressed())) {
+ return NULL;
+ }
+ else if (window->useTabletAPI(GHOST_kTabletNative)) {
+ /* Tablet input handled in WM_POINTER* events. WM_MOUSEMOVE events in response to tablet
+ * input aren't normally generated when using WM_POINTER events, but manually moving the
+ * system cursor as we do in WM_POINTER handling does. */
return NULL;
}
+
+ /* If using Wintab but no button event is currently active,
+ * fall through to default handling. */
}
system->getCursorPosition(x_screen, y_screen);
@@ -1076,7 +1198,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
window,
x_screen + x_accum,
y_screen + y_accum,
- window->getTabletData());
+ GHOST_TABLET_DATA_NONE);
}
}
else {
@@ -1085,7 +1207,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
window,
x_screen,
y_screen,
- window->getTabletData());
+ GHOST_TABLET_DATA_NONE);
}
return NULL;
}
@@ -1202,7 +1324,6 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type,
if (type == GHOST_kEventWindowActivate) {
system->getWindowManager()->setActiveWindow(window);
- window->bringTabletContextToFront();
}
return new GHOST_Event(system->getMilliSeconds(), type, window);
@@ -1230,6 +1351,20 @@ GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
system->getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, data));
}
+void GHOST_SystemWin32::setTabletAPI(GHOST_TTabletAPI api)
+{
+ GHOST_System::setTabletAPI(api);
+
+ GHOST_WindowManager *wm = getWindowManager();
+ GHOST_WindowWin32 *activeWindow = (GHOST_WindowWin32 *)wm->getActiveWindow();
+
+ for (GHOST_IWindow *win : wm->getWindows()) {
+ GHOST_WindowWin32 *windowsWindow = (GHOST_WindowWin32 *)win;
+ windowsWindow->updateWintab(windowsWindow == activeWindow,
+ !::IsIconic(windowsWindow->getHWND()));
+ }
+}
+
void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax)
{
minmax->ptMinTrackSize.x = 320;
@@ -1467,14 +1602,19 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
////////////////////////////////////////////////////////////////////////
- // Tablet events, processed
+ // Wintab events, processed
////////////////////////////////////////////////////////////////////////
- case WT_PACKET:
- window->processWin32TabletEvent(wParam, lParam);
+ case WT_INFOCHANGE: {
+ window->processWintabInfoChangeEvent(lParam);
+ break;
+ }
+ case WT_PROXIMITY: {
+ bool inRange = LOWORD(lParam);
+ window->processWintabProximityEvent(inRange);
break;
- case WT_CSRCHANGE:
- case WT_PROXIMITY:
- window->processWin32TabletInitEvent();
+ }
+ case WT_PACKET:
+ window->updatePendingWintabEvents();
break;
////////////////////////////////////////////////////////////////////////
// Pointer events, processed
@@ -1484,7 +1624,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
case WM_POINTERUPDATE:
case WM_POINTERUP:
case WM_POINTERLEAVE:
- processPointerEvents(msg, window, wParam, lParam, eventHandled);
+ processPointerEvent(msg, window, wParam, lParam, eventHandled);
break;
////////////////////////////////////////////////////////////////////////
// Mouse events, processed
@@ -1614,7 +1754,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* will not be dispatched to OUR active window if we minimize one of OUR windows. */
if (LOWORD(wParam) == WA_INACTIVE)
window->lostMouseCapture();
- window->processWin32TabletActivateEvent(GET_WM_ACTIVATE_STATE(wParam, lParam));
+
+ window->updateWintab(LOWORD(wParam) != WA_INACTIVE, !::IsIconic(window->getHWND()));
+
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
break;
}
@@ -1672,6 +1814,14 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
else {
event = processWindowEvent(GHOST_kEventWindowSize, window);
}
+
+ /* Window might be minimized while inactive. When a window is inactive but not minimized,
+ * Wintab is left enabled (to catch the case where a pen is used to activate a window).
+ * When an inactive window is minimized, we need to disable Wintab. */
+ if (msg == WM_SIZE && wParam == SIZE_MINIMIZED) {
+ window->updateWintab(false, false);
+ }
+
break;
case WM_CAPTURECHANGED:
window->lostMouseCapture();
@@ -1722,6 +1872,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
SWP_NOZORDER | SWP_NOACTIVATE);
}
break;
+ case WM_DISPLAYCHANGE:
+ for (GHOST_IWindow *iter_win : system->getWindowManager()->getWindows()) {
+ GHOST_WindowWin32 *iter_win32win = (GHOST_WindowWin32 *)iter_win;
+ iter_win32win->processWintabDisplayChangeEvent();
+ }
+ break;
////////////////////////////////////////////////////////////////////////
// Window events, ignored
////////////////////////////////////////////////////////////////////////
@@ -1915,6 +2071,7 @@ void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const
}
}
+/* -------------------------------------------------------------------- */
/** \name Message Box
* \{ */
GHOST_TSuccess GHOST_SystemWin32::showMessageBox(const char *title,
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index b91a9d7a154..00b626511ab 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -64,6 +64,8 @@ class GHOST_SystemWin32 : public GHOST_System {
** Time(r) functionality
***************************************************************************************/
+ GHOST_TUns64 millisSinceStart(__int64 ms) const;
+
/**
* This method converts performance counter measurements into milliseconds since the start of the
* system process.
@@ -111,19 +113,19 @@ class GHOST_SystemWin32 : public GHOST_System {
/**
* Create a new window.
* The new window is added to the list of windows managed.
- * Never explicitly delete the window, use disposeWindow() instead.
- * \param title The name of the window
+ * Never explicitly delete the window, use #disposeWindow() instead.
+ * \param title: The name of the window.
* (displayed in the title bar of the window if the OS supports it).
- * \param left The coordinate of the left edge of the window.
- * \param top The coordinate of the top edge of the window.
- * \param width The width the window.
- * \param height The height the window.
- * \param state The state of the window when opened.
- * \param type The type of drawing context installed in this window.
+ * \param left: The coordinate of the left edge of the window.
+ * \param top: The coordinate of the top edge of the window.
+ * \param width: The width the window.
+ * \param height: The height the window.
+ * \param state: The state of the window when opened.
+ * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
- * \param parentWindow Parent window
- * \return The new window (or 0 if creation failed).
+ * \param parentWindow: Parent window.
+ * \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *createWindow(const char *title,
GHOST_TInt32 left,
@@ -140,14 +142,14 @@ class GHOST_SystemWin32 : public GHOST_System {
/**
* Create a new offscreen context.
* Never explicitly delete the window, use disposeContext() instead.
- * \return The new context (or 0 if creation failed).
+ * \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
/**
* Dispose of a context.
- * \param context Pointer to the context to be disposed.
- * \return Indication of success.
+ * \param context: Pointer to the context to be disposed.
+ * \return Indication of success.
*/
GHOST_TSuccess disposeContext(GHOST_IContext *context);
@@ -156,15 +158,15 @@ class GHOST_SystemWin32 : public GHOST_System {
* Never explicitly delete the context, use disposeContext() instead.
* This is for GHOST internal, Win32 specific use, so it can be called statically.
*
- * \return The new context (or 0 if creation failed).
+ * \return The new context (or 0 if creation failed).
*/
static GHOST_ContextD3D *createOffscreenContextD3D();
/**
* Dispose of a DirectX context.
* This is for GHOST internal, Win32 specific use, so it can be called statically.
- * \param context Pointer to the context to be disposed.
- * \return Indication of success.
+ * \param context: Pointer to the context to be disposed.
+ * \return Indication of success.
*/
static GHOST_TSuccess disposeContextD3D(GHOST_ContextD3D *context);
@@ -174,7 +176,7 @@ class GHOST_SystemWin32 : public GHOST_System {
/**
* Gets events from the system and stores them in the queue.
- * \param waitForEvent Flag to wait for an event (or return immediately).
+ * \param waitForEvent: Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
*/
bool processEvents(bool waitForEvent);
@@ -185,17 +187,17 @@ class GHOST_SystemWin32 : public GHOST_System {
/**
* Returns the current location of the cursor (location in screen coordinates)
- * \param x The x-coordinate of the cursor.
- * \param y The y-coordinate of the cursor.
- * \return Indication of success.
+ * \param x: The x-coordinate of the cursor.
+ * \param y: The y-coordinate of the cursor.
+ * \return Indication of success.
*/
GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
/**
* Updates the location of the cursor (location in screen coordinates).
- * \param x The x-coordinate of the cursor.
- * \param y The y-coordinate of the cursor.
- * \return Indication of success.
+ * \param x: The x-coordinate of the cursor.
+ * \param y: The y-coordinate of the cursor.
+ * \return Indication of success.
*/
GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
@@ -205,40 +207,40 @@ class GHOST_SystemWin32 : public GHOST_System {
/**
* Returns the state of all modifier keys.
- * \param keys The state of all modifier keys (true == pressed).
- * \return Indication of success.
+ * \param keys: The state of all modifier keys (true == pressed).
+ * \return Indication of success.
*/
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const;
/**
* Returns the state of the mouse buttons (outside the message queue).
- * \param buttons The state of the buttons.
- * \return Indication of success.
+ * \param buttons: The state of the buttons.
+ * \return Indication of success.
*/
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const;
/**
* Returns unsigned char from CUT_BUFFER0
- * \param selection Used by X11 only
- * \return Returns the Clipboard
+ * \param selection: Used by X11 only.
+ * \return Returns the Clipboard.
*/
GHOST_TUns8 *getClipboard(bool selection) const;
/**
- * Puts buffer to system clipboard
- * \param selection Used by X11 only
- * \return No return
+ * Puts buffer to system clipboard.
+ * \param selection: Used by X11 only.
+ * \return No return.
*/
void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
/**
* Show a system message box
- * \param title The title of the message box
- * \param message The message to display
- * \param help_label Help button label
- * \param continue_label Continue button label
- * \param link An optional hyperlink
- * \param dialog_options Options how to display the message
+ * \param title: The title of the message box.
+ * \param message: The message to display.
+ * \param help_label: Help button label.
+ * \param continue_label: Continue button label.
+ * \param link: An optional hyperlink.
+ * \param dialog_options: Options how to display the message.
*/
GHOST_TSuccess showMessageBox(const char *title,
const char *message,
@@ -265,6 +267,16 @@ class GHOST_SystemWin32 : public GHOST_System {
int mouseY,
void *data);
+ /***************************************************************************************
+ ** Modify tablet API
+ ***************************************************************************************/
+
+ /**
+ * Set which tablet API to use.
+ * \param api: Enum indicating which API to use.
+ */
+ void setTabletAPI(GHOST_TTabletAPI api) override;
+
protected:
/**
* Initializes the system.
@@ -281,27 +293,27 @@ class GHOST_SystemWin32 : public GHOST_System {
/**
* Converts raw WIN32 key codes from the wndproc to GHOST keys.
- * \param vKey The virtual key from hardKey
- * \param ScanCode The ScanCode of pressed key (similar to PS/2 Set 1)
- * \param extend Flag if key is not primly (left or right)
+ * \param vKey: The virtual key from #hardKey.
+ * \param ScanCode: The ScanCode of pressed key (similar to PS/2 Set 1).
+ * \param extend: Flag if key is not primly (left or right).
* \return The GHOST key (GHOST_kKeyUnknown if no match).
*/
GHOST_TKey convertKey(short vKey, short ScanCode, short extend) const;
/**
* Catches raw WIN32 key codes from WM_INPUT in the wndproc.
- * \param raw RawInput structure with detailed info about the key event
- * \param keyDown Pointer flag that specify if a key is down
- * \param vk Pointer to virtual key
+ * \param raw: RawInput structure with detailed info about the key event.
+ * \param keyDown: Pointer flag that specify if a key is down.
+ * \param vk: Pointer to virtual key.
* \return The GHOST key (GHOST_kKeyUnknown if no match).
*/
GHOST_TKey hardKey(RAWINPUT const &raw, bool *r_keyDown, bool *r_is_repeated_modifier);
/**
* Creates mouse button event.
- * \param type The type of event to create.
- * \param window The window receiving the event (the active window).
- * \param mask The button mask of this event.
+ * \param type: The type of event to create.
+ * \param window: The window receiving the event (the active window).
+ * \param mask: The button mask of this event.
* \return The event created.
*/
static GHOST_EventButton *processButtonEvent(GHOST_TEventType type,
@@ -310,34 +322,40 @@ class GHOST_SystemWin32 : public GHOST_System {
/**
* Creates tablet events from Wintab events.
- * \param type The type of pointer event
- * \param window The window receiving the event (the active window).
+ * \param type: The type of pointer event.
+ * \param window: The window receiving the event (the active window).
+ * \param mask: The button mask of the calling event.
+ * \param mousePressed: Whether the mouse is currently pressed.
+ * \return True if the method handled the event.
*/
- static GHOST_TSuccess processWintabEvents(GHOST_TEventType type, GHOST_WindowWin32 *window);
+ static GHOST_TSuccess processWintabEvent(GHOST_TEventType type,
+ GHOST_WindowWin32 *window,
+ GHOST_TButtonMask mask,
+ bool mousePressed);
/**
* Creates tablet events from pointer events.
- * \param type The type of pointer event
- * \param window The window receiving the event (the active window).
- * \param wParam The wParam from the wndproc
- * \param lParam The lParam from the wndproc
- * \param eventhandled true if the method handled the event
+ * \param type: The type of pointer event.
+ * \param window: The window receiving the event (the active window).
+ * \param wParam: The wParam from the wndproc.
+ * \param lParam: The lParam from the wndproc.
+ * \param eventhandled: True if the method handled the event.
*/
- static void processPointerEvents(
+ static void processPointerEvent(
UINT type, GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam, bool &eventhandled);
/**
* Creates cursor event.
- * \param window The window receiving the event (the active window).
+ * \param window: The window receiving the event (the active window).
* \return The event created.
*/
static GHOST_EventCursor *processCursorEvent(GHOST_WindowWin32 *window);
/**
* Handles a mouse wheel event.
- * \param window The window receiving the event (the active window).
- * \param wParam The wParam from the wndproc
- * \param lParam The lParam from the wndproc
+ * \param window: The window receiving the event (the active window).
+ * \param wParam: The wParam from the wndproc.
+ * \param lParam: The lParam from the wndproc.
*/
static void processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam);
@@ -345,23 +363,23 @@ class GHOST_SystemWin32 : public GHOST_System {
* Creates a key event and updates the key data stored locally (m_modifierKeys).
* In most cases this is a straightforward conversion of key codes.
* For the modifier keys however, we want to distinguish left and right keys.
- * \param window The window receiving the event (the active window).
- * \param raw RawInput structure with detailed info about the key event
+ * \param window: The window receiving the event (the active window).
+ * \param raw: RawInput structure with detailed info about the key event.
*/
static GHOST_EventKey *processKeyEvent(GHOST_WindowWin32 *window, RAWINPUT const &raw);
/**
* Process special keys (VK_OEM_*), to see if current key layout
* gives us anything special, like ! on french AZERTY.
- * \param vKey The virtual key from hardKey
- * \param scanCode The ScanCode of pressed key (similar to PS/2 Set 1)
+ * \param vKey: The virtual key from #hardKey.
+ * \param scanCode: The ScanCode of pressed key (similar to PS/2 Set 1).
*/
GHOST_TKey processSpecialKey(short vKey, short scanCode) const;
/**
* Creates a window event.
- * \param type The type of event to create.
- * \param window The window receiving the event (the active window).
+ * \param type: The type of event to create.
+ * \param window: The window receiving the event (the active window).
* \return The event created.
*/
static GHOST_Event *processWindowEvent(GHOST_TEventType type, GHOST_WindowWin32 *window);
@@ -369,9 +387,9 @@ class GHOST_SystemWin32 : public GHOST_System {
#ifdef WITH_INPUT_IME
/**
* Creates a IME event.
- * \param type The type of event to create.
- * \param window The window receiving the event (the active window).
- * \param data IME data.
+ * \param type: The type of event to create.
+ * \param window: The window receiving the event (the active window).
+ * \param data: IME data.
* \return The event created.
*/
static GHOST_Event *processImeEvent(GHOST_TEventType type,
@@ -381,7 +399,7 @@ class GHOST_SystemWin32 : public GHOST_System {
/**
* Handles minimum window size.
- * \param minmax The MINMAXINFO structure.
+ * \param minmax: The MINMAXINFO structure.
*/
static void processMinMaxInfo(MINMAXINFO *minmax);
@@ -390,7 +408,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* Handles Motion and Button events from a SpaceNavigator or related device.
* Instead of returning an event object, this function communicates directly
* with the GHOST_NDOFManager.
- * \param raw RawInput structure with detailed info about the NDOF event
+ * \param raw: RawInput structure with detailed info about the NDOF event.
* \return Whether an event was generated and sent.
*/
bool processNDOF(RAWINPUT const &raw);
@@ -398,7 +416,7 @@ class GHOST_SystemWin32 : public GHOST_System {
/**
* Returns the local state of the modifier keys (from the message queue).
- * \param keys The state of the keys.
+ * \param keys: The state of the keys.
*/
inline void retrieveModifierKeys(GHOST_ModifierKeys &keys) const;
@@ -421,7 +439,7 @@ class GHOST_SystemWin32 : public GHOST_System {
/**
* Toggles console
- * \param action
+ * \param action:
* - 0 - Hides
* - 1 - Shows
* - 2 - Toggles
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 1906ec67c33..ecab61f6964 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -325,19 +325,19 @@ void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32
/**
* Create a new window.
* The new window is added to the list of windows managed.
- * Never explicitly delete the window, use disposeWindow() instead.
- * \param title The name of the window
+ * Never explicitly delete the window, use #disposeWindow() instead.
+ * \param title: The name of the window
* (displayed in the title bar of the window if the OS supports it).
- * \param left The coordinate of the left edge of the window.
- * \param top The coordinate of the top edge of the window.
- * \param width The width the window.
- * \param height The height the window.
- * \param state The state of the window when opened.
- * \param type The type of drawing context installed in this window.
+ * \param left: The coordinate of the left edge of the window.
+ * \param top: The coordinate of the top edge of the window.
+ * \param width: The width the window.
+ * \param height: The height the window.
+ * \param state: The state of the window when opened.
+ * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
- * \param exclusive: Use to show the window ontop and ignore others (used fullscreen).
- * \param parentWindow Parent window
- * \return The new window (or 0 if creation failed).
+ * \param exclusive: Use to show the window on top and ignore others (used full-screen).
+ * \param parentWindow: Parent window.
+ * \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
GHOST_TInt32 left,
@@ -393,7 +393,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
/**
* Create a new offscreen context.
* Never explicitly delete the context, use disposeContext() instead.
- * \return The new context (or 0 if creation failed).
+ * \return The new context (or 0 if creation failed).
*/
GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSettings)
{
@@ -505,8 +505,8 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
/**
* Dispose of a context.
- * \param context Pointer to the context to be disposed.
- * \return Indication of success.
+ * \param context: Pointer to the context to be disposed.
+ * \return Indication of success.
*/
GHOST_TSuccess GHOST_SystemX11::disposeContext(GHOST_IContext *context)
{
@@ -2284,6 +2284,7 @@ void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const
}
}
+/* -------------------------------------------------------------------- */
/** \name Message Box
* \{ */
class DialogData {
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index ee29f463fb6..3fab115afff 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -121,20 +121,19 @@ class GHOST_SystemX11 : public GHOST_System {
/**
* Create a new window.
* The new window is added to the list of windows managed.
- * Never explicitly delete the window, use disposeWindow() instead.
- * \param title The name of the window
+ * Never explicitly delete the window, use #disposeWindow() instead.
+ * \param title: The name of the window.
* (displayed in the title bar of the window if the OS supports it).
- * \param left The coordinate of the left edge of the window.
- * \param top The coordinate of the top edge of the window.
- * \param width The width the window.
- * \param height The height the window.
- * \param state The state of the window when opened.
- * \param type The type of drawing context installed in this window.
- * \param stereoVisual Create a stereo visual for quad buffered stereo.
- * \param exclusive Use to show the window ontop and ignore others
- * (used fullscreen).
- * \param parentWindow Parent (embedder) window
- * \return The new window (or 0 if creation failed).
+ * \param left: The coordinate of the left edge of the window.
+ * \param top: The coordinate of the top edge of the window.
+ * \param width: The width the window.
+ * \param height: The height the window.
+ * \param state: The state of the window when opened.
+ * \param type: The type of drawing context installed in this window.
+ * \param stereoVisual: Create a stereo visual for quad buffered stereo.
+ * \param exclusive: Use to show the window ontop and ignore others (used full*screen).
+ * \param parentWindow: Parent (embedder) window.
+ * \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *createWindow(const char *title,
GHOST_TInt32 left,
@@ -151,20 +150,20 @@ class GHOST_SystemX11 : public GHOST_System {
/**
* Create a new offscreen context.
* Never explicitly delete the context, use disposeContext() instead.
- * \return The new context (or 0 if creation failed).
+ * \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
/**
* Dispose of a context.
- * \param context Pointer to the context to be disposed.
- * \return Indication of success.
+ * \param context: Pointer to the context to be disposed.
+ * \return Indication of success.
*/
GHOST_TSuccess disposeContext(GHOST_IContext *context);
/**
* Retrieves events from the system and stores them in the queue.
- * \param waitForEvent Flag to wait for an event (or return immediately).
+ * \param waitForEvent: Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
*/
bool processEvents(bool waitForEvent);
@@ -175,15 +174,15 @@ class GHOST_SystemX11 : public GHOST_System {
/**
* Returns the state of all modifier keys.
- * \param keys The state of all modifier keys (true == pressed).
- * \return Indication of success.
+ * \param keys: The state of all modifier keys (true == pressed).
+ * \return Indication of success.
*/
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const;
/**
* Returns the state of the mouse buttons (outside the message queue).
- * \param buttons The state of the buttons.
- * \return Indication of success.
+ * \param buttons: The state of the buttons.
+ * \return Indication of success.
*/
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const;
@@ -220,26 +219,26 @@ class GHOST_SystemX11 : public GHOST_System {
/**
* Returns unsigned char from CUT_BUFFER0
- * \param selection Get selection, X11 only feature
- * \return Returns the Clipboard indicated by Flag
+ * \param selection: Get selection, X11 only feature.
+ * \return Returns the Clipboard indicated by Flag.
*/
GHOST_TUns8 *getClipboard(bool selection) const;
/**
* Puts buffer to system clipboard
- * \param buffer The buffer to copy to the clipboard
- * \param selection Set the selection into the clipboard, X11 only feature
+ * \param buffer: The buffer to copy to the clipboard.
+ * \param selection: Set the selection into the clipboard, X11 only feature.
*/
void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
/**
* Show a system message box
- * \param title The title of the message box
- * \param message The message to display
- * \param help_label Help button label
- * \param continue_label Continue button label
- * \param link An optional hyperlink
- * \param dialog_options Options how to display the message
+ * \param title: The title of the message box.
+ * \param message: The message to display.
+ * \param help_label: Help button label.
+ * \param continue_label: Continue button label.
+ * \param link: An optional hyperlink.
+ * \param dialog_options: Options how to display the message.
*/
GHOST_TSuccess showMessageBox(const char *title,
const char *message,
@@ -251,12 +250,12 @@ class GHOST_SystemX11 : public GHOST_System {
/**
* Creates a drag'n'drop event and pushes it immediately onto the event queue.
* Called by GHOST_DropTargetX11 class.
- * \param eventType The type of drag'n'drop event
- * \param draggedObjectType The type object concerned
+ * \param eventType: The type of drag'n'drop event.
+ * \param draggedObjectType: The type object concerned.
* (currently array of file names, string, ?bitmap)
- * \param mouseX x mouse coordinate (in window coordinates)
- * \param mouseY y mouse coordinate
- * \param window The window on which the event occurred
+ * \param mouseX: x mouse coordinate (in window coordinates).
+ * \param mouseY: y mouse coordinate.
+ * \param window: The window on which the event occurred.
* \return Indication whether the event was handled.
*/
static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType,
diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h
index 2e0f5d42230..3ca62202e5e 100644
--- a/intern/ghost/intern/GHOST_TimerManager.h
+++ b/intern/ghost/intern/GHOST_TimerManager.h
@@ -62,7 +62,7 @@ class GHOST_TimerManager {
/**
* Adds a timer task to the list.
* It is only added when it not already present in the list.
- * \param timer The timer task added to the list.
+ * \param timer: The timer task added to the list.
* \return Indication as to whether addition has succeeded.
*/
GHOST_TSuccess addTimer(GHOST_TimerTask *timer);
@@ -70,7 +70,7 @@ class GHOST_TimerManager {
/**
* Removes a timer task from the list.
* It is only removed when it is found in the list.
- * \param timer The timer task to be removed from the list.
+ * \param timer: The timer task to be removed from the list.
* \return Indication as to whether removal has succeeded.
*/
GHOST_TSuccess removeTimer(GHOST_TimerTask *timer);
@@ -84,15 +84,15 @@ class GHOST_TimerManager {
/**
* Checks all timer tasks to see if they are expired and fires them if needed.
- * \param time The current time.
+ * \param time: The current time.
* \return True if any timers were fired.
*/
bool fireTimers(GHOST_TUns64 time);
/**
* Checks this timer task to see if they are expired and fires them if needed.
- * \param time The current time.
- * \param task The timer task to check and optionally fire.
+ * \param time: The current time.
+ * \param task: The timer task to check and optionally fire.
* \return True if the timer fired.
*/
bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task);
diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h
index 6dc0728e19b..9c81d3d2637 100644
--- a/intern/ghost/intern/GHOST_TimerTask.h
+++ b/intern/ghost/intern/GHOST_TimerTask.h
@@ -33,9 +33,9 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
public:
/**
* Constructor.
- * \param start The timer start time.
- * \param interval The interval between calls to the timerProc
- * \param timerProc The callback invoked when the interval expires.
+ * \param start: The timer start time.
+ * \param interval: The interval between calls to the #timerProc.
+ * \param timerProc: The callback invoked when the interval expires.
* \param userData: The timer user data.
*/
GHOST_TimerTask(GHOST_TUns64 start,
@@ -62,7 +62,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
/**
* Changes the timer start time.
- * \param start The timer start time.
+ * \param start: The timer start time.
*/
void setStart(GHOST_TUns64 start)
{
@@ -80,7 +80,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
/**
* Changes the timer interval.
- * \param interval The timer interval.
+ * \param interval: The timer interval.
*/
void setInterval(GHOST_TUns64 interval)
{
@@ -98,7 +98,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
/**
* Changes the time the timerProc will be called.
- * \param next The time the timerProc will be called.
+ * \param next: The time the timerProc will be called.
*/
void setNext(GHOST_TUns64 next)
{
@@ -152,7 +152,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
/**
* Changes the auxiliary storage room.
- * \param auxData The auxiliary storage room.
+ * \param auxData: The auxiliary storage room.
*/
void setAuxData(GHOST_TUns32 auxData)
{
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index c8c21b2b08f..d897fafc003 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -41,13 +41,12 @@ class GHOST_Window : public GHOST_IWindow {
* Constructor.
* Creates a new window and opens it.
* To check if the window was created properly, use the getValid() method.
- * \param width The width the window.
- * \param heigh The height the window.
- * \param state The state the window is initially opened with.
- * \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
- * \param exclusive Use to show the window ontop and ignore others
- * (used fullscreen).
+ * \param width: The width the window.
+ * \param heigh: The height the window.
+ * \param state: The state the window is initially opened with.
+ * \param type: The type of drawing context installed in this window.
+ * \param stereoVisual: Stereo visual for quad buffered stereo.
+ * \param exclusive: Use to show the window ontop and ignore others (used full-screen).
*/
GHOST_Window(GHOST_TUns32 width,
GHOST_TUns32 height,
@@ -103,7 +102,7 @@ class GHOST_Window : public GHOST_IWindow {
/**
* Returns the current cursor shape.
- * \return The current cursor shape.
+ * \return The current cursor shape.
*/
inline GHOST_TStandardCursor getCursorShape() const;
@@ -114,18 +113,18 @@ class GHOST_Window : public GHOST_IWindow {
/**
* Set the shape of the cursor.
- * \param cursorShape: The new cursor shape type id.
- * \return Indication of success.
+ * \param cursorShape: The new cursor shape type id.
+ * \return Indication of success.
*/
GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape);
/**
* 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 hot-spot.
- * \param hotY The Y coordinate of the cursor hot-spot.
- * \return Indication of success.
+ * \param bitmap: The bitmap data for the cursor.
+ * \param mask: The mask data for the cursor.
+ * \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,
GHOST_TUns8 *mask,
@@ -137,7 +136,7 @@ class GHOST_Window : public GHOST_IWindow {
/**
* Returns the visibility state of the cursor.
- * \return The visibility state of the cursor.
+ * \return The visibility state of the cursor.
*/
inline bool getCursorVisibility() const;
inline GHOST_TGrabCursorMode getCursorGrabMode() const;
@@ -149,15 +148,15 @@ class GHOST_Window : public GHOST_IWindow {
/**
* Shows or hides the cursor.
- * \param visible The new visibility state of the cursor.
- * \return Indication of success.
+ * \param visible: The new visibility state of the cursor.
+ * \return Indication of success.
*/
GHOST_TSuccess setCursorVisibility(bool visible);
/**
* Sets the cursor grab.
- * \param mode The new grab state of the cursor.
- * \return Indication of success.
+ * \param mode: The new grab state of the cursor.
+ * \return Indication of success.
*/
GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode,
GHOST_TAxisFlag wrap_axis,
@@ -172,7 +171,7 @@ class GHOST_Window : public GHOST_IWindow {
/**
* Sets the progress bar value displayed in the window/application icon
- * \param progress The progress % (0.0 to 1.0)
+ * \param progress: The progress percentage (0.0 to 1.0).
*/
virtual GHOST_TSuccess setProgressBar(float /*progress*/)
{
@@ -188,14 +187,14 @@ class GHOST_Window : public GHOST_IWindow {
}
/**
- * Sets the swap interval for swapBuffers.
- * \param interval The swap interval to use.
+ * Sets the swap interval for #swapBuffers.
+ * \param interval: The swap interval to use.
* \return A boolean success indicator.
*/
GHOST_TSuccess setSwapInterval(int interval);
/**
- * Gets the current swap interval for swapBuffers.
+ * Gets the current swap interval for #swapBuffers.
* \return An integer.
*/
GHOST_TSuccess getSwapInterval(int &intervalOut);
@@ -213,7 +212,7 @@ class GHOST_Window : public GHOST_IWindow {
/**
* Sets the window "modified" status, indicating unsaved changes
- * \param isUnsavedChanges Unsaved changes or not
+ * \param isUnsavedChanges: Unsaved changes or not.
* \return Indication of success.
*/
virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges);
@@ -233,21 +232,21 @@ class GHOST_Window : public GHOST_IWindow {
/**
* Tries to install a rendering context in this window.
* Child classes do not need to overload this method,
- * They should overload newDrawingContext instead.
- * \param type The type of rendering context installed.
+ * They should overload #newDrawingContext instead.
+ * \param type: The type of rendering context installed.
* \return Indication as to whether installation has succeeded.
*/
GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type);
/**
* Swaps front and back buffers of a window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
virtual GHOST_TSuccess swapBuffers();
/**
* Activates the drawing context of this window.
- * \return A boolean success indicator.
+ * \return A boolean success indicator.
*/
virtual GHOST_TSuccess activateDrawingContext();
@@ -259,8 +258,8 @@ class GHOST_Window : public GHOST_IWindow {
GHOST_TSuccess updateDrawingContext();
/**
- * Gets the OpenGL framebuffer associated with the window's contents.
- * \return The ID of an OpenGL framebuffer object.
+ * Gets the OpenGL frame-buffer associated with the window's contents.
+ * \return The ID of an OpenGL frame-buffer object.
*/
virtual unsigned int getDefaultFramebuffer();
@@ -314,7 +313,7 @@ class GHOST_Window : public GHOST_IWindow {
protected:
/**
* Tries to install a rendering context in this window.
- * \param type The type of rendering context installed.
+ * \param type: The type of rendering context installed.
* \return Indication as to whether installation has succeeded.
*/
virtual GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) = 0;
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index 97486c9e77a..3cfe46a080b 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -44,16 +44,16 @@ class GHOST_WindowCocoa : public GHOST_Window {
/**
* Constructor.
* Creates a new window and opens it.
- * To check if the window was created properly, use the getValid() method.
- * \param systemCocoa The associated system class to forward events to
- * \param title The text shown in the title bar of the window.
- * \param left The coordinate of the left edge of the window.
- * \param bottom The coordinate of the bottom edge of the window.
- * \param width The width the window.
- * \param height The height the window.
- * \param state The state the window is initially opened with.
- * \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
+ * To check if the window was created properly, use the #getValid() method.
+ * \param systemCocoa: The associated system class to forward events to.
+ * \param title: The text shown in the title bar of the window.
+ * \param left: The coordinate of the left edge of the window.
+ * \param bottom: The coordinate of the bottom edge of the window.
+ * \param width: The width the window.
+ * \param height: The height the window.
+ * \param state: The state the window is initially opened with.
+ * \param type: The type of drawing context installed in this window.
+ * \param stereoVisual: Stereo visual for quad buffered stereo.
*/
GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
const char *title,
@@ -88,12 +88,12 @@ class GHOST_WindowCocoa : public GHOST_Window {
/**
* Sets the title displayed in the title bar.
- * \param title The title to display in the title bar.
+ * \param title: The title to display in the title bar.
*/
void setTitle(const char *title);
/**
* Returns the title displayed in the title bar.
- * \param title The title displayed in the title bar.
+ * \param title: The title displayed in the title bar.
*/
std::string getTitle() const;
@@ -101,33 +101,33 @@ class GHOST_WindowCocoa : public GHOST_Window {
* Returns the window rectangle dimensions.
* The dimensions are given in screen coordinates that are
* relative to the upper-left corner of the screen.
- * \param bounds The bounding rectangle of the window.
+ * \param bounds: The bounding rectangle of the window.
*/
void getWindowBounds(GHOST_Rect &bounds) const;
/**
* Returns the client rectangle dimensions.
* The left and top members of the rectangle are always zero.
- * \param bounds The bounding rectangle of the client area of the window.
+ * \param bounds: The bounding rectangle of the client area of the window.
*/
void getClientBounds(GHOST_Rect &bounds) const;
/**
* Resizes client rectangle width.
- * \param width The new width of the client area of the window.
+ * \param width: The new width of the client area of the window.
*/
GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
/**
* Resizes client rectangle height.
- * \param height The new height of the client area of the window.
+ * \param height: The new height of the client area of the window.
*/
GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
/**
* Resizes client rectangle.
- * \param width The new width of the client area of the window.
- * \param height The new height of the client area of the window.
+ * \param width: The new width of the client area of the window.
+ * \param height: The new height of the client area of the window.
*/
GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
@@ -139,17 +139,17 @@ class GHOST_WindowCocoa : public GHOST_Window {
/**
* Sets the window "modified" status, indicating unsaved changes
- * \param isUnsavedChanges Unsaved changes or not
+ * \param isUnsavedChanges: Unsaved changes or not.
* \return Indication of success.
*/
GHOST_TSuccess setModifiedState(bool isUnsavedChanges);
/**
* Converts a point in screen coordinates to client rectangle coordinates
- * \param inX The x-coordinate on the screen.
- * \param inY The y-coordinate on the screen.
- * \param outX The x-coordinate in the client rectangle.
- * \param outY The y-coordinate in the client rectangle.
+ * \param inX: The x-coordinate on the screen.
+ * \param inY: The y-coordinate on the screen.
+ * \param outX: The x-coordinate in the client rectangle.
+ * \param outY: The y-coordinate in the client rectangle.
*/
void screenToClient(GHOST_TInt32 inX,
GHOST_TInt32 inY,
@@ -158,10 +158,10 @@ class GHOST_WindowCocoa : public GHOST_Window {
/**
* Converts a point in screen coordinates to client rectangle coordinates
- * \param inX The x-coordinate in the client rectangle.
- * \param inY The y-coordinate in the client rectangle.
- * \param outX The x-coordinate on the screen.
- * \param outY The y-coordinate on the screen.
+ * \param inX: The x-coordinate in the client rectangle.
+ * \param inY: The y-coordinate in the client rectangle.
+ * \param outX: The x-coordinate on the screen.
+ * \param outY: The y-coordinate on the screen.
*/
void clientToScreen(GHOST_TInt32 inX,
GHOST_TInt32 inY,
@@ -171,10 +171,10 @@ class GHOST_WindowCocoa : public GHOST_Window {
/**
* Converts a point in screen coordinates to client rectangle coordinates
* but without the y coordinate conversion needed for ghost compatibility.
- * \param inX The x-coordinate in the client rectangle.
- * \param inY The y-coordinate in the client rectangle.
- * \param outX The x-coordinate on the screen.
- * \param outY The y-coordinate on the screen.
+ * \param inX: The x-coordinate in the client rectangle.
+ * \param inY: The y-coordinate in the client rectangle.
+ * \param outX: The x-coordinate on the screen.
+ * \param outY: The y-coordinate on the screen.
*/
void clientToScreenIntern(GHOST_TInt32 inX,
GHOST_TInt32 inY,
@@ -184,10 +184,10 @@ class GHOST_WindowCocoa : public GHOST_Window {
/**
* Converts a point in screen coordinates to client rectangle coordinates,
* but without the y coordinate conversion needed for ghost compatibility.
- * \param inX The x-coordinate in the client rectangle.
- * \param inY The y-coordinate in the client rectangle.
- * \param outX The x-coordinate on the screen.
- * \param outY The y-coordinate on the screen.
+ * \param inX: The x-coordinate in the client rectangle.
+ * \param inY: The y-coordinate in the client rectangle.
+ * \param outX: The x-coordinate on the screen.
+ * \param outY: The y-coordinate on the screen.
*/
void screenToClientIntern(GHOST_TInt32 inX,
GHOST_TInt32 inY,
@@ -202,14 +202,14 @@ class GHOST_WindowCocoa : public GHOST_Window {
/**
* Sets the state of the window (normal, minimized, maximized).
- * \param state The state of the window.
+ * \param state: The state of the window.
* \return Indication of success.
*/
GHOST_TSuccess setState(GHOST_TWindowState state);
/**
* Sets the order of the window (bottom, top).
- * \param order The order of the window.
+ * \param order: The order of the window.
* \return Indication of success.
*/
GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
@@ -226,7 +226,7 @@ class GHOST_WindowCocoa : public GHOST_Window {
/**
* Sets the progress bar value displayed in the window/application icon
- * \param progress The progress % (0.0 to 1.0)
+ * \param progress: The progress percentage (0.0 to 1.0).
*/
GHOST_TSuccess setProgressBar(float progress);
@@ -265,7 +265,7 @@ class GHOST_WindowCocoa : public GHOST_Window {
protected:
/**
- * \param type The type of rendering context create.
+ * \param type: The type of rendering context create.
* \return Indication of success.
*/
GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index f8e2f96d111..3f0ed2a4def 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -404,7 +404,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
[m_window setAcceptsMouseMovedEvents:YES];
NSView *contentview = [m_window contentView];
- [contentview setAcceptsTouchEvents:YES];
+ [contentview setAllowedTouchTypes:(NSTouchTypeMaskDirect | NSTouchTypeMaskIndirect)];
[m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
NSStringPboardType,
@@ -869,28 +869,26 @@ GHOST_TSuccess GHOST_WindowCocoa::setProgressBar(float progress)
NSImage *dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128, 128)];
[dockIcon lockFocus];
- NSRect progressBox = {{4, 4}, {120, 16}};
[[NSImage imageNamed:@"NSApplicationIcon"] drawAtPoint:NSZeroPoint
fromRect:NSZeroRect
operation:NSCompositingOperationSourceOver
fraction:1.0];
- // Track & Outline
- [[NSColor blackColor] setFill];
- NSRectFill(progressBox);
+ NSRect progressRect = {{8, 8}, {112, 14}};
+ NSBezierPath *progressPath;
- [[NSColor whiteColor] set];
- NSFrameRect(progressBox);
+ /* Draw white track. */
+ [[[NSColor whiteColor] colorWithAlphaComponent:0.6] setFill];
+ progressPath = [NSBezierPath bezierPathWithRoundedRect:progressRect xRadius:7 yRadius:7];
+ [progressPath fill];
- // Progress fill
- progressBox = NSInsetRect(progressBox, 1, 1);
-
- progressBox.size.width = progressBox.size.width * progress;
- NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:[NSColor darkGrayColor]
- endingColor:[NSColor lightGrayColor]];
- [gradient drawInRect:progressBox angle:90];
- [gradient release];
+ /* Black progress fill. */
+ [[[NSColor blackColor] colorWithAlphaComponent:0.7] setFill];
+ progressRect = NSInsetRect(progressRect, 2, 2);
+ progressRect.size.width *= progress;
+ progressPath = [NSBezierPath bezierPathWithRoundedRect:progressRect xRadius:5 yRadius:5];
+ [progressPath fill];
[dockIcon unlockFocus];
diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h
index 34fdfd30f27..cb0337773c6 100644
--- a/intern/ghost/intern/GHOST_WindowManager.h
+++ b/intern/ghost/intern/GHOST_WindowManager.h
@@ -47,54 +47,54 @@ class GHOST_WindowManager {
/**
* Add a window to our list.
* It is only added if it is not already in the list.
- * \param window Pointer to the window to be added.
- * \return Indication of success.
+ * \param window: Pointer to the window to be added.
+ * \return Indication of success.
*/
GHOST_TSuccess addWindow(GHOST_IWindow *window);
/**
* Remove a window from our list.
- * \param window Pointer to the window to be removed.
- * \return Indication of success.
+ * \param window: Pointer to the window to be removed.
+ * \return Indication of success.
*/
GHOST_TSuccess removeWindow(const GHOST_IWindow *window);
/**
* Returns whether the window is in our list.
- * \param window Pointer to the window to query.
- * \return A boolean indicator.
+ * \param window: Pointer to the window to query.
+ * \return A boolean indicator.
*/
bool getWindowFound(const GHOST_IWindow *window) const;
/**
- * Returns whether one of the windows is fullscreen.
- * \return A boolean indicator.
+ * Returns whether one of the windows is full-screen.
+ * \return A boolean indicator.
*/
bool getFullScreen(void) const;
/**
* Returns pointer to the full-screen window.
- * \return The full-screen window (NULL if not in full-screen).
+ * \return The full-screen window (NULL if not in full-screen).
*/
GHOST_IWindow *getFullScreenWindow(void) const;
/**
- * Activates fullscreen mode for a window.
- * \param window The window displayed fullscreen.
- * \return Indication of success.
+ * Activates full-screen mode for a window.
+ * \param window: The window displayed full-screen.
+ * \return Indication of success.
*/
GHOST_TSuccess beginFullScreen(GHOST_IWindow *window, const bool stereoVisual);
/**
- * Closes fullscreen mode down.
- * \return Indication of success.
+ * Closes full-screen mode down.
+ * \return Indication of success.
*/
GHOST_TSuccess endFullScreen(void);
/**
* Sets new window as active window (the window receiving events).
* There can be only one window active which should be in the current window list.
- * \param window The new active window.
+ * \param window: The new active window.
*/
GHOST_TSuccess setActiveWindow(GHOST_IWindow *window);
@@ -107,7 +107,7 @@ class GHOST_WindowManager {
/**
* Set this window to be inactive (not receiving events).
- * \param window The window to deactivate.
+ * \param window: The window to deactivate.
*/
void setWindowInactive(const GHOST_IWindow *window);
@@ -119,9 +119,9 @@ class GHOST_WindowManager {
const std::vector<GHOST_IWindow *> &getWindows() const;
/**
- * Finds the window associated with an OS window object/handle
- * \param osWindow The OS window object/handle
- * \return The associated window, null if none corresponds
+ * Finds the window associated with an OS window object/handle.
+ * \param osWindow: The OS window object/handle.
+ * \return The associated window, null if none corresponds.
*/
GHOST_IWindow *getWindowAssociatedWithOSWindow(void *osWindow);
diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h
index 0b5a7ee3450..aca06ba75b5 100644
--- a/intern/ghost/intern/GHOST_WindowNULL.h
+++ b/intern/ghost/intern/GHOST_WindowNULL.h
@@ -168,7 +168,7 @@ class GHOST_WindowNULL : public GHOST_Window {
GHOST_SystemNULL *m_system;
/**
- * \param type The type of rendering context create.
+ * \param type: The type of rendering context create.
* \return Indication of success.
*/
GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type)
diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h
index 643c54c282e..bfe07af1c70 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.h
+++ b/intern/ghost/intern/GHOST_WindowSDL.h
@@ -85,7 +85,7 @@ class GHOST_WindowSDL : public GHOST_Window {
protected:
/**
- * \param type The type of rendering context create.
+ * \param type: The type of rendering context create.
* \return Indication of success.
*/
GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h
index 1ee41f4d0f6..b62b5c24d60 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.h
+++ b/intern/ghost/intern/GHOST_WindowWayland.h
@@ -118,7 +118,7 @@ class GHOST_WindowWayland : public GHOST_Window {
std::string title;
/**
- * \param type The type of rendering context create.
+ * \param type: The type of rendering context create.
* \return Indication of success.
*/
GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) override;
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 18a48c9169e..5904a72b186 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -81,6 +81,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_nPressedButtons(0),
m_customCursor(0),
m_wantAlphaBackground(alphaBackground),
+ m_wintab(),
m_normal_state(GHOST_kWindowStateNormal),
m_user32(NULL),
m_fpGetPointerInfoHistory(NULL),
@@ -89,10 +90,6 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : NULL),
m_debug_context(is_debug)
{
- // Initialize tablet variables
- memset(&m_wintab, 0, sizeof(m_wintab));
- m_tabletData = GHOST_TABLET_DATA_NONE;
-
// Create window
if (state != GHOST_kWindowStateFullScreen) {
RECT rect;
@@ -297,66 +294,25 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_user32, "GetPointerTouchInfoHistory");
}
- // Initialize Wintab
- m_wintab.handle = ::LoadLibrary("Wintab32.dll");
- if (m_wintab.handle && m_system->getTabletAPI() != GHOST_kTabletNative) {
- // Get API functions
- m_wintab.info = (GHOST_WIN32_WTInfo)::GetProcAddress(m_wintab.handle, "WTInfoA");
- m_wintab.open = (GHOST_WIN32_WTOpen)::GetProcAddress(m_wintab.handle, "WTOpenA");
- m_wintab.close = (GHOST_WIN32_WTClose)::GetProcAddress(m_wintab.handle, "WTClose");
- m_wintab.packet = (GHOST_WIN32_WTPacket)::GetProcAddress(m_wintab.handle, "WTPacket");
- m_wintab.enable = (GHOST_WIN32_WTEnable)::GetProcAddress(m_wintab.handle, "WTEnable");
- m_wintab.overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(m_wintab.handle, "WTOverlap");
-
- // Let's see if we can initialize tablet here.
- // Check if WinTab available by getting system context info.
- LOGCONTEXT lc = {0};
- lc.lcOptions |= CXO_SYSTEM;
- if (m_wintab.open && m_wintab.info && m_wintab.info(WTI_DEFSYSCTX, 0, &lc)) {
- // Now init the tablet
- /* The maximum tablet size, pressure and orientation (tilt) */
- AXIS TabletX, TabletY, Pressure, Orientation[3];
-
- // Open a Wintab context
-
- // Open the context
- lc.lcPktData = PACKETDATA;
- lc.lcPktMode = PACKETMODE;
- lc.lcOptions |= CXO_MESSAGES;
- lc.lcMoveMask = PACKETDATA;
-
- /* Set the entire tablet as active */
- m_wintab.info(WTI_DEVICES, DVC_X, &TabletX);
- m_wintab.info(WTI_DEVICES, DVC_Y, &TabletY);
-
- /* get the max pressure, to divide into a float */
- BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
- if (pressureSupport)
- m_wintab.maxPressure = Pressure.axMax;
- else
- m_wintab.maxPressure = 0;
-
- /* get the max tilt axes, to divide into floats */
- BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
- if (tiltSupport) {
- /* does the tablet support azimuth ([0]) and altitude ([1]) */
- if (Orientation[0].axResolution && Orientation[1].axResolution) {
- /* all this assumes the minimum is 0 */
- m_wintab.maxAzimuth = Orientation[0].axMax;
- m_wintab.maxAltitude = Orientation[1].axMax;
- }
- else { /* no so dont do tilt stuff */
- m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
- }
- }
-
- // The Wintab spec says we must open the context disabled if we are using cursor masks.
- m_wintab.tablet = m_wintab.open(m_hWnd, &lc, FALSE);
- if (m_wintab.enable && m_wintab.tablet) {
- m_wintab.enable(m_wintab.tablet, TRUE);
- }
- }
+ if ((m_wintab.handle = ::LoadLibrary("Wintab32.dll")) &&
+ (m_wintab.info = (GHOST_WIN32_WTInfo)::GetProcAddress(m_wintab.handle, "WTInfoA")) &&
+ (m_wintab.open = (GHOST_WIN32_WTOpen)::GetProcAddress(m_wintab.handle, "WTOpenA")) &&
+ (m_wintab.get = (GHOST_WIN32_WTGet)::GetProcAddress(m_wintab.handle, "WTGetA")) &&
+ (m_wintab.set = (GHOST_WIN32_WTSet)::GetProcAddress(m_wintab.handle, "WTSetA")) &&
+ (m_wintab.close = (GHOST_WIN32_WTClose)::GetProcAddress(m_wintab.handle, "WTClose")) &&
+ (m_wintab.packetsGet = (GHOST_WIN32_WTPacketsGet)::GetProcAddress(m_wintab.handle,
+ "WTPacketsGet")) &&
+ (m_wintab.queueSizeGet = (GHOST_WIN32_WTQueueSizeGet)::GetProcAddress(m_wintab.handle,
+ "WTQueueSizeGet")) &&
+ (m_wintab.queueSizeSet = (GHOST_WIN32_WTQueueSizeSet)::GetProcAddress(m_wintab.handle,
+ "WTQueueSizeSet")) &&
+ (m_wintab.enable = (GHOST_WIN32_WTEnable)::GetProcAddress(m_wintab.handle, "WTEnable")) &&
+ (m_wintab.overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(m_wintab.handle, "WTOverlap"))) {
+ initializeWintab();
+ // Determine which tablet API to use and enable it.
+ updateWintab(m_system->m_windowFocus, m_system->m_windowFocus);
}
+
CoCreateInstance(
CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
}
@@ -370,8 +326,9 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
}
if (m_wintab.handle) {
- if (m_wintab.close && m_wintab.tablet) {
- m_wintab.close(m_wintab.tablet);
+ updateWintab(false, false);
+ if (m_wintab.close && m_wintab.context) {
+ m_wintab.close(m_wintab.context);
}
FreeLibrary(m_wintab.handle);
@@ -819,6 +776,27 @@ bool GHOST_WindowWin32::getMousePressed() const
return m_nPressedButtons;
}
+bool GHOST_WindowWin32::wintabSysButPressed() const
+{
+ return m_wintab.numSysButtons;
+}
+
+void GHOST_WindowWin32::updateWintabSysBut(GHOST_MouseCaptureEventWin32 event)
+{
+ switch (event) {
+ case MousePressed:
+ m_wintab.numSysButtons++;
+ break;
+ case MouseReleased:
+ if (m_wintab.numSysButtons)
+ m_wintab.numSysButtons--;
+ break;
+ case OperatorGrab:
+ case OperatorUngrab:
+ break;
+ }
+}
+
HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
{
// Convert GHOST cursor to Windows OEM cursor
@@ -1022,6 +1000,98 @@ GHOST_TSuccess GHOST_WindowWin32::hasCursorShape(GHOST_TStandardCursor cursorSha
return (getStandardCursor(cursorShape)) ? GHOST_kSuccess : GHOST_kFailure;
}
+void GHOST_WindowWin32::updateWintab(bool active, bool visible)
+{
+ if (m_wintab.enable && m_wintab.overlap && m_wintab.context) {
+ bool enable = useTabletAPI(GHOST_kTabletWintab) && visible;
+ bool overlap = enable && active;
+
+ /* Disabling context while the Window is not minimized can cause issues on receiving Wintab
+ * input while changing a window for some drivers, so only disable if either Wintab had been
+ * disabled or the window is minimized. */
+ m_wintab.enable(m_wintab.context, enable);
+ m_wintab.overlap(m_wintab.context, overlap);
+
+ if (!overlap) {
+ /* WT_PROXIMITY event doesn't occur unless tablet's cursor leaves the proximity while the
+ * window is active. */
+ m_tabletInRange = false;
+ m_wintab.numSysButtons = 0;
+ m_wintab.sysButtonsPressed = 0;
+ }
+ }
+}
+
+void GHOST_WindowWin32::initializeWintab()
+{
+ /* Return if wintab library handle doesn't exist or wintab is already initialized. */
+ if (!m_wintab.handle || m_wintab.context) {
+ return;
+ }
+
+ /* Check if WinTab available by getting system context info. */
+ LOGCONTEXT lc = {0};
+ if (m_wintab.open && m_wintab.info && m_wintab.queueSizeGet && m_wintab.queueSizeSet &&
+ m_wintab.info(WTI_DEFSYSCTX, 0, &lc)) {
+
+ /* The pressure and orientation (tilt) */
+ AXIS Pressure, Orientation[3];
+ lc.lcPktData = PACKETDATA;
+ lc.lcPktMode = PACKETMODE;
+ lc.lcMoveMask = PACKETDATA;
+ lc.lcOptions |= CXO_CSRMESSAGES | CXO_MESSAGES;
+ /* Wacom maps y origin to the tablet's bottom. Invert to match Windows y origin mapping to the
+ * screen top. */
+ lc.lcOutExtY = -lc.lcOutExtY;
+
+ m_wintab.info(WTI_INTERFACE, IFC_NDEVICES, &m_wintab.numDevices);
+
+ BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
+ m_wintab.maxPressure = pressureSupport ? Pressure.axMax : 0;
+
+ BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
+ /* Does the tablet support azimuth ([0]) and altitude ([1])? */
+ if (tiltSupport && Orientation[0].axResolution && Orientation[1].axResolution) {
+ /* All this assumes the minimum is 0. */
+ m_wintab.maxAzimuth = Orientation[0].axMax;
+ m_wintab.maxAltitude = Orientation[1].axMax;
+ }
+ else { /* No so dont do tilt stuff. */
+ m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
+ }
+
+ /* The Wintab spec says we must open the context disabled if we are using cursor masks. */
+ m_wintab.context = m_wintab.open(m_hWnd, &lc, FALSE);
+
+ /* Wintab provides no way to determine the maximum queue size aside from checking if attempts
+ * to change the queue size are successful. */
+ const int maxQueue = 500;
+ int queueSize = m_wintab.queueSizeGet(m_wintab.context);
+
+ while (queueSize < maxQueue) {
+ int testSize = min(queueSize + 16, maxQueue);
+ if (m_wintab.queueSizeSet(m_wintab.context, testSize)) {
+ queueSize = testSize;
+ }
+ else {
+ /* From Windows Wintab Documentation for WTQueueSizeSet:
+ * "If the return value is zero, the context has no queue because the function deletes the
+ * original queue before attempting to create a new one. The application must continue
+ * calling the function with a smaller queue size until the function returns a non - zero
+ * value."
+ *
+ * In our case we start with a known valid queue size and in the event of failure roll
+ * back to the last valid queue size. The Wintab spec dates back to 16 bit Windows, thus
+ * assumes memory recently deallocated may not be available, which is no longer a practical
+ * concern. */
+ m_wintab.queueSizeSet(m_wintab.context, queueSize);
+ break;
+ }
+ }
+ m_wintab.pkts.resize(queueSize);
+ }
+}
+
GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM lParam)
{
@@ -1104,28 +1174,20 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
return GHOST_kSuccess;
}
-void GHOST_WindowWin32::setTabletData(GHOST_TabletData *pTabletData)
+void GHOST_WindowWin32::processWintabDisplayChangeEvent()
{
- if (pTabletData) {
- m_tabletData = *pTabletData;
- }
- else {
- m_tabletData = GHOST_TABLET_DATA_NONE;
- }
-}
+ LOGCONTEXT lc_sys = {0}, lc_curr = {0};
-void GHOST_WindowWin32::processWin32TabletActivateEvent(WORD state)
-{
- if (!useTabletAPI(GHOST_kTabletWintab)) {
- return;
- }
+ if (m_wintab.info && m_wintab.get && m_wintab.set && m_wintab.info(WTI_DEFSYSCTX, 0, &lc_sys)) {
- if (m_wintab.enable && m_wintab.tablet) {
- m_wintab.enable(m_wintab.tablet, state);
+ m_wintab.get(m_wintab.context, &lc_curr);
- if (m_wintab.overlap && state) {
- m_wintab.overlap(m_wintab.tablet, TRUE);
- }
+ lc_curr.lcOutOrgX = lc_sys.lcOutOrgX;
+ lc_curr.lcOutOrgY = lc_sys.lcOutOrgY;
+ lc_curr.lcOutExtX = lc_sys.lcOutExtX;
+ lc_curr.lcOutExtY = -lc_sys.lcOutExtY;
+
+ m_wintab.set(m_wintab.context, &lc_curr);
}
}
@@ -1135,7 +1197,7 @@ bool GHOST_WindowWin32::useTabletAPI(GHOST_TTabletAPI api) const
return true;
}
else if (m_system->getTabletAPI() == GHOST_kTabletAutomatic) {
- if (m_wintab.tablet)
+ if (m_wintab.numDevices)
return api == GHOST_kTabletWintab;
else
return api == GHOST_kTabletNative;
@@ -1145,114 +1207,232 @@ bool GHOST_WindowWin32::useTabletAPI(GHOST_TTabletAPI api) const
}
}
-void GHOST_WindowWin32::processWin32TabletInitEvent()
+void GHOST_WindowWin32::processWintabProximityEvent(bool inRange)
{
if (!useTabletAPI(GHOST_kTabletWintab)) {
return;
}
// Let's see if we can initialize tablet here
- if (m_wintab.info && m_wintab.tablet) {
+ if (m_wintab.info && m_wintab.context) {
AXIS Pressure, Orientation[3]; /* The maximum tablet size */
BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
- if (pressureSupport)
- m_wintab.maxPressure = Pressure.axMax;
- else
- m_wintab.maxPressure = 0;
+ m_wintab.maxPressure = pressureSupport ? Pressure.axMax : 0;
BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
- if (tiltSupport) {
- /* does the tablet support azimuth ([0]) and altitude ([1]) */
- if (Orientation[0].axResolution && Orientation[1].axResolution) {
- m_wintab.maxAzimuth = Orientation[0].axMax;
- m_wintab.maxAltitude = Orientation[1].axMax;
- }
- else { /* no so dont do tilt stuff */
- m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
- }
+ /* does the tablet support azimuth ([0]) and altitude ([1]) */
+ if (tiltSupport && Orientation[0].axResolution && Orientation[1].axResolution) {
+ m_wintab.maxAzimuth = Orientation[0].axMax;
+ m_wintab.maxAltitude = Orientation[1].axMax;
}
+ else { /* no so dont do tilt stuff */
+ m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
+ }
+ }
+
+ m_tabletInRange = inRange;
+}
+
+void GHOST_WindowWin32::processWintabInfoChangeEvent(LPARAM lParam)
+{
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
+
+ // Update number of connected Wintab digitizers
+ if (LOWORD(lParam) == WTI_INTERFACE && HIWORD(lParam) == IFC_NDEVICES) {
+ m_wintab.info(WTI_INTERFACE, IFC_NDEVICES, &m_wintab.numDevices);
+ updateWintab((GHOST_WindowWin32 *)system->getWindowManager()->getActiveWindow() == this,
+ !::IsIconic(m_hWnd));
}
+}
+
+GHOST_TSuccess GHOST_WindowWin32::wintabMouseToGhost(UINT cursor,
+ WORD physicalButton,
+ GHOST_TButtonMask &ghostButton)
+{
+ const WORD numButtons = 32;
+ BYTE logicalButtons[numButtons] = {0};
+ BYTE systemButtons[numButtons] = {0};
- m_tabletData.Active = GHOST_kTabletModeNone;
+ m_wintab.info(WTI_CURSORS + cursor, CSR_BUTTONMAP, &logicalButtons);
+ m_wintab.info(WTI_CURSORS + cursor, CSR_SYSBTNMAP, &systemButtons);
+
+ if (physicalButton >= numButtons) {
+ return GHOST_kFailure;
+ }
+ BYTE lb = logicalButtons[physicalButton];
+
+ if (lb >= numButtons) {
+ return GHOST_kFailure;
+ }
+ switch (systemButtons[lb]) {
+ case SBN_LCLICK:
+ ghostButton = GHOST_kButtonMaskLeft;
+ return GHOST_kSuccess;
+ case SBN_RCLICK:
+ ghostButton = GHOST_kButtonMaskRight;
+ return GHOST_kSuccess;
+ case SBN_MCLICK:
+ ghostButton = GHOST_kButtonMaskMiddle;
+ return GHOST_kSuccess;
+ default:
+ return GHOST_kFailure;
+ }
}
-void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
+GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
{
if (!useTabletAPI(GHOST_kTabletWintab)) {
- return;
+ return GHOST_kFailure;
}
- if (m_wintab.packet && m_wintab.tablet) {
- PACKET pkt;
- if (m_wintab.packet((HCTX)lParam, wParam, &pkt)) {
- switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */
- case 0:
- m_tabletData.Active = GHOST_kTabletModeNone; /* puck - not yet supported */
- break;
- case 1:
- m_tabletData.Active = GHOST_kTabletModeStylus; /* stylus */
- break;
- case 2:
- m_tabletData.Active = GHOST_kTabletModeEraser; /* eraser */
- break;
- }
+ if (!(m_wintab.packetsGet && m_wintab.context)) {
+ return GHOST_kFailure;
+ }
- if (m_wintab.maxPressure > 0) {
- m_tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_wintab.maxPressure;
- }
- else {
- m_tabletData.Pressure = 1.0f;
- }
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
- if ((m_wintab.maxAzimuth > 0) && (m_wintab.maxAltitude > 0)) {
- ORIENTATION ort = pkt.pkOrientation;
- float vecLen;
- float altRad, azmRad; /* in radians */
+ updatePendingWintabEvents();
- /*
- * from the wintab spec:
- * orAzimuth Specifies the clockwise rotation of the
- * cursor about the z axis through a full circular range.
- *
- * orAltitude Specifies the angle with the x-y plane
- * through a signed, semicircular range. Positive values
- * specify an angle upward toward the positive z axis;
- * negative values specify an angle downward toward the negative z axis.
- *
- * wintab.h defines .orAltitude as a UINT but documents .orAltitude
- * as positive for upward angles and negative for downward angles.
- * WACOM uses negative altitude values to show that the pen is inverted;
- * therefore we cast .orAltitude as an (int) and then use the absolute value.
- */
-
- /* convert raw fixed point data to radians */
- altRad = (float)((fabs((float)ort.orAltitude) / (float)m_wintab.maxAltitude) * M_PI / 2.0);
- azmRad = (float)(((float)ort.orAzimuth / (float)m_wintab.maxAzimuth) * M_PI * 2.0);
-
- /* find length of the stylus' projected vector on the XY plane */
- vecLen = cos(altRad);
-
- /* from there calculate X and Y components based on azimuth */
- m_tabletData.Xtilt = sin(azmRad) * vecLen;
- m_tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
+ auto &pendingEvents = m_wintab.pendingEvents;
+ size_t pendingEventSize = pendingEvents.size();
+ outWintabInfo.resize(pendingEventSize);
+
+ for (int i = 0; i < pendingEventSize; i++) {
+ PACKET pkt = pendingEvents.front();
+ pendingEvents.pop();
+
+ GHOST_TabletData tabletData = GHOST_TABLET_DATA_NONE;
+ switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */
+ case 0:
+ tabletData.Active = GHOST_kTabletModeNone; /* puck - not yet supported */
+ break;
+ case 1:
+ tabletData.Active = GHOST_kTabletModeStylus; /* stylus */
+ break;
+ case 2:
+ tabletData.Active = GHOST_kTabletModeEraser; /* eraser */
+ break;
+ }
+
+ if (m_wintab.maxPressure > 0) {
+ tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_wintab.maxPressure;
+ }
+
+ if ((m_wintab.maxAzimuth > 0) && (m_wintab.maxAltitude > 0)) {
+ ORIENTATION ort = pkt.pkOrientation;
+ float vecLen;
+ float altRad, azmRad; /* in radians */
+
+ /*
+ * from the wintab spec:
+ * orAzimuth Specifies the clockwise rotation of the
+ * cursor about the z axis through a full circular range.
+ *
+ * orAltitude Specifies the angle with the x-y plane
+ * through a signed, semicircular range. Positive values
+ * specify an angle upward toward the positive z axis;
+ * negative values specify an angle downward toward the negative z axis.
+ *
+ * wintab.h defines .orAltitude as a UINT but documents .orAltitude
+ * as positive for upward angles and negative for downward angles.
+ * WACOM uses negative altitude values to show that the pen is inverted;
+ * therefore we cast .orAltitude as an (int) and then use the absolute value.
+ */
+
+ /* convert raw fixed point data to radians */
+ altRad = (float)((fabs((float)ort.orAltitude) / (float)m_wintab.maxAltitude) * M_PI / 2.0);
+ azmRad = (float)(((float)ort.orAzimuth / (float)m_wintab.maxAzimuth) * M_PI * 2.0);
+
+ /* find length of the stylus' projected vector on the XY plane */
+ vecLen = cos(altRad);
+
+ /* from there calculate X and Y components based on azimuth */
+ tabletData.Xtilt = sin(azmRad) * vecLen;
+ tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
+ }
+
+ outWintabInfo[i].x = pkt.pkX;
+ outWintabInfo[i].y = pkt.pkY;
+
+ /* Some Wintab libraries don't handle relative button input correctly, so we track button
+ * presses manually. Examples include Wacom's Bamboo modifying button events in the queue when
+ * peeked, or missing events when entering the window when the context is not on top. */
+ DWORD buttonsChanged = m_wintab.sysButtonsPressed ^ pkt.pkButtons;
+
+ /* Find the index for the changed button from the button map. */
+ WORD physicalButton = 0;
+ for (DWORD diff = (unsigned)buttonsChanged >> 1; diff > 0; diff = (unsigned)diff >> 1) {
+ physicalButton++;
+ }
+
+ if (buttonsChanged &&
+ wintabMouseToGhost(pkt.pkCursor, physicalButton, outWintabInfo[i].button)) {
+ if (buttonsChanged & pkt.pkButtons) {
+ outWintabInfo[i].type = GHOST_kEventButtonDown;
}
else {
- m_tabletData.Xtilt = 0.0f;
- m_tabletData.Ytilt = 0.0f;
+ outWintabInfo[i].type = GHOST_kEventButtonUp;
}
}
+ else {
+ outWintabInfo[i].type = GHOST_kEventCursorMove;
+ }
+
+ m_wintab.sysButtonsPressed = pkt.pkButtons;
+
+ outWintabInfo[i].time = system->millisSinceStart(pkt.pkTime);
+ outWintabInfo[i].tabletData = tabletData;
}
+
+ return GHOST_kSuccess;
}
-void GHOST_WindowWin32::bringTabletContextToFront()
+/* Wintab (per documentation but may vary with implementation) does not update when its event
+ * buffer is full. This is an issue because we need some synchronization point between Wintab
+ * events and Win32 events, so we can't drain and process the queue immediately. We need to
+ * associate Wintab mouse events to Win32 mouse events because Wintab buttons are modal (a button
+ * associated to left click is not always a left click) and there's no way to reconstruct their
+ * mode from the Wintab API alone. There is no guaranteed ordering between Wintab and Win32 mouse
+ * events and no documented time stamp shared between the two, so we synchronize on mouse button
+ * events. */
+void GHOST_WindowWin32::updatePendingWintabEvents()
{
- if (!useTabletAPI(GHOST_kTabletWintab)) {
+ if (!(m_wintab.packetsGet && m_wintab.context)) {
return;
}
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
+
+ auto &pendingEvents = m_wintab.pendingEvents;
+
+ /* Clear outdated events from queue. */
+ GHOST_TUns64 currTime = system->getMilliSeconds();
+ GHOST_TUns64 timeout = 300;
+ while (!pendingEvents.empty()) {
+ GHOST_TUns64 pktTime = system->millisSinceStart(pendingEvents.front().pkTime);
+ if (currTime - pktTime > timeout) {
+ pendingEvents.pop();
+ }
+ else {
+ break;
+ }
+ }
- if (m_wintab.overlap && m_wintab.tablet) {
- m_wintab.overlap(m_wintab.tablet, TRUE);
+ /* Get new packets. */
+ const int numPackets = m_wintab.packetsGet(
+ m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data());
+
+ int i = 0;
+ /* Don't queue outdated packets, such events can include packets that occurred before the current
+ * window lost and regained focus. */
+ for (; i < numPackets; i++) {
+ GHOST_TUns64 pktTime = system->millisSinceStart(m_wintab.pkts[i].pkTime);
+ if (currTime - pktTime < timeout) {
+ break;
+ }
+ }
+ for (; i < numPackets; i++) {
+ pendingEvents.push(m_wintab.pkts[i]);
}
}
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index 224ff53bf7b..a761d7d84dc 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -34,11 +34,14 @@
# include "GHOST_ImeWin32.h"
#endif
+#include <queue>
#include <vector>
#include <wintab.h>
-#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
-#define PACKETMODE PK_BUTTONS
+// PACKETDATA and PACKETMODE modify structs in pktdef.h, so make sure they come first
+#define PACKETDATA \
+ (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_X | PK_Y | PK_TIME)
+#define PACKETMODE 0
#include <pktdef.h>
class GHOST_SystemWin32;
@@ -46,9 +49,13 @@ class GHOST_DropTargetWin32;
// typedefs for WinTab functions to allow dynamic loading
typedef UINT(API *GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID);
+typedef BOOL(API *GHOST_WIN32_WTGet)(HCTX, LPLOGCONTEXTA);
+typedef BOOL(API *GHOST_WIN32_WTSet)(HCTX, LPLOGCONTEXTA);
typedef HCTX(API *GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL);
typedef BOOL(API *GHOST_WIN32_WTClose)(HCTX);
-typedef BOOL(API *GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID);
+typedef int(API *GHOST_WIN32_WTPacketsGet)(HCTX, int, LPVOID);
+typedef int(API *GHOST_WIN32_WTQueueSizeGet)(HCTX);
+typedef BOOL(API *GHOST_WIN32_WTQueueSizeSet)(HCTX, int);
typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL);
typedef BOOL(API *GHOST_WIN32_WTOverlap)(HCTX, BOOL);
@@ -229,7 +236,14 @@ struct GHOST_PointerInfoWin32 {
GHOST_TButtonMask buttonMask;
POINT pixelLocation;
GHOST_TUns64 time;
+ GHOST_TabletData tabletData;
+};
+struct GHOST_WintabInfoWin32 {
+ GHOST_TInt32 x, y;
+ GHOST_TEventType type;
+ GHOST_TButtonMask button;
+ GHOST_TUns64 time;
GHOST_TabletData tabletData;
};
@@ -248,16 +262,16 @@ class GHOST_WindowWin32 : public GHOST_Window {
/**
* Constructor.
* Creates a new window and opens it.
- * To check if the window was created properly, use the getValid() method.
- * \param title The text shown in the title bar of the window.
- * \param left The coordinate of the left edge of the window.
- * \param top The coordinate of the top edge of the window.
- * \param width The width the window.
- * \param height The height the window.
- * \param state The state the window is initially opened with.
- * \param type The type of drawing context installed in this window.
- * \param wantStereoVisual Stereo visual for quad buffered stereo.
- * \param parentWindowHwnd
+ * To check if the window was created properly, use the #getValid() method.
+ * \param title: The text shown in the title bar of the window.
+ * \param left: The coordinate of the left edge of the window.
+ * \param top: The coordinate of the top edge of the window.
+ * \param width: The width the window.
+ * \param height: The height the window.
+ * \param state: The state the window is initially opened with.
+ * \param type: The type of drawing context installed in this window.
+ * \param wantStereoVisual: Stereo visual for quad buffered stereo.
+ * \param parentWindowHwnd: TODO.
*/
GHOST_WindowWin32(GHOST_SystemWin32 *system,
const char *title,
@@ -293,7 +307,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
/**
* Sets the title displayed in the title bar.
- * \param title The title to display in the title bar.
+ * \param title: The title to display in the title bar.
*/
void setTitle(const char *title);
@@ -307,33 +321,33 @@ class GHOST_WindowWin32 : public GHOST_Window {
* Returns the window rectangle dimensions.
* The dimensions are given in screen coordinates that are
* relative to the upper-left corner of the screen.
- * \param bounds The bounding rectangle of the window.
+ * \param bounds: The bounding rectangle of the window.
*/
void getWindowBounds(GHOST_Rect &bounds) const;
/**
* Returns the client rectangle dimensions.
* The left and top members of the rectangle are always zero.
- * \param bounds The bounding rectangle of the client area of the window.
+ * \param bounds: The bounding rectangle of the client area of the window.
*/
void getClientBounds(GHOST_Rect &bounds) const;
/**
* Resizes client rectangle width.
- * \param width The new width of the client area of the window.
+ * \param width: The new width of the client area of the window.
*/
GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
/**
* Resizes client rectangle height.
- * \param height The new height of the client area of the window.
+ * \param height: The new height of the client area of the window.
*/
GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
/**
* Resizes client rectangle.
- * \param width The new width of the client area of the window.
- * \param height The new height of the client area of the window.
+ * \param width: The new width of the client area of the window.
+ * \param height: The new height of the client area of the window.
*/
GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
@@ -345,10 +359,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
/**
* Converts a point in screen coordinates to client rectangle coordinates
- * \param inX The x-coordinate on the screen.
- * \param inY The y-coordinate on the screen.
- * \param outX The x-coordinate in the client rectangle.
- * \param outY The y-coordinate in the client rectangle.
+ * \param inX: The x-coordinate on the screen.
+ * \param inY: The y-coordinate on the screen.
+ * \param outX: The x-coordinate in the client rectangle.
+ * \param outY: The y-coordinate in the client rectangle.
*/
void screenToClient(GHOST_TInt32 inX,
GHOST_TInt32 inY,
@@ -357,10 +371,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
/**
* Converts a point in screen coordinates to client rectangle coordinates
- * \param inX The x-coordinate in the client rectangle.
- * \param inY The y-coordinate in the client rectangle.
- * \param outX The x-coordinate on the screen.
- * \param outY The y-coordinate on the screen.
+ * \param inX: The x-coordinate in the client rectangle.
+ * \param inY: The y-coordinate in the client rectangle.
+ * \param outX: The x-coordinate on the screen.
+ * \param outY: The y-coordinate on the screen.
*/
void clientToScreen(GHOST_TInt32 inX,
GHOST_TInt32 inY,
@@ -369,14 +383,14 @@ class GHOST_WindowWin32 : public GHOST_Window {
/**
* Sets the state of the window (normal, minimized, maximized).
- * \param state The state of the window.
+ * \param state: The state of the window.
* \return Indication of success.
*/
GHOST_TSuccess setState(GHOST_TWindowState state);
/**
* Sets the order of the window (bottom, top).
- * \param order The order of the window.
+ * \param order: The order of the window.
* \return Indication of success.
*/
GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
@@ -388,7 +402,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
/**
* Sets the progress bar value displayed in the window/application icon
- * \param progress The progress %
+ * \param progress: The progress percentage (0.0 to 1.0).
*/
GHOST_TSuccess setProgressBar(float progress);
@@ -402,8 +416,8 @@ class GHOST_WindowWin32 : public GHOST_Window {
* for any real button press, controls mouse
* capturing).
*
- * \param event Whether mouse was pressed and released, or an operator grabbed or ungrabbed the
- * mouse
+ * \param event: Whether mouse was pressed and released,
+ * or an operator grabbed or ungrabbed the mouse.
*/
void updateMouseCapture(GHOST_MouseCaptureEventWin32 event);
@@ -417,34 +431,64 @@ class GHOST_WindowWin32 : public GHOST_Window {
/**
* Loads the windows equivalent of a standard GHOST cursor.
- * \param visible Flag for cursor visibility.
- * \param cursorShape The cursor shape.
+ * \param visible: Flag for cursor visibility.
+ * \param cursorShape: The cursor shape.
*/
HCURSOR getStandardCursor(GHOST_TStandardCursor shape) const;
void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const;
- const GHOST_TabletData &getTabletData()
- {
- return m_tabletData;
- }
+ /**
+ * Handle setup and switch between Wintab and Pointer APIs.
+ * \param active: Whether the window is or will be in an active state.
+ * \param visible: Whether the window is currently (or will be) visible).
+ */
+ void updateWintab(bool active, bool visible);
- void setTabletData(GHOST_TabletData *tabletData);
+ /**
+ * Query whether given tablet API should be used.
+ * \param api: Tablet API to test.
+ */
bool useTabletAPI(GHOST_TTabletAPI api) const;
/**
* Translate WM_POINTER events into GHOST_PointerInfoWin32 structs.
- * \param outPointerInfo Storage to return resulting GHOST_PointerInfoWin32 structs
- * \param wParam WPARAM of the event
- * \param lParam LPARAM of the event
+ * \param outPointerInfo: Storage to return resulting GHOST_PointerInfoWin32 structs.
+ * \param wParam: WPARAM of the event.
+ * \param lParam: LPARAM of the event.
+ * \return True if #outPointerInfo was updated.
*/
GHOST_TSuccess getPointerInfo(std::vector<GHOST_PointerInfoWin32> &outPointerInfo,
WPARAM wParam,
LPARAM lParam);
- void processWin32TabletActivateEvent(WORD state);
- void processWin32TabletInitEvent();
- void processWin32TabletEvent(WPARAM wParam, LPARAM lParam);
- void bringTabletContextToFront();
+ /**
+ * Handle Wintab coordinate changes when DisplayChange events occur.
+ */
+ void processWintabDisplayChangeEvent();
+
+ /**
+ * Set tablet details when a cursor enters range.
+ * \param inRange: Whether the Wintab device is in tracking range.
+ */
+ void processWintabProximityEvent(bool inRange);
+
+ /**
+ * Handle Wintab info changes such as change in number of connected tablets.
+ * \param lParam: LPARAM of the event.
+ */
+ void processWintabInfoChangeEvent(LPARAM lParam);
+
+ /**
+ * Translate Wintab packets into GHOST_WintabInfoWin32 structs.
+ * \param outWintabInfo: Storage to return resulting GHOST_WintabInfoWin32 structs.
+ * \return Success if able to read packets, even if there are none.
+ */
+ GHOST_TSuccess getWintabInfo(std::vector<GHOST_WintabInfoWin32> &outWintabInfo);
+
+ /**
+ * Updates stored pending Wintab events.
+ */
+ void updatePendingWintabEvents();
GHOST_TSuccess beginFullScreen() const
{
@@ -459,12 +503,25 @@ class GHOST_WindowWin32 : public GHOST_Window {
GHOST_TUns16 getDPIHint() override;
/**
- * Get whether there are currently any mouse buttons pressed
- * \return True if there are any currently pressed mouse buttons
+ * Get whether there are currently any mouse buttons pressed.
+ * \return True if there are any currently pressed mouse buttons.
*/
bool getMousePressed() const;
- /** Whether a tablet stylus is being tracked */
+ /**
+ * Get if there are currently pressed Wintab buttons associated to a Windows mouse button press.
+ * \return True if there are currently any pressed Wintab buttons associated to a Windows
+ * mouse button press.
+ */
+ bool wintabSysButPressed() const;
+
+ /**
+ * Register a Wintab button has been associated to a Windows mouse button press.
+ * \param event: Whether the button was pressed or released.
+ */
+ void updateWintabSysBut(GHOST_MouseCaptureEventWin32 event);
+
+ /** Whether a tablet stylus is being tracked. */
bool m_tabletInRange;
/** if the window currently resizing */
@@ -483,7 +540,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
private:
/**
- * \param type The type of rendering context create.
+ * \param type: The type of rendering context create.
* \return Indication of success.
*/
GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
@@ -497,7 +554,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
/**
* Sets the cursor grab on the window using native window system calls.
* Using registerMouseClickEvent.
- * \param mode GHOST_TGrabCursorMode.
+ * \param mode: GHOST_TGrabCursorMode.
*/
GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
@@ -547,28 +604,55 @@ class GHOST_WindowWin32 : public GHOST_Window {
static const wchar_t *s_windowClassName;
static const int s_maxTitleLength;
- /** Tablet data for GHOST */
- GHOST_TabletData m_tabletData;
-
/* Wintab API */
struct {
/** WinTab dll handle */
- HMODULE handle;
+ HMODULE handle = NULL;
/** API functions */
- GHOST_WIN32_WTInfo info;
- GHOST_WIN32_WTOpen open;
- GHOST_WIN32_WTClose close;
- GHOST_WIN32_WTPacket packet;
- GHOST_WIN32_WTEnable enable;
- GHOST_WIN32_WTOverlap overlap;
+ GHOST_WIN32_WTInfo info = NULL;
+ GHOST_WIN32_WTGet get = NULL;
+ GHOST_WIN32_WTSet set = NULL;
+ GHOST_WIN32_WTOpen open = NULL;
+ GHOST_WIN32_WTClose close = NULL;
+ GHOST_WIN32_WTPacketsGet packetsGet = NULL;
+ GHOST_WIN32_WTQueueSizeGet queueSizeGet = NULL;
+ GHOST_WIN32_WTQueueSizeSet queueSizeSet = NULL;
+ GHOST_WIN32_WTEnable enable = NULL;
+ GHOST_WIN32_WTOverlap overlap = NULL;
/** Stores the Tablet context if detected Tablet features using WinTab.dll */
- HCTX tablet;
- LONG maxPressure;
- LONG maxAzimuth, maxAltitude;
+ HCTX context = NULL;
+ /** Number of connected Wintab digitizers */
+ UINT numDevices = 0;
+ /** Number of cursors currently in contact mapped to system buttons */
+ GHOST_TUns8 numSysButtons = 0;
+ /** Cursors currently in contact mapped to system buttons */
+ DWORD sysButtonsPressed = 0;
+ LONG maxPressure = 0;
+ LONG maxAzimuth = 0, maxAltitude = 0;
+ /** Reusable buffer to read in Wintab Packets. */
+ std::vector<PACKET> pkts;
+ /** Queue of packets to process. */
+ std::queue<PACKET> pendingEvents;
} m_wintab;
+ /**
+ * Wintab setup.
+ */
+ void initializeWintab();
+
+ /**
+ * Convert Wintab system mapped (mouse) buttons into Ghost button mask.
+ * \param cursor: The Wintab cursor associated to the button.
+ * \param physicalButton: The physical button ID to inspect.
+ * \param buttonMask: Return pointer for button found.
+ * \return Whether an associated button was found.
+ */
+ GHOST_TSuccess wintabMouseToGhost(UINT cursor,
+ WORD physicalButton,
+ GHOST_TButtonMask &buttonMask);
+
GHOST_TWindowState m_normal_state;
/** user32 dll handle*/
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index a4d17d1add3..01699e9d1ce 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -54,16 +54,16 @@ class GHOST_WindowX11 : public GHOST_Window {
* Constructor.
* Creates a new window and opens it.
* To check if the window was created properly, use the getValid() method.
- * \param title The text shown in the title bar of the window.
- * \param left The coordinate of the left edge of the window.
- * \param top The coordinate of the top edge of the window.
- * \param width The width the window.
- * \param height The height the window.
- * \param state The state the window is initially opened with.
- * \param parentWindow Parent (embedder) window
- * \param type The type of drawing context installed in this window.
- * \param stereoVisual Stereo visual for quad buffered stereo.
- * \param alphaBackground Enable alpha blending of window with display background
+ * \param title: The text shown in the title bar of the window.
+ * \param left: The coordinate of the left edge of the window.
+ * \param top: The coordinate of the top edge of the window.
+ * \param width: The width the window.
+ * \param height: The height the window.
+ * \param state: The state the window is initially opened with.
+ * \param parentWindow: Parent (embedder) window.
+ * \param type: The type of drawing context installed in this window.
+ * \param stereoVisual: Stereo visual for quad buffered stereo.
+ * \param alphaBackground: Enable alpha blending of window with display background.
*/
GHOST_WindowX11(GHOST_SystemX11 *system,
Display *display,
@@ -186,7 +186,7 @@ class GHOST_WindowX11 : public GHOST_Window {
protected:
/**
- * \param type The type of rendering context create.
+ * \param type: The type of rendering context create.
* \return Indication of success.
*/
GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type);
diff --git a/intern/ghost/intern/GHOST_XrContext.cpp b/intern/ghost/intern/GHOST_XrContext.cpp
index 583bda9731a..2bf67c121f8 100644
--- a/intern/ghost/intern/GHOST_XrContext.cpp
+++ b/intern/ghost/intern/GHOST_XrContext.cpp
@@ -277,7 +277,7 @@ void GHOST_XrContext::setErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *c
* \{ */
/**
- * \param layer_name May be NULL for extensions not belonging to a specific layer.
+ * \param layer_name: May be NULL for extensions not belonging to a specific layer.
*/
void GHOST_XrContext::initExtensionsEx(std::vector<XrExtensionProperties> &extensions,
const char *layer_name)
diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp
index e43991853cb..73b73a8f046 100644
--- a/intern/ghost/intern/GHOST_XrSession.cpp
+++ b/intern/ghost/intern/GHOST_XrSession.cpp
@@ -222,7 +222,7 @@ GHOST_XrSession::LifeExpectancy GHOST_XrSession::handleStateChangeEvent(
m_oxr->session_state = lifecycle.state;
/* Runtime may send events for apparently destroyed session. Our handle should be NULL then. */
- assert((m_oxr->session == XR_NULL_HANDLE) || (m_oxr->session == lifecycle.session));
+ assert(m_oxr->session == XR_NULL_HANDLE || m_oxr->session == lifecycle.session);
switch (lifecycle.state) {
case XR_SESSION_STATE_READY: {
diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt
index b6e3c0ecf5f..27a764cd050 100644
--- a/intern/ghost/test/CMakeLists.txt
+++ b/intern/ghost/test/CMakeLists.txt
@@ -233,8 +233,8 @@ else()
set(GLEW_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/extern/glew/include")
endif()
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PLATFORM_CFLAGS}")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PLATFORM_CFLAGS}")
+string(APPEND CMAKE_C_FLAGS " ${PLATFORM_CFLAGS}")
+string(APPEND CMAKE_CXX_FLAGS " ${PLATFORM_CFLAGS}")
# -----------------------------------------------------------------------------
# Executables
diff --git a/intern/libmv/CMakeLists.txt b/intern/libmv/CMakeLists.txt
index b372cfe92bb..6fcf664d1f5 100644
--- a/intern/libmv/CMakeLists.txt
+++ b/intern/libmv/CMakeLists.txt
@@ -51,8 +51,6 @@ if(WITH_LIBMV)
list(APPEND INC
${GFLAGS_INCLUDE_DIRS}
${GLOG_INCLUDE_DIRS}
- ../../extern/ceres/include
- ../../extern/ceres/config
../guardedalloc
)
@@ -60,6 +58,8 @@ if(WITH_LIBMV)
${EIGEN3_INCLUDE_DIRS}
${PNG_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
+ ../../extern/ceres/include
+ ../../extern/ceres/config
)
list(APPEND LIB
diff --git a/intern/libmv/bundle.sh b/intern/libmv/bundle.sh
index 48da102b801..db8f88845a8 100755
--- a/intern/libmv/bundle.sh
+++ b/intern/libmv/bundle.sh
@@ -127,8 +127,6 @@ if(WITH_LIBMV)
list(APPEND INC
\${GFLAGS_INCLUDE_DIRS}
\${GLOG_INCLUDE_DIRS}
- ../../extern/ceres/include
- ../../extern/ceres/config
../guardedalloc
)
@@ -136,6 +134,8 @@ if(WITH_LIBMV)
\${EIGEN3_INCLUDE_DIRS}
\${PNG_INCLUDE_DIRS}
\${ZLIB_INCLUDE_DIRS}
+ ../../extern/ceres/include
+ ../../extern/ceres/config
)
list(APPEND LIB
diff --git a/intern/libmv/intern/reconstruction.cc b/intern/libmv/intern/reconstruction.cc
index 64f00b19df0..0f4e890d4ca 100644
--- a/intern/libmv/intern/reconstruction.cc
+++ b/intern/libmv/intern/reconstruction.cc
@@ -95,12 +95,23 @@ void libmv_solveRefineIntrinsics(
if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) {
bundle_intrinsics |= libmv::BUNDLE_PRINCIPAL_POINT;
}
- if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) {
- bundle_intrinsics |= libmv::BUNDLE_RADIAL_K1;
- }
- if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) {
- bundle_intrinsics |= libmv::BUNDLE_RADIAL_K2;
- }
+
+#define SET_DISTORTION_FLAG_CHECKED(type, coefficient) \
+ do { \
+ if (refine_intrinsics & LIBMV_REFINE_ ## type ##_DISTORTION_ ## coefficient) { \
+ bundle_intrinsics |= libmv::BUNDLE_ ## type ## _ ## coefficient; \
+ } \
+ } while (0)
+
+ SET_DISTORTION_FLAG_CHECKED(RADIAL, K1);
+ SET_DISTORTION_FLAG_CHECKED(RADIAL, K2);
+ SET_DISTORTION_FLAG_CHECKED(RADIAL, K3);
+ SET_DISTORTION_FLAG_CHECKED(RADIAL, K4);
+
+ SET_DISTORTION_FLAG_CHECKED(TANGENTIAL, P1);
+ SET_DISTORTION_FLAG_CHECKED(TANGENTIAL, P2);
+
+#undef SET_DISTORTION_FLAG_CHECKED
progress_update_callback(callback_customdata, 1.0, "Refining solution");
diff --git a/intern/libmv/intern/reconstruction.h b/intern/libmv/intern/reconstruction.h
index 727a4943add..408ac884684 100644
--- a/intern/libmv/intern/reconstruction.h
+++ b/intern/libmv/intern/reconstruction.h
@@ -31,10 +31,22 @@ struct libmv_CameraIntrinsicsOptions;
typedef struct libmv_Reconstruction libmv_Reconstruction;
enum {
- LIBMV_REFINE_FOCAL_LENGTH = (1 << 0),
- LIBMV_REFINE_PRINCIPAL_POINT = (1 << 1),
- LIBMV_REFINE_RADIAL_DISTORTION_K1 = (1 << 2),
- LIBMV_REFINE_RADIAL_DISTORTION_K2 = (1 << 4),
+ LIBMV_REFINE_FOCAL_LENGTH = (1 << 0),
+ LIBMV_REFINE_PRINCIPAL_POINT = (1 << 1),
+
+ LIBMV_REFINE_RADIAL_DISTORTION_K1 = (1 << 2),
+ LIBMV_REFINE_RADIAL_DISTORTION_K2 = (1 << 3),
+ LIBMV_REFINE_RADIAL_DISTORTION_K3 = (1 << 4),
+ LIBMV_REFINE_RADIAL_DISTORTION_K4 = (1 << 5),
+ LIBMV_REFINE_RADIAL_DISTORTION = (LIBMV_REFINE_RADIAL_DISTORTION_K1 |
+ LIBMV_REFINE_RADIAL_DISTORTION_K2 |
+ LIBMV_REFINE_RADIAL_DISTORTION_K3 |
+ LIBMV_REFINE_RADIAL_DISTORTION_K4),
+
+ LIBMV_REFINE_TANGENTIAL_DISTORTION_P1 = (1 << 6),
+ LIBMV_REFINE_TANGENTIAL_DISTORTION_P2 = (1 << 7),
+ LIBMV_REFINE_TANGENTIAL_DISTORTION = (LIBMV_REFINE_TANGENTIAL_DISTORTION_P1 |
+ LIBMV_REFINE_TANGENTIAL_DISTORTION_P2),
};
typedef struct libmv_ReconstructionOptions {
diff --git a/intern/libmv/libmv/image/array_nd_test.cc b/intern/libmv/libmv/image/array_nd_test.cc
index 313f21b60e9..dc7cfacf90d 100644
--- a/intern/libmv/libmv/image/array_nd_test.cc
+++ b/intern/libmv/libmv/image/array_nd_test.cc
@@ -191,10 +191,10 @@ TEST(ArrayND, CopyFrom) {
a(1, 1, 0) = 4;
ArrayND<float, 3> b;
b.CopyFrom(a);
- EXPECT_FLOAT_EQ(1.f, b(0, 0, 0));
- EXPECT_FLOAT_EQ(2.f, b(0, 1, 0));
- EXPECT_FLOAT_EQ(3.f, b(1, 0, 0));
- EXPECT_FLOAT_EQ(4.f, b(1, 1, 0));
+ EXPECT_FLOAT_EQ(1.0f, b(0, 0, 0));
+ EXPECT_FLOAT_EQ(2.0f, b(0, 1, 0));
+ EXPECT_FLOAT_EQ(3.0f, b(1, 0, 0));
+ EXPECT_FLOAT_EQ(4.0f, b(1, 1, 0));
}
TEST(ArrayND, MultiplyElements) {
diff --git a/intern/libmv/libmv/multiview/homography.h b/intern/libmv/libmv/multiview/homography.h
index 6d810c845ed..a76aa9405a5 100644
--- a/intern/libmv/libmv/multiview/homography.h
+++ b/intern/libmv/libmv/multiview/homography.h
@@ -27,21 +27,23 @@ namespace libmv {
/**
* 2D homography transformation estimation.
- *
+ *
* This function estimates the homography transformation from a list of 2D
* correspondences which represents either:
*
* - 3D points on a plane, with a general moving camera.
* - 3D points with a rotating camera (pure rotation).
* - 3D points + different planar projections
- *
- * \param x1 The first 2xN or 3xN matrix of euclidean or homogeneous points.
- * \param x2 The second 2xN or 3xN matrix of euclidean or homogeneous points.
- * \param H The 3x3 homography transformation matrix (8 dof) such that
- * x2 = H * x1 with |a b c|
- * H = |d e f|
- * |g h 1|
- * \param expected_precision The expected precision in order for instance
+ *
+ * \param x1: The first 2xN or 3xN matrix of euclidean or homogeneous points.
+ * \param x2: The second 2xN or 3xN matrix of euclidean or homogeneous points.
+ * \param H: The 3x3 homography transformation matrix (8 dof) such that
+ * <pre>
+ * x2 = H * x1 with |a b c|
+ * H = |d e f|
+ * |g h 1|
+ * </pre>
+ * \param expected_precision: The expected precision in order for instance
* to accept almost homography matrices.
*
* \return True if the transformation estimation has succeeded.
@@ -113,16 +115,18 @@ bool EstimateHomography2DFromCorrespondences(
* \param[in] x1 The first 4xN matrix of homogeneous points
* \param[in] x2 The second 4xN matrix of homogeneous points
* \param[out] H The 4x4 homography transformation matrix (15 dof) such that
- * x2 = H * x1 with |a b c d|
- * H = |e f g h|
- * |i j k l|
- * |m n o 1|
- * \param[in] expected_precision The expected precision in order for instance
+ * <pre>
+ * x2 = H * x1 with |a b c d|
+ * H = |e f g h|
+ * |i j k l|
+ * |m n o 1|
+ * </pre>
+ * \param[in] expected_precision The expected precision in order for instance
* to accept almost homography matrices.
*
* \return true if the transformation estimation has succeeded
*
- * \note Need at least 5 non coplanar points
+ * \note Need at least 5 non coplanar points
* \note Points coordinates must be in homogeneous coordinates
*/
bool Homography3DFromCorrespondencesLinear(const Mat &x1,
diff --git a/intern/libmv/libmv/simple_pipeline/bundle.cc b/intern/libmv/libmv/simple_pipeline/bundle.cc
index 3df39ab8936..d62f0ebe94f 100644
--- a/intern/libmv/libmv/simple_pipeline/bundle.cc
+++ b/intern/libmv/libmv/simple_pipeline/bundle.cc
@@ -368,6 +368,8 @@ void BundleIntrinsicsLogMessage(const int bundle_intrinsics) {
APPEND_BUNDLING_INTRINSICS("px, py", BUNDLE_PRINCIPAL_POINT);
APPEND_BUNDLING_INTRINSICS("k1", BUNDLE_RADIAL_K1);
APPEND_BUNDLING_INTRINSICS("k2", BUNDLE_RADIAL_K2);
+ APPEND_BUNDLING_INTRINSICS("k3", BUNDLE_RADIAL_K3);
+ APPEND_BUNDLING_INTRINSICS("k4", BUNDLE_RADIAL_K4);
APPEND_BUNDLING_INTRINSICS("p1", BUNDLE_TANGENTIAL_P1);
APPEND_BUNDLING_INTRINSICS("p2", BUNDLE_TANGENTIAL_P2);
@@ -744,7 +746,8 @@ void EuclideanBundleCommonIntrinsics(
std::vector<int> constant_intrinsics;
#define MAYBE_SET_CONSTANT(bundle_enum, offset) \
- if (!(bundle_intrinsics & bundle_enum)) { \
+ if (!(bundle_intrinsics & bundle_enum) || \
+ !packed_intrinsics.IsParameterDefined(offset)) { \
constant_intrinsics.push_back(offset); \
}
MAYBE_SET_CONSTANT(BUNDLE_FOCAL_LENGTH,
@@ -755,22 +758,19 @@ void EuclideanBundleCommonIntrinsics(
PackedIntrinsics::OFFSET_PRINCIPAL_POINT_Y);
MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K1, PackedIntrinsics::OFFSET_K1);
MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K2, PackedIntrinsics::OFFSET_K2);
+ MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K3, PackedIntrinsics::OFFSET_K3);
+ MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K4, PackedIntrinsics::OFFSET_K4);
MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P1, PackedIntrinsics::OFFSET_P1);
MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P2, PackedIntrinsics::OFFSET_P2);
#undef MAYBE_SET_CONSTANT
- // Always set K3 and K4 constant, it's not used at the moment.
- constant_intrinsics.push_back(PackedIntrinsics::OFFSET_K3);
- constant_intrinsics.push_back(PackedIntrinsics::OFFSET_K4);
+ if (!constant_intrinsics.empty()) {
+ ceres::SubsetParameterization *subset_parameterization =
+ new ceres::SubsetParameterization(PackedIntrinsics::NUM_PARAMETERS,
+ constant_intrinsics);
- // TODO(sergey): Mark all parameters which are not used by the distortion
- // model as constant.
-
- ceres::SubsetParameterization *subset_parameterization =
- new ceres::SubsetParameterization(PackedIntrinsics::NUM_PARAMETERS,
- constant_intrinsics);
-
- problem.SetParameterization(intrinsics_block, subset_parameterization);
+ problem.SetParameterization(intrinsics_block, subset_parameterization);
+ }
}
// Configure the solver.
diff --git a/intern/libmv/libmv/simple_pipeline/bundle.h b/intern/libmv/libmv/simple_pipeline/bundle.h
index 781bd8476fe..5f420da0045 100644
--- a/intern/libmv/libmv/simple_pipeline/bundle.h
+++ b/intern/libmv/libmv/simple_pipeline/bundle.h
@@ -101,14 +101,22 @@ void EuclideanBundle(const Tracks &tracks,
*/
enum BundleIntrinsics {
BUNDLE_NO_INTRINSICS = 0,
- BUNDLE_FOCAL_LENGTH = 1,
- BUNDLE_PRINCIPAL_POINT = 2,
- BUNDLE_RADIAL_K1 = 4,
- BUNDLE_RADIAL_K2 = 8,
- BUNDLE_RADIAL = 12,
- BUNDLE_TANGENTIAL_P1 = 16,
- BUNDLE_TANGENTIAL_P2 = 32,
- BUNDLE_TANGENTIAL = 48,
+
+ BUNDLE_FOCAL_LENGTH = (1 << 0),
+ BUNDLE_PRINCIPAL_POINT = (1 << 1),
+
+ BUNDLE_RADIAL_K1 = (1 << 2),
+ BUNDLE_RADIAL_K2 = (1 << 3),
+ BUNDLE_RADIAL_K3 = (1 << 4),
+ BUNDLE_RADIAL_K4 = (1 << 5),
+ BUNDLE_RADIAL = (BUNDLE_RADIAL_K1 |
+ BUNDLE_RADIAL_K2 |
+ BUNDLE_RADIAL_K3 |
+ BUNDLE_RADIAL_K4),
+
+ BUNDLE_TANGENTIAL_P1 = (1 << 6),
+ BUNDLE_TANGENTIAL_P2 = (1 << 7),
+ BUNDLE_TANGENTIAL = (BUNDLE_TANGENTIAL_P1 | BUNDLE_TANGENTIAL_P2),
};
enum BundleConstraints {
BUNDLE_NO_CONSTRAINTS = 0,
diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h
index 30b0f1abf7b..ba67ec468dc 100644
--- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h
+++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h
@@ -292,7 +292,7 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics {
PolynomialCameraIntrinsics();
PolynomialCameraIntrinsics(const PolynomialCameraIntrinsics &from);
- DistortionModelType GetDistortionModelType() const {
+ DistortionModelType GetDistortionModelType() const override {
return DISTORTION_MODEL_POLYNOMIAL;
}
@@ -316,7 +316,7 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics {
void ApplyIntrinsics(double normalized_x,
double normalized_y,
double *image_x,
- double *image_y) const;
+ double *image_y) const override;
// Invert camera intrinsics on the image point to get normalized coordinates.
//
@@ -325,7 +325,7 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics {
void InvertIntrinsics(double image_x,
double image_y,
double *normalized_x,
- double *normalized_y) const;
+ double *normalized_y) const override;
virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
@@ -354,7 +354,7 @@ class DivisionCameraIntrinsics : public CameraIntrinsics {
DivisionCameraIntrinsics();
DivisionCameraIntrinsics(const DivisionCameraIntrinsics &from);
- DistortionModelType GetDistortionModelType() const {
+ DistortionModelType GetDistortionModelType() const override {
return DISTORTION_MODEL_DIVISION;
}
@@ -372,7 +372,7 @@ class DivisionCameraIntrinsics : public CameraIntrinsics {
void ApplyIntrinsics(double normalized_x,
double normalized_y,
double *image_x,
- double *image_y) const;
+ double *image_y) const override;
// Invert camera intrinsics on the image point to get normalized coordinates.
//
@@ -381,7 +381,7 @@ class DivisionCameraIntrinsics : public CameraIntrinsics {
void InvertIntrinsics(double image_x,
double image_y,
double *normalized_x,
- double *normalized_y) const;
+ double *normalized_y) const override;
virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
@@ -407,7 +407,7 @@ class NukeCameraIntrinsics : public CameraIntrinsics {
NukeCameraIntrinsics();
NukeCameraIntrinsics(const NukeCameraIntrinsics &from);
- DistortionModelType GetDistortionModelType() const {
+ DistortionModelType GetDistortionModelType() const override {
return DISTORTION_MODEL_NUKE;
}
@@ -425,7 +425,7 @@ class NukeCameraIntrinsics : public CameraIntrinsics {
void ApplyIntrinsics(double normalized_x,
double normalized_y,
double *image_x,
- double *image_y) const;
+ double *image_y) const override;
// Invert camera intrinsics on the image point to get normalized coordinates.
//
@@ -434,7 +434,7 @@ class NukeCameraIntrinsics : public CameraIntrinsics {
void InvertIntrinsics(double image_x,
double image_y,
double *normalized_x,
- double *normalized_y) const;
+ double *normalized_y) const override;
virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
@@ -464,7 +464,7 @@ class BrownCameraIntrinsics : public CameraIntrinsics {
BrownCameraIntrinsics();
BrownCameraIntrinsics(const BrownCameraIntrinsics &from);
- DistortionModelType GetDistortionModelType() const {
+ DistortionModelType GetDistortionModelType() const override {
return DISTORTION_MODEL_BROWN;
}
@@ -489,7 +489,7 @@ class BrownCameraIntrinsics : public CameraIntrinsics {
void ApplyIntrinsics(double normalized_x,
double normalized_y,
double *image_x,
- double *image_y) const;
+ double *image_y) const override;
// Invert camera intrinsics on the image point to get normalized coordinates.
//
@@ -498,7 +498,7 @@ class BrownCameraIntrinsics : public CameraIntrinsics {
void InvertIntrinsics(double image_x,
double image_y,
double *normalized_x,
- double *normalized_y) const;
+ double *normalized_y) const override;
virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
diff --git a/intern/libmv/libmv/simple_pipeline/keyframe_selection.h b/intern/libmv/libmv/simple_pipeline/keyframe_selection.h
index aa3eeaf193d..25253af32fe 100644
--- a/intern/libmv/libmv/simple_pipeline/keyframe_selection.h
+++ b/intern/libmv/libmv/simple_pipeline/keyframe_selection.h
@@ -38,11 +38,11 @@ namespace libmv {
// and if expected error estimation is too large, keyframe candidate
// is rejecting.
//
-// \param tracks contains all tracked correspondences between frames
-// expected to be undistorted and normalized
-// \param intrinsics is camera intrinsics
-// \param keyframes will contain all images number which are considered
-// good to be used for reconstruction
+// \param tracks: contains all tracked correspondences between frames
+// expected to be undistorted and normalized.
+// \param intrinsics: is camera intrinsics.
+// \param keyframes: will contain all images number which are considered
+// good to be used for reconstruction.
void SelectKeyframesBasedOnGRICAndVariance(
const Tracks &tracks,
const CameraIntrinsics &intrinsics,
diff --git a/intern/libmv/libmv/simple_pipeline/packed_intrinsics.cc b/intern/libmv/libmv/simple_pipeline/packed_intrinsics.cc
index e9d7c2e78be..73ad4faed9c 100644
--- a/intern/libmv/libmv/simple_pipeline/packed_intrinsics.cc
+++ b/intern/libmv/libmv/simple_pipeline/packed_intrinsics.cc
@@ -47,7 +47,7 @@ double PackedIntrinsics::GetPrincipalPointY() const {
void PackedIntrinsics::SetParameter(int index, double value) {
parameters_.at(index) = value;
- known_parameters_.at(index) = value;
+ known_parameters_.at(index) = true;
}
double PackedIntrinsics::GetParameter(int index) const {
// TODO(sergey): Consider adding a check for whether the parameter is known.
@@ -55,4 +55,8 @@ double PackedIntrinsics::GetParameter(int index) const {
return parameters_.at(index);
}
+bool PackedIntrinsics::IsParameterDefined(int offset) {
+ return known_parameters_.at(offset);
+}
+
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h b/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h
index e551fe74800..cbea599fccd 100644
--- a/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h
+++ b/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h
@@ -86,6 +86,8 @@ class PackedIntrinsics {
double* GetParametersBlock() { return parameters_.data(); }
const double* GetParametersBlock() const { return parameters_.data(); }
+ bool IsParameterDefined(int offset);
+
private:
void SetParameter(int index, double value);
double GetParameter(int index) const;
diff --git a/intern/mantaflow/extern/manta_fluid_API.h b/intern/mantaflow/extern/manta_fluid_API.h
index 6827ac35050..e4ad4c66d8a 100644
--- a/intern/mantaflow/extern/manta_fluid_API.h
+++ b/intern/mantaflow/extern/manta_fluid_API.h
@@ -33,44 +33,44 @@ struct MANTA;
/* Fluid functions */
struct MANTA *manta_init(int *res, struct FluidModifierData *fmd);
void manta_free(struct MANTA *fluid);
-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);
-int manta_read_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
-int manta_read_data(struct MANTA *fluid,
- struct FluidModifierData *fmd,
- int framenr,
- bool resumable);
-int manta_read_noise(struct MANTA *fluid,
+bool manta_ensure_obstacle(struct MANTA *fluid, struct FluidModifierData *fmd);
+bool manta_ensure_guiding(struct MANTA *fluid, struct FluidModifierData *fmd);
+bool manta_ensure_invelocity(struct MANTA *fluid, struct FluidModifierData *fmd);
+bool manta_ensure_outflow(struct MANTA *fluid, struct FluidModifierData *fmd);
+bool manta_write_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_write_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_write_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_read_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_read_data(struct MANTA *fluid,
struct FluidModifierData *fmd,
int framenr,
bool resumable);
-int manta_read_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
-int manta_read_particles(struct MANTA *fluid,
- struct FluidModifierData *fmd,
- int framenr,
- bool resumable);
-int manta_read_guiding(struct MANTA *fluid,
- struct FluidModifierData *fmd,
- int framenr,
- bool sourceDomain);
-int manta_bake_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
-int manta_bake_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
-int manta_bake_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
-int manta_bake_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
-int manta_bake_guiding(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
-int manta_has_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
-int manta_has_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
-int manta_has_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
-int manta_has_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
-int manta_has_guiding(struct MANTA *fluid,
+bool manta_read_noise(struct MANTA *fluid,
struct FluidModifierData *fmd,
int framenr,
- bool domain);
+ bool resumable);
+bool manta_read_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_read_particles(struct MANTA *fluid,
+ struct FluidModifierData *fmd,
+ int framenr,
+ bool resumable);
+bool manta_read_guiding(struct MANTA *fluid,
+ struct FluidModifierData *fmd,
+ int framenr,
+ bool sourceDomain);
+bool manta_bake_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_bake_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_bake_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_bake_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_bake_guiding(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_has_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_has_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_has_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_has_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr);
+bool manta_has_guiding(struct MANTA *fluid,
+ struct FluidModifierData *fmd,
+ int framenr,
+ bool domain);
void manta_update_variables(struct MANTA *fluid, struct FluidModifierData *fmd);
int manta_get_frame(struct MANTA *fluid);
@@ -113,7 +113,7 @@ float *manta_get_phi(struct MANTA *fluid);
float *manta_get_pressure(struct MANTA *fluid);
/* Smoke functions */
-void manta_smoke_export_script(struct MANTA *smoke, struct FluidModifierData *fmd);
+bool manta_smoke_export_script(struct MANTA *smoke, struct FluidModifierData *fmd);
void manta_smoke_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,
@@ -124,9 +124,9 @@ 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);
+bool manta_smoke_ensure_heat(struct MANTA *smoke, struct FluidModifierData *fmd);
+bool manta_smoke_ensure_fire(struct MANTA *smoke, struct FluidModifierData *fmd);
+bool manta_smoke_ensure_colors(struct MANTA *smoke, struct FluidModifierData *fmd);
/* Smoke accessors */
float *manta_smoke_get_density(struct MANTA *smoke);
@@ -147,9 +147,9 @@ float *manta_smoke_get_color_b_in(struct MANTA *smoke);
float *manta_smoke_get_fuel_in(struct MANTA *smoke);
float *manta_smoke_get_react_in(struct MANTA *smoke);
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);
+bool manta_smoke_has_heat(struct MANTA *smoke);
+bool manta_smoke_has_fuel(struct MANTA *smoke);
+bool manta_smoke_has_colors(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);
@@ -163,14 +163,14 @@ 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);
+bool manta_noise_has_fuel(struct MANTA *smoke);
+bool 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);
-int manta_liquid_ensure_sndparts(struct MANTA *fluid, struct FluidModifierData *fmd);
+bool manta_liquid_export_script(struct MANTA *smoke, struct FluidModifierData *fmd);
+bool manta_liquid_ensure_sndparts(struct MANTA *fluid, struct FluidModifierData *fmd);
/* Liquid accessors */
int manta_liquid_get_particle_res_x(struct MANTA *liquid);
@@ -212,9 +212,6 @@ float manta_liquid_get_snd_particle_position_z_at(struct MANTA *liquid, int i);
float manta_liquid_get_snd_particle_velocity_x_at(struct MANTA *liquid, int i);
float manta_liquid_get_snd_particle_velocity_y_at(struct MANTA *liquid, int i);
float manta_liquid_get_snd_particle_velocity_z_at(struct MANTA *liquid, int i);
-bool manta_liquid_flip_from_file(struct MANTA *liquid);
-bool manta_liquid_mesh_from_file(struct MANTA *liquid);
-bool manta_liquid_particle_from_file(struct MANTA *liquid);
#ifdef __cplusplus
}
diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp
index dec05831e61..fef6399ab23 100644
--- a/intern/mantaflow/intern/MANTA_main.cpp
+++ b/intern/mantaflow/intern/MANTA_main.cpp
@@ -458,8 +458,7 @@ bool MANTA::initObstacle(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- mUsingObstacle = true;
- return runPythonString(pythonCommands);
+ return (mUsingObstacle = runPythonString(pythonCommands));
}
return false;
}
@@ -473,8 +472,7 @@ bool MANTA::initGuiding(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- mUsingGuiding = true;
- return runPythonString(pythonCommands);
+ return (mUsingGuiding = runPythonString(pythonCommands));
}
return false;
}
@@ -486,8 +484,7 @@ bool MANTA::initFractions(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- mUsingFractions = true;
- return runPythonString(pythonCommands);
+ return (mUsingFractions = runPythonString(pythonCommands));
}
bool MANTA::initInVelocity(FluidModifierData *fmd)
@@ -498,8 +495,7 @@ bool MANTA::initInVelocity(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- mUsingInvel = true;
- return runPythonString(pythonCommands);
+ return (mUsingInvel = runPythonString(pythonCommands));
}
return false;
}
@@ -512,8 +508,7 @@ bool MANTA::initOutflow(FluidModifierData *fmd)
string finalString = parseScript(tmpString, fmd);
pythonCommands.push_back(finalString);
- mUsingOutflow = true;
- return runPythonString(pythonCommands);
+ return (mUsingOutflow = runPythonString(pythonCommands));
}
return false;
}
@@ -565,7 +560,7 @@ MANTA::~MANTA()
pythonCommands.push_back(finalString);
result = runPythonString(pythonCommands);
- assert(result);
+ BLI_assert(result);
UNUSED_VARS(result);
}
@@ -610,7 +605,7 @@ bool MANTA::runPythonString(vector<string> commands)
}
PyGILState_Release(gilstate);
- assert(success);
+ BLI_assert(success);
return success;
}
@@ -697,12 +692,6 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd)
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0)
borderCollisions += "Z";
- string simulationMethod = "";
- if (fds->simulation_method & FLUID_DOMAIN_METHOD_FLIP)
- simulationMethod += "'FLIP'";
- else if (fds->simulation_method & FLUID_DOMAIN_METHOD_APIC)
- simulationMethod += "'APIC'";
-
string particleTypesStr = "";
if (fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY)
particleTypesStr += "PtypeSpray";
@@ -837,7 +826,7 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd)
mRNAMap["CACHE_MESH_FORMAT"] = getCacheFileEnding(fds->cache_mesh_format);
mRNAMap["CACHE_NOISE_FORMAT"] = getCacheFileEnding(fds->cache_noise_format);
mRNAMap["CACHE_PARTICLE_FORMAT"] = getCacheFileEnding(fds->cache_particle_format);
- mRNAMap["SIMULATION_METHOD"] = simulationMethod;
+ mRNAMap["USING_APIC"] = getBooleanString(fds->simulation_method == FLUID_DOMAIN_METHOD_APIC);
mRNAMap["FLIP_RATIO"] = to_string(fds->flip_ratio);
mRNAMap["PARTICLE_RANDOMNESS"] = to_string(fds->particle_randomness);
mRNAMap["PARTICLE_NUMBER"] = to_string(fds->particle_number);
@@ -1596,7 +1585,7 @@ bool MANTA::updateVariables(FluidModifierData *fmd)
return runPythonString(pythonCommands);
}
-void MANTA::exportSmokeScript(FluidModifierData *fmd)
+bool MANTA::exportSmokeScript(FluidModifierData *fmd)
{
if (with_debug)
cout << "MANTA::exportSmokeScript()" << endl;
@@ -1702,9 +1691,14 @@ void MANTA::exportSmokeScript(FluidModifierData *fmd)
myfile.open(cacheDirScript);
myfile << final_script;
myfile.close();
+ if (!myfile) {
+ cerr << "Fluid Error -- Could not export standalone Mantaflow smoke domain script";
+ return false;
+ }
+ return true;
}
-void MANTA::exportLiquidScript(FluidModifierData *fmd)
+bool MANTA::exportLiquidScript(FluidModifierData *fmd)
{
if (with_debug)
cout << "MANTA::exportLiquidScript()" << endl;
@@ -1810,6 +1804,11 @@ void MANTA::exportLiquidScript(FluidModifierData *fmd)
myfile.open(cacheDirScript);
myfile << final_script;
myfile.close();
+ if (!myfile) {
+ cerr << "Fluid Error -- Could not export standalone Mantaflow liquid domain script";
+ return false;
+ }
+ return true;
}
/* Call Mantaflow Python functions through this function. Use isAttribute for object attributes,
diff --git a/intern/mantaflow/intern/MANTA_main.h b/intern/mantaflow/intern/MANTA_main.h
index 6425614cf4b..163b168e43d 100644
--- a/intern/mantaflow/intern/MANTA_main.h
+++ b/intern/mantaflow/intern/MANTA_main.h
@@ -104,8 +104,8 @@ struct MANTA {
bool bakeGuiding(FluidModifierData *fmd, int framenr);
/* IO for Mantaflow scene script. */
- void exportSmokeScript(struct FluidModifierData *fmd);
- void exportLiquidScript(struct FluidModifierData *fmd);
+ bool exportSmokeScript(struct FluidModifierData *fmd);
+ bool exportLiquidScript(struct FluidModifierData *fmd);
/* Check cache status by frame. */
bool hasConfig(FluidModifierData *fmd, int framenr);
diff --git a/intern/mantaflow/intern/manta_fluid_API.cpp b/intern/mantaflow/intern/manta_fluid_API.cpp
index e4754131f34..c04180c8c46 100644
--- a/intern/mantaflow/intern/manta_fluid_API.cpp
+++ b/intern/mantaflow/intern/manta_fluid_API.cpp
@@ -37,203 +37,145 @@ void manta_free(MANTA *fluid)
fluid = nullptr;
}
-int manta_ensure_obstacle(MANTA *fluid, struct FluidModifierData *fmd)
+bool manta_ensure_obstacle(MANTA *fluid, struct FluidModifierData *fmd)
{
- if (!fluid || !fmd)
- return 0;
return fluid->initObstacle(fmd);
}
-int manta_ensure_guiding(MANTA *fluid, struct FluidModifierData *fmd)
+bool manta_ensure_guiding(MANTA *fluid, struct FluidModifierData *fmd)
{
- if (!fluid || !fmd)
- return 0;
return fluid->initGuiding(fmd);
}
-int manta_ensure_invelocity(MANTA *fluid, struct FluidModifierData *fmd)
+bool manta_ensure_invelocity(MANTA *fluid, struct FluidModifierData *fmd)
{
- if (!fluid || !fmd)
- return 0;
return fluid->initInVelocity(fmd);
}
-int manta_ensure_outflow(MANTA *fluid, struct FluidModifierData *fmd)
+bool manta_ensure_outflow(MANTA *fluid, struct FluidModifierData *fmd)
{
- if (!fluid || !fmd)
- return 0;
return fluid->initOutflow(fmd);
}
-int manta_write_config(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_write_config(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->writeConfiguration(fmd, framenr);
}
-int manta_write_data(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_write_data(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->writeData(fmd, framenr);
}
-int manta_write_noise(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_write_noise(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->writeNoise(fmd, framenr);
}
-int manta_read_config(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_read_config(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->readConfiguration(fmd, framenr);
}
-int manta_read_data(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable)
+bool manta_read_data(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable)
{
- if (!fluid || !fmd)
- return 0;
return fluid->readData(fmd, framenr, resumable);
}
-int manta_read_noise(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable)
+bool manta_read_noise(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable)
{
- if (!fluid || !fmd)
- return 0;
return fluid->readNoise(fmd, framenr, resumable);
}
-int manta_read_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_read_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->readMesh(fmd, framenr);
}
-int manta_read_particles(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable)
+bool manta_read_particles(MANTA *fluid, FluidModifierData *fmd, int framenr, bool resumable)
{
- if (!fluid || !fmd)
- return 0;
return fluid->readParticles(fmd, framenr, resumable);
}
-int manta_read_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr, bool sourceDomain)
+bool manta_read_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr, bool sourceDomain)
{
- if (!fluid || !fmd)
- return 0;
return fluid->readGuiding(fmd, framenr, sourceDomain);
}
-int manta_bake_data(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_bake_data(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->bakeData(fmd, framenr);
}
-int manta_bake_noise(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_bake_noise(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->bakeNoise(fmd, framenr);
}
-int manta_bake_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_bake_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->bakeMesh(fmd, framenr);
}
-int manta_bake_particles(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_bake_particles(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->bakeParticles(fmd, framenr);
}
-int manta_bake_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_bake_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->bakeGuiding(fmd, framenr);
}
-int manta_has_data(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_has_data(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->hasData(fmd, framenr);
}
-int manta_has_noise(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_has_noise(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->hasNoise(fmd, framenr);
}
-int manta_has_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_has_mesh(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->hasMesh(fmd, framenr);
}
-int manta_has_particles(MANTA *fluid, FluidModifierData *fmd, int framenr)
+bool manta_has_particles(MANTA *fluid, FluidModifierData *fmd, int framenr)
{
- if (!fluid || !fmd)
- return 0;
return fluid->hasParticles(fmd, framenr);
}
-int manta_has_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr, bool domain)
+bool manta_has_guiding(MANTA *fluid, FluidModifierData *fmd, int framenr, bool domain)
{
- if (!fluid || !fmd)
- return 0;
return fluid->hasGuiding(fmd, framenr, domain);
}
void manta_update_variables(MANTA *fluid, FluidModifierData *fmd)
{
- if (!fluid)
- return;
fluid->updateVariables(fmd);
}
int manta_get_frame(MANTA *fluid)
{
- if (!fluid)
- return 0;
return fluid->getFrame();
}
float manta_get_timestep(MANTA *fluid)
{
- if (!fluid)
- return 0;
return fluid->getTimestep();
}
void manta_adapt_timestep(MANTA *fluid)
{
- if (!fluid)
- return;
fluid->adaptTimestep();
}
bool manta_needs_realloc(MANTA *fluid, FluidModifierData *fmd)
{
- 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);
}
@@ -372,11 +314,9 @@ float *manta_get_pressure(MANTA *fluid)
}
/* Smoke functions */
-void manta_smoke_export_script(MANTA *smoke, FluidModifierData *fmd)
+bool manta_smoke_export_script(MANTA *smoke, FluidModifierData *fmd)
{
- if (!smoke || !fmd)
- return;
- smoke->exportSmokeScript(fmd);
+ return smoke->exportSmokeScript(fmd);
}
static void get_rgba(
@@ -452,18 +392,13 @@ void manta_noise_get_rgba_fixed_color(MANTA *smoke, float color[3], float *data,
get_rgba_fixed_color(color, smoke->getTotalCellsHigh(), data, sequential);
}
-int manta_smoke_ensure_heat(MANTA *smoke, struct FluidModifierData *fmd)
+bool manta_smoke_ensure_heat(MANTA *smoke, struct FluidModifierData *fmd)
{
- if (!smoke || !fmd)
- return 0;
return smoke->initHeat(fmd);
}
-int manta_smoke_ensure_fire(MANTA *smoke, struct FluidModifierData *fmd)
+bool manta_smoke_ensure_fire(MANTA *smoke, struct FluidModifierData *fmd)
{
- if (!smoke || !fmd)
- return 0;
-
bool result = smoke->initFire(fmd);
if (smoke->usingNoise()) {
result &= smoke->initFireHigh(fmd);
@@ -471,11 +406,8 @@ int manta_smoke_ensure_fire(MANTA *smoke, struct FluidModifierData *fmd)
return result;
}
-int manta_smoke_ensure_colors(MANTA *smoke, struct FluidModifierData *fmd)
+bool manta_smoke_ensure_colors(MANTA *smoke, struct FluidModifierData *fmd)
{
- if (!smoke || !fmd)
- return 0;
-
bool result = smoke->initColors(fmd);
if (smoke->usingNoise()) {
result &= smoke->initColorsHigh(fmd);
@@ -560,107 +492,104 @@ float *manta_smoke_get_emission_in(MANTA *smoke)
return smoke->getEmissionIn();
}
-int manta_smoke_has_heat(MANTA *smoke)
+bool manta_smoke_has_heat(MANTA *smoke)
{
- return (smoke->getHeat()) ? 1 : 0;
+ return smoke->getHeat() != nullptr;
+ ;
}
-int manta_smoke_has_fuel(MANTA *smoke)
+bool manta_smoke_has_fuel(MANTA *smoke)
{
- return (smoke->getFuel()) ? 1 : 0;
+ return smoke->getFuel() != nullptr;
}
-int manta_smoke_has_colors(MANTA *smoke)
+bool manta_smoke_has_colors(MANTA *smoke)
{
- return (smoke->getColorR() && smoke->getColorG() && smoke->getColorB()) ? 1 : 0;
+ return smoke->getColorR() != nullptr && smoke->getColorG() != nullptr &&
+ smoke->getColorB() != nullptr;
}
float *manta_noise_get_density(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getDensityHigh() : nullptr;
+ return smoke->getDensityHigh();
}
float *manta_noise_get_fuel(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getFuelHigh() : nullptr;
+ return smoke->getFuelHigh();
}
float *manta_noise_get_react(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getReactHigh() : nullptr;
+ return smoke->getReactHigh();
}
float *manta_noise_get_color_r(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getColorRHigh() : nullptr;
+ return smoke->getColorRHigh();
}
float *manta_noise_get_color_g(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getColorGHigh() : nullptr;
+ return smoke->getColorGHigh();
}
float *manta_noise_get_color_b(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getColorBHigh() : nullptr;
+ return smoke->getColorBHigh();
}
float *manta_noise_get_flame(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getFlameHigh() : nullptr;
+ return smoke->getFlameHigh();
}
float *manta_noise_get_texture_u(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getTextureU() : nullptr;
+ return smoke->getTextureU();
}
float *manta_noise_get_texture_v(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getTextureV() : nullptr;
+ return smoke->getTextureV();
}
float *manta_noise_get_texture_w(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getTextureW() : nullptr;
+ return smoke->getTextureW();
}
float *manta_noise_get_texture_u2(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getTextureU2() : nullptr;
+ return smoke->getTextureU2();
}
float *manta_noise_get_texture_v2(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getTextureV2() : nullptr;
+ return smoke->getTextureV2();
}
float *manta_noise_get_texture_w2(MANTA *smoke)
{
- return (smoke && smoke->usingNoise()) ? smoke->getTextureW2() : nullptr;
+ return smoke->getTextureW2();
}
-int manta_noise_has_fuel(MANTA *smoke)
+bool manta_noise_has_fuel(MANTA *smoke)
{
- return (smoke->getFuelHigh()) ? 1 : 0;
+ return smoke->getFuelHigh() != nullptr;
}
-int manta_noise_has_colors(MANTA *smoke)
+bool manta_noise_has_colors(MANTA *smoke)
{
- return (smoke->getColorRHigh() && smoke->getColorGHigh() && smoke->getColorBHigh()) ? 1 : 0;
+ return smoke->getColorRHigh() != nullptr && smoke->getColorGHigh() != nullptr &&
+ smoke->getColorBHigh() != nullptr;
+ ;
}
void manta_noise_get_res(MANTA *smoke, int *res)
{
- if (smoke && smoke->usingNoise()) {
- res[0] = smoke->getResXHigh();
- res[1] = smoke->getResYHigh();
- res[2] = smoke->getResZHigh();
- }
+ res[0] = smoke->getResXHigh();
+ res[1] = smoke->getResYHigh();
+ res[2] = smoke->getResZHigh();
}
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;
+ return smoke->getResXHigh() * smoke->getResYHigh() * smoke->getResZHigh();
}
/* Liquid functions */
-void manta_liquid_export_script(MANTA *liquid, FluidModifierData *fmd)
+bool manta_liquid_export_script(MANTA *liquid, FluidModifierData *fmd)
{
- if (!liquid || !fmd)
- return;
- liquid->exportLiquidScript(fmd);
+ return liquid->exportLiquidScript(fmd);
}
-int manta_liquid_ensure_sndparts(MANTA *liquid, struct FluidModifierData *fmd)
+bool manta_liquid_ensure_sndparts(MANTA *liquid, struct FluidModifierData *fmd)
{
- if (!liquid || !fmd)
- return 0;
return liquid->initLiquidSndParts(fmd);
}
@@ -834,16 +763,3 @@ float manta_liquid_get_snd_particle_velocity_z_at(MANTA *liquid, int i)
{
return liquid->getSndParticleVelocityZAt(i);
}
-
-bool manta_liquid_flip_from_file(MANTA *liquid)
-{
- return liquid->usingFlipFromFile();
-}
-bool manta_liquid_mesh_from_file(MANTA *liquid)
-{
- return liquid->usingMeshFromFile();
-}
-bool manta_liquid_particle_from_file(MANTA *liquid)
-{
- return liquid->usingParticleFromFile();
-}
diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h
index c416a84c71c..1f22f4b3d21 100644
--- a/intern/mantaflow/intern/strings/fluid_script.h
+++ b/intern/mantaflow/intern/strings/fluid_script.h
@@ -39,11 +39,7 @@ isWindows = platform.system() != 'Darwin' and platform.system() != 'Linux'\n\
#try:\n\
# multiprocessing.set_start_method('spawn')\n\
#except:\n\
-# pass\n\
-\n\
-bpy = sys.modules.get('bpy')\n\
-if bpy is not None:\n\
- sys.executable = bpy.app.binary_path_python\n";
+# pass\n";
//////////////////////////////////////////////////////////////////////
// DEBUG
diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h
index 7622fc5a602..8e0d113d680 100644
--- a/intern/mantaflow/intern/strings/liquid_script.h
+++ b/intern/mantaflow/intern/strings/liquid_script.h
@@ -50,7 +50,8 @@ 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\
-maxSysParticles_s$ID$ = $PP_PARTICLE_MAXIMUM$\n";
+maxSysParticles_s$ID$ = $PP_PARTICLE_MAXIMUM$\n\
+using_apic_s$ID$ = $USING_APIC$\n";
const std::string liquid_variables_particles =
"\n\
@@ -91,6 +92,14 @@ curvature_s$ID$ = None\n\
pp_s$ID$ = s$ID$.create(BasicParticleSystem, name='$NAME_PARTS$')\n\
pVel_pp$ID$ = pp_s$ID$.create(PdataVec3, name='$NAME_PARTSVELOCITY$')\n\
\n\
+pCx_pp$ID$ = None\n\
+pCy_pp$ID$ = None\n\
+pCz_pp$ID$ = None\n\
+if using_apic_s$ID$:\n\
+ pCx_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
+ pCy_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
+ pCz_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
+\n\
# Acceleration data for particle nbs\n\
pindex_s$ID$ = s$ID$.create(ParticleIndexSystem, name='$NAME_PINDEX$')\n\
gpi_s$ID$ = s$ID$.create(IntGrid, name='$NAME_GPI$')\n\
@@ -275,8 +284,12 @@ def liquid_step_$ID$():\n\
resetOutflow(flags=flags_s$ID$, phi=phi_s$ID$, parts=pp_s$ID$, index=gpi_s$ID$, indexSys=pindex_s$ID$)\n\
flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\
\n\
- # combine particles velocities with advected grid velocities\n\
- mapPartsToMAC(vel=velParts_s$ID$, flags=flags_s$ID$, velOld=velOld_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, weight=mapWeights_s$ID$)\n\
+ # combine particle velocities with advected grid velocities\n\
+ if using_apic_s$ID$:\n\
+ apicMapPartsToMAC(flags=flags_s$ID$, vel=vel_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, cpx=pCx_pp$ID$, cpy=pCy_pp$ID$, cpz=pCz_pp$ID$)\n\
+ else:\n\
+ mapPartsToMAC(vel=velParts_s$ID$, flags=flags_s$ID$, velOld=velOld_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, weight=mapWeights_s$ID$)\n\
+ \n\
extrapolateMACFromWeight(vel=velParts_s$ID$, distance=2, weight=mapWeights_s$ID$)\n\
combineGridVel(vel=velParts_s$ID$, weight=mapWeights_s$ID$, combineVel=vel_s$ID$, phi=phi_s$ID$, narrowBand=combineBandWidth_s$ID$, thresh=0)\n\
velOld_s$ID$.copyFrom(vel_s$ID$)\n\
@@ -319,7 +332,11 @@ def liquid_step_$ID$():\n\
# set source grids for resampling, used in adjustNumber!\n\
pVel_pp$ID$.setSource(grid=vel_s$ID$, isMAC=True)\n\
adjustNumber(parts=pp_s$ID$, vel=vel_s$ID$, flags=flags_s$ID$, minParticles=minParticles_s$ID$, maxParticles=maxParticles_s$ID$, phi=phi_s$ID$, exclude=phiObs_s$ID$, radiusFactor=radiusFactor_s$ID$, narrowBand=adjustedNarrowBandWidth_s$ID$)\n\
- flipVelocityUpdate(vel=vel_s$ID$, velOld=velOld_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, flipRatio=flipRatio_s$ID$)\n";
+ \n\
+ if using_apic_s$ID$:\n\
+ apicMapMACGridToParts(partVel=pVel_pp$ID$, cpx=pCx_pp$ID$, cpy=pCy_pp$ID$, cpz=pCz_pp$ID$, parts=pp_s$ID$, vel=vel_s$ID$, flags=flags_s$ID$)\n\
+ else:\n\
+ flipVelocityUpdate(vel=vel_s$ID$, velOld=velOld_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, flipRatio=flipRatio_s$ID$)\n";
const std::string liquid_step_mesh =
"\n\
diff --git a/intern/sky/source/sky_model.cpp b/intern/sky/source/sky_model.cpp
index e835e04d164..165444003d3 100644
--- a/intern/sky/source/sky_model.cpp
+++ b/intern/sky/source/sky_model.cpp
@@ -272,9 +272,8 @@ static double ArHosekSkyModel_CookRadianceConfiguration(ArHosekSkyModel_Radiance
return res;
}
-static double ArHosekSkyModel_GetRadianceInternal(SKY_ArHosekSkyModelConfiguration configuration,
- double theta,
- double gamma)
+static double ArHosekSkyModel_GetRadianceInternal(
+ const SKY_ArHosekSkyModelConfiguration configuration, const double theta, const double gamma)
{
const double expM = exp(configuration[4] * gamma);
const double rayM = cos(gamma) * cos(gamma);
diff --git a/intern/sky/source/sky_nishita.cpp b/intern/sky/source/sky_nishita.cpp
index f36bfcc3d7b..e3b6ca021fe 100644
--- a/intern/sky/source/sky_nishita.cpp
+++ b/intern/sky/source/sky_nishita.cpp
@@ -87,7 +87,7 @@ static float3 geographical_to_direction(float lat, float lon)
return make_float3(cosf(lat) * cosf(lon), cosf(lat) * sinf(lon), sinf(lat));
}
-static float3 spec_to_xyz(float *spectrum)
+static float3 spec_to_xyz(const float *spectrum)
{
float3 xyz = make_float3(0.0f, 0.0f, 0.0f);
for (int i = 0; i < num_wavelengths; i++) {
@@ -112,10 +112,12 @@ static float density_mie(float height)
static float density_ozone(float height)
{
float den = 0.0f;
- if (height >= 10000.0f && height < 25000.0f)
+ if (height >= 10000.0f && height < 25000.0f) {
den = 1.0f / 15000.0f * height - 2.0f / 3.0f;
- else if (height >= 25000 && height < 40000)
+ }
+ else if (height >= 25000 && height < 40000) {
den = -(1.0f / 15000.0f * height - 8.0f / 3.0f);
+ }
return den;
}
@@ -133,15 +135,16 @@ static float phase_mie(float mu)
/* Intersection helpers */
static bool surface_intersection(float3 pos, float3 dir)
{
- if (dir.z >= 0)
+ if (dir.z >= 0) {
return false;
+ }
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)
+ if (t >= 0.0f) {
return true;
- else
- return false;
+ }
+ return false;
}
static float3 atmosphere_intersection(float3 pos, float3 dir)